Joda-Time:DateTime,DateMidnight和LocalDate用法

时间:2010-03-29 14:05:46

标签: java datetime interface jodatime

Joda-Time库包含不同的日期时间类

  

DateTime - 不可变更替   对于JDK日历
DateMidnight    - 表示强制时间的日期的不可变类   午夜时间LocalDateTime -   表示本地的不可变类   日期和时间(无时区)

我想知道您如何在分层应用程序中使用这些类。

我看到几乎所有接口都使用LocalDateTime(至少在服务层)的优势,因此我的应用程序不必管理时区,并且可以安全地假设时间始终为UTC。然后我的应用程序可以在执行流程的最开始使用DateTime来管理时区。

我也想知道DateMidnight在哪种情况下很有用。

2 个答案:

答案 0 :(得分:76)

  

我看到几乎所有的优势   使用LocalDateTime的接口(at   至少服务层)这样我的   应用程序无需管理   时区,可以安全地假设时间总是在UTC。

我不确定我在这里理解你的想法。 LocalDateTimeDateTime代表两个完全不同的概念。情况并非LocalDateTime有一些隐含的UTC时区:它实际上有 no 时区(内部可能用UTC时区表示为DateTime,但它只是一个实现细节,对使用它的程序员来说无关紧要)。

You can see in the API docs,虽然 DateTime 是“ Instant ”(世界时间线上的一个点,物理概念), LocalDateTime 不是这样的事情。 LocalDateTime实际上是一个Partial,(一个“民间”概念),在不同的类层次结构中。不幸的是,类名称可能会让您认为LocalDateTimeDateTime的某种特化:嗯,它不是。

LocalDateTime 应被视为一对{ Date Y/M/D); Time hh:mm:ss.msec)},一组数字,对应于与时间相关的数据的“民用”标准表示。如果我们获得LocalDateTime,我们无法将其直接转换为DateTime,我们需要指定时区;并且转换将我们带到另一种实体。 (类比:Java中的字符串和字节流:要在它们之间进行转换,您必须指定字符集编码,因为它们在概念上是不同的东西)

何时在应用程序中使用其中一个...它有时是有争议的,但是一旦理解了Jodatime概念,通常就足够清楚了。 IMO与“层”没有多大关系,或许更多的是用于案例或场景。

一个非平凡的边界线示例:您在Google工作,编写日历。您必须让用户管理(添加,查看,修改)包含日期时间的事件(让我们忽略重复发生的事件),说“我在2019年7月3日10:00与我的医生会面上午”。什么是在软件层中使用的时间 - 日期实体(对于此用例)?我会说:LocalDateTime。因为用户并没有真正处理物理时间点,而是处理民用时间:在手腕或家中显示时钟的日期和时间。他甚至没有想到时区(让我们忽略在世界各地旅行的用户的特殊情况......)然后,在商业和表示层中,LocalDateTime似乎是正确的实体。

但是假设您还必须编写不同的方案:提醒。当Google内部调度程序检测到用户存储的事件从现在开始是N分钟时,它必须向他发送提醒。在这里,“从现在起N分钟”是一个完全“物理”的时间概念,所以这里的“业务层”将处理DateTime。例如,有几种选择:事件作为LocalDateTime存储在数据库中(即只有时区和时间没有时区 - 一个经常使用UTC时间戳来表示,但这是一个实现细节)。在这种情况下(仅在此情况下),我们必须将其加载为DateTime,我们使用时区进行转换,可能来自用户的个人资料。

答案 1 :(得分:0)

Answer by leonbloy是正确且至关重要的。我只是转换为替换Joda-Time项目的java.time类。

java.time

具体时刻

在时间轴上的特定时刻:

这些都取代了Instant& Joda-Time中的DateTime课程。这些java.time类的分辨率均为nanoseconds,相对于Joda-Time使用的毫秒数。

午夜与开始日期

午夜时分,Joda-Time项目总结“午夜”是一个模糊而无效的概念。与午夜相关的课程和午夜时间都在Joda-Time的后期版本中被弃用,取而代之的是“一天中的第一时刻”的实用概念。

java.time课程采用相同的课程,使用"当天的第一时刻"做法。在java.time类上查找atStartOfDay方法,例如LocalDate

永远不要假设一天从00:00开始。夏令时(DST)等异常表示该日可能会在其他时间开始,例如01:00。

ZonedDateTime zdt = 
    LocalDate.of( 2017 , Month.MARCH , 12 )                    // Instantiate a date-only value without time zone.
             .atStartOfDay( ZoneId.of( "America/Havana" ) ) ;  // Cuba jumps from 00:00 to 01:00 on Spring DST cut-over.

例如,看看古巴在春季DST切换时间凌晨1点开始。

  

zdt:2017-03-12T01:00-04:00 [America / Havana]

不分区

为了表示在约26-27小时范围内可能的时刻的模糊概念,而不是时间线上的实际时刻,请使用LocalDateTime。此类故意缺少与UTC或时区的任何偏移。

LocalDateTime ldt = LocalDateTime.of( 2017 , Month.JANUARY , 23 , 1 , 2 , 3 , 0 ) ;

如果您的业务环境意味着特定时区,您可以应用它来获取ZonedDateTime

ZoneId z = ZoneId.of( "Africa/Tunis" ) ;
ZonedDateTime zdt = ldt.atZone( z ) ;  // Determine a specific point on timeline by providing the context of a time zone.

关于java.time

java.time框架内置于Java 8及更高版本中。这些类取代了麻烦的旧legacy日期时间类,例如java.util.DateCalendar和& SimpleDateFormat

现在位于Joda-Timemaintenance mode项目建议迁移到java.time类。

要了解详情,请参阅Oracle Tutorial。并搜索Stack Overflow以获取许多示例和解释。规范是JSR 310

从哪里获取java.time类?

ThreeTen-Extra项目使用其他类扩展java.time。该项目是未来可能添加到java.time的试验场。您可以在此处找到一些有用的课程,例如IntervalYearWeekYearQuartermore