Rrule: 尽管“时区支持”,夏令时更改未正确处理

创建于 2018-11-20  ·  21评论  ·  资料来源: jakubroztocil/rrule

我一直在将前端的这个库(v2.5.6)的行为与后端的等效 PHP 库(v2.3.3)的行为进行比较。 夏令时更改的处理方式存在明显的不一致,我相信 PHP 版本处理得更好。

代码示例:

America/Denver时区,夏令时切换发生在 2018 年 11 月 4 日星期日(从 GMT-6 到 GMT-7)。 因此,让我们设置一个从下午 1 点开始的循环系列,从 11 月 1 日开始,即时间切换之前的每个周一、周三、周四重复:

RRule.fromString(
  "DTSTART;TZID=America/Denver:20181101T190000;\n"
  + "RRULE:FREQ=WEEKLY;BYDAY=MO,WE,TH;INTERVAL=1;COUNT=7"
).all()

在这种情况下,我希望所有重复都在下午 1:00 开始,如下所示。 (根据文档,我使用的是 Luxon 库。我没有看到任何说我必须以某种方式初始化它,所以我假设它是通过 yarn 正确“安装”的。)

预期结果(全部从 13:00:00 开始):

(7) [
    Thu Nov 01 2018 13:00:00 GMT-0600 (Mountain Daylight Time),
    Mon Nov 05 2018 13:00:00 GMT-0700 (Mountain Standard Time),
    Wed Nov 07 2018 13:00:00 GMT-0700 (Mountain Standard Time),
    Thu Nov 08 2018 13:00:00 GMT-0700 (Mountain Standard Time),
    Mon Nov 12 2018 13:00:00 GMT-0700 (Mountain Standard Time),
    Wed Nov 14 2018 13:00:00 GMT-0700 (Mountain Standard Time),
    Thu Nov 15 2018 13:00:00 GMT-0700 (Mountain Standard Time)
]

实际结果:

(7) [
    Thu Nov 01 2018 13:00:00 GMT-0600 (Mountain Daylight Time),
    Mon Nov 05 2018 12:00:00 GMT-0700 (Mountain Standard Time), <-- Should be 13:00:00
    Wed Nov 07 2018 12:00:00 GMT-0700 (Mountain Standard Time), <-- same
    Thu Nov 08 2018 12:00:00 GMT-0700 (Mountain Standard Time), <-- same
    Mon Nov 12 2018 12:00:00 GMT-0700 (Mountain Standard Time), <-- same
    Wed Nov 14 2018 12:00:00 GMT-0700 (Mountain Standard Time), <-- same
    Thu Nov 15 2018 12:00:00 GMT-0700 (Mountain Standard Time)  <-- same
]

当我在 PHP 库中设置类似的情况时,结果如上预期,所有实例都在 America/Denver 时区的 13:00:00 开始,而不是 UTC

其他详情:

  • 版本 2.5.6
  • Mac OS X 10.13.6
  • 铬 70
  • 我当前的当地时间是 MST(美国/丹佛,GMT-7)

编辑:修正错字

所有21条评论

您是否收到任何控制台警告? 例如:

'Using TZID without Luxon available is unsupported. Returned times are in UTC, not the requested time zone'

Luxon 在optionalDependencies中,因此如果它在您的node_modules中,它将被导入,否则不会。

当我在 rrule 测试套件中运行您的代码时,我得到:

      [
        [Date: 2018-11-01T19:00:00.000Z]
        [Date: 2018-11-05T19:00:00.000Z]
        [Date: 2018-11-07T19:00:00.000Z]
        [Date: 2018-11-08T19:00:00.000Z]
        [Date: 2018-11-12T19:00:00.000Z]
        [Date: 2018-11-14T19:00:00.000Z]
        [Date: 2018-11-15T19:00:00.000Z]
      ]

