将日期转换为不同的时区

Bob*_*r02 24 java timezone datetime calendar date

我正在尝试使用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());
Run Code Online (Sandbox Code Playgroud)

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

Yog*_*ngh 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()))
Run Code Online (Sandbox Code Playgroud)

  • 显然,formatter.format(instance2.getTime())会更改timeZone,但是当我们将此字符串日期转换回日期对象时,它会再次选择本地时区.这有什么解决方案吗? (2认同)

Bas*_*que 15

接受的答案是正确的.java.util.Date类没有分配时区,但它的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 );
Run Code Online (Sandbox Code Playgroud)

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 );
Run Code Online (Sandbox Code Playgroud)

实际上,java.util.Date该类确实其源代码中埋藏了一个时区.但是为了大多数实际目的,该课程忽略了该时区.因此,作为速记,通常会说juDate没有分配时区.混乱?是.避免混乱是juDate并使用Joda-Time和/或java.time.