【问题标题】:rruleJS: Consideration of timezone for weekly caserruleJS:考虑每周案例的时区
【发布时间】:2015-12-12 02:41:10
【问题描述】:

我正在使用 rruleJS (https://github.com/jkbrzt/rrule) 并且开始日期如下:

开始日期和时间:2015-09-15 23:45 每第三周 工作日:周一、周三、周日

我保存它并得到这个规则:

FREQ=WEEKLY;INTERVAL=3;DTSTART=20150915T234500Z;BYDAY=MO,WE,SU

我现在预计我的重复开始时间是 23:45,

Wed Sep 16 2015 23:45:00 GMT+0200 (CEST), 
Sun Sep 20 2015 23:45:00 GMT+0200 (CEST), 
Mon Oct 05 2015 23:45:00 GMT+0200 (CEST), 
Wed Oct 07 2015 23:45:00 GMT+0200 (CEST), 

...

但相反,我得到了这些重复:

Wed Sep 16 2015 01:45:00 GMT+0200 (CEST), 
Sun Sep 20 2015 01:45:00 GMT+0200 (CEST), 
Mon Oct 05 2015 01:45:00 GMT+0200 (CEST), 
Wed Oct 07 2015 01:45:00 GMT+0200 (CEST), 
Sun Oct 11 2015 01:45:00 GMT+0200 (CEST), 
....

这是因为转换为当地时间(CEST-> +2 小时 -> 23:45 变为 01:45)。我可以减去时区偏移,但这会切换到另一个工作日。例如,如果我从 2015 年 9 月 16 日星期三 01:45:00 GMT+0200 (CEST) 减去 2 小时,我将得到 2015 年 9 月 15 日星期二 23:45:00 GMT+0200 (CEST)。

但这不是我想要的:时间是正确的,但不是工作日。我不希望它在周二再次发生,而是在周一、周三或周日再次发生。

如何考虑时区但仍保留起始工作日?

【问题讨论】:

    标签: javascript recurrence rrule


    【解决方案1】:

    我们遇到了类似的问题,因为我们在服务器端以 UTC 格式存储重复规则,但在客户端使用 RRule.js 组合规则。我们仍然希望能够在客户端生成日期供用户预览。

    我们的解决方案是创建 RRule 对象的副本,其中 dtstartuntil 时间偏移到本地时区。我们使用此副本生成预览日期。

    我们不得不在几个地方这样做,所以很容易在 RRule 上编写扩展方法:

    RRule.prototype.toOffsetRRule = function () {
        var localRule;
        var offset;
    
        localRule = RRule.fromString(this.toString());
    
        var dtstart = localRule.origOptions.dtstart;
        if (dtstart) {
            offset = dtstart.getTimezoneOffset();
            localRule.origOptions.dtstart = new Date(dtstart.getTime() + offset * 60000);
        }
    
        var until = localRule.origOptions.until;
        if (until) {
            offset = until.getTimezoneOffset();
            localRule.origOptions.until = new Date(until.getTime() + offset * 60000);
        }
    
        localRule = new RRule(localRule.origOptions);
        return localRule;
    }
    

    然后,每当我们需要在客户端生成日期时,我们都会调用此方法并根据我们的 RRule 的本地时区副本生成日期:

    var localRule= myRule.toOffsetRRule();
    var dates = localRule.all();
    

    当我们将循环规则保存到服务器时,我们实际上存储了myRule.toString()生成的字符串。

    【讨论】:

      【解决方案2】:

      首先,你的 RRULE 看起来像吗

      FREQ=WEEKLY;INTERVAL=3;DTSTART=20150915T234500Z;BYDAY=MO,WE,SU
      

      ?

      DTSTART 是一个属性,而不是 RRULE 的参数。

      那么对于您的 DTSTART,您要使用的是带有时区参考的本地时间(来自 https://www.rfc-editor.org/rfc/rfc5545#section-3.3.5 的 FORM #3)

      所以你想要这样的东西:

      DTSTART;TZID=Europe/Berlin:20150915T234500
      RRULE:FREQ=WEEKLY;INTERVAL=3;BYDAY=MO,WE,SU
      

      【讨论】:

      • rrule 重复的字符串如下所示。您可以将“FREQ=WEEKLY;INTERVAL=3;DTSTART=20150915T234500Z;BYDAY=MO,WE,SU”粘贴到jkbrzt.github.io/rrule(请参阅标签 RRULE 字符串),您将获得相应的数据集。
      • 也许我的回答不够清楚:RRULE 属性中没有 DTSTART 参数之类的东西。一个特定工具接受或生成这样的规则这一事实并不能使其有效。请查看实际的 iCalendar 规范:tools.ietf.org/html/rfc5545#section-3.8.5.3。您是否尝试过我在回答中提到的语法?
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2023-03-15
      • 1970-01-01
      • 2017-09-15
      • 2019-12-06
      • 2021-12-26
      • 2019-08-26
      • 1970-01-01
      相关资源
      最近更新 更多