这是我所期望的,因为您请求的时间是丹佛时区的 1900 年。 (由于这是 JavaScript 而不是 PHP,我们不能在本地机器时区或 UTC 以外的时区为您提供Date对象,因此该库始终使用 UTC。)

您看到的是本地 (MST/MDT) 日期而不是 UTC 日期,这让我有点困惑。 据我所知,该库当前配置为仅返回 UTC 日期,尽管它以前用于返回本地日期。

您是否收到任何控制台警告? 例如:

'不支持在没有 Luxon 的情况下使用 TZID。 返回的时间是 UTC,而不是请求的时区'

没有控制台警告。 看来 Luxon 提供得当。

至于时区,由于直接在 Chrome devtools 控制台命令行中运行我的代码,我得到了 MST/DST。

步骤: 打开 Chrome --> 导航到提供 RRule 和 Luxon 的页面 --> Cmd+Opt+I --> “控制台”选项卡 --> 将上面的代码段复制并粘贴到底部的命令行中 --> 输入

此库当前配置为仅返回 UTC 日期,尽管它以前用于返回本地日期。

你知道这是在哪个版本上更改的吗? 为什么会做出这样的改变? 返回 UTC 日期实际上会引入这种夏令时差异! 始终在 13:00 UTC 发生的事件几乎可以保证该事件将在夏令时切换之前/之后的不同时间开始。 我认为应该恢复这种更改,或者应该提供另一种替代方法来考虑夏令时。 UTC 非常有用,但并非在所有情况下都是正确的方法。 在处理重复事件时,我们必须考虑事件发生的具体时区,因为夏令时是一回事。

事实上,我从 Chrome 中获得的行为与从 Node 中获得的行为不同。

我会说我不明白为什么您给定的“预期”输出是您真正期望的。 这些时间似乎不正确。

如果您将每次的 TZ 偏移量添加到给定的本地时间,_would be_ 正确的是时间。 然后所有时间都是 19:00。 这就是 RRule 使用 UTC 交易的原因,以及为什么它对 UTC 的使用与这个特定的错误无关。

事实上,如果你这样做:

const dates = RRule.fromString(
  "DTSTART;TZID=America/Denver:20181101T190000;\n"
  + "RRULE:FREQ=WEEKLY;BYDAY=MO,WE,TH;INTERVAL=1;COUNT=7"
).all()
dates.map((date) => date.toISOString())

您将看到生成的 ISO 字符串始终具有正确的日期和时间。

此外,Chrome 似乎根本不支持以 UTC 格式返回日期:

> new Date(Date.UTC(2016, 10, 5))
Fri Nov 04 2016 17:00:00 GMT-0700 (Pacific Daylight Time)
// ^ I asked for a date in UTC, not in PDT!

RRule 使用 Luxon 为世界上的所有时区生成正确的本地时间,而不仅仅是您的本地时区。 这就是为什么它对 UTC 的使用至关重要:如果时区代码为您的本地时区返回“正确”日期,但您需要在不同的时区生成日期(使用TZID参数),您会得到非常不正确的结果。 我们使用“UTC 日期”不是因为我们在 UTC 中进行 DST 数学运算(我们不是,您可以检查测试套件并查看大量正确 DST 计算的示例),而是因为 JavaScript 规范中的时区非常糟糕坏了,UTC 最接近可用的“中性”日期概念。 很抱歉,它的使用令人困惑,并且这个库对它的使用再清楚不过了(尽管我愿意接受建议)。

_is_ 关注的是您提出的浏览器兼容性问题。 我想请您现在在运行的 Node 控制台或 Firefox 中尝试您自己的示例代码。 您会看到非常不同(且正确)的结果。

所以这里真正的问题是 Chrome 中的结果令人困惑。 我认为这是值得解决的,尽管我并不清楚具体如何去做。 我_可以_告诉你的是两种环境都会生成完全相同的 ISO 字符串和时间戳。

