我可以在不更改日期的情况下更改java代码中Date对象的时区吗?
当我写作
Date date = new Date(longValue);
我在当地时区得到这个日期。我希望得到这个日期,但我的时区应该是我的用户ID(例如“美国/芝加哥”)的DB(非本地)中的一个。
提前感谢您的帮助。
答案 0 :(得分:9)
ZonedDateTime zdtMontreal =
ZonedDateTime.now( ZoneId.of( "America/Montreal" ) );
ZonedDateTime zdtAuckland =
zdtMontreal.withZoneSameLocal( ZoneId.of( "Pacific/Auckland" ) );
不同一时刻。 zdtAuckland
时刻发生了几个小时。
确定这是你真正的意图。我有一种沉闷的感觉,你做错了事,对日期时间处理的工作方式感到困惑。日期时间工作 令人困惑。务必搜索和研究Stack Overflow。
现在位于Joda-Time的maintenance 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/Montreal
,Africa/Casablanca
或Pacific/Auckland
。切勿使用诸如EST
或IST
或CST
之类的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 [太平洋/奥克兰]
要获取当前时刻,请致电Instant.now
。 Instant
类代表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 8及更高版本中。这些类取代了麻烦的旧legacy日期时间类,例如java.util.Date
,Calendar
和&amp; SimpleDateFormat
现在位于Joda-Time的maintenance mode项目建议迁移到java.time。
要了解详情,请参阅Oracle Tutorial。并搜索Stack Overflow以获取许多示例和解释。规范是JSR 310。
从哪里获取java.time类?
ThreeTen-Extra项目使用其他类扩展java.time。该项目是未来可能添加到java.time的试验场。您可以在此处找到一些有用的课程,例如Interval
,YearWeek
,YearQuarter
和more。
答案 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你不再需要它了。