Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to parse calendar file dates with JavaScript?

We need to use JavaScript on the browser to read and parse calendar files (.ics) (also called iCal formats). I wrote a custom function to read these values and then use the JavaScript Date() function to make a data object.

Is any easier and better way to do this? Please look at my function (below), your comments would be welcome.

A typical date value from an .ics file looks like this:

DTSTART:20110914T184000Z

Need to break it apart at the colon, so:

var strData = 'DTSTART:20110914T184000Z'
var x = strData.indexOf(":");
var strVal = strData.slice(x + 1 );

next, call a function that returns a date object:

var dateObj = calenDate(strVal);

//resulting dateObj value: Fri Oct 14 2011 18:40:00 GMT-0400 (Eastern Daylight Time)

Here is the function that parses the date.

function calenDate(icalStr)  {
    // icalStr = '20110914T184000Z'             
    var strYear = icalStr.substr(0,4);
    var strMonth = icalStr.substr(4,2);
    var strDay = icalStr.substr(6,2);
    var strHour = icalStr.substr(9,2);
    var strMin = icalStr.substr(11,2);
    var strSec = icalStr.substr(13,2);

    var oDate =  new Date(strYear,strMonth, strDay, strHour, strMin, strSec)

return oDate;
}

I think something is wrong since it is getting the month wrong.

like image 357
TGanoe Avatar asked Dec 28 '11 15:12

TGanoe


2 Answers

For some odd reason the month parameter is zero-based (reference).

Change this line in your function.

var strMonth = icalStr.substr(4,2);

to this:

var strMonth = parseInt(icalStr.substr(4,2),10)-1;

See working demo on jsFiddle: http://jsfiddle.net/cTkTQ/

like image 170
jessegavin Avatar answered Oct 18 '22 09:10

jessegavin


A somewhat more robust way of parsing the dates would be:

    var parser = XRegExp("^ (?<prefix> [^:;]+       )    # DTSTART/DTEND/DTSTAMP \n\
                            ((:|;TZID=(?<tz>[^:]+):))    # timezone \n\
                            (?<year>   [0-9]{4}     )    # year    \n\
                            (?<month>  [0-9]{2}     )    # month   \n\
                            (?<day>    [0-9]{2}     ) T  # day     \n\
                            (?<hour>   [0-9]{2}     )    # hour    \n\
                            (?<minute> [0-9]{2}     )    # minute  \n\
                            (?<second> [0-9]{2}     )    # second  \n\
                            (?<utc>     Z?          )    # utc", "x");

     parts = parser.exec (d);

     var od = new Date (parseInt (parts.year, 10),
                        parseInt (parts.month, 10) - 1,
                        parseInt (parts.day, 10),
                        parseInt (parts.hour, 10),
                        parseInt (parts.minute, 10),
                        parseInt (parts.second, 10));

This requires you to add an additional (tiny) dependency, XRegExp, which might be a bit overkill depending on your further needs, but it allows for a clean, easy to read regexp parsing of the date format in .ics files. This also takes into account the time zone identifier, if the date is not UTC. I leave it to you to add proper handling of time zones as well as the use of the prefix part.

The short answer (as noted by jessegavin) however, is that the month-parameter of the constructor expects a number between 0-11 (refer Mozilla Developer Network for more information). However, parseInt() tries to parse leading zeros as radix 8 (octal), so you should make sure to add radix 10 too, that would be the second parameter to parseInt(string [, radix]).

like image 21
zrvan Avatar answered Oct 18 '22 10:10

zrvan