@davidgoli没错,Firefox 在运行我的原始代码时确实在控制台中显示了不同的结果。 但是,结果最终是相同的时间,只是结果在 Firefox 中以 UTC 时间表示,而在 Chrome 中则以America/Denver时间(或者可能是您当地的时区)表示。

我会说我不明白为什么您给定的“预期”输出是您真正期望的。 这些时间似乎不正确。

如果您将每次的 TZ 偏移量添加到给定的本地时间,那么正确的是时间。 然后所有时间都是 19:00。 这就是 RRule 使用 UTC 交易的原因,以及为什么它对 UTC 的使用与这个特定的错误无关。

让我尝试解释一下为什么我们不希望每个重复事件都使用 19:00 UTC 时间。

假设用户想要在每个星期三下午 1 点在America/Denver时区的某个特定位置安排重复事件。 简单地说,这意味着——无论是一年中的什么时候——用户都希望在每周三下午 1 点发生同样的事件,只要是周三下午 1 点在那个位置。 不是中午十二点,不是下午两点。 美国/丹佛时间总是在下午 1 点。

但是, rrule 正在根据 UTC 时间解决重复问题——即使传入时区也是如此。通过这样做,它基本上是在说,“哦,美国/丹佛下午 1:00 计算为 19:00。因此,19:00必须始终指美国/丹佛的下午 1:00,全年无休。但事实并非如此。 在 2018 年 11 月 4 日之前确实如此,但在 11 月 4 日之后,美国/丹佛将关闭夏令时,此时, UTC 时间 19:00现在计算为美国/丹佛时间下午 12:00 。 所以我们的用户被错误地告知事件发生在中午 12 点,而不是下午 1 点。

换句话说,美国/丹佛下午 1 点可以19:00 或 20:00 UTC,具体取决于我们是否处于夏令时,并且不可能使用 rrule 来获得正确的重现,因为它想说 19: 00 是全年的正确时间。

我觉得 rrule 正在接受大多数程序员所相信的神话,即在处理日期和时间时,UTC始终是正确的解决方案。 但是在某些情况下它不是最佳解决方案,而这种情况(在特定位置重复未来事件)就是其中之一。


编辑:理论上,我可以使用 rrule 返回 UTC 时间,但是当传入时区时,这些时间对于给定的时区应该是正确的。这意味着我们应该看到 19:00 UTC 切换到 20:00 UTC结果集中的某个点,对于此处讨论的示例。

Lemme back up here - 我认为这是一个文档问题。

RRule _always_ 返回 JS“UTC”日期。 然而,这并不意味着这些日期代表 UTC 时间。 相反,由于唯一替代方案(本地日期)的限制,已决定 _only_ 具有 0 时区偏移量的 JS 日期可用于该库正在执行的日期数学运算。 这会产生误导性的副作用,即这些时间实际上代表 UTC 时间,而实际上它们应该在TZID参数所代表的时区中进行解释。 例如,在 Firefox 中,预期的行为是库返回一个表示 19:00 的日期,并且由于您要求该时间为丹佛时间,因此丹佛时间将是正确的。 您应该忽略这个日期报告它是 UTC 日期的事实,因为这是 JavaScript 中唯一有用的日期。 相反,您应该使用此规则具有丹佛时区的知识将 19:00 解释为丹佛的当地时间。

当您使用本地计算机区域之外的时区时,这一点会更清楚。 例如,如果您使用区域名称America/New_York设置 RRule,您将看到日期返回为 17:00,因为这是您机器时区(丹佛)中的本地时间,当时是 19 :00 在请求的时区(纽约)。

JavaScript 无法将日期“固定”到特定时区,因此无论如何我们始终表示正确的日期和时间,并且您可以放弃 Date 将自身报告为 UTC 的事实。 在 RRule 中使用时区时,实际上是本地时间。 这就是为什么 Firefox 会为您提供正确的本地时间为 19:00(即使该日期报告为 UTC,它实际上是丹佛时间)。

