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

时间:2015-07-14 15:17:40

标签: java date time timezone jodatime

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

LocalDateTime start可能来自 Nevada LocalDateTime end可能来自 Tokyo 。每个"时间"与LocalDateTime相关联的显然是该位置的本地。

所以如果我说......

LocalDateTime start = LocalDateTime.parse("2015-07-14T10:00:00");并表示start代表芝加哥,这意味着芝加哥时间上午10:00。 然后我可以说...

LocalDateTime end = LocalDateTime.parse("2015-07-14T03:00:00");end代表莫斯科,所以现在是莫斯科时间凌晨3点。

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

1 个答案:

答案 0 :(得分:4)

“LocalDateTime”并不意味着特定的地点

我认为你误解了LocalDateTime的目的。 “本地”表示任何位置,不是特定位置。如“2015年12月25日午夜圣诞节开始”,我们指的是任何地点的午夜。例如,比蒙特利尔早几个小时在巴黎开始圣诞节。

如果您知道日期时间是代表内华达州的日期时间,则使用Joda-Time DateTime分配America/Boise LocalDateTime。在Java 8及更高版本中内置的新proper time zone namejava.time package)中,使用具有指定时区的Tutorial对象。

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

经过的

一对TIMESTAMP WITH TIME ZONE个实例之间的经过时间毫无意义。例如,时间可能是同一天的14:00和18:00,但意味着四小时的差异。如果你真正意味着巴黎的14:00和芝加哥的18:00,那将是几个小时的差异,而不是两个小时。

我没有讨论计算经过的时间,因为在StackOverflow上已经多次处理过了。我想在这里澄清一些概念。然后,您可以转到ZonedDateTime

数据库存储UTC

通常在SQL数据库中,您应该使用数据类型TIMESTAMPZ(a.k.a。ZTIMESTAMP WITHOUT TIME ZONE代表“existing Questions & Answers for calculating elapsed time”。这种误称实际上意味着“尊重时区”。具有从zulu或其他时区信息的偏移量的传入数据被调整为UTC。数据的偏移量或时区保留。

SQL数据类型TIMESTAMP(a.k.a。LocalDateTime)与Java中的LocalDateTime相同:根本没有时区。与时间表无关。输入数据的任何偏移或时区信息都被忽略,未进行任何调整。

UTC可能有助于解释。

坚持使用UTC

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

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

将LocalDateTime转换为时区

如果你有一个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 ); 对象,并且你想为它分配一个时区,这里有一些示例代码。我们也会调整以获得与蒙特利尔和UTC相同的时刻。首先,示例在Joda-Time中显示,然后在java.time中显示。

约达时间

Joda-Time 2.8中的示例。

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

跑步时。

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.

java.time

Java 8 Update 51的java.time中的示例。

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

跑步时。

Dim iIndex as Integer
Dim ws As Excel.Worksheet
Dim wb      As Workbook
Dim strPath As String
Dim strFile As String

strPath = "D:\Personal\"
strFile = Dir(strPath & "*.xlsx")

Do While strFile <> ""
    Set wb = Workbooks.Open(Filename:=strPath & strFile)

    For iIndex = 1 To wb.Worksheets.count
        Set ws = wb.Worksheets(iIndex)

        'Do something here.

    Next iIndex

 strFile = Dir 'This moves the value of strFile to the next file.
Loop