【问题标题】:Joda-Time: DateTime, DateMidnight and LocalDate usageJoda-Time:DateTime、DateMidnight 和 LocalDate 用法
【发布时间】:2011-02-02 01:34:53
【问题描述】:

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

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

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

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

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

【问题讨论】:

    标签: java datetime interface jodatime


    【解决方案1】:

    我看到拥有几乎所有的优势 使用 LocalDateTime 的接口(在 至少服务层)这样我的 应用程序不必管理 时区,并且可以安全地假设 Times 始终采用 UTC。

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

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

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

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

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

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

    【讨论】:

    • DateMidnight 是个坏主意,现在已弃用
    • 而不是midnight相关的类和方法(全部弃用),请参阅新方法DateTime::withTimeAtStartOfDay
    • @NickSiderakis 那个方法DateTime::withTimeAtStartOfDay 通常表示时间00:00:00.000。但并非总是因为夏令时和可能的其他异常情况。
    • @NickSiderakis 另外,了解“半开放”的概念,在这个概念中,通过一个包容的开头来跟踪时间跨度通常是有意义的,而结尾是唯一的。所以一天从今天的第一刻一直到明天的第一刻,但不包括明天的第一刻。一周从星期一的第一刻到但不包括下星期一的第一刻。
    • 我总是发现航班状态很好地说明了LocalDateTimeDateTime 的使用。当您在 Google 上查找航班时,例如 BA005 (LHR-NRT),它会为您提供出发和到达的当地时间:分别为第二天的 13:50 和 10:35 - 但航班没有取 20h45,因为10:35 Tokyo time in GMT 实际上是格林威治标准时间 01:35(第二天)。因此,这次旅行需要 11h45。在内部,航班状态可能使用DateTime(分区),但它可能只公开LocalDateTime...
    【解决方案2】:

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

    java.time

    特定时刻

    时间轴上的特定时刻:

    • 始终采用 UTC 由 Instant 表示。
    • 分配的与 UTC 的偏移由 OffsetDateTime 表示。
    • 分配一个完整的时区,而不仅仅是由ZonedDateTime 表示的偏移量。

    这些都替换了 Joda-Time 中的 InstantDateTime 类。这些 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[美国/哈瓦那]

    未分区

    要表示大约 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.DateCalendarSimpleDateFormat

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

    要了解更多信息,请参阅Oracle Tutorial。并在 Stack Overflow 上搜索许多示例和解释。规格为JSR 310

    从哪里获得 java.time 类?

    ThreeTen-Extra 项目通过附加类扩展了 java.time。该项目是未来可能添加到 java.time 的试验场。您可以在这里找到一些有用的类,例如IntervalYearWeekYearQuartermore

    【讨论】:

      猜你喜欢
      • 2013-07-14
      • 2011-06-07
      • 2015-05-30
      • 2021-08-10
      • 2011-05-22
      • 2014-07-12
      • 2017-11-27
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多