这是否完全澄清了事情? 我知道它令人困惑且不直观,但希望它足够简单,一旦理解就很容易理解。 我们绝对应该更好地记录这一点。

我想从中探索的一件事是使用 Luxon 将结果日期重新划分为本地时区的可能性,因此它至少符合您的期望。 我认为这应该不会太难,并且应该有助于澄清诸如此类的误解。 Chrome 问题对我来说真的很新鲜,而且是个坏消息。

然而,这将是一个突破性的变化,所以我想在发布之前提供社区反馈的机会。

@shorlbeck我相信这个差异实现了您期望看到的行为:

diff --git a/src/datewithzone.ts b/src/datewithzone.ts
index 8ae3ed0..d9b917c 100644
--- a/src/datewithzone.ts
+++ b/src/datewithzone.ts
@@ -38,7 +38,10 @@ export class DateWithZone {

       const rezoned = datetime.setZone(this.tzid!, { keepLocalTime: true })

-      return rezoned.toJSDate()
+      return rezoned
+        .toUTC()
+        .setZone('local', { keepLocalTime: true })
+        .toJSDate()
     } catch (e) {
       if (e instanceof TypeError) {
         console.error('Using TZID without Luxon available is unsupported. Returned times are in UTC, not the requested time zone')
diff --git a/test/rrule.test.ts b/test/rrule.test.ts
index 7774b8a..a794e02 100644
--- a/test/rrule.test.ts
+++ b/test/rrule.test.ts
@@ -3804,4 +3804,17 @@ describe('RRule', function () {
     expect(() => rule.between(invalidDate, validDate)).to.throw('Invalid date passed in to RRule.between')
     expect(() => rule.between(validDate, invalidDate)).to.throw('Invalid date passed in to RRule.between')
   })
+
+  it('#300', () => {
+    const rule = RRule.fromString(
+      "DTSTART;TZID=America/Denver:20181101T190000;\n"
+      + "RRULE:FREQ=WEEKLY;BYDAY=MO,WE,TH;INTERVAL=1;COUNT=3"
+    )
+
+    expect(rule.all()).to.deep.equal([
+      DateTime.utc(2018, 11, 2, 1, 0, 0).toJSDate(),
+      DateTime.utc(2018, 11, 6, 2, 0, 0).toJSDate(),
+      DateTime.utc(2018, 11, 8, 2, 0, 0).toJSDate(),
+    ])
+  })
 })

但是,我并不完全相信这是该库的必经之路。 考虑到图书馆返回“浮动”时间的一般方法,这些时间总是打算在客户端的本地时区中解释(尽管偏移量为 0)。 rrule返回的日期的适当 getter 是getUTC* getter,例如,如果您在原始结果中的每个日期使用getUTCHours() ,您将获得正确的时间,即使在 Chrome 中也是如此。

我倾向于认为正确的解决方法不是改变这个库的行为,而是更清楚地记录它对伪“UTC”(实际上是“浮动”)时间的某种特殊用法。 但是,我愿意就此进行说服。

我已经更新了自述文件,其中包含一些针对您的用例的说明和说明。 然而,我有兴趣继续这个讨论,并愿意在未来版本的库中改变这种行为。

谢谢你的回复和详细的解释。

不幸的是,我从未如此困惑过。

当这些日期时间实际上是UTC 或实际上是本地时间时,使用日期和时间就足够困难了,但还必须记住,有时 UTC 时间实际上并不是 UTC 时间,这超出了我的大脑可以处理的范围。 我今天花了一整天的时间试图理解你写的东西,但归根结底,这完全违反直觉,以至于我无法理解它。

每当我查看代码并看到“UTC”日期时,我不记得它实际上是 UTC还是只是伪 UTC ,尤其是当您在其中添加 Chrome 问题时。 这让我几乎不可能编写代码。 它破坏了我对代码可读性的信任。

