简体   繁体   English

rrule.js - 重复系列在夏令时后更改时区中的一天中的时间

[英]rrule.js - Recurrence series changes time of day in time zone after Daylight Savings

I have what seems like a very common use case: I want to have a recurring event that occurs at the same time each day in a specific time zone (in the example below, 6:00 AM in the America/Denver time zone).我有一个看起来很常见的用例:我想要在特定时区每天同一时间发生一个重复事件(在下面的示例中,美国/丹佛时区早上 6:00)。 I want this to recur at the same time of day after a change in Daylight Savings as before.我希望在夏令时更改后的同一时间再次发生这种情况。 Right now, it is changing by one hour after Daylight Savings, which seems to indicate that Daylight Savings is not being accounted for when the recurring datetimes are generated.现在,它在夏令时后一小时发生变化,这似乎表明在生成循环日期时间时没有考虑夏令时。

I have tried various configurations for the rrule as indicated in the documentation here and here .我已经尝试了 rrule 的各种配置,如文档herehere中所示。 It says the time of day should be the same across Daylight Savings, but that is not what I am seeing.它说夏令时的一天中的时间应该相同,但这不是我所看到的。

Code sample代码示例

const rrule = new RRule({
  freq: RRule.DAILY,
  dtstart: new Date(Date.UTC(2022, 7, 18, 12, 0, 0)),
  // tzid: 'America/Denver', // output is the same whether this is included or not
})
const datetimes = rrule.between(
  new Date('2022-10-31'),
  new Date('2022-11-10')
)

Try out the CodeSandbox .试用CodeSandbox Should get similar results as long as you are in a time zone that has Daylight Savings and the between range includes a change in Daylight Savings.只要您处于具有夏令时的时区并且between的范围包括夏令时的变化,就应该得到类似的结果。

Expected output预计 output

The time of day in America/Denver time zone should not change after Daylight Savings (ie recurrence should account for Daylight Savings):美国/丹佛时区的时间在夏令时后不应更改(即重复应考虑夏令时):

Mon Oct 31 2022 06:00:00 GMT-0600 (Mountain Daylight Time)
Tue Nov 01 2022 06:00:00 GMT-0600 (Mountain Daylight Time)
Wed Nov 02 2022 06:00:00 GMT-0600 (Mountain Daylight Time)
Thu Nov 03 2022 06:00:00 GMT-0600 (Mountain Daylight Time)
Fri Nov 04 2022 06:00:00 GMT-0600 (Mountain Daylight Time)
Sat Nov 05 2022 06:00:00 GMT-0600 (Mountain Daylight Time)
Sun Nov 06 2022 06:00:00 GMT-0700 (Mountain Standard Time) <-- Daylight savings change
Mon Nov 07 2022 06:00:00 GMT-0700 (Mountain Standard Time)
Tue Nov 08 2022 06:00:00 GMT-0700 (Mountain Standard Time)
Wed Nov 09 2022 06:00:00 GMT-0700 (Mountain Standard Time)
                ^^

Actual output实际output

The time of day in America/Denver time zone is changing from 6:00 to 5:00:美国/丹佛时区的时间从 6:00 更改为 5:00:

Mon Oct 31 2022 06:00:00 GMT-0600 (Mountain Daylight Time)
Tue Nov 01 2022 06:00:00 GMT-0600 (Mountain Daylight Time)
Wed Nov 02 2022 06:00:00 GMT-0600 (Mountain Daylight Time)
Thu Nov 03 2022 06:00:00 GMT-0600 (Mountain Daylight Time)
Fri Nov 04 2022 06:00:00 GMT-0600 (Mountain Daylight Time)
Sat Nov 05 2022 06:00:00 GMT-0600 (Mountain Daylight Time)
Sun Nov 06 2022 05:00:00 GMT-0700 (Mountain Standard Time) <-- Daylight savings change
Mon Nov 07 2022 05:00:00 GMT-0700 (Mountain Standard Time)
Tue Nov 08 2022 05:00:00 GMT-0700 (Mountain Standard Time)
Wed Nov 09 2022 05:00:00 GMT-0700 (Mountain Standard Time)
                ^^

I've opened an issue for this on GitHub, but I'm wondering if I'm just missing something.我已经在 GitHub 上为此打开了一个问题,但我想知道我是否只是遗漏了什么。 It seems like a common use case, so I would think I'd be able to find something out there about it.这似乎是一个常见的用例,所以我想我可以找到一些关于它的东西。 I did find a couple of SO questions about it here and here , but I'm already applying the solutions suggested.我确实在这里这里找到了几个关于它的问题,但我已经在应用建议的解决方案。

Is this an actual bug in rrule or am I just missing something?这是 rrule 中的实际错误还是我只是遗漏了什么?

I had to dig very deep and surprisingly it seems like there is no bug.我不得不深入挖掘,令人惊讶的是似乎没有错误。 If you change your CodeSandbox to the following then it should work:如果您将 CodeSandbox 更改为以下内容,那么它应该可以工作:

import { RRule } from "rrule";
import "./styles.css";

const rrule = new RRule({
  freq: RRule.DAILY,
  dtstart: new Date(Date.UTC(2022, 7 - 1, 18, 12, 0)), // See note 1
  tzid: 'America/Denver',
})
const datetimes = rrule.between(
  new Date('2022-10-31'),
  new Date('2022-11-10')
)
const output = datetimes.map((d) => new Date( // See note 2
  d.getUTCFullYear(),
  d.getUTCMonth(),
  d.getUTCDate(),
  d.getUTCHours(),
  d.getUTCMinutes(),
)).join('<br/>')
document.getElementById("app").innerHTML = output;

Notes:笔记:

  1. The docs at https://github.com/jakubroztocil/rrule#timezone-support state that using new Date(2022, 7, ...) will produce unexpected timezone offsets.位于https://github.com/jakubroztocil/rrule#timezone-support state 的文档指出使用new Date(2022, 7, ...)会产生意外的时区偏移。 Instead use rrule's datetime function. Since this function currently is not working (see https://github.com/jakubroztocil/rrule/issues/551 ) we have to use new Date(Date.UTC(2022, 7 - 1, ...)) (which is excatly what the datetime function is doing).而是使用 rrule 的datetime时间 function。由于此 function 当前无法正常工作(请参阅https://github.com/jakubroztocil/rrule/issues/551 ),我们必须使用new Date(Date.UTC(2022, 7 - 1, ...)) (这正是datetime function 正在做的事情)。
  2. The result will be a date in UTC which you have to interpret as a date in the timezone you specified in tzid .结果将是 UTC 日期,您必须将其解释为您在tzid中指定的时区中的日期。 It seems very weird but it is stated in the docs at https://github.com/jakubroztocil/rrule#important-use-utc-dates that: Even though the given offset is Z (UTC), these are local times, not UTC times.这看起来很奇怪,但在https://github.com/jakubroztocil/rrule#important-use-utc-dates的文档中指出:即使给定的偏移量是Z (UTC),这些都是当地时间,而不是UTC 时间。 Just to emphasize this my code example transforms the UTC dates to America/Denver dates by creating a new instance of Date using the UTC values (only works if your operating's system timezone is America/Denver ).只是为了强调这一点,我的代码示例通过使用UTC值创建Date的新实例将UTC日期转换为America/Denver日期(仅当您的操作系统时区为America/Denver时才有效)。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM