Skip to content Skip to sidebar Skip to footer

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.js doesn't actually provide the concept of an event duration or

Solution 1:

Now let's fast forward to any 6pm Tuesday in the future. Does my event always end on Wednesday at 2am (or does that 8 hour duration sometimes make my event end at 1am or 3am)? How do I get it to always end at 2am?

The standard Javascript Date object automatically handles the daylight savings shift for you. 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.

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.

This example can be seen on 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 = newSchedule({
  rrules: [
    {
      start: newDate(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).

Solution 2:

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'). 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). But as @RobG pointed out, formatting in this way causes it to be parsed as 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

The Z at the end of that timestamp means it is in UTC, and UTC does not observe daylight savings time. So if you start with 2014-11-02T00:00:00.000Z, and add 24 hours, you get 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.

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. 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).

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. 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.

Post a Comment for "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)"