这是我的问题,然后……回到我原来的例子……在真正的 UTC 中, 2018-11-01 19:00:00指的是美国/丹佛时间下午 1 点(13:00)。 在我的示例中,美国/丹佛下午 1 点是我活动的正确时间。 但是,如果 UTC 不是真正的 UTC,这是否意味着我应该在使用tzid参数时传入new Date(Date.UTC(2018, 10, 1, 13, 0, 0))new Date(Date.UTC(2018, 10, 1, 19, 0, 0)) ? (区别是 13:00 和 19:00)

是伪UTC进出吗? 还是真正的 UTC 进入但伪 UTC 出来? 我怎么能可靠地记住这一点?

您的规则指定为:

DTSTART;TZID=America/Denver:20181101T190000
RRULE:FREQ=WEEKLY;BYDAY=MO,WE,TH;INTERVAL=1;COUNT=7

但根据 RRULE RFC5545,这表示丹佛时区的规则,当地时间为 1900: https: //tools.ietf.org/html/rfc5545#section -3.3.5

For example, the following represents 2:00 A.M. in New York on January 19, 1998:

       TZID=America/New_York:19980119T020000

如果您想要丹佛当地时间 1300 的 DTSTART,则应在您的规则中将其指定为 1300。 该库应完全符合这方面的规范。 (嗯,除了它将返回 1300 UTC 的小事实......)

此外,请务必阅读“浮动时间”部分:

FORM #1: DATE WITH LOCAL TIME

      The date with local time form is simply a DATE-TIME value that
      does not contain the UTC designator nor does it reference a time
      zone.  For example, the following represents January 18, 1998, at
      11 PM:

       19980118T230000

      DATE-TIME values of this type are said to be "floating" and are
      not bound to any time zone in particular.  They are used to
      represent the same hour, minute, and second value regardless of
      which time zone is currently being observed.  For example, an
      event can be defined that indicates that an individual will be
      busy from 11:00 AM to 1:00 PM every day, no matter which time zone
      the person is in.  In these cases, a local time can be specified.

不幸的是,JavaScript 不提供“浮动时间”的实现。 我们拥有的最接近“纯”、无时区时间的选项是 UTC,因此是“伪 UTC”。 (作为记录, rrule也支持浮动时间,既没有使用 TZID 也没有使用Z UTC 指示符指定。)

切换到 UTC 是从这个提交开始的: https ://github.com/jakubroztocil/rrule/commit/850ed075175eb1acfcbd7b2cddf0606f2b2206f7

如果您检查之前的提交,并从 #850ed075 中挑选添加的测试,您会看到它失败。 事实上,除非整个套件在 UTC 中运行,否则数百个测试都失败了。 这是因为,为了计算跨越 DST 边界的未来日期,我们必须在当前时钟在 DST 中运行时实例化日期,然后计算使我们进入标准时间的数学,从而导致错误的 1 小时偏移。 当前的实现总是给出正确的当地时间。 现在,整个测试套件实际上将在任何本地环境中通过,但需要注意的是,要获得正确的日期/时间,您必须使用getUTCDate() / getUTCHour()方法。

我正在研究在未来的版本中对此进行更改,但如果不采用像 Luxon 这样的必需的 3rd 方库,更改并非微不足道。

在即将发布的版本中,我希望更改行为以返回在您当地时区始终正确的日期,例如:

  • 如果您在丹佛, DTSTART;TZID=America/Denver:20181101T130000将返回1300-0700 (标准时间)的日期,如果您在 UTC,则返回2000Z
  • 如果你在丹佛, DTSTART=20181101T130000会给你1300-0700 ,如果你在 UTC,会给你 $# 1300Z
  • 如果你在丹佛, DTSTART=20181101T130000Z会给你0600-0700 ,如果你在 UTC,会给你 $# 1300Z

这是您期望的行为吗?

一个大问题是给定的本地 JS 环境只能表示单个时区中的日期。 因此,当您想在特定时区(可能与您当前的时区不同)中表示日期时间时, new Date(...)new Date(Date.UTC(...))都不是真正合适的。

