简体   繁体   English

为重复活动的开始时间添加持续时间,以便结束时间始终是同一时间(即下午2点至下午4点)

[英]Add a duration to a repeating event's start time so that it's end is always the same time (i.e 2pm to 4 pm)

I have a bunch of rrules (implemented in rrule.js ) that gives me an array of event start times (see the demo ). 我有一堆rrule(在rrule.js中实现),为我提供了一系列事件开始时间(请参见演示 )。 rrule.js doesn't actually provide the concept of an event duration or endtime ... So it can tell me the precise date when the millionth occurrence of a repeating event will start but not when it will end. rrule.js 实际上并没有提供事件持续时间endtime 时间的概念 ...因此它可以告诉我确切的日期,即重复事件的百万分之一开始发生的时间,而不是结束时间。 Turns out I actually want to know when an event ends so I'll have to get creative. 原来,我实际上是想知道活动何时结束,所以我必须发挥创造力。 As far as I see it I've got two options 据我所知,我有两种选择

  1. DB SIDE: Store an rrule string + an event duration . DB SIDE:存储规则字符串+事件duration

    CLIENT SIDE: Reconstitute events start date array from rrule string. 客户端:从事件字符串重构事件开始日期数组。 Only start times would be known and end times would be calculated by adding the duration as an offset to each start time in the array. 通过将持续时间添加为数组中每个开始时间的偏移量,将仅知道start times ,并且将计算end times

  2. DB SIDE: Store a modified rrule string which encodes an endtime . DB SIDE:存储修改后的rrule字符串,该字符串对endtime进行编码。

    CLIENT SIDE: A special wrapper function reads the modified rrule string and reconstitutes it as two date arrays; 客户端:一个特殊的包装函数读取修改后的rrule字符串,并将其重构为两个日期数组。 one representing event start times and the other end times. 一个代表事件的开始时间,另一个代表事件的结束时间。

Option 1 seems easier but I suspect it will run into problems with daylight savings. 选项1似乎更容易,但我怀疑它会遇到夏令时的问题。 For example, say I've an event that is every Tuesday from 6pm to 2 am Wednesday. 例如,假设我有一个活动,该活动在每个星期二的晚上6点至星期三的凌晨2点。 In that case I'd store a duration of 8 hours in my database alongside that stringified rrule. 在这种情况下,我将在数据库中存储8个小时的时间以及该字符串规则。 Now let's fast forward to any 6pm Tuesday in the future. 现在,让我们快进到星期二下午6点。 Does my event always end on Wednesday at 2am (or does that 8 hour duration sometimes make my event end at 1am or 3am)? 我的活动是否总是在星期三凌晨2点结束(或者持续8个小时有时使我的活动在凌晨1点或凌晨3点结束)? How do I get it to always end at 2am? 如何使它始终在凌晨2点结束?

... If you know the answer then just stop reading here. ...如果您知道答案,请在这里停止阅读。

How I've seen others handle duration offset 我如何看待其他人处理持续时间偏移

According to Kip in How to add 30 minutes to a JavaScript Date object? 根据Kip中的方法, 如何向JavaScript Date对象添加30分钟? the smart way to offset a date time is to use a fancy library like moment.js. 偏移日期时间的明智方法是使用精美的库,例如moment.js。

He emphasizes that point by showing how easily things go wrong using non fancy date time libraries (showing how a naive minute offset function fails due to daylight savings) 他通过使用非理想的日期时间库显示问题出处的难易程度来强调这一点(显示天真的分钟偏移量功能由于夏令时而失败)

function addMinutes(date, minutes) {
    return new Date(date.getTime() + minutes*60000);
}
addMinutes(new Date('2014-11-02'), 60*24) //In USA, prints 11pm on Nov 2, not 12am Nov 3!

But something weird happens for me. 但是对我来说有些奇怪的事情发生了。 The function above was supposed to output 11pm on Nov 2 - which is the wrong answer ie it was supposed to fail because of daylight savings. 上面的函数应该11pm on Nov 2输出-这是错误的答案,即由于夏令时而失败。 When I run it, it actually outputs the right time 12am on Nov 3 (note: I'm in Chicago/Central time). 当我运行它时,它实际上12am on Nov 3输出正确的时间(注意:我在芝加哥/中部时间)。

When I compare the output of his naive function to the output of moment.js and luxon.js, I get the same answer as you can see in this observable notebook . 当我将其朴素函数的输出与moment.js和luxon.js的输出进行比较时,得到的答案与您在此可观察笔记本中看到的相同。

Scratching my head 挠头

What's more, if using luxon or moment, when you add a days worth of minutes to 2014-11-02 you get 2014-11-03T00:00:00.000Z but if you just directly add a day to 2014-11-02 you get 2014-11-03T01:00:00.000Z - it's an hour off. 更重要的是,如果使用luxon或moment,当您在2014-11-02增加一分钟的时间时,您将获得2014-11-03T00:00:00.000Z但如果您直接在2014-11-02增加一天,则得到2014-11-03T01:00:00.000Z这是一个小时的2014-11-03T01:00:00.000Z

So am I better off pursuing option 2? 所以我最好选择选项2吗?

Now let's fast forward to any 6pm Tuesday in the future. 现在,让我们快进到星期二下午6点。 Does my event always end on Wednesday at 2am (or does that 8 hour duration sometimes make my event end at 1am or 3am)? 我的活动是否总是在星期三凌晨2点结束(或者持续8个小时有时使我的活动在凌晨1点或凌晨3点结束)? How do I get it to always end at 2am? 如何使它始终在凌晨2点结束?

The standard Javascript Date object automatically handles the daylight savings shift for you. 标准的Javascript Date对象自动为您处理夏令时。 Even if you add 8 hours to a date at 6pm the day before daylight savings, the new date will still end at 2am the next day. 即使您在夏令时的前一天下午6点增加8小时的日期,新日期仍将在第二天凌晨2点结束。

Incidently, I implemented duration support in rSchedule and since it supports both the standard javascript Date as well as moment / luxon dates, you can test a recurring event with a duration using either library and see that they both produce the same result. 顺便说一句,我在rSchedule中实现了持续时间支持,并且由于它支持标准的javascript Date以及moment / luxon日期,因此您可以使用任一库来测试持续时间的重复事件,并查看它们是否产生相同的结果。

This example can be seen on stackblitz . 这个例子可以在stackblitz上看到

import { Schedule } from '@rschedule/rschedule';
import { StandardDateAdapter } from '@rschedule/standard-date-adapter';

// This example will also work with `moment`, `moment-timezone`, and `luxon`
// (assuming you import the proper date adapter -- see rSchedule docs)

const schedule = new Schedule({
  rrules: [
    {
      start: new Date(2019,9,10,18),
      frequency: "DAILY",
      duration: 1000 * 60 * 60 * 8,
      count: 30
    }
  ],
  dateAdapter: StandardDateAdapter,
});

schedule.occurrences().toArray().forEach(adapter => {
  console.log(
      {
        start: adapter.date.toLocaleString(),
        end: adapter.end.toLocaleString(),
      }
    )
})

Turns out I actually want to know when an event ends 原来我真的想知道事件何时结束

To find out when this event ends, you could do: 要了解此事件何时结束,您可以执行以下操作:

const iterator = schedule.occurrences({ reverse: true })

const { end } = iterator.next().value

This trick would only work with an event that actually has an end date (so not an event with infinite occurrences). 此技巧仅适用于实际具有结束日期的事件(因此不适用于无限次发生的事件)。

I wrote the original answer you are referring to about a decade ago. 我写的原始答案大约是十年前。 Seven years later, I made an edit, changing new Date(2014, 10, 2) to new Date('2014-11-02') . 七年后,我进行了修改,将new Date(2014, 10, 2)更改为new Date('2014-11-02') I thought this would be easier to read (because you don't have to explain that the months in that version of the constructor start at 0 instead of 1). 我认为这将更易于阅读(因为您不必解释该版本的构造函数中的月份从0而不是1开始)。 But as @RobG pointed out , formatting in this way causes it to be parsed as UTC. 但是正如@RobG指出的那样 ,以这种方式进行格式化会导致将其解析为UTC。 I've gone back and fixed this now (thanks for pointing it out). 我已经回过头来,现在解决了这个问题(感谢您指出)。

To get to your "scratching my head" part of your question: 为了解决您的问题“抓我的头”部分:

What's more, if using luxon or moment, when you add a days worth of minutes to 2014-11-02 you get 2014-11-03T00:00:00.000Z 更重要的是,如果使用luxon或moment,当您在2014-11-02添加一整天的分钟数时,您将获得2014-11-03T00:00:00.000Z

The Z at the end of that timestamp means it is in UTC, and UTC does not observe daylight savings time. 该时间戳记末尾的Z表示它位于UTC中,并且UTC不遵守夏令时。 So if you start with 2014-11-02T00:00:00.000Z , and add 24 hours, you get 2014-11-03T00:00:00.000Z . 因此,如果您从2014-11-02T00:00:00.000Z ,并加上24小时,您将获得2014-11-03T00:00:00.000Z When you add hours/minutes/seconds, there's no need to worry about daylight saving time. 当您增加小时/分钟/秒时,则无需担心夏令时。

but if you just directly add a day to 2014-11-02 you get 2014-11-03T01:00:00.000Z - it's an hour off. 但是,如果您直接在2014-11-02添加一天,则会获得2014-11-03T01:00:00.000Z这是一个小时的休假。

In this case what is happening is you are starting with 2014-11-02T00:00:00.000Z , but when you tell the library to add one day, and you don't specify a time zone, the library is assuming you are in your local time zone, so it adds one local day. 在这种情况下,发生的事情是您从2014-11-02T00:00:00.000Z ,但是当您告诉图书馆增加一天,而您未指定时区时,图书馆就会假设您位于您当地的时区,因此会增加一个本地日期。 Because you cross a DST boundary, that day is 25 hours long, and when you print it as an ISO timestamp in UTC, you end up with 2014-11-03T01:00:00.000Z (25 hours later). 因为您越过DST边界,所以这一天长达25小时,而当您将其打印为UTC中的ISO时间戳时,您将得到2014-11-03T01:00:00.000Z (25小时后)。

Time zone stuff is hard, even if you are using a library. 即使使用库,时区内容也很难。 Most people can get by for a long time not knowing or caring that for many users one day a year is 25 hours long. 大多数人可以在很长一段时间内不了解或关心许多用户一年一天的时间长达25小时。 But if these edge cases will matter to you, the best approach is to play around with them like you're doing, and make sure you really understand what is happening and why. 但是,如果这些极端情况对您来说很重要,那么最好的方法就是像您所做的那样与它们一起玩耍,并确保您真正了解正在发生的事情以及原因。

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

相关问题 JavaScript使用Moment.js检查所选日期是今天的日期,时间是2pm - JavaScript to check selected date is today's date and time is 2pm using Moment.js 如何开始我的JS倒数2pm到2pm? - How to start my JS countdown 2pm to 2pm? 使用moment.js计算直到下午2点出现的时间 - Calculate time until the next occurance of 2pm using moment.js 如何从特定时间(例如从上午 9 点到下午)以分钟为单位开始时间 - how to start time in minutes from specific time such as from 9 AM to PM 我需要验证时间的格式AM | PM - I need to validate the format of time AM|PM 什么是在javascript中将上午/下午时间转换为24小时时间的简单方法 - What's a simple way to convert between an am/pm time to 24 hour time in javascript 将“ am”或“ pm”添加到取决于时间的特定时间格式-Javascript - Add “am” or “pm” to Specific Time Format Dependent on Time of Day - Javascript 仅在下午1点至下午2点之间在网站背景上播放音频 - Audio to play on background of website only if it is between 1pm and 2pm 如果用户的机器使用 12 小时制(上午/下午)或 24 小时制(军用时间),则使用 javascript 检测 - Detect with javascript if user's machine is using 12 hour clock (am/pm) or 24 clock (military time) 在月视图中削减活动的结束时间 - Cut event's end time in month view
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM