【问题标题】:How to compare LocalDate with ZonedDateTime in js-joda?如何在 js-joda 中比较 LocalDate 和 ZonedDateTime?
【发布时间】:2017-11-27 19:56:27
【问题描述】:

我正在寻找一种方法来比较 js-joda 中的 LocalDateZonedDateTime 的实例,但这些类不兼容。我愿意接受,LocalDateZonedDateTime,时间和时区设置为零。

比较这两个对象最简单的方法是什么?

【问题讨论】:

    标签: javascript localdate zoneddatetime datetime-comparison js-joda


    【解决方案1】:

    LocalDate只有日期(日、月和年),而ZonedDateTime 也有时间(小时、分钟、秒和纳秒)和时区。要比较它们,您必须选择将哪一个转换为另一个的类型。

    正如@Dummy's answer 已经解释的那样,一种方法是将ZonedDateTime 转换为LocalDate。假设我们有:

    var z = ZonedDateTime.now(); // 2017-08-23T13:12:24.856-03:00[America/Sao_Paulo]
    var dt = LocalDate.now(); // 2017-08-23
    

    您可以使用equalsisBeforeisAfter方法来检查本地日期(日/月/年)是否相同,在另一个之前或之后

    z.toLocalDate().equals(dt); // true
    z.toLocalDate().isBefore(dt); // false
    z.toLocalDate().isAfter(dt); // false
    

    您也可以使用compareTo,如果第一个日期在第二个日期之前、等于或之后,则可以返回-101

    作为told in the comments,调用toLocalDate() 会丢弃时间和时区信息,只保留日期(日/月/年)。但是LocalDate只有这些字段,所以不需要其他人做比较。


    相反(将LocalDate 转换为ZonedDateTime),您必须做出一些假设。相同的日期可以代表不同的时刻,具体取决于您所在的时区(现在在圣保罗是 8 月 23 日th,但在东京是 8 月 24 日 - 您的时区选择可能会影响最终结果)。

    您还需要定义该日期的时间(小时/分钟/秒/纳秒)。您告诉过您可以假设 LocalDate 是 ZonedDateTime,时间和时区设置为零。这意味着 时间 将是午夜 (00:00),时区将是 UTC(偏移量为零):

    // consider LocalDate = ZonedDateTime with time and timezone set to zero (midnight in UTC)
    var z2 = dt.atStartOfDay(ZoneOffset.UTC); // 2017-08-23T00:00Z
    

    然后你可以比较:

    z2.equals(z); // false: check if all fields are the same (date/time/timezone)
    z2.isEqual(z); // false: check if both represent the same instant (even if timezones are different)
    z2.isBefore(z); // true
    z2.isAfter(z); // false
    z2.compareTo(z); // -1
    

    注意equals检查所有字段是否相同(日期、时间和时区),而所有其他方法比较等效的Instant(即使时区不同,也使用对应的Instant来做比较)。

    在这种情况下,z22017-08-23T00:00Z(UTC 时间 2017 年 8 月 23 日 午夜),而 z2017-08-23T13:12:24.856-03:00[America/Sao_Paulo],在 UTC 中相当于 2017-08-23T16:12:24.856Z (UTC 时间 2017 年 8 月 23 日th 16:12:24.856)。

    因此,equals 返回 false,因为时间和时区不同,isEquals 返回 false,因为它们不代表同一时刻(即使转换为 UTC,它们也是不同的)。 isBefore 返回 true,因为 z2 实际上在 z 之前(午夜


    如果您想使用其他时区而不是 UTC,则必须使用 js-joda-timezoneZoneId 类:

    // get this date at midnight in London timezone
    dt.atStartOfDay(ZoneId.of("Europe/London"));
    

    API 使用IANA timezones names(始终采用Region/City 格式,如America/Sao_PauloEurope/Berlin)。 避免使用三个字母的缩写(如CSTPST),因为它们是ambiguous and not standard

    您可以致电ZoneId.getAvailableZoneIds() 获取可用时区列表(并选择最适合您系统的时区)。

    您也可以将系统的默认时区与ZoneId.systemDefault() 一起使用,但这将取决于系统/浏览器,因此最好明确使用特定的时区。

    【讨论】:

      【解决方案2】:

      你可以这样做

      zonedDateTime.toLocalDate().compareTo(otherLocalDate)

      如果zonedDateTimeotherLocalDate之前,1在之后,0相同,则返回-1

      【讨论】:

      • 当使用toLocalDate() 时我们不会丢失时间信息吗?我猜这可能会导致错误的结果。
      • 嗯,LocalDate 存储时间相关数据,所以不用担心,toLocalDate 只需将年月日复制过来,这 3 位信息存储在 LocalDate
      • 但是ZonedDateTime 包含时间信息,当它被转换为LocalDate 时,这些信息就丢失了,不是吗?
      • 是的,它将被丢弃,但您将ZonedDateTimeLocalDate 进行比较,这不存储时间相关数据所以拥有钟表对 LocalDate没有意义
      猜你喜欢
      • 2019-03-12
      • 1970-01-01
      • 2016-09-04
      • 2020-12-20
      • 2011-06-07
      • 1970-01-01
      • 2017-09-10
      • 2011-02-02
      • 1970-01-01
      相关资源
      最近更新 更多