如何显示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 时区问题,我可以在我的应用程序中看到它。有什么办法可以通过程序实现这一点。下面是我用来查看日期是否在夏令时的代码。

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 点。有什么办法可以实现吗?

预期输出:

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

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

实际输出错误的 JVM:

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

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

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

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[Brazil/East]
2018-10-21T07:52:16-02:00[Brazil/East]
2018-10-21T08:52:16-02:00[Brazil/East]

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

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

    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]

“Gap”表示夏令时开始时时钟拨快了。时钟向后转动的过渡打印为“重叠”。

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

我推荐 java.time,现代 Java 日期和时间 API。您使用的日期时间 类 — TimeZoneCalendarDateFormatSimpleDateFormatDate — 都设计得很糟糕而且很长过时了。

链接