比较 EST EDT 中的两个 joda DateTime 实例

Posted

技术标签:

【中文标题】比较 EST EDT 中的两个 joda DateTime 实例【英文标题】:Comparing two joda DateTime instances across EST EDT 【发布时间】:2018-08-30 20:45:26 【问题描述】:

我有两个 DateTime 实例,AB,其中:

DateTime A = new DateTime(2018, 11, 4, 1, 00, 0).plusHours(1);
DateTime B = new DateTime(2018, 11, 4, 2, 00, 0);

println("A: "+ A +", "+ A.getChronology() +", ms "+ A.getMillis());
println("B: "+ B +", "+ B.getChronology() +", ms "+ B.getMillis());
println("A == B is "+ A.equals(B));

产生:

A: 2018-11-04T01:00:00.000-05:00, ISOChronology[America/New_York], ms 1541311200000
B: 2018-11-04T02:00:00.000-05:00, ISOChronology[America/New_York], ms 1541314800000
A == B is false

如何比较 AB 以查看它们是否是同一个实例?

仔细看看AB 是如何实例化的。关键是AB 实际上指的是同一个时间点,即时钟从 EDT 调回纽约市的 EST。

【问题讨论】:

【参考方案1】:

为了比较,您正确地使用了equals。但它正在返回false,因为它们不是同一时间点。如果您查看它们的值,您会发现A 实际上比B 早一小时:

A: 2018-11-04T01:00:00.000-05:00, ISOChronology[America/New_York], ms 1541311200000 B: 2018-11-04T02:00:00.000-05:00, ISOChronology[America/New_York], ms 1541314800000

getMillis() 的结果也不同,这意味着这些日期不是同一时间点。

这是因为new DateTime(2018, 11, 4, 1, 00, 0) 产生的日期/时间仍在美国东部时间 ("2018-11-04T01:00:00.000-04:00" ->凌晨 1 点在 -04:00 偏移)。

一小时后 (plusHours(1)),您应该在偏移量 -04:00 处获得凌晨 2 点,但那是 DST ends in New York 的瞬间:时钟设置为 1 小时回到凌晨 1 点,并且偏移量变为 -05 :00 - 这就是为什么 A 是凌晨 1 点 -05:00。

另一方面,B 已经在美国东部标准时间(不再是夏令时),所以它设置为 -05:00 的凌晨 2 点。在A 之后一小时。


当 DST 结束时,我们有一个本地时间存在两次的奇怪情况(在这种情况下,1AM 和 1:59AM 之间的时间出现了两次:在 -04:00 偏移量,然后在 -05:00 偏移量) , Joda-Time 默认选择 DST 转换前的偏移量 (-04:00)。

不过,您可以使用withLaterOffsetAtOverlap() 覆盖它,这将在 DST 结束后采用偏移量。

// new DateTime creates 2018-11-04T01:00:00.000-04:00
DateTime A = new DateTime(2018, 11, 4, 1, 00, 0)
    // adjust to offset after DST ends (2018-11-04T01:00:00.000-05:00)
    .withLaterOffsetAtOverlap()
    // add 1 hour
    .plusHours(1);
DateTime B = new DateTime(2018, 11, 4, 2, 00, 0);

// now A and B are the same instant
System.out.println(A.equals(B)); // true

【讨论】:

我的问题是关于如何比较,而不是如何创建 DateTime 实例,因为我不创建这些实例。但事实上,无论您选择通过 EST 还是 EDT 来表示它们,它们都代表着相同的实际时刻。就像说 10/5 和 8/4 这两个比率不同,但它们确实评估为相同的数字,即 2。所以当我将 10/5 与 8/4 进行比较时,我可以使用 10/5 == 8 /4。声称它们不是同一个实例是错误的,因为当我转换为 UTC 时,两者都会给我完全相同的结果 @Norcal 如果getMillis() 返回不同的值,那么它们不是同一时刻 - 它们不对应于同一 UTC 时刻,只需调用 toInstant() 和你会发现 A 和 B 是不同的。我只是在解释,根据问题中的代码,为什么 A 和 B 不同。如果你仍然认为它们是一样的,那我也无能为力了。祝你好运 @Norcal 不管怎样,使用equals 是比较的正确方法,所以如果它返回false,那么它们就不一样了。您的输出显示 A 是凌晨 1 点,B 是凌晨 2 点,所以我看不出它们如何相同。 也许您在 America/New_York 不是默认时区的某些环境中进行了测试 - 在这种情况下,A 和 B 将是相同的。但是当默认时区是 America/New_York 时,似乎是这种情况,那么你就有了我在回答中提到的 DST 效果(实际上,这就是我可以重现错误的方式 - 通过将我的默认时区设置为纽约,因为使用另一个,这不会发生)-我只是在猜测。如果您说它们相同,为什么问题中的输出显示 A 和 B 的值不同? @Norcal 为了清楚起见,A 和 B 不一样,因为它们不会评估到相同的 UTC 时刻。 A2018-11-04T01:00:00.000-05:00,转换为 UTC(使用 A.toInstant())我得到 2018-11-04T06:00:00.000Z,而 B2018-11-04T02:00:00.000-05:00 并转换为 UTC(B.toInstant())得到 2018-11-04T07:00:00.000Z。使用您在问题中提供的代码(并假设默认时区是 America/New_York,基于 getChronology() 的输出),A 比 B 早一小时,因此它们相同。 【参考方案2】:

根据javadoc,你可以使用:

equals:基于毫秒瞬间、年表和时区的平等 isEqual: 这个瞬间是否等于传入的瞬间,仅以毫秒为单位进行比较

但是使用您示例中的日期,两种方法都返回false。这是有道理的,主要是因为getMillis() 返回的值不同,所以日期实际上并不对应于同一 UTC 时刻,正如另一个答案所解释的那样。

【讨论】:

以上是关于比较 EST EDT 中的两个 joda DateTime 实例的主要内容,如果未能解决你的问题,请参考以下文章

在 R 中处理东部标准时间 (EST) 和东部夏令时 (EDT)

如何获取 pytz 时区的通用名称,例如。美国/纽约的 EST/EDT

修改linux系统的时间EDT和EST为CST

如何使用纯函数可靠地将 POSIX 纪元秒转换为 EST/EDT 时间

Joda DateTime 到 BigDecimal 分数计算

更改 MySQL 中的连接时区