如何根据UTC时间+ TimeZone ID计算待机时间?

时间:2011-11-27 14:13:00

标签: java timezone utc dst wall-time

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

假设我有一个UTC时间和一个TimeZone ID,我如何计算Java中的墙上时间(= UTC时间+时区偏移+夏令时),知道一年中夏令时的变化?

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

2 个答案:

答案 0 :(得分:3)

在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

答案 1 :(得分:3)

当你说你有时间在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点。现在您只需要将时区从UTC更改为澳大利亚Melbounre:

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。在6月的UTC时区,澳大利亚有冬天,因此他们没有观察夏令时。

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


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

Calendar winter = new GregorianCalendar(TimeZone.getTimeZone("Europe/Oslo"));
winter.set(2011, Calendar.DECEMBER, 27, 9, 0, 0);
奥斯陆的9:00在冬季是8:00 UTC,但在墨尔本是19:00( +10小时)。

但是在夏天的同一时间:

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

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

不知何故,人们认为两个时区之间的差异总是不变的(“奥斯陆和墨尔本之间的差异总是 10小时) - 这是不是是真的,特别是考虑到不同的半球时。

实际上,在Oslo的冬季(没有DST,UTC + 1),在Melbourne(UTC + 11)中观察到DST。另一方面,虽然奥斯陆有夏季,但观察到夏令时(UTC + 2),但在墨尔本没有观测到(UTC + 10)。现在很明显,为什么差异在8到10小时之间变化,具体取决于一年中的某一天。

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