diff --git a/.gitignore b/.gitignore index 3c3629e..eb79dd5 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,2 @@ node_modules +.idea diff --git a/ical.js b/ical.js index 54146de..51de6b1 100755 --- a/ical.js +++ b/ical.js @@ -1,3 +1,5 @@ +var UUID = require('node-uuid'); + (function(name, definition) { /**************** @@ -51,71 +53,110 @@ return curr } - } + }; - var addTZ = function(dt, name, params){ + var addTZ = function(dateObj, params){ var p = parseParams(params); - if (params && p){ - dt[name].tz = p.TZID + if (params && p && dateObj){ + dateObj.tz = p.TZID } - return dt - } - - - var dateParam = function(name){ - return function(val, params, curr){ + return dateObj; + }; - // Store as string - worst case scenario - storeParam(name)(val, undefined, curr) + /** + * Convert a date string from ICS format into a native Date object + * @param {string} val - The ICS string to be parsed + * @param {array} params + * @param {object} curr - The current Object that we're building + * @return {object} The Javascript date object + */ + function parseDate(val, params, curr) { + var objToReturn = val; - if (params && params[0] === "VALUE=DATE") { - // Just Date + if (params && params[0] === "VALUE=DATE") { + // Just Date - var comps = /^(\d{4})(\d{2})(\d{2})$/.exec(val); - if (comps !== null) { - // No TZ info - assume same timezone as this computer - curr[name] = new Date( - comps[1], + var comps = /^(\d{4})(\d{2})(\d{2})$/.exec(val); + if (comps !== null) { + // No TZ info - assume same timezone as this computer + objToReturn = new Date( + comps[1], parseInt(comps[2], 10)-1, - comps[3] - ); + comps[3] + ); - return addTZ(curr, name, params); - } + return addTZ(objToReturn, params); } + } - //typical RFC date-time format - var comps = /^(\d{4})(\d{2})(\d{2})T(\d{2})(\d{2})(\d{2})(Z)?$/.exec(val); - if (comps !== null) { - if (comps[7] == 'Z'){ // GMT - curr[name] = new Date(Date.UTC( - parseInt(comps[1], 10), + //typical RFC date-time format + var comps = /^(\d{4})(\d{2})(\d{2})T(\d{2})(\d{2})(\d{2})(Z)?$/.exec(val); + if (comps !== null) { + if (comps[7] == 'Z'){ // GMT + return new Date(Date.UTC( + parseInt(comps[1], 10), parseInt(comps[2], 10)-1, - parseInt(comps[3], 10), - parseInt(comps[4], 10), - parseInt(comps[5], 10), - parseInt(comps[6], 10 ) - )); - // TODO add tz - } else { - curr[name] = new Date( - parseInt(comps[1], 10), + parseInt(comps[3], 10), + parseInt(comps[4], 10), + parseInt(comps[5], 10), + parseInt(comps[6], 10 ) + )); + // TODO add tz + } else { + return new Date( + parseInt(comps[1], 10), parseInt(comps[2], 10)-1, - parseInt(comps[3], 10), - parseInt(comps[4], 10), - parseInt(comps[5], 10), - parseInt(comps[6], 10) - ); - } + parseInt(comps[3], 10), + parseInt(comps[4], 10), + parseInt(comps[5], 10), + parseInt(comps[6], 10) + ); } + } - return addTZ(curr, name, params) + // date format (no time) + comps = /^(\d{4})(\d{2})(\d{2})$/.exec(val); + if (comps !== null) { + // No TZ info - assume same timezone as this computer + objToReturn = new Date( + comps[1], + parseInt(comps[2], 10)-1, + comps[3] + ); + + return addTZ(objToReturn, params); } } + var dateParam = function(name){ + return function(val, params, curr){ + var dateObj = parseDate(val, params, curr); + dateObj = addTZ(dateObj, params); + if (dateObj) { + curr[name] = dateObj; + } else { + // Store as string - worst case scenario + storeParam(name)(val, undefined, curr); + } + return curr; + } + }; + + var dateParamArray = function(name) { + return function(date, params, curr) { + // initialize + curr[name] = curr[name] || []; + // load date + var dateObj = parseDate(date, params, curr); + dateObj = addTZ(dateObj, params); + curr[name].push(dateObj); + return curr; + } + + }; var geoParam = function(name){ return function(val, params, curr){ @@ -193,11 +234,7 @@ } var par = stack.pop() - - if (curr.uid) - par[curr.uid] = curr - else - par[Math.random()*100000] = curr // Randomly assign ID : TODO - use true GUID + par[UUID.v4()] = curr; return par } @@ -216,6 +253,8 @@ , 'COMPLETED': dateParam('completed') , 'CATEGORIES': categoriesParam('categories') , 'FREEBUSY': freebusyParam('freebusy') + , 'EXDATE': dateParamArray('exdate') + , 'RECURRENCE-ID': storeParam('recurrenceId') }, diff --git a/package.json b/package.json index 285d215..9b25838 100644 --- a/package.json +++ b/package.json @@ -15,8 +15,9 @@ "url": "git://github.com/peterbraden/ical.js.git" }, "dependencies": { - "request": "2.40.0", - "rrule": "2.0.0" + "node-uuid": "^1.4.1", + "rrule": "2.1.0", + "request": "2.40.0" }, "devDependencies": { "vows": "0.7.0", diff --git a/test/test.js b/test/test.js index e7b5221..733c56d 100755 --- a/test/test.js +++ b/test/test.js @@ -72,7 +72,7 @@ vows.describe('node-ical').addBatch({ } , 'todo item uid4@host1.com' : { topic : function(items){ - return items['uid4@host1.com'] + return _.filter(items,function(obj) { { return obj.uid == 'uid4@host1.com'; } })[0]; } , 'is a VTODO' : function(topic){ assert.equal(topic.type, 'VTODO')