Momentjs Grabbing today's date and setting time causes it to fast-forward 24 hours

16,221

There's no need to calculate machineTZ, diffTZ or add any minutes. Just do this instead:

moment().zone(userTZ).startOf('day').hour(7).minute(0)

But do keep in mind that a value such as 420 is not a time zone, it's a time zone offset. It only tells you what the offset is for a particular point in time. Since you are applying it unilaterally, you may get incorrect results during daylight saving time.

Instead, you should try using the moment-timezone addon, and do something like this instead:

moment().tz("America/Los_Angeles").startOf('day').hour(7).minute(0)

See also the timezone tag wiki, in particular the sections titled "Time Zone != Offset" and "The IANA/Olson Time Zone Database".

Share:
16,221
Warner Onstine
Author by

Warner Onstine

Updated on July 29, 2022

Comments

  • Warner Onstine
    Warner Onstine over 1 year

    I'm trying to time out email messages based on user preferences. My morning calculations are working correctly but it's the evening emails that are never getting sent because dates aren't behaving as expected.

    First, here's the code I'm using to grab the time and perform adjustments based on user location, etc.

    var time = moment();
    var machineTZ = time.zone();
    var userTZ = 420;
    var diffTZ = userTZ - machineTZ;
    
    var oneHour = moment(time).add('minutes', 60);
    
    var morningRun = moment().startOf('day');
    morningRun.hour(7).minute(0);
    morningRun.add('minutes', diffTZ);
    
    var eveningRun = moment().startOf('day');
    eveningRun.hour(19).minute(30);
    eveningRun.add('minutes', diffTZ);
    

    I'm checking every hour to see if it's time to schedule another email to go out. Right now this is hard-coded, but when I begin to add user preferences they'll be able to select their local time they'd like things to go out at.

    I've been debugging my values to troubleshoot. Here's output from a job that ran early morning (from the server's perspective):

    lastRun:    2013-10-12T00:06:55.088Z (this one is being run at 1 am)
    morningRun: 2013-10-11T14:00:00.000Z
    eveningRun: 2013-10-12T02:30:00.000Z
    

    The run numbers are as I would expect them to be. In two hours time I want the evening email to go out (7:30pm my time = 2:30am the following day server-time).

    Looking again an hour later we see:

    lastRun:    2013-10-12T01:06:58.267Z (this one is at 2 am)
    morningRun: 2013-10-12T14:00:00.000Z
    eveningRun: 2013-10-13T02:30:00.000Z <---- what?
    

    All of a sudden my calculation for my evening has flipped over the date line, even though it's still 10/12 (not 10/13 yet). Because of this my check to see if I should schedule the email fails since it now thinks I need to send the email in 24 hours, not 30 minutes.

    Been battling with this weird inconsistency for a while, I thought I had figured out why it was doing it and adjusted my calculations using the time zone stuff above but that didn't do the trick :(. This certainly seems like some sort of weird bug as I would expect this to be happening:

    //Today is 10/12
    var eveningRun = moment().startOf('day'); //10/12/2013 - 00:00:00
    eveningRun.hour(19).minute(30); //10/12/2013 - 19:30
    eveningRun.add('minutes', diffTZ); //10/13/2013 - 2:30 am
    

    This works until at some point it decides that "today" is actually 10/13 and sets the evening run is to take place on 10/14 instead. Help is greatly appreciated, or if this is a bug would love to know what I can do to work around this issue until it's resolved.

  • Warner Onstine
    Warner Onstine over 10 years
    I just found the moment-timezone yesterday and was going to give that a shot after I had figured this issue out. Giving your suggestion a shot and will let you know if it works :).
  • Warner Onstine
    Warner Onstine over 10 years
    Finally got through! Thank you :).