关于日期时间:JBOSS Java日期夏令时

Jboss Java Date daylight saving time

有一个问题,当时钟由于夏时制(每年两次)而移动时,Java中的日期不正确(我在中欧:EDOCX1,0在夏天,EDOCX1,1)在冬天。

如果时间提前1小时移动,new Date()仍返回旧时间(比当前时间晚1小时)。

在Java 7中,可以在不重启JBASE应用服务器的情况下解决这个问题吗?

如果在Windows中手动更改时间,则会重现问题:除非重新启动JBoss,否则Date不会更新到系统日期。

1
2
Calendar c = Calendar.getInstance();
c.setTime(new Date());


在Java <=7中,可以使用StuteTeN后端,这是Java 8新的日期/时间类的一个很大的后端。

有了这个,您可以轻松地处理DST更改。

首先,您可以使用org.threeten.bp.DateTimeUtilsCalendar转换为Calendar

下面的代码将Calendar转换为org.threeten.bp.Instant,这是一个表示"UTC即时"(与时区无关的时间戳)的类:现在,世界上的每个人都在同一时刻,尽管他们的本地日期和时间可能不同,但取决于他们在哪里)。

然后,Instant转换为org.threeten.bp.ZonedDateTime(意思是:此时此刻,这个时区的日期和时间是什么?).I还使用org.threeten.bp.ZoneId获得时区:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
Calendar c = Calendar.getInstance();
c.setTime(new Date());

// get the current instant in UTC timestamp
Instant now = DateTimeUtils.toInstant(c);

// convert to some timezone
ZonedDateTime z = now.atZone(ZoneId.of("Europe/Berlin"));

// today is 08/06/2017, so Berlin is in DST (GMT+2)
System.out.println(z); // 2017-06-08T14:11:58.608+02:00[Europe/Berlin]

// testing with a date in January (not in DST, GMT+1)
System.out.println(z.withMonth(1)); // 2017-01-08T14:11:58.608+01:00[Europe/Berlin]

我刚刚选择了一些使用中欧时区的时区(Europe/Berlin):您不能使用这些3个字母的缩写,因为它们不明确且不标准。您可以将代码更改为最适合您的系统的时区(您可以使用ZoneId.getAvailableZoneIds())获得所有可用时区的列表。

我更喜欢这个解决方案,因为它明确了我们用来向用户显示的时区(DateCalendartoString()方法在后台使用默认时区,而您永远不知道它们在做什么)。

在内部,我们可以继续使用Instant,它是在UTC中,所以它不受时区的影响(并且您可以随时转换到时区和从时区转换到时区),如果您想将ZonedDateTime转换回Instant,只需使用toInstant()方法。

实际上,如果你想得到当前的日期/时间,只需忘记旧的类(DateCalendar并只使用Instant

1
2
// get the current instant in UTC timestamp
Instant now = Instant.now();

但是如果仍然需要使用旧类,只需使用DateTimeUtils进行转换。

上述示例的输出是ZonedDateTime.toString()方法的结果。如果要更改格式,请使用org.threeten.bp.format.DateTimeFormatter类(查看javadoc以了解有关所有可能格式的更多详细信息):

1
2
3
4
5
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("dd/MM/yyyy HH:mm:ss z X");
// DST (GMT+02)
System.out.println(formatter.format(z)); // 08/06/2017 14:11:58 CEST +02
// not DST (GMT+01)
System.out.println(formatter.format(z.withMonth(1))); // 08/01/2017 14:11:58 CET +01

使用jdk 8 java.time中的ZonedDateTime类。它适应夏令时的变化。详情请访问:https://docs.oracle.com/javase/8/docs/api/java/time/zoneddatetime.html