Jas*_*cht 7 java linux datetime
当OS使用POSIX时区描述而不是时区名称时,Java似乎没有应用DST偏移量。JRE不支持使用TZ描述吗?或者这是一个错误吗?
更多细节...
我正在基于Linux(Debian)的系统上工作,其中TZ环境变量设置为POSIX格式的TZ,STD+7DST+6,M3.2.0/02:00:00,M11.1.0/02:00:00而不是诸如的TZ名称America/Denver。(请参阅TZ变量)
尽管这对于date相关的系统工具似乎正常工作,但是当我尝试在Java应用程序中查找时间时,似乎并未针对DST进行正确调整。导致夏令时生效的一年中的部分时间错误。
我已经在几个不同的系统上进行了测试,并在每个系统上看到了相同的结果(测试结果如下)
这种现象实际上在使用Quartz Scheduler的应用程序中浮出水面,但是我已经能够使用以下SSCCE重现该问题:
import java.util.Date;
import java.util.TimeZone;
public class CheckTime {
public static void main(String[] args) {
TimeZone tz = TimeZone.getDefault();
Date now = new Date();
System.out.println("Current time " + now.toString());
System.out.println("Current time zone " + tz.getDisplayName());
System.out.println("Current time zone in DST? " + tz.inDaylightTime(now));
}
}
Run Code Online (Sandbox Code Playgroud)
Ubuntu 18.04.2 LTS(仿生)
$ java -version
openjdk version "1.8.0_222"
OpenJDK Runtime Environment (build 1.8.0_222-8u222-b10-1ubuntu1~18.04.1-b10)
OpenJDK 64-Bit Server VM (build 25.222-b10, mixed mode)
$ export TZ="STD+7DST+6,M3.2.0/02:00:00,M11.1.0/02:00:00"
$ date
Fri Aug 9 07:02:27 DST 2019
$ java CheckTime
Current time Fri Aug 09 06:02:30 GMT-07:00 2019
Current timezone GMT-07:00
Current timezone in DST? false
$ export TZ="America/Denver"
$ date
Fri Aug 9 07:03:29 MDT 2019
$ java CheckTime
Current time Fri Aug 09 07:03:32 MDT 2019
Current timezone Mountain Standard Time
Current timezone in DST? true
Run Code Online (Sandbox Code Playgroud)
基于debian的定制ARM32hf构建(内核4.1.0-altera)
$ java -version
openjdk version "1.8.0_162"
OpenJDK Runtime Environment (Zulu Embedded 8.27.0.91-linux-aarch32hf) (build 1.8.0_162-b91)
$ export TZ="STD+7DST+6,M3.2.0/02:00:00,M11.1.0/02:00:00"
$ date
Fri Aug 9 07:06:59 DST 2019
$ java CheckTime
Current time Fri Aug 09 06:07:03 GMT-07:00 2019
Current time zone GMT-07:00
Current time zone in DST? false
$ export TZ="America/Denver"
$ date
Fri Aug 9 07:09:45 MDT 2019
$ java CheckTime
Current time Fri Aug 09 07:09:49 MDT 2019
Current time zone Mountain Standard Time
Current time zone in DST? true
Run Code Online (Sandbox Code Playgroud)
Raspbian 9.9(拉伸)
$ java -version
java version "1.8.0_65"
Java(TM) SE Runtime Environment (build 1.8.0_65-b17)
Java HotSpot(TM) Client VM (build 25.65-b01, mixed mode)
$ export TZ="STD+7DST+6,M3.2.0/02:00:00,M11.1.0/02:00:00"
$ date
Fri Aug 9 07:12:52 DST 2019
$ java CheckTime
Current time Fri Aug 09 06:12:57 GMT-07:00 2019
Current time zone GMT-07:00
Current time zone in DST? false
$ export TZ="America/Denver"
$ date
Fri Aug 9 07:13:42 MDT 2019
$ java CheckTime
Current time Fri Aug 09 07:13:44 MDT 2019
Current time zone Mountain Standard Time
Current time zone in DST? true
Run Code Online (Sandbox Code Playgroud)
编辑
奇怪的是,我在Mac上看到的结果略有不同。Java仍然没有报告该系统处于DST中,但是至少报告了正确的本地时间。
MacOS 10.14.6(Mojave)
$ java -version
openjdk version "1.8.0_212"
OpenJDK Runtime Environment Corretto-8.212.04.2 (build 1.8.0_212-b04)
OpenJDK 64-Bit Server VM Corretto-8.212.04.2 (build 25.212-b04, mixed mode)
$ export TZ="STD+7DST+6,M3.2.0/02:00:00,M11.1.0/02:00:00"
$ date
Fri Aug 9 09:47:14 DST 2019
$ java CheckTime
Current time Fri Aug 09 09:47:18 GMT-06:00 2019
Current timezone GMT-06:00
Current timezone in DST? false
$ export TZ="America/Denver"
$ date
Fri Aug 9 09:49:04 MDT 2019
$ java CheckTime
Current time Fri Aug 09 09:49:08 MDT 2019
Current timezone Mountain Standard Time
Current timezone in DST? true
$java -version
java version "1.8.0_161"
Java(TM) SE Runtime Environment (build 1.8.0_161-b12)
Java HotSpot(TM) 64-Bit Server VM (build 25.161-b12, mixed mode)
$ export TZ="STD+7DST+6,M3.2.0/02:00:00,M11.1.0/02:00:00"
$ date
Fri Aug 9 10:19:23 DST 2019
$java CheckTime
Current time Fri Aug 09 10:19:40 GMT-06:00 2019
Current timezone GMT-06:00
Current timezone in DST? false
$ export TZ="America/Denver"
$ date
Fri Aug 9 10:21:03 MDT 2019
$ java CheckTime
Current time Fri Aug 09 10:21:07 MDT 2019
Current timezone Mountain Standard Time
Current timezone in DST? true
Run Code Online (Sandbox Code Playgroud)
这不是一个错误。这是一个特点。
根据javadoc for ZoneId,不支持指定区域的 POSIX 语法:
时区 ID
该ID在系统内是唯一的。ID 分为三种类型。
最简单的 ID 类型是来自 ZoneOffset 的 ID。它由“Z”和以“+”或“-”开头的 ID 组成。
下一种类型的 ID 是具有某种形式前缀的偏移式 ID,例如“GMT+2”或“UTC+01:00”。识别的前缀是“UTC”、“GMT”和“UT”。偏移量是后缀,将在创建过程中进行标准化。可以使用normized()将这些ID标准化为ZoneOffset。
第三种类型的 ID 是基于区域的 ID。基于区域的 ID 必须包含两个或更多字符,并且不能以“UTC”、“GMT”、“UT”、“+”或“-”开头。基于区域的 ID 由配置定义,请参阅 ZoneRulesProvider。该配置的重点是提供从 ID 到底层 ZoneRules 的查找。
时区规则由政府定义并经常变化。有许多组织(此处称为团体)负责监视时区变化并对其进行整理。默认组是 IANA 时区数据库 (TZDB)。其他组织包括 IATA(航空业机构)和 Microsoft。
每个组为其提供的区域 ID 定义自己的格式。TZDB 组定义了“Europe/London”或“America/New_York”等 ID。TZDB ID 优先于其他组。
也可以看看:
如果您编写了一些代码来解析该语法,您应该能够使用这些数据来构造一个SimpleTimeZone(javadoc)。不幸的是,这迫使您继续使用旧的(“大部分已弃用”)Date类和朋友。
The new (in Java 8) java.time.* classes don't appear to have an easy way to construct your own ZoneId from a set of rules. (Maybe it could be done by implementing your own ZoneRuleProvider (javadoc), but it looks complicated.)
So (IMO) you would be better off getting your OS to use the standard TZDB zone ids.
You commented:
On this particular system, neither "/etc/localtime" nor "/etc/timezone" exist.
If you are running Ubuntu Bionic, "/etc/localtime" should exist. It should be a symlink to a binary timezone file in the "/usr/share/zoneinfo" tree. See https://linuxize.com/post/how-to-set-or-change-timezone-on-ubuntu-18-04/. Or perhaps the problem is that the system has been deliberately configured to not know its local timezone.
| 归档时间: |
|
| 查看次数: |
110 次 |
| 最近记录: |