Jos*_*hua 1 java time timezone date jodatime
我正在尝试计算两个实例之间的持续时间LocalDateTime
。这里的特别之处在于,每个实例都LocalDateTime
可能来自世界上的任何地方:
LocalDateTime start
可能来自内华达州,LocalDateTime end
也可能来自东京。LocalDateTime
显然,与 相关联的每个“时间”都是该位置的本地。
所以如果我说...
LocalDateTime start = LocalDateTime.parse("2015-07-14T10:00:00");
并说start
代表芝加哥,这意味着芝加哥时间上午 10:00。那我可以说...
LocalDateTime end = LocalDateTime.parse("2015-07-14T03:00:00");
并且end
代表莫斯科,所以现在是莫斯科时间凌晨 3:00。
我能否创建一个足够强大的解决方案,允许start
并end
代表世界上任何城市,并且仍然正确计算两者之间的持续时间?
我想你误解了LocalDateTime
. “本地”是指任何地点,而不是特定地点。如“圣诞节从 2015 年 12 月 25 日午夜开始”,我们指的是任何地方的午夜。例如,圣诞节在巴黎比蒙特利尔早几个小时开始。
如果您知道日期时间用于表示内华达州的日期时间,请使用DateTime
分配了正确时区名称的Joda-Time America/Boise
。在Java 8 及更高版本中内置的新java.time 包( Tutorial ) 中,使用ZonedDateTime
具有指定时区的对象。
同样,如果您知道日期时间是东京本地,请不要使用LocalDateTime
. 使用DateTime
指定时区的Joda-Time Asia/Tokyo
。
一对LocalDateTime
实例之间经过的时间没有意义。例如,时间可能是在同日14:00和18:00,但这并不意味着4小时差异。如果您真的指的是巴黎的 14:00 和芝加哥的 18:00,那将是几个小时的差异,而不是两个小时。
我不是在讨论计算经过的时间,因为在 StackOverflow 上已经处理过很多次了。我试图在这里澄清一些概念。然后,您可以继续使用现有的问答来计算经过的时间。
一般来说,在SQL数据库,你应该使用的数据类型TIMESTAMP WITH TIME ZONE
(又名TIMESTAMPZ
一个Z
为“祖鲁”)。这个用词不当实际上意味着“尊重时区”。与UTC或其他时区信息有偏差的传入数据将调整为 UTC。不保留数据的偏移量或时区。
SQL 数据类型TIMESTAMP WITHOUT TIME ZONE
(又名TIMESTAMP
)的含义与LocalDateTime
Java 中的a 相同:根本没有时区。与时间线无关。忽略输入数据的任何偏移或时区信息,不进行任何调整。
Postgres 文档可能有助于解释。
从数据库中检索此类值时,您的管理工具(例如 Postgres 中的 pgAdmin)或数据库驱动程序或应用程序可能会将 UTC 值调整为特定时区。
在您的应用程序中,通常最好尽可能将日期时间值保持为 UTC。在 UTC 中完成几乎所有的存储、业务逻辑和数据交换。仅在用户预期时调整到特定时区。
如果您确实有一个LocalDateTime
对象,并且您想为其分配一个时区,这里有一些示例代码。我们还进行了调整,以获得与蒙特利尔和 UTC 相同的时刻。该示例首先在 Joda-Time 中显示,然后在 java.time 中显示。
Joda-Time 2.8 中的示例。
LocalDateTime ldt = new LocalDateTime( "2015-07-14T10:00:00" ); // Nowhere in particular.
DateTimeZone zoneChicago = DateTimeZone.forID( "America/Chicago" );
DateTime dateTimeChicago = ldt.toDateTime( zoneChicago );
DateTime dateTimeMontreal = dateTimeChicago.withZone( DateTimeZone.forID( "America/Montreal" ) );
DateTime dateTimeUtc = dateTimeChicago.withZone( DateTimeZone.UTC );
Run Code Online (Sandbox Code Playgroud)
转储到控制台。
System.out.println( "LocalDateTime (nowhere): " + ldt );
System.out.println( "Chicago: " + dateTimeChicago );
System.out.println( "Montréal: " + dateTimeMontreal );
System.out.println( "UTC: " + dateTimeUtc);
Run Code Online (Sandbox Code Playgroud)
跑的时候。
LocalDateTime ldt = new LocalDateTime( "2015-07-14T10:00:00" ); // Nowhere in particular.
DateTimeZone zoneChicago = DateTimeZone.forID( "America/Chicago" );
DateTime dateTimeChicago = ldt.toDateTime( zoneChicago );
DateTime dateTimeMontreal = dateTimeChicago.withZone( DateTimeZone.forID( "America/Montreal" ) );
DateTime dateTimeUtc = dateTimeChicago.withZone( DateTimeZone.UTC );
Run Code Online (Sandbox Code Playgroud)
Java 8 Update 51 的 java.time 中的示例。
LocalDateTime ldt = LocalDateTime.parse( "2015-07-14T10:00:00" ); // Nowhere in particular.
ZoneId zoneChicago = ZoneId.of( "America/Chicago" );
ZonedDateTime zdtChicago = ZonedDateTime.of( ldt, zoneChicago );
ZonedDateTime zdtMontreal = zdtChicago.withZoneSameInstant( ZoneId.of( "America/Montreal" ) );
ZonedDateTime zdtUtc = zdtChicago.withZoneSameInstant( ZoneOffset.UTC ); // ZoneOffset is a subclass of ZoneId.
Run Code Online (Sandbox Code Playgroud)
转储到控制台。
System.out.println( "LocalDateTime (nowhere): " + ldt );
System.out.println( "Chicago: " + zdtChicago );
System.out.println( "Montréal: " + zdtMontreal );
System.out.println( "UTC: " + zdtUtc);
Run Code Online (Sandbox Code Playgroud)
跑的时候。
System.out.println( "LocalDateTime (nowhere): " + ldt );
System.out.println( "Chicago: " + dateTimeChicago );
System.out.println( "Montréal: " + dateTimeMontreal );
System.out.println( "UTC: " + dateTimeUtc);
Run Code Online (Sandbox Code Playgroud)