更改Date对象的时区而不更改日期

时间:2016-12-06 20:57:22

标签: java-8 jodatime

我可以在不更改日期的情况下更改java代码中Date对象的时区吗? 当我写作 Date date = new Date(longValue); 我在当地时区得到这个日期。我希望得到这个日期,但我的时区应该是我的用户ID(例如“美国/芝加哥”)的DB(非本地)中的一个。

提前感谢您的帮助。

3 个答案:

答案 0 :(得分:9)

TL;博士

ZonedDateTime zdtMontreal = 
    ZonedDateTime.now( ZoneId.of( "America/Montreal" ) );

ZonedDateTime zdtAuckland = 
    zdtMontreal.withZoneSameLocal( ZoneId.of( "Pacific/Auckland" ) );  

同一时刻。 zdtAuckland时刻发生了几个小时

确定这是你真正的意图。我有一种沉闷的感觉,你做错了事,对日期时间处理的工作方式感到困惑。日期时间工作 令人困惑。务必搜索和研究Stack Overflow。

java.time

现在位于Joda-Timemaintenance mode项目建议迁移到java.time。

Local…类故意没有时区或offset-from-UTC信息。

LocalDate ld = LocalDate.of( 2016 , Month.January , 23 ); // 2016-01-23
LocalTime lt = LocalTime.of( 12 , 34 , 56 );  // 12:34:56

这些值表示时间轴上的一个点。那是奥克兰新西兰,巴黎FR或蒙特利尔加州的中午时间吗?我们必须应用时区来确定实际时刻。我们应用ZoneId来获取ZonedDateTime

continent/region的格式指定proper time zone name,例如America/MontrealAfrica/CasablancaPacific/Auckland。切勿使用诸如ESTISTCST之类的3-4字母缩写,因为它们不是真正的时区,不是标准化的,甚至不是唯一的( !)。

ZoneId zMontreal = ZoneId.of( "America/Montreal" );
ZonedDateTime zdtMontreal = ZonedDateTime.of( ld , lt , zMontreal );

要查看以标准ISO 8601格式表示此值的字符串,请致电toString。实际上,ZonedDateTime类通过在方括号中明智地附加时区名称来扩展标准格式。

String outputMontreal = zdtMontreal.toString();
  

2016-01-23T12:34:56-05:00 [美国/蒙特利尔]

要在另一个时区中获取相同的日期和相同的时间,请重复此过程。

ZoneId zParis = ZoneId.of( "Europe/Paris" );
ZonedDateTime zdtParis = ZonedDateTime.of( ld , lt , zParis );

ZoneId zAuckland = ZoneId.of( "Pacific/Auckland" );
ZonedDateTime zdtAuckland = ZonedDateTime.of( ld , lt , zAuckland );

但要知道你正在及时获得不同的时刻。奥克兰的正午时间发生在巴黎正午前几个小时,而蒙特利尔的中午甚至更晚,三个<强>不同的时间点碰巧碰巧分享wall-clock time

  

2016-01-23T12:34:56-05:00 [美国/蒙特利尔]

     

2016-01-23T12:34:56 + 01:00 [欧洲/巴黎]

     

2016-01-23T12:34:56 + 13:00 [太平洋/奥克兰]

enter image description here

当前时刻

要获取当前时刻,请致电Instant.nowInstant类代表UTC中时间轴上的一个时刻,分辨率为nanoseconds(小数部分最多九(9)位)。

Instant instance = Instance.now();

应用ZoneId调整时区。

ZoneId z = ZoneId.of( "America/Montreal" );
ZonedDateTime zdt = instance.atZone( z );

对其他所需时区重复此过程,类似于我们上面所做的。

作为快捷方式,您可以直接获得ZonedDateTime

ZonedDateTime zdtMontreal = ZonedDateTime.now( ZoneId.of( "America/Montreal" ) );

作为另一种快捷方式,您可以应用不同的时区,同时保留相同的日期和相同的时间(相同的挂钟时间)。致电ZonedDateTime::withZoneSameLocal

ZonedDateTime zdtAuckland = zdtMontreal.withZoneSameLocal( ZoneId.of( "Pacific/Auckland" ) );

我再说一遍:这个结果在时间线上是不同的点。 zdtAuckland发生在zdtMontreal发生前几个小时。

要保持相同的时刻,请拨打ZonedDateTime::withZoneSameInstant

数据库

通常最好将日期时间值存储在UTC的数据库中。已经在Stack Overflow上进行了广泛讨论。搜索更多信息。

关于java.time

java.time框架内置于Java 8及更高版本中。这些类取代了麻烦的旧legacy日期时间类,例如java.util.DateCalendar和&amp; SimpleDateFormat

现在位于Joda-Timemaintenance mode项目建议迁移到java.time。

要了解详情,请参阅Oracle Tutorial。并搜索Stack Overflow以获取许多示例和解释。规范是JSR 310

从哪里获取java.time类?

ThreeTen-Extra项目使用其他类扩展java.time。该项目是未来可能添加到java.time的试验场。您可以在此处找到一些有用的课程,例如IntervalYearWeekYearQuartermore

答案 1 :(得分:0)

您可能会发现ZonedDateTime非常有用:

Java 8 Convert given time and time zone to UTC time

或者,您可以创建另一个Date对象并手动应用一些偏移量。

答案 2 :(得分:0)

使用Java8 ZonedDateTime类:

的示例
Date date = new Date(longValue);
ZoneId = ZoneId.of("America/Chicago");
ZonedDateTime dt = ZonedDateTime.ofInstant(date.toInstant(), zoneId);

你已经用Joda标记了这个问题,但是真的用Java8你不再需要它了。