将日期转换为其他时区避免 java.util.Date & .日历城大时间java.time

2022-09-01 20:07:30

我正在尝试使用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小时...整个问题似乎微不足道,但我找不到任何简单的答案。提前感谢您的帮助。


答案 1

使用 打印日期时,返回的 by 始终以本地时区打印日期。System.out.println(date); or System.out.println(instance2.getTime());Dateinstance2.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()))

答案 2

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

避免 java.util.Date & .日历

这是避免臭名昭着的麻烦的java.util.Date,的众多原因之一。Calendar 和 SimpleDateFormat 类与 Java 捆绑在一起。避免它们。请改用:

城大时间

以下是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 );

实际上,该类在其源代码确实有一个隐藏在时区中。但是,出于大多数实际目的,该类忽略了该时区。因此,作为简写,人们常说j.u.Date没有分配时区。混乱?是的。避免j.u.Date的混乱,并使用Joda-Time和/或java.time。java.util.Date