使用两个 LocalDateTime 实例计算持续时间
Using two LocalDateTime instances to calculate a duration
我正在尝试计算 LocalDateTime
的两个实例之间的持续时间。这里的特殊之处在于 LocalDateTime
的每个实例都可以来自世界上的任何地方:
LocalDateTime start
可能来自 内华达州 而 LocalDateTime end
可能来自 东京 。显然,与 LocalDateTime
关联的每个 "time" 都位于该位置的本地。
所以如果我说...
LocalDateTime start = LocalDateTime.parse("2015-07-14T10:00:00");
并说 start
代表芝加哥,这意味着芝加哥时间 10:00 上午。
那么我可以说...
LocalDateTime end = LocalDateTime.parse("2015-07-14T03:00:00");
和end
代表莫斯科,所以莫斯科时间是3:00AM。
我能否创建一个足够强大的解决方案,让 start
和 end
代表世界上的 任何 个城市,并且仍然正确计算之间的持续时间两个?
"LocalDateTime" 不代表特定地区
我认为你误解了 LocalDateTime
的目的。 "local"表示任何地区,不是特定地区。如在 "Christmas starts at midnight on December 25, 2015" 中,我们指的是 任何 地点的午夜。例如,巴黎的圣诞节比蒙特利尔早几个小时开始。
如果您知道日期时间表示内华达州的日期时间,请使用 Joda-Time DateTime
为 proper time zone name of America/Boise
. In the new java.time package (Tutorial) built into Java 8 and later, use a ZonedDateTime
对象分配指定的时区。
同样,如果您知道日期时间是东京本地时间,请不要使用LocalDateTime
。使用指定时区 Asia/Tokyo
.
的 Joda-Time DateTime
已过
一对 LocalDateTime
实例之间经过的时间没有意义。例如,时间可能是 14:00 和 18:00 在同一天,但这确实 而不是 意味着四个小时的差异。如果您真的是指巴黎的 14:00 和芝加哥的 18:00,那将是几个小时的差异,而不是两个小时。
我不是在讨论计算运行时间,因为在 Whosebug 上已经处理过很多次了。我想在这里澄清一些概念。然后你可以继续 existing Questions & Answers for calculating elapsed time.
数据库存储 UTC
通常在 SQL 数据库中,您应该使用数据类型 TIMESTAMP WITH TIME ZONE
(a.k.a。TIMESTAMPZ
带有 Z
表示“zulu"). This misnomer actually means "with respect for time zone". Incoming data with an offset from UTC或其他时区信息调整为UTC。数据的偏移量或时区未保留。
SQL数据类型TIMESTAMP WITHOUT TIME ZONE
(a.k.a.TIMESTAMP
)的意思和Java中的LocalDateTime
一样:没有时间完全没有区域。不拘泥于时间线。任何带有输入数据的偏移量或时区信息都被忽略,不进行任何调整。
Postgres doc 可以帮忙解释一下。
坚持使用 UTC
从数据库中检索此类值时,您的管理工具(例如 Postgres 中的 pgAdmin)或您的数据库驱动程序或您的应用程序可能会将 UTC 值调整为特定时区。
在您的应用中,通常最好尽可能将日期时间值保留为 UTC。在 UTC 中执行几乎所有的存储、业务逻辑和数据交换。仅在用户期望时调整到特定时区。
将 LocalDateTime 转换为时区
如果您确实有一个 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 );
转储到控制台。
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.time 中的示例 Java 8 更新 51.
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
我正在尝试计算 LocalDateTime
的两个实例之间的持续时间。这里的特殊之处在于 LocalDateTime
的每个实例都可以来自世界上的任何地方:
LocalDateTime start
可能来自 内华达州 而 LocalDateTime end
可能来自 东京 。显然,与 LocalDateTime
关联的每个 "time" 都位于该位置的本地。
所以如果我说...
LocalDateTime start = LocalDateTime.parse("2015-07-14T10:00:00");
并说 start
代表芝加哥,这意味着芝加哥时间 10:00 上午。
那么我可以说...
LocalDateTime end = LocalDateTime.parse("2015-07-14T03:00:00");
和end
代表莫斯科,所以莫斯科时间是3:00AM。
我能否创建一个足够强大的解决方案,让 start
和 end
代表世界上的 任何 个城市,并且仍然正确计算之间的持续时间两个?
"LocalDateTime" 不代表特定地区
我认为你误解了 LocalDateTime
的目的。 "local"表示任何地区,不是特定地区。如在 "Christmas starts at midnight on December 25, 2015" 中,我们指的是 任何 地点的午夜。例如,巴黎的圣诞节比蒙特利尔早几个小时开始。
如果您知道日期时间表示内华达州的日期时间,请使用 Joda-Time DateTime
为 proper time zone name of America/Boise
. In the new java.time package (Tutorial) built into Java 8 and later, use a ZonedDateTime
对象分配指定的时区。
同样,如果您知道日期时间是东京本地时间,请不要使用LocalDateTime
。使用指定时区 Asia/Tokyo
.
DateTime
已过
一对 LocalDateTime
实例之间经过的时间没有意义。例如,时间可能是 14:00 和 18:00 在同一天,但这确实 而不是 意味着四个小时的差异。如果您真的是指巴黎的 14:00 和芝加哥的 18:00,那将是几个小时的差异,而不是两个小时。
我不是在讨论计算运行时间,因为在 Whosebug 上已经处理过很多次了。我想在这里澄清一些概念。然后你可以继续 existing Questions & Answers for calculating elapsed time.
数据库存储 UTC
通常在 SQL 数据库中,您应该使用数据类型 TIMESTAMP WITH TIME ZONE
(a.k.a。TIMESTAMPZ
带有 Z
表示“zulu"). This misnomer actually means "with respect for time zone". Incoming data with an offset from UTC或其他时区信息调整为UTC。数据的偏移量或时区未保留。
SQL数据类型TIMESTAMP WITHOUT TIME ZONE
(a.k.a.TIMESTAMP
)的意思和Java中的LocalDateTime
一样:没有时间完全没有区域。不拘泥于时间线。任何带有输入数据的偏移量或时区信息都被忽略,不进行任何调整。
Postgres doc 可以帮忙解释一下。
坚持使用 UTC
从数据库中检索此类值时,您的管理工具(例如 Postgres 中的 pgAdmin)或您的数据库驱动程序或您的应用程序可能会将 UTC 值调整为特定时区。
在您的应用中,通常最好尽可能将日期时间值保留为 UTC。在 UTC 中执行几乎所有的存储、业务逻辑和数据交换。仅在用户期望时调整到特定时区。
将 LocalDateTime 转换为时区
如果您确实有一个 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 );
转储到控制台。
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.time 中的示例 Java 8 更新 51.
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