Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

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.

like image 346
Warner Onstine Avatar asked Oct 12 '13 22:10

Warner Onstine


People also ask

How do I get the current time in MomentJS?

To get the current date and time, just call javascript moment() with no parameters like so: var now = moment();

How do you check if a date is valid in moment?

isValid() is the method available on moment which tells if the date is valid or not. MomentJS also provides many parsing flags which can be used to check for date validation.

How do you get moments from the day?

The moment(). day() method is used to get or set the day of week of the Moment object. The day of the week can have a value between 0 and 6, where 0 denotes Sunday and 6 denotes Saturday.

What is MomentJS?

Moment. js is a stand-alone open-source JavaScript framework wrapper for date objects that eliminates native JavaScript date objects, which are cumbersome to use. Moment. js makes dates and time easy to display, format, parse, validate, and manipulate using a clean and concise API.


1 Answers

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

like image 64
Matt Johnson-Pint Avatar answered Oct 19 '22 02:10

Matt Johnson-Pint