那么应该有什么行为:

new RRule({
  dtstart: new Date(2018, 10, 1, 10, 0, 0),
  tzid: 'America/Denver'
})

如果本地机器在America/Los_Angeles中? 您必须至少在一定程度上意识到您正在创建的时间与您想要该时间所在的时区之间的 1 小时差异。所以它应该代表上午 11 点(丹佛时间,请求的区域)还是上午 10 点(洛杉矶时间,始发区)? 我认为你可以为任何一个提出理由。

迂腐地, Date对象不同于 ISO 日期字符串和 DTSTART 字符串,因为它表示以 UTC 毫秒为单位的时间戳,没有时区或偏移量的概念。 所以我认为在正确的区域中表示所需时间的时间戳是最有意义的,这意味着如果你在洛杉矶并且你想表示丹佛的时间,你必须传入一个用相对值初始化的 Date 对象应用了偏移量(因此上面的示例将代表丹佛的上午 11 点)。 但这很令人困惑,因为如果您随后前往纽约并想代表同一时间,则必须写new Date(2018, 10, 1, 13, 0, 0)

放弃本地日期的整个概念的一个好处是您不必处理这个问题。 表示的日期和时间可以视为浮动时间,无需进行任何转换即可投影到任何时区。

当然,这很复杂,因为 Chrome 等引擎的行为。

出于您的目的,您可能可以通过以下方式获得所需的值:

rule.all().map(d => new Date(
    d.getUTCFullYear(),
    d.getUTCMonth(),
    d.getUTCDate(),
    d.getUTCHours(),
    d.getUTCMinutes(),
    d.getUTCMilliseconds()
  ))

我目前正在尝试确定这是否属于图书馆本身...

谢谢! 你的回答真的让我明白了一些事情。 我想我昨天在试图理解一切时感到疲倦和精疲力尽。 我现在看到发生了什么,你是对的,我在使用tzid参数时传递了错误的时间。

出于您的目的,您可能可以通过以下方式获得所需的值:

rule.all().map(d => new Date(
    d.getUTCFullYear(),
    d.getUTCMonth(),
    d.getUTCDate(),
    d.getUTCHours(),
    d.getUTCMinutes(),
    d.getUTCMilliseconds()
  ))

我目前正在尝试确定这是否属于图书馆本身...

这对我有用! 非常感谢。 如果有一种方法可以配置rule.all()rule.between()返回的内容,那就太好了,这样我们就不会再引入另一个重大更改,但仍然可以原生地获得上述行为。 当您还认为我喜欢使用rrulestr()RRule.fromString()但可能还有一个额外的参数或其他东西来指定返回的日期类型时,不确定如何实现这一点?


更新:上面的d.getUTCMilliseconds()应该更改为d.getUTCSeconds()

因此,当我的系统的时区与请求的时区相同时,您的解决方案有效,但是当我的系统时区与系统时区不同时,我很难弄清楚如何让RRule返回请求的时区中的日期。 它始终返回以系统时区表示的日期,而不是以请求的时区表示的日期。 例子:

  1. 将您的操作系统系统时区设置为America/Denver
  2. 在 Chrome devtools 控制台中,输入:
RRule.fromString(
    "DTSTART;TZID=America/Denver:20181101T130000;\n"
    + "RRULE:FREQ=WEEKLY;BYDAY=MO,WE,TH;INTERVAL=1;COUNT=7"
).all().map(d => new Date(
    d.getUTCFullYear(),
    d.getUTCMonth(),
    d.getUTCDate(),
    d.getUTCHours(),
    d.getUTCMinutes(),
    d.getUTCSeconds()
));

结果是正确的(对于我的期望/需要):

