Search code examples
node.jsmomentjstimezone-offsetrrule

How do I convert date into UTC format from rrule string using moment js and a timezone offset on a server running node.js?


On the browser I made a widget that generates an rrule string:

var rruleString = "FREQ=WEEKLY;WKST=SU;BYDAY=MO,WE,FR;BYHOUR=8;BYMINUTE=30;BYSECOND=0"

Also I get the timezone offset from the browser with this function:

//This is 300 for me    
var timezoneOffSet = (new Date()).getTimezoneOffset(); 

I send those to a server running node.js. On the server I want to use the rrule and the timezone offset to generate a list of dates in UTC format. Here's how I do it now:

var rruleOptions = RRule.parseString(rruleString);

rruleOptions.dtstart = new Date();
rruleOptions.until = new Date();
rruleOptions.until.setMonth(options.until.getMonth() + 4);

var rule = new RRule(rruleOptions);

var dates = rule.all();

//Convert the dates into moment.js objects
momentDates = dates.map(function(date){

    //This is where I think the problem is because I think moment is
    //using the server's timezone
    return moment(date).utcOffset(timezoneOffSet*-1);      
});

//Convert the moment object array into an array of strings
var dateStringArray = momentDates.map(function(date){
    //Doesn't work returns 2015-11-27T08:30:00.00Z
    //return date.toISOString(); 

    //Doesn't work returns 2015-11-27T08:30:00.00Z
    //return date.utc().toISOString(); 

    //This works returns 2015-11-27T03:30:00.00Z for one of the objects
    return date.format('YYYY-MM-DDThh:mm')+":00.00Z";  
});

It seems like I should be able to use the functions that didn't work to get the date in the UTC, but for some reason they don't work. I think I am missing something on how to use moment the right way to do this. Can anyone see what I'm doing wrong?


Solution

  • I have this figured out now.

    When rrule generates the dates (from rule.all()) the dates are already in UTC mode (someone correct me if I'm wrong, but using the example above one of the dates I get from doing a console.log is Mon Dec 07 2015 08:30:00 GMT+0000 (UTC) which seems to indicate that it's in UTC time).

    So this:

    //Convert the dates into moment.js objects
    momentDates = dates.map(function(date){
    
        //This is where I think the problem is because I think moment is
        //using the server's timezone
        return moment(date).utcOffset(timezoneOffSet*-1);      
    });
    

    Turns into this:

    momentDates = dates.map(function(date){
        return moment(date).add(timezoneOffSet, 'minutes');      
    });
    

    Adding the offset gets the date in UTC time from the clients perspective not the servers. Also now I realize I was going the wrong way before; I was trying to subtract instead of adding the offset.

    So for the last bit:

    //Convert the moment object array into an array of strings
    var dateStringArray = momentDates.map(function(date){
        //Doesn't work returns 2015-11-27T08:30:00.00Z
        //return date.toISOString(); 
    
        //Doesn't work returns 2015-11-27T08:30:00.00Z
        //return date.utc().toISOString(); 
    
        //This works returns 2015-11-27T03:30:00.00Z for one of the objects
        return date.format('YYYY-MM-DDThh:mm')+":00.00Z";  
    });
    

    Can now turn into this:

    var dateStringArray = momentDates.map(function(date){
        return date.toISOString();   
    });
    

    Using the date above, that returns this string:

    2015-12-07T13:30:00.000Z
    

    Which is the correct UTC time!