24

我正在尝试使用 Java 日期和日历进行从一个时区到另一个时区的简单转换。我正在尝试运行以下代码

    Calendar instance = Calendar.getInstance(TimeZone.getTimeZone("Europe/London"));
    Date date = instance.getTime();
    System.out.println(date);

    GregorianCalendar instance2 = new GregorianCalendar(TimeZone.getTimeZone("Europe/Athens"));
    instance2.setTime(instance.getTime());
    System.out.println(instance2.getTime());

但这仍然返回相同的日期,而不是 +1 小时......整个问题似乎微不足道,但我找不到任何简单的答案。在此先感谢您的帮助。

4

3 回答 3

37

当您使用 打印日期System.out.println(date); or System.out.println(instance2.getTime());时,Date 返回的instance2.getTime()TimeZone independent并且始终以本地时区打印日期。

相反,您可能想使用DateFormat/SimpleDateFormat

  DateFormat formatter= new SimpleDateFormat("MM/dd/yyyy HH:mm:ss Z");
  formatter.setTimeZone(TimeZone.getTimeZone("Europe/London"));
  System.out.println(formatter.format(date));

  formatter.setTimeZone(TimeZone.getTimeZone("Europe/Athens"));
  System.out.println(formatter.format(instance2.getTime()))
于 2012-11-02T15:12:40.903 回答
15

接受的答案是正确的。java.util.Date 类没有分配时区†</sup>,但它的toString实现令人困惑地应用了 JVM 当前的默认时区。

避免使用 java.util.Date & .Calendar

这是避免与 Java 捆绑在一起的臭名昭著的麻烦 java.util.Date、.Calendar 和 SimpleDateFormat 类的众多原因之一。避开他们。而是使用:

乔达时间

Joda-Time 2.3 中的一些示例代码如下。在 StackOveflow 中搜索更多示例和讨论。

DateTimeZone timeZoneLondon = DateTimeZone.forID( "Europe/London" );
DateTimeZone timeZoneAthens = DateTimeZone.forID( "Europe/Athens" );

DateTime nowLondon = DateTime.now( timeZoneLondon );
DateTime nowAthens = nowLondon.withZone( timeZoneAthens );
DateTime nowUtc = nowLondon.withZone( DateTimeZone.UTC );

java.time

Java 8 及更高版本内置了一个新的java.time 包。这个包的灵感来自 Joda-Time。虽然它们有一些相似之处和类名,但它们是不同的;每个都有其他人缺乏的功能。一个显着的区别是 java.time 避免使用构造函数,而是使用静态实例化方法。

在这个问题的情况下,它们以相同的方式工作。指定时区,并调用now方法获取当前时刻,然后基于旧的不可变实例创建新实例以适应时区。

请注意两个不同的时区类。一个是命名时区,包括夏令时和其他此类异常的所有规则以及与 UTC 的偏移量,而另一个只是偏移量。

ZoneId zoneMontréal = ZoneId.of("America/Montreal"); 
ZonedDateTime nowMontréal = ZonedDateTime.now ( zoneMontréal );

ZoneId zoneTokyo = ZoneId.of("Asia/Tokyo"); 
ZonedDateTime nowTokyo = nowMontréal.withZoneSameInstant( zoneTokyo );

ZonedDateTime nowUtc = nowMontréal.withZoneSameInstant( ZoneOffset.UTC );

†</sup>实际上,java.util.Date该类在其源代码中确实有一个时区。但是出于大多数实际目的,该课程忽略了该时区。因此,作为简写,人们常说 juDate 没有指定时区。令人困惑?是的。避免 juDate 的混乱并使用 Joda-Time 和/或 java.time。

于 2014-07-15T07:19:36.773 回答
3

您可以使用以下代码片段

String dateString = "14 Jul 2014 00:11:04 CEST";
date = formatter.parse(dateString);
System.out.println(formatter.format(date));

// Set the formatter to use a different timezone - Indochina Time
formatter.setTimeZone(TimeZone.getTimeZone("Asia/Bangkok"));
System.out.println("ICT time : "+formatter.format(date));
于 2014-07-15T04:35:34.833 回答