(7) [Thu Nov 01 2018 13:00:00 GMT-0600 (Mountain Daylight Time), Mon Nov 05 2018 13:00:00 GMT-0700 (Mountain Standard Time), Wed Nov 07 2018 13:00:00 GMT-0700 (Mountain Standard Time), Thu Nov 08 2018 13:00:00 GMT-0700 (Mountain Standard Time), Mon Nov 12 2018 13:00:00 GMT-0700 (Mountain Standard Time), Wed Nov 14 2018 13:00:00 GMT-0700 (Mountain Standard Time), Thu Nov 15 2018 13:00:00 GMT-0700 (Mountain Standard Time)]
  1. 将操作系统系统时区更改为America/New_York
  2. 在 Chrome devtools 控制台中运行相同的命令。

结果不同,因为它以系统时区表示:

(7) [Thu Nov 01 2018 15:00:00 GMT-0400 (Eastern Daylight Time), Mon Nov 05 2018 15:00:00 GMT-0500 (Eastern Standard Time), Wed Nov 07 2018 15:00:00 GMT-0500 (Eastern Standard Time), Thu Nov 08 2018 15:00:00 GMT-0500 (Eastern Standard Time), Mon Nov 12 2018 15:00:00 GMT-0500 (Eastern Standard Time), Wed Nov 14 2018 15:00:00 GMT-0500 (Eastern Standard Time), Thu Nov 15 2018 15:00:00 GMT-0500 (Eastern Standard Time)]

但我希望结果代表America/Denver时间,而不是我的系统时区,也不是真正的 UTC。 如何将其重新分区为America/Denver ? 我对 Luxon 不熟悉,所以我尝试moment()

RRule.fromString(
    "DTSTART;TZID=America/Denver:20181101T130000;\n"
    + "RRULE:FREQ=WEEKLY;BYDAY=MO,WE,TH;INTERVAL=1;COUNT=7"
).all().map(d => moment(new Date(
    d.getUTCFullYear(),
    d.getUTCMonth(),
    d.getUTCDate(),
    d.getUTCHours(),
    d.getUTCMinutes(),
    d.getUTCSeconds()
)).tz('America/Denver').toDate());

但这在纽约时间会返回相同的内容,因为toDate()会立即将其放回系统时区(至少在 Chrome 中)。

@shorlbeck如果您注意到,MDT 和 EDT 中的结果在 UTC 中是相同的,所以我的问题是:您确定要使用TZID参数而不仅仅是浮动时间吗? 如果您希望它始终生成 13:00 而不管系统时区如何,我建议浮动时间(基本上相同,但使用DSTART:<datetime>而不是DSTART;TZID=<timezone>:<datetime> )。

即 13:00 伪 UTC。 如果您想解决 Chrome 问题,您仍然需要使用我之前评论中的方法转换为本地日期。

@davidgoli哦,哇,你是对的。 在我了解了浮动时间/伪 UTC 的实际工作原理后,我没有意识到我实际上并不需要 tzid 参数。 这意味着我也不需要上面的.map()解决方案。 您的评论为我指明了正确的方向。 非常感谢。

如果我说这不是我长期以来所做的最令人困惑的事情,我会撒谎,但我很高兴现在朝着正确的方向前进。

您是否考虑过使用明确表示您需要的内容(没有时区的浮动日期)? 使用带有 UTC 时区的本机 JS Date在文档中声称它是 UTC 非常令人困惑,因为它在遇到 DST 错误之前一直有效。

我建议一个对象,我们称它为“RRuleDate”,它采用(year, month, day, hours?, minutes?, seconds?, milliseconds?)构造函数并具有.toDate()方法。

这个 RRuleDate 是before()after()between()all()应该返回的内容,也是before()after()的唯一内容between()dtstart选项应该接受作为参数。

此页面是否有帮助?
0 / 5 - 0 等级

相关问题

spurreiter picture spurreiter  ·  3评论

maconfr picture maconfr  ·  6评论

fatshotty picture fatshotty  ·  5评论

jimmywarting picture jimmywarting  ·  9评论

grigio picture grigio  ·  7评论