如何根据 UTC 时间计算墙上时间 +时区 ID?

发布于 2024-12-18 09:07:35 字数 150 浏览 5 评论 0原文

我一直在谷歌上搜索这个问题,但找不到清晰明确的文档。

假设我有一个 UTC 时间和一个时区 ID,在知道夏令时在一年中发生变化的情况下,如何在 Java 中计算挂壁时间(= UTC 时间 + 时区偏移 + 夏令时)?

我正在寻找经过测试的代码示例。谢谢。

I have been googling around this issue, but could not find clear and definitive documentation.

Assuming I have a UTC time and a TimeZone ID, how do I calculate wall time (= UTC time + Timezone offset + daylight savings) in Java knowing that daylight savings change during the year?

I am looking for a tested code example. Thanks.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

七秒鱼° 2024-12-25 09:07:35

当您说您有 UTC 时间时,我假设您将其保存在 Calendar 中(Date 没有时区的概念,尽管有误导性的 toString())。如果您有时间,例如在 String 中,您可以轻松解析它或日历实例,如下所示:

Calendar summer = new GregorianCalendar(DateUtils.UTC_TIME_ZONE);
summer.set(2011, Calendar.JUNE, 27, 9, 0, 0);

summer 代表 2011 年 6 月 27 日上午 9:00 UTC。现在您需要做的就是要做的是将时区从 UTC 更改为澳大利亚墨尔本:

summer.setTimeZone(TimeZone.getTimeZone("Australia/Melbourne"));

我将使用 FastDateFormat 正确打印日期:

final FastDateFormat formatter = FastDateFormat.getDateTimeInstance(FastDateFormat.SHORT, FastDateFormat.SHORT);

System.out.println(formatter.format(summer));

墨尔本的时间是 19:00 (+10小时)。但是将日期更改为冬季:

Calendar winter = new GregorianCalendar(DateUtils.UTC_TIME_ZONE);
winter.set(2011, Calendar.DECEMBER, 27, 9, 0, 0);
System.out.println(formatter.format(winter));

墨尔本的时间突然变为20:00(+11 小时)。

这一差异证明,更改Calendar 上的时区会考虑 DST。 UTC 时区的 6 月,澳大利亚处于冬季,因此不遵守 DST。

但在 UTC 的冬天,澳大利亚却是夏天 - 他们通过将时钟移动一小时来切换到夏令时。这就是为什么冬季时差为 +11 小时,而夏季时差为 +10 小时。


但是等等!当考虑到观察夏令时的多个时区时,它会变得更加有趣。首先,我在欧洲/奥斯陆时区创建相同的日期:

Calendar winter = new GregorianCalendar(TimeZone.getTimeZone("Europe/Oslo"));
winter.set(2011, Calendar.DECEMBER, 27, 9, 0, 0);

冬季奥斯陆的 9:00 是 UTC 8:00,但墨尔本是 19:00(+10 小时)。

但夏季的同一时间:

Calendar summer = new GregorianCalendar(TimeZone.getTimeZone("Europe/Oslo"));
summer.set(2011, Calendar.JUNE, 27, 9, 0, 0);

实际上是 UTC 7:00 和墨尔本 17:00! +8 小时

不知何故,人们认为两个时区之间的差异始终是恒定的(“奥斯陆和墨尔本之间的时差始终 10 小时),但事实并非 确实如此,尤其是考虑到

奥斯陆<的冬季的不同半球时 。 /a>(没有夏令时,UTC+1) 墨尔本遵守夏令时 (UTC+11另一方面,虽然奥斯陆处于夏季并且遵守夏令时 (UTC+2),但墨尔本却没有遵守夏令时 (UTC+10)。的一天 另请记住,

DST 的第一天和最后一天不是全球性的,而是针对每个时区任意选择的,这意味着 9 小时的差异也是可能的 (!) 例如,查看今年的 4 月 1 日。

When you say that you have time in UTC I assume you hold it in Calendar (Date has no notion of time zone, despite the misleading toString()). If you have time e.g. in String you can easily parse it or calendar instance like here:

Calendar summer = new GregorianCalendar(DateUtils.UTC_TIME_ZONE);
summer.set(2011, Calendar.JUNE, 27, 9, 0, 0);

summer represents 9:00 AM UTC on 27th of June 2011. Now all you need to do is to change the time zone from UTC to Melbounre, Australia:

summer.setTimeZone(TimeZone.getTimeZone("Australia/Melbourne"));

I will use FastDateFormat to print the date correctly:

final FastDateFormat formatter = FastDateFormat.getDateTimeInstance(FastDateFormat.SHORT, FastDateFormat.SHORT);

System.out.println(formatter.format(summer));

The time in Melbourne is 19:00 (+10 hours). But change the date to winter:

Calendar winter = new GregorianCalendar(DateUtils.UTC_TIME_ZONE);
winter.set(2011, Calendar.DECEMBER, 27, 9, 0, 0);
System.out.println(formatter.format(winter));

And suddenly the the time in Melbourne is 20:00 (+11 hours).

The difference proves that changing the time zone on Calendar takes DST into account. During June in UTC time zone there is winter in Australia, hence they do not observe DST.

But during winter in UTC there is summer in Australia - and they switch to DST by shifting the clocks by one hour. This is the reason why during winter the difference is +11 hours as opposed to +10 during summer UTC.


But wait! It gets even more interesting when multiple time zones observing DST are taken into account. First I create the same date in Europe/Oslo time zone:

Calendar winter = new GregorianCalendar(TimeZone.getTimeZone("Europe/Oslo"));
winter.set(2011, Calendar.DECEMBER, 27, 9, 0, 0);

9:00 in Oslo during winter is 8:00 UTC but 19:00 in Melbourne (+10 hours).

But the same time in summer:

Calendar summer = new GregorianCalendar(TimeZone.getTimeZone("Europe/Oslo"));
summer.set(2011, Calendar.JUNE, 27, 9, 0, 0);

Is actually 7:00 UTC and 17:00 in Melbourne! +8 hours!

Somehow people assume that the difference between two time zones is always constant ("the difference between Oslo and Melbourne is always 10 hours) - which is not true, especially when different hemispheres are taken into account.

In reality during winter in Oslo (no DST, UTC+1) DST is observed in Melbourne (UTC+11). On the other hand while there is summer in Oslo and DST is observed (UTC+2), it is not observed in Melbourne (UTC+10). Now it becomes obvious why the difference varies between 8 and 10 hours depending on the day of year.

Also remember that the first and last day of DST is not global but chosen arbitrarily for each time zone. This means that the difference of 9 hours is also possible (!) E.g. check out the 1st of April this year.

荭秂 2024-12-25 09:07:35

当您在 java 中使用 Date 时,它​​内部始终采用 UTC。时区包括 DST 设置,因此实际上非常简单。

public static void main(String[] args) throws ParseException {
    String stringAugust = "2011-08-01 12:00:00";
    String stringNovember = "2011-11-01 12:00:00";

    // Outputting the time in Stockholm and Santiago
    // Stockholm has DST in August and not in November
    // Santiago has DST in November and not in August

    SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");

    // Parsing the Strings
    sdf.setTimeZone(TimeZone.getTimeZone("UTC"));
    Date dateAugust = sdf.parse(stringAugust);
    Date dateNovember = sdf.parse(stringNovember);

    // outputting the dates for Stockholm
    sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss Z");
    sdf.setTimeZone(TimeZone.getTimeZone("Europe/Stockholm"));
    System.out.println(sdf.format(dateAugust));
    System.out.println(sdf.format(dateNovember));

    // outputting the dates for Santiago
    sdf.setTimeZone(TimeZone.getTimeZone("America/Santiago"));
    System.out.println(sdf.format(dateAugust));
    System.out.println(sdf.format(dateNovember));

}

输出

2011-08-01 14:00:00 +0200
2011-11-01 13:00:00 +0100
2011-08-01 08:00:00 -0400
2011-11-01 09:00:00 -0300

When you use Date in java it's always in UTC internally. And Timezone include DST settings so it's actually quite easy.

public static void main(String[] args) throws ParseException {
    String stringAugust = "2011-08-01 12:00:00";
    String stringNovember = "2011-11-01 12:00:00";

    // Outputting the time in Stockholm and Santiago
    // Stockholm has DST in August and not in November
    // Santiago has DST in November and not in August

    SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");

    // Parsing the Strings
    sdf.setTimeZone(TimeZone.getTimeZone("UTC"));
    Date dateAugust = sdf.parse(stringAugust);
    Date dateNovember = sdf.parse(stringNovember);

    // outputting the dates for Stockholm
    sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss Z");
    sdf.setTimeZone(TimeZone.getTimeZone("Europe/Stockholm"));
    System.out.println(sdf.format(dateAugust));
    System.out.println(sdf.format(dateNovember));

    // outputting the dates for Santiago
    sdf.setTimeZone(TimeZone.getTimeZone("America/Santiago"));
    System.out.println(sdf.format(dateAugust));
    System.out.println(sdf.format(dateNovember));

}

outputs

2011-08-01 14:00:00 +0200
2011-11-01 13:00:00 +0100
2011-08-01 08:00:00 -0400
2011-11-01 09:00:00 -0300
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文