java - 使用两个 LocalDateTime 实例计算持续时间

标签 java date time timezone jodatime

我正在尝试计算 LocalDateTime 的两个实例之间的持续时间。这里的特殊之处在于 LocalDateTime 的每个实例都可以来自世界上的任何地方:

LocalDateTime 开始 可能来自内华达LocalDateTime 结束 可能来自东京。显然,与 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时间。

我能否创建一个足够强大的解决方案,让 startend 代表世界上的任何城市,并且仍然正确计算持续时间两者之间?

最佳答案

“LocalDateTime”并不表示特定地点

我认为您误解了 LocalDateTime 的用途。 “本地”是指任何地方,不是特定地方。如“圣诞节从 2015 年 12 月 25 日午夜开始”,我们指的是任何地方的午夜。例如,巴黎的圣诞节比蒙特利尔早几个小时开始。

如果您知道日期时间表示内华达州的日期时间,请使用分配给 proper time zone name 的 Joda-Time DateTime 美国/博伊西。在新java.time package ( Tutorial ) 内置于 Java 8 及更高版本中,使用 ZonedDateTime具有指定时区的对象。

同样,如果您知道日期时间是东京本地时间,请不要使用LocalDateTime。使用指定时区 Asia/Tokyo 的 Joda-Time DateTime

已过

一对 LocalDateTime 实例之间耗时没有意义。例如,时间可能是同一天的 14:00 和 18:00,但这并不意味着相差四个小时。如果您真的指的是巴黎的 14:00 和芝加哥的 18:00,那将相差几个小时,而不是两个小时。

我不讨论计算运行时间,因为在 StackOverflow 上已经处理过很多次了。我想在这里澄清一些概念。然后你可以继续existing Questions & Answers for calculating elapsed time .

数据库存储 UTC

通常在 SQL 数据库中,您应该使用数据类型 TIMESTAMP WITH TIME ZONE(又名 TIMESTAMPZ,带有 Z 表示“zulu” ”)。这个用词不当实际上意味着“尊重时区”。来自 UTC 的偏移量的传入数据或其他时区信息调整为UTC。数据的偏移量或时区 保留。

SQL 数据类型 TIMESTAMP WITHOUT TIME ZONE(又名 TIMESTAMP)与 Java 中的 LocalDateTime 含义相同:根本没有时区.不拘泥于时间线。输入数据的任何偏移量或时区信息都将被忽略,不进行任何调整。

Postgres doc可以帮忙解释一下。

坚持使用 UTC

从数据库中检索此类值时,UTC 值可能会被您的管理工具(例如 Postgres 中的 pgAdmin)或您的数据库驱动程序或您的应用程序调整为特定时区。

在您的应用中,通常最好尽可能将日期时间值保留为 UTC。在 UTC 中执行几乎所有的存储、业务逻辑和数据交换。仅在用户期望时调整到特定时区。

将 LocalDateTime 转换为时区

如果您确实有一个 LocalDateTime 对象,并且您想要为其分配一个时区,下面是一些示例代码。我们还进行调整以获得与在蒙特利尔和 UTC 中看到的完全相同的时刻。首先,示例在 Joda-Time 中显示,然后在 java.time 中显示。

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

转储到控制台。

System.out.println( "LocalDateTime (nowhere): " + ldt );
System.out.println( "Chicago: " + dateTimeChicago );
System.out.println( "Montréal: " + dateTimeMontreal );
System.out.println( "UTC: " + dateTimeUtc);

运行时。

LocalDateTime (nowhere): 2015-07-14T10:00:00.000
Chicago: 2015-07-14T10:00:00.000-05:00
Montréal: 2015-07-14T11:00:00.000-04:00
UTC: 2015-07-14T15:00:00.000Z

java.time

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.

转储到控制台。

System.out.println( "LocalDateTime (nowhere): " + ldt );
System.out.println( "Chicago: " + zdtChicago );
System.out.println( "Montréal: " + zdtMontreal );
System.out.println( "UTC: " + zdtUtc);

运行时。

LocalDateTime (nowhere): 2015-07-14T10:00
Chicago: 2015-07-14T10:00-05:00[America/Chicago]
Montréal: 2015-07-14T11:00-04:00[America/Montreal]
UTC: 2015-07-14T15:00Z

关于java - 使用两个 LocalDateTime 实例计算持续时间,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31410665/

相关文章:

java - 2个线程同时访问同步函数

ActionScript 日期比较

java - 从 System.currentTimeMillis 值中去除秒和毫秒

php - 如何解析任何日期格式

java - 这个(简单的)代码的时间复杂度是多少?

php - 检查当前时间是否在 PHP 中的某个时间之间?

java - 从文件中读取公钥或私钥时如何修复 "invalid key format"?

java - 如何在Hibernate中映射多个一对多关联

java - 在 Android 中使用 Retrofit 时带有动态键的 JSON

java - 两个日期之间的 Android 天数