Commit cdb5fd21 authored by Sebastian's avatar Sebastian
Browse files

Merge pull request #33 from takkaria/timezone-fixes

Timezone fixes
parents b76ed63e c89a71d0
......@@ -271,7 +271,7 @@ Empty the Calender.
#### uid([_String_|_Number_ uid]) or id([_String_|_Number_ id])
Use this method to set the event's ID. If not set, an UID will be generated randomly.
Use this method to set the event's ID. If not set, an UID will be generated randomly. When output, the ID will be suffixed with '@' + your calendar's domain.
#### start([_Date_ start])
......@@ -284,6 +284,13 @@ Appointment date of beginning as Date object. This is required for all events!
Appointment date of end as Date object.
#### timezone([_String_ timezone])
Use this method to set your event's timezone using the TZID property parameter on start and end dates, as per [date-time form #3 in section 3.3.5 of RFC 554](https://tools.ietf.org/html/rfc5545#section-3.3.5).
This and the 'floating' flag (see below) are mutually exclusive, and setting a timezone will unset the 'floating' flag. If neither 'timezone' nor 'floating' are set, the date will be output with in UTC format (see [date-time form #2 in section 3.3.5 of RFC 554](https://tools.ietf.org/html/rfc5545#section-3.3.5)).
#### timestamp([_Date_ stamp]) or stamp([_Date_ stamp])
Appointment date of creation as Date object. Default to `new Date()`.
......@@ -295,6 +302,7 @@ When allDay == true -> appointment is for the whole day
#### floating([_Boolean_ floating])
Appointment is a "floating" time. From [section 3.3.12 of RFC 554](https://tools.ietf.org/html/rfc5545#section-3.3.12):
> Time values of this type are said to be "floating" and are not
......@@ -305,8 +313,11 @@ Appointment is a "floating" time. From [section 3.3.12 of RFC 554](https://tools
> AM to 1:00 PM every day, no matter which time zone the person is
> in. In these cases, a local time can be specified.
This and the 'timezone' setting (see above) are mutually exclusive, and setting the floating flag will unset the 'timezone'. If neither 'timezone' nor 'floating' are set, the date will be output with in UTC format (see [date-time form #2 in section 3.3.5 of RFC 554](https://tools.ietf.org/html/rfc5545#section-3.3.5)).
#### repeating([_Object_ repeating])
Appointment is a repeating event
```javascript
......
......@@ -27,6 +27,23 @@ module.exports.formatDate = function formatDate(d, dateonly, floating) {
return s;
};
// For information about this format, see RFC 5545, section 3.3.5
// https://tools.ietf.org/html/rfc5545#section-3.3.5
module.exports.formatDateTZ = function formatDateTZ(property, date, eventData) {
var tzParam = '';
var floating = eventData.floating;
if(eventData.timezone) {
tzParam = ';TZID=' + eventData.timezone;
// This isn't a 'floating' event because it has a timezone;
// but we use it to omit the 'Z' UTC specifier in formatDate()
floating = true;
}
return property + tzParam + ':' + module.exports.formatDate(date, false, floating);
};
module.exports.escape = function escape(str) {
return str.replace(/[\\;,"]/g, function(match) {
return '\\' + match;
......
......@@ -123,10 +123,10 @@ var ICalCalendar = function(_data) {
* string like "//sebbo.net//ical-generator//EN" or an
* object like
* {
* "company": "sebbo.net",
* "product": "ical-generator"
* "language": "EN"
* }
* "company": "sebbo.net",
* "product": "ical-generator"
* "language": "EN"
* }
*
* `language` is optional and defaults to `EN`.
*
......@@ -285,11 +285,6 @@ var ICalCalendar = function(_data) {
throw 'event.start is a mandatory item!';
}
// validation: end
if(!event.end) {
throw 'event.end is a mandatory item!';
}
// validation: summary
if(!event.summary) {
throw 'event.summary is a mandatory item!';
......
......@@ -7,7 +7,7 @@
* @constructor ICalEvent Event
*/
var ICalEvent = function(_data) {
var attributes = ['id', 'uid', 'start', 'end', 'stamp', 'timestamp', 'allDay', 'floating', 'repeating', 'summary', 'location', 'description', 'organizer', 'attendees', 'alarms', 'method', 'status', 'url'],
var attributes = ['id', 'uid', 'start', 'end', 'timezone', 'stamp', 'timestamp', 'allDay', 'floating', 'repeating', 'summary', 'location', 'description', 'organizer', 'attendees', 'alarms', 'method', 'status', 'url'],
vars,
i,
data;
......@@ -22,6 +22,7 @@ var ICalEvent = function(_data) {
id: ('0000' + (Math.random() * Math.pow(36, 4) << 0).toString(36)).substr(-4),
start: null,
end: null,
timezone: null,
stamp: new Date(),
allDay: false,
floating: false,
......@@ -124,6 +125,26 @@ var ICalEvent = function(_data) {
};
/**
* Set/Get the event's timezone. This unsets the event's floating flag.
* Used on date properties
*
* @param [timezone] Timezone
* @example event.timezone('America/New_York');
* @since 0.2.6
* @returns {ICalEvent|String}
*/
this.timezone = function(timezone) {
if(!timezone) {
return data.timezone;
}
data.timezone = timezone.toString();
data.floating = false;
return this;
};
/**
* Set/Get the event's timestamp
*
......@@ -176,7 +197,7 @@ var ICalEvent = function(_data) {
/**
* Set/Get the event's floating flag
* Set/Get the event's floating flag. This unsets the event's timezone.
* See https://tools.ietf.org/html/rfc5545#section-3.3.12
*
* @param {Boolean} floating
......@@ -189,6 +210,7 @@ var ICalEvent = function(_data) {
}
data.floating = !!floating;
data.timezone = null;
return this;
};
......@@ -573,9 +595,9 @@ var ICalEvent = function(_data) {
g += 'DTEND;VALUE=DATE:' + tools.formatDate(data.end, true) + '\r\n';
}
} else {
g += 'DTSTART:' + tools.formatDate(data.start, false, data.floating) + '\r\n';
g += tools.formatDateTZ('DTSTART', data.start, data) + '\r\n';
if (data.end) {
g += 'DTEND:' + tools.formatDate(data.end, false, data.floating) + '\r\n';
g += tools.formatDateTZ('DTEND', data.end, data) + '\r\n';
}
}
......
......@@ -185,17 +185,6 @@ describe('ical-generator 0.1.x', function() {
}, /event\.start must be a Date Object/);
});
it('should throw error when no end time given', function() {
var generator = require(__dirname + '/../lib/index.js'),
cal = generator();
assert.throws(function() {
cal.addEvent({
start: new Date()
});
}, /event\.end is a mandatory item/);
});
it('should throw error when end time is not a date', function() {
var generator = require(__dirname + '/../lib/index.js'),
cal = generator();
......
......@@ -147,7 +147,7 @@ describe('ical-generator 0.2.x / ICalCalendar', function() {
assert.equal(cal.timezone(), 'Europe/Berlin');
});
it('should change something', function() {
it('should make a difference to iCal output', function() {
var cal = ical().timezone('Europe/London');
cal.createEvent({
start: new Date(),
......@@ -156,6 +156,20 @@ describe('ical-generator 0.2.x / ICalCalendar', function() {
});
assert.ok(cal.toString().indexOf('Europe/London') > -1);
});
it('should mark event as not floating', function() {
var cal = ical().timezone('Europe/London'),
evt = cal.createEvent({
start: new Date(),
end: new Date(new Date().getTime() + 3600000),
summary: 'Example Event',
floating: true
});
evt.timezone('Europe/Berlin');
assert.equal(evt.floating(), false);
});
});
describe('ttl()', function() {
......@@ -216,6 +230,15 @@ describe('ical-generator 0.2.x / ICalCalendar', function() {
assert.equal(event.summary(), 'Patch-Day');
});
it('should not require optional parameters', function() {
assert.doesNotThrow(function () {
ical().addEvent({
start: new Date(),
summary: 'Patch-Day'
});
}, Error);
});
});
describe('events()', function() {
......@@ -467,6 +490,30 @@ describe('ical-generator 0.2.x / ICalCalendar', function() {
});
});
describe('timezone()', function() {
it('setter should return this', function() {
var e = ical().createEvent();
assert.deepEqual(e, e.timezone('Europe/Berlin'));
});
it('getter should return value', function() {
var e = ical().createEvent().timezone('Europe/Berlin');
assert.equal(e.timezone(), 'Europe/Berlin');
});
it('should change something', function() {
var cal = ical(),
e = cal.createEvent({
start: new Date(),
end: new Date(new Date().getTime() + 3600000),
summary: 'Example Event'
});
e.timezone('Europe/London');
assert.ok(cal.toString().indexOf('Europe/London') > -1);
});
});
describe('stamp()', function() {
it('setter should return this', function() {
var e = ical().createEvent();
......@@ -555,6 +602,20 @@ describe('ical-generator 0.2.x / ICalCalendar', function() {
event.floating(true);
assert.ok(str !== cal.toString());
});
it('should mark event as having no time zone', function() {
var cal = ical().timezone('Europe/London'),
evt = cal.createEvent({
start: new Date(),
end: new Date(new Date().getTime() + 3600000),
summary: 'Example Event',
timezone: 'Europe/Berlin'
});
evt.floating(true);
assert.equal(evt.timezone(), null);
});
});
describe('repeating()', function() {
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment