【发布时间】:2017-11-27 19:56:27
【问题描述】:
我正在寻找一种方法来比较 js-joda 中的 LocalDate 和 ZonedDateTime 的实例,但这些类不兼容。我愿意接受,LocalDate 是 ZonedDateTime,时间和时区设置为零。
比较这两个对象最简单的方法是什么?
【问题讨论】:
标签: javascript localdate zoneddatetime datetime-comparison js-joda
我正在寻找一种方法来比较 js-joda 中的 LocalDate 和 ZonedDateTime 的实例,但这些类不兼容。我愿意接受,LocalDate 是 ZonedDateTime,时间和时区设置为零。
比较这两个对象最简单的方法是什么?
【问题讨论】:
标签: javascript localdate zoneddatetime datetime-comparison js-joda
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
您可以使用equals、isBefore或isAfter方法来检查本地日期(日/月/年)是否相同,在另一个之前或之后
z.toLocalDate().equals(dt); // true
z.toLocalDate().isBefore(dt); // false
z.toLocalDate().isAfter(dt); // false
您也可以使用compareTo,如果第一个日期在第二个日期之前、等于或之后,则可以返回-1、0 或1。
作为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来做比较)。
在这种情况下,z2 是 2017-08-23T00:00Z(UTC 时间 2017 年 8 月 23 日 午夜),而 z 是 2017-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-timezone 和 ZoneId 类:
// get this date at midnight in London timezone
dt.atStartOfDay(ZoneId.of("Europe/London"));
API 使用IANA timezones names(始终采用Region/City 格式,如America/Sao_Paulo 或Europe/Berlin)。
避免使用三个字母的缩写(如CST 或PST),因为它们是ambiguous and not standard。
您可以致电ZoneId.getAvailableZoneIds() 获取可用时区列表(并选择最适合您系统的时区)。
您也可以将系统的默认时区与ZoneId.systemDefault() 一起使用,但这将取决于系统/浏览器,因此最好明确使用特定的时区。
【讨论】:
你可以这样做
zonedDateTime.toLocalDate().compareTo(otherLocalDate)
如果zonedDateTime在otherLocalDate之前,1在之后,0相同,则返回-1
【讨论】:
toLocalDate() 时我们不会丢失时间信息吗?我猜这可能会导致错误的结果。
LocalDate 不 存储时间相关数据,所以不用担心,toLocalDate 只需将年月日复制过来,这 3 位信息存储在 LocalDate
ZonedDateTime 包含时间信息,当它被转换为LocalDate 时,这些信息就丢失了,不是吗?
ZonedDateTime 与LocalDate 进行比较,这不存储时间相关数据所以拥有钟表对 LocalDate没有意义