2012-11-02 98 views
18

我想获得从一个时区到另一个使用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

你想使用[乔达时间](http://stackoverflow.com/a/375803/1037210)?这是我的偏好。 – Lion

+0

检查[这个答案](http://stackoverflow.com/questions/230126/how-to-handle-calendar-timezones-using-java)。它可以派上用场。 – Gamb

+0

我在网上发现了另一件事,它可能是最干净的解决方案,它使用日期时间格式来解析日期字符串并在相应时区返回日期 – Bober02

回答

31

当您使用System.out.println(date); or System.out.println(instance2.getTime());打印日期时,instance2.getTime()返回的DateTimeZone 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())) 
+0

你确定它是本地时区而不是EPOCH秒(timezone-independant)? http://docs.oracle.com/javase/7/docs/api/java/util/Calendar.html#getTime() – akaIDIOT

+0

@akaIDIOT内部表示形式自epoch以来,当打印日期时使用本地时区,一个'java.util.Date'的特性/错误。 – dan

+0

@ Bober02:你找到更好的东西了吗?如果是,请分享。 –

2

您可以使用下面的代码片段

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)); 
8

接受的答案是正确的。 java.util.Date类没有分配时区,但它的toString实现混淆地应用了JVM的当前默认时区。

避免java.util.Date & .Calendar

这是很多原因,以避免出了名的麻烦java.util.Date,.Calendar,和SimpleDateFormat类与Java捆绑之一。避免它们。相反,请使用:

约达时间

在约达时间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 package内置。这个软件包受到了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); 

其实java.util.Date确实有埋内its source code一个时区。但是班级为了最实际的目的忽略了那个时区。所以,作为简写,通常会说j.u.Date没有分配时区。混乱?是。避免使用j.u.Date,并使用Joda-Time和/或java.time。