Fix bug 469477 - Move fromRFC3339 from calGoogleUtils.js to calProviderUtils.jsm. r=philipp

This commit is contained in:
Patrick Cloke 2009-01-18 18:23:51 +01:00
Родитель 49c344cd06
Коммит 3bc0de1c97
4 изменённых файлов: 171 добавлений и 164 удалений

Просмотреть файл

@ -39,6 +39,7 @@
Components.utils.import("resource://calendar/modules/calUtils.jsm");
Components.utils.import("resource://calendar/modules/calAuthUtils.jsm");
Components.utils.import("resource://calendar/modules/calProviderUtils.jsm");
/*
* Provider helper code
@ -280,6 +281,140 @@ cal.getEmailIdentityOfCalendar = function calGetEmailIdentityOfCalendar(aCalenda
}
};
/**
* fromRFC3339
* Convert a RFC3339 compliant Date string to a calIDateTime.
*
* @param aStr The RFC3339 compliant Date String
* @param aTimezone The timezone this date string is most likely in
* @return A calIDateTime object
*/
cal.fromRFC3339 = function fromRFC3339(aStr, aTimezone) {
// XXX I have not covered leapseconds (matches[8]), this might need to
// be done. The only reference to leap seconds I found is bug 227329.
//
// Create a DateTime instance (calUtils.js)
let dateTime = cal.createDateTime();
// Killer regex to parse RFC3339 dates
var re = new RegExp("^([0-9]{4})-([0-9]{2})-([0-9]{2})" +
"([Tt]([0-9]{2}):([0-9]{2}):([0-9]{2})(\\.[0-9]+)?)?" +
"(([Zz]|([+-])([0-9]{2}):([0-9]{2})))?");
var matches = re.exec(aStr);
if (!matches) {
return null;
}
// Set usual date components
dateTime.isDate = (matches[4]==null);
dateTime.year = matches[1];
dateTime.month = matches[2] - 1; // Jan is 0
dateTime.day = matches[3];
if (!dateTime.isDate) {
dateTime.hour = matches[5];
dateTime.minute = matches[6];
dateTime.second = matches[7];
}
// Timezone handling
if (matches[9] == "Z") {
// If the dates timezone is "Z", then this is UTC, no matter
// what timezone was passed
dateTime.timezone = UTC();
} else if (matches[9] == null) {
// We have no timezone info, only a date. We have no way to
// know what timezone we are in, so lets assume we are in the
// timezone of our local calendar, or whatever was passed.
dateTime.timezone = aTimezone;
} else {
var offset_in_s = (matches[11] == "-" ? -1 : 1) *
( (matches[12] * 3600) + (matches[13] * 60) );
// try local timezone first
dateTime.timezone = aTimezone;
// If offset does not match, go through timezones. This will
// give you the first tz in the alphabet and kill daylight
// savings time, but we have no other choice
if (dateTime.timezoneOffset != offset_in_s) {
// TODO A patch to Bug 363191 should make this more efficient.
var tzService = getTimezoneService();
// Enumerate timezones, set them, check their offset
var enumerator = tzService.timezoneIds;
while (enumerator.hasMore()) {
var id = enumerator.getNext();
dateTime.timezone = tzService.getTimezone(id);
if (dateTime.timezoneOffset == offset_in_s) {
// This is our last step, so go ahead and return
return dateTime;
}
}
// We are still here: no timezone was found
dateTime.timezone = UTC();
if (!dateTime.isDate) {
dateTime.hour += (matches[11] == "-" ? -1 : 1) * matches[12];
dateTime.minute += (matches[11] == "-" ? -1 : 1) * matches[13];
}
}
}
return dateTime;
};
/**
* toRFC3339
* Convert a calIDateTime to a RFC3339 compliant Date string
*
* @param aDateTime The calIDateTime object
* @return The RFC3339 compliant date string
*/
cal.toRFC3339 = function toRFC3339(aDateTime) {
if (!aDateTime) {
return "";
}
var full_tzoffset = aDateTime.timezoneOffset;
var tzoffset_hr = Math.floor(Math.abs(full_tzoffset) / 3600);
var tzoffset_mn = ((Math.abs(full_tzoffset) / 3600).toFixed(2) -
tzoffset_hr) * 60;
var str = aDateTime.year + "-" +
("00" + (aDateTime.month + 1)).substr(-2) + "-" +
("00" + aDateTime.day).substr(-2);
// Time and Timezone extension
if (!aDateTime.isDate) {
str += "T" +
("00" + aDateTime.hour).substr(-2) + ":" +
("00" + aDateTime.minute).substr(-2) + ":" +
("00" + aDateTime.second).substr(-2);
if (aDateTime.timezoneOffset != 0) {
str += (full_tzoffset < 0 ? "-" : "+") +
("00" + tzoffset_hr).substr(-2) + ":" +
("00" + tzoffset_mn).substr(-2);
} else if (aDateTime.timezone.isFloating) {
// RFC3339 Section 4.3 Unknown Local Offset Convention
str += "-00:00";
} else {
// ZULU Time, according to ISO8601's timezone-offset
str += "Z";
}
}
return str;
};
/**
* Base prototype to be used implementing a provider.
*

Просмотреть файл

@ -36,6 +36,8 @@
*
* ***** END LICENSE BLOCK ***** */
Components.utils.import("resource://calendar/modules/calProviderUtils.jsm");
/**
* calGoogleCalendar
* This Implements a calICalendar Object adapted to the Google Calendar
@ -586,8 +588,8 @@ calGoogleCalendar.prototype = {
aRangeEnd.isDate = false;
}
var rfcRangeStart = toRFC3339(aRangeStart);
var rfcRangeEnd = toRFC3339(aRangeEnd);
var rfcRangeStart = cal.toRFC3339(aRangeStart);
var rfcRangeEnd = cal.toRFC3339(aRangeEnd);
var request = new calGoogleRequest(this);
@ -898,10 +900,10 @@ calGoogleCalendar.prototype = {
var status = oid.parent().gd::eventStatus.@value.toString().substring(39);
if (status == "canceled") {
var rId = oid.gd::when.@startTime.toString();
LOG("Negative exception " + rId + "/" + fromRFC3339(rId, timezone));
rId = (rId.length > 0 ? fromRFC3339(rId, timezone) : null);
item.recurrenceInfo.removeOccurrenceAt(rId);
let rId = oid.gd::when.@startTime.toString();
let rDate = cal.fromRFC3339(rId, timezone));
LOG("Negative exception " + rId + "/" + rDate);
item.recurrenceInfo.removeOccurrenceAt(rDate);
} else {
// Parse the exception and modify the current item
var excItem = XMLEntryToItem(oid.parent(),
@ -1078,7 +1080,7 @@ calGoogleCalendar.prototype = {
if (lastUpdateDateTime) {
// Partial sync requires sending updated-min
request.addQueryParameter("updated-min", toRFC3339(lastUpdateDateTime));
request.addQueryParameter("updated-min", cal.toRFC3339(lastUpdateDateTime));
}
// Request the item. The response function is ready to take care of both
@ -1168,9 +1170,10 @@ calGoogleCalendar.prototype = {
var status = oid.parent().gd::eventStatus.@value.toString().substring(39);
if (status == "canceled") {
var rId = oid.gd::when.@startTime.toString();
rId = (rId.length > 0 ? fromRFC3339(rId, timezone) : null);
item.recurrenceInfo.removeOccurrenceAt(rId);
let rId = oid.gd::when.@startTime.toString();
let rDate = cal.fromRFC3339(rId, timezone));
item.recurrenceInfo.removeOccurrenceAt(rDate);
LOG("Negative exception " + rId + "/" + rDate);
} else {
// Parse the exception and modify the current item
var excItem = XMLEntryToItem(oid.parent(),

Просмотреть файл

@ -34,6 +34,8 @@
*
* ***** END LICENSE BLOCK ***** */
Components.utils.import("resource://calendar/modules/calProviderUtils.jsm");
// This constant is an arbitrary large number. It is used to tell google to get
// many events, the exact number is not important.
const kMANY_EVENTS = 0x7FFFFFFF;
@ -522,8 +524,8 @@ calGoogleSession.prototype = {
aRangeEnd.isDate = false;
}
var rfcRangeStart = toRFC3339(aRangeStart);
var rfcRangeEnd = toRFC3339(aRangeEnd);
var rfcRangeStart = cal.toRFC3339(aRangeStart);
var rfcRangeEnd = cal.toRFC3339(aRangeEnd);
var request = new calGoogleRequest(this);
@ -590,8 +592,8 @@ calGoogleSession.prototype = {
var intervals = [];
const fbtypes = Components.interfaces.calIFreeBusyInterval;
for each (var entry in xml.entry) {
let start = fromRFC3339(entry.gd::when.@startTime.toString(), timezone);
let end = fromRFC3339(entry.gd::when.@endTime.toString(), timezone);
let start = cal.fromRFC3339(entry.gd::when.@startTime.toString(), timezone);
let end = cal.fromRFC3339(entry.gd::when.@endTime.toString(), timezone);
let interval = new cal.FreeBusyInterval(aCalId, fbtypes.BUSY, start, end);
LOGinterval(interval);
intervals.push(interval);

Просмотреть файл

@ -183,139 +183,6 @@ var gdataTimezoneService = {
}
};
/**
* fromRFC3339
* Convert a RFC3339 compliant Date string to a calIDateTime.
*
* @param aStr The RFC3339 compliant Date String
* @param aTimezone The timezone this date string is most likely in
* @return A calIDateTime object
*/
function fromRFC3339(aStr, aTimezone) {
// XXX I have not covered leapseconds (matches[8]), this might need to
// be done. The only reference to leap seconds I found is bug 227329.
//
// Create a DateTime instance (calUtils.js)
let dateTime = cal.createDateTime();
// Killer regex to parse RFC3339 dates
var re = new RegExp("^([0-9]{4})-([0-9]{2})-([0-9]{2})" +
"([Tt]([0-9]{2}):([0-9]{2}):([0-9]{2})(\\.[0-9]+)?)?" +
"(([Zz]|([+-])([0-9]{2}):([0-9]{2})))?");
var matches = re.exec(aStr);
if (!matches) {
return null;
}
// Set usual date components
dateTime.isDate = (matches[4]==null);
dateTime.year = matches[1];
dateTime.month = matches[2] - 1; // Jan is 0
dateTime.day = matches[3];
if (!dateTime.isDate) {
dateTime.hour = matches[5];
dateTime.minute = matches[6];
dateTime.second = matches[7];
}
// Timezone handling
if (matches[9] == "Z") {
// If the dates timezone is "Z", then this is UTC, no matter
// what timezone was passed
dateTime.timezone = UTC();
} else if (matches[9] == null) {
// We have no timezone info, only a date. We have no way to
// know what timezone we are in, so lets assume we are in the
// timezone of our local calendar, or whatever was passed.
dateTime.timezone = aTimezone;
} else {
var offset_in_s = (matches[11] == "-" ? -1 : 1) *
( (matches[12] * 3600) + (matches[13] * 60) );
// try local timezone first
dateTime.timezone = aTimezone;
// If offset does not match, go through timezones. This will
// give you the first tz in the alphabet and kill daylight
// savings time, but we have no other choice
if (dateTime.timezoneOffset != offset_in_s) {
// TODO A patch to Bug 363191 should make this more efficient.
var tzService = getTimezoneService();
// Enumerate timezones, set them, check their offset
var enumerator = tzService.timezoneIds;
while (enumerator.hasMore()) {
var id = enumerator.getNext();
dateTime.timezone = tzService.getTimezone(id);
if (dateTime.timezoneOffset == offset_in_s) {
// This is our last step, so go ahead and return
return dateTime;
}
}
// We are still here: no timezone was found
dateTime.timezone = UTC();
if (!dateTime.isDate) {
dateTime.hour += (matches[11] == "-" ? -1 : 1) * matches[12];
dateTime.minute += (matches[11] == "-" ? -1 : 1) * matches[13];
}
}
}
return dateTime;
}
/**
* toRFC3339
* Convert a calIDateTime to a RFC3339 compliant Date string
*
* @param aDateTime The calIDateTime object
* @return The RFC3339 compliant date string
*/
function toRFC3339(aDateTime) {
if (!aDateTime) {
return "";
}
var full_tzoffset = aDateTime.timezoneOffset;
var tzoffset_hr = Math.floor(Math.abs(full_tzoffset) / 3600);
var tzoffset_mn = ((Math.abs(full_tzoffset) / 3600).toFixed(2) -
tzoffset_hr) * 60;
var str = aDateTime.year + "-" +
("00" + (aDateTime.month + 1)).substr(-2) + "-" +
("00" + aDateTime.day).substr(-2);
// Time and Timezone extension
if (!aDateTime.isDate) {
str += "T" +
("00" + aDateTime.hour).substr(-2) + ":" +
("00" + aDateTime.minute).substr(-2) + ":" +
("00" + aDateTime.second).substr(-2);
if (aDateTime.timezoneOffset != 0) {
str += (full_tzoffset < 0 ? "-" : "+") +
("00" + tzoffset_hr).substr(-2) + ":" +
("00" + tzoffset_mn).substr(-2);
} else if (aDateTime.timezone.isFloating) {
// RFC3339 Section 4.3 Unknown Local Offset Convention
str += "-00:00";
} else {
// ZULU Time, according to ISO8601's timezone-offset
str += "Z";
}
}
return str;
}
/**
* passwordManagerSave
* Helper to insert an entry to the password manager.
@ -494,8 +361,8 @@ function ItemToXMLEntry(aItem, aAuthorEmail, aAuthorName) {
// gd:when
var duration = aItem.endDate.subtractDate(aItem.startDate);
entry.gd::when.@startTime = toRFC3339(aItem.startDate);
entry.gd::when.@endTime = toRFC3339(aItem.endDate);
entry.gd::when.@startTime = cal.toRFC3339(aItem.startDate);
entry.gd::when.@endTime = cal.toRFC3339(aItem.endDate);
// gd:reminder
let alarms = aItem.getAlarms({});
@ -511,7 +378,7 @@ function ItemToXMLEntry(aItem, aAuthorEmail, aAuthorName) {
if (alarm.related == alarm.ALARM_RELATED_ABSOLUTE) {
// Setting an absolute date can be done directly. Google will take
// care of calculating the offset.
gdReminder.@absoluteTime = toRFC3339(alarm.alarmDate);
gdReminder.@absoluteTime = cal.toRFC3339(alarm.alarmDate);
} else {
let alarmOffset = alarm.offset;
if (alarm.related == alarm.ALARM_RELATED_END) {
@ -540,7 +407,7 @@ function ItemToXMLEntry(aItem, aAuthorEmail, aAuthorName) {
}
// gd:extendedProperty (alarmLastAck)
addExtendedProperty("X-MOZ-LASTACK", toRFC3339(aItem.alarmLastAck));
addExtendedProperty("X-MOZ-LASTACK", cal.toRFC3339(aItem.alarmLastAck));
// XXX While Google now supports multiple alarms and alarm values, we still
// need to fix bug 353492 first so we can better take care of finding out
@ -554,7 +421,7 @@ function ItemToXMLEntry(aItem, aAuthorEmail, aAuthorName) {
icalSnoozeTime = cal.createDateTime();
icalSnoozeTime.icalString = itemSnoozeTime;
}
addExtendedProperty("X-MOZ-SNOOZE-TIME", toRFC3339(icalSnoozeTime));
addExtendedProperty("X-MOZ-SNOOZE-TIME", cal.toRFC3339(icalSnoozeTime));
// gd:extendedProperty (snooze recurring alarms)
var snoozeValue = "";
@ -626,7 +493,7 @@ function ItemToXMLEntry(aItem, aAuthorEmail, aAuthorName) {
if (aItem.recurrenceId) {
entry.gd::originalEvent.@id = aItem.parentItem.id;
entry.gd::originalEvent.gd::when.@startTime =
toRFC3339(aItem.recurrenceId.getInTimezone(UTC()));
cal.toRFC3339(aItem.recurrenceId.getInTimezone(UTC()));
}
// While it may sometimes not work out, we can always try to set the uid and
@ -799,7 +666,7 @@ function getRecurrenceIdFromEntry(aXMLEntry, aTimezone) {
var gd = new Namespace("gd", "http://schemas.google.com/g/2005");
if (aXMLEntry.gd::originalEvent.toString().length > 0) {
var rId = aXMLEntry.gd::originalEvent.gd::when.@startTime;
return fromRFC3339(rId.toString(), aTimezone);
return cal.fromRFC3339(rId.toString(), aTimezone);
}
return null;
}
@ -897,8 +764,8 @@ function XMLEntryToItem(aXMLEntry, aTimezone, aCalendar, aReferenceItem) {
alarm.action = actionMap[reminderTag.@method] || "DISPLAY";
if (reminderTag.@absoluteTime.toString()) {
alarm.related = Components.interfaces.calIAlarm.ALARM_RELATED_ABSOLUTE;
let absolute = fromRFC3339(reminderTag.@absoluteTime,
aTimezone);
let absolute = cal.fromRFC3339(reminderTag.@absoluteTime,
aTimezone);
alarm.alarmDate = absolute;
} else {
alarm.related = Components.interfaces.calIAlarm.ALARM_RELATED_START;
@ -927,8 +794,8 @@ function XMLEntryToItem(aXMLEntry, aTimezone, aCalendar, aReferenceItem) {
// one gd:when tag. Otherwise, we will be parsing the startDate from
// the recurrence information.
var when = aXMLEntry.gd::when;
item.startDate = fromRFC3339(when.@startTime, aTimezone);
item.endDate = fromRFC3339(when.@endTime, aTimezone);
item.startDate = cal.fromRFC3339(when.@startTime, aTimezone);
item.endDate = cal.fromRFC3339(when.@endTime, aTimezone);
if (!item.endDate) {
// We have a zero-duration event
@ -1026,12 +893,12 @@ function XMLEntryToItem(aXMLEntry, aTimezone, aCalendar, aReferenceItem) {
var alarmLastAck = aXMLEntry.gd::extendedProperty
.(@name == "X-MOZ-LASTACK")
.@value.toString();
item.alarmLastAck = fromRFC3339(alarmLastAck, aTimezone);
item.alarmLastAck = cal.fromRFC3339(alarmLastAck, aTimezone);
// gd:extendedProperty (snooze time)
var xmlSnoozeTime = aXMLEntry.gd::extendedProperty
.(@name == "X-MOZ-SNOOZE-TIME").@value.toString();
var dtSnoozeTime = fromRFC3339(xmlSnoozeTime, aTimezone);
var dtSnoozeTime = cal.fromRFC3339(xmlSnoozeTime, aTimezone);
var snoozeProperty = (dtSnoozeTime ? dtSnoozeTime.icalString : null);
item.setProperty("X-MOZ-SNOOZE-TIME", snoozeProperty);
@ -1122,12 +989,12 @@ function XMLEntryToItem(aXMLEntry, aTimezone, aCalendar, aReferenceItem) {
item.setCategories(categories.length, categories);
// published
item.setProperty("CREATED", fromRFC3339(aXMLEntry.published,
aTimezone));
item.setProperty("CREATED", cal.fromRFC3339(aXMLEntry.published,
aTimezone));
// updated (This must be set last!)
item.setProperty("LAST-MODIFIED", fromRFC3339(aXMLEntry.updated,
aTimezone));
item.setProperty("LAST-MODIFIED", cal.fromRFC3339(aXMLEntry.updated,
aTimezone));
// TODO gd:comments: Enhancement tracked in bug 362653