关于时区:如何显示Java开始夏令时后的时间差异?

How to show the difference in time after the daylight saving started in Java?

我想检查夏令时开始之前和之后的时间差。 我正在使用JVM,其中时区与巴西时间的DST WRT存在一些问题。 我可以看到10月21日属于DST的输出,这是11月4日开始夏令时的错误。 我希望看到10月20日到10月21日之间的1小时的时间差,由于JRE时区问题,我可以在我的申请中看到。 我有什么方法可以通过一个程序实现这一目标。 下面是我用来查看日期是否在DST之下的代码。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.TimeZone;
public class Timezone
{
    public static void main(String[] args) throws ParseException {
        TimeZone TIMEZONE = TimeZone.getTimeZone("Brazil/East");

        System.out.println("timeZone :" + TIMEZONE);
        Calendar c = Calendar.getInstance(TIMEZONE);
        DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss");
        dateFormat.setTimeZone(TIMEZONE);

        Date date = dateFormat.parse("2018-10-20T00:00:00");
        c.setTime(date);
        System.out.println("In dst" + c.getTimeZone().inDaylightTime(c.getTime()));

        date = dateFormat.parse("2018-10-21T00:00:00");
        c.setTime(date);

        System.out.println("In dst" + c.getTimeZone().inDaylightTime(c.getTime()));

        date = dateFormat.parse("2018-11-04T00:00:00");
        c.setTime(date);
        System.out.println("In dst" + c.getTimeZone().inDaylightTime(c.getTime()));

    }
}

进一步添加到我的问题,我能够通过使用我的上述程序找出夏令时。 我想要一些它应该告诉我的东西:10月20日时间是上午9点,而同一时间由于DST转移了1小时,即上午10点。 有没有办法实现这个目标?

预期产量:

1
2
3
     timeZone : sun.util.calendar.ZoneInfo[id="Brazil/East"]

         Time is: 21-10-2018 07:52:16

实际输出故障JVM:

1
2
3
        timeZone : timeZone : sun.util.calendar.ZoneInfo[id="Brazil/East"]

       Time is: 21-10-2018 08:52:30


解决方案是使用故障(过时)时区数据修复JVM。使用Oracle的时区更新工具非常简单。请参阅底部的链接(对于OpenJDK,请参阅下一个链接)。

如果您想知道JVM"认为"夏令时(DST)何时开始,您可以使用以下代码:

1
2
3
4
    ZoneId zone = ZoneId.of("America/Sao_Paulo");
    ZoneRules rules = zone.getRules();
    ZoneOffsetTransition dstStarted = rules.previousTransition(Instant.now());
    System.out.println(dstStarted);

显然我的Java 11有11月4日夏天开始的新时区数据。我得到了这个输出:

Transition[Gap at 2018-11-04T00:00-03:00 to -02:00]

"差距"意味着时钟在夏季时间开始时向前转。向后翻转的时钟被打印为"重叠"。

如果需要,您还可以查询ZoneOffsetTransition有关转换前后的本地日期和时间,转换的瞬间,转换前后应用的UTC偏移,转换的签名长度(此处为1小时) )和其他信息。

我推荐java.time,现代Java日期和时间API。您使用的日期时间类 - TimeZoneCalendarDateFormatSimpleDateFormatDate - 设计都很差,而且已经过时了。

链接

  • 时区更新工具(适用于Oracle JDK)
  • 如何更新OpenJDK的时区信息? (致Matt Johnson,在评论中提供此链接)
  • Oracle教程:日期时间,解释如何使用java.time


我将添加一个非常简短的答案。它表明1天不等于24小时,即DST改变了??。我也步入Java 8,因为我对它更熟悉。

1
2
3
4
5
6
7
ZoneId timezone = ZoneId.of("Brazil/East");

ZonedDateTime t = ZonedDateTime.of(2018, 10, 20, 7, 52, 16, 0, timezone);

System.out.println(t);
System.out.println(t.plus(1, ChronoUnit.DAYS));
System.out.println(t.plus(24, ChronoUnit.HOURS));

输出:

2018-10-20T07:52:16-03:00 [巴西/东]
2018-10-21T07:52:16-02:00 [巴西/东]
2018-10-21T08:52:16-02:00 [巴西/东]