diff --git a/calendar/base/public/calIDateTime.idl b/calendar/base/public/calIDateTime.idl index 888a6ec8ef9..2ea918bf519 100644 --- a/calendar/base/public/calIDateTime.idl +++ b/calendar/base/public/calIDateTime.idl @@ -57,10 +57,9 @@ interface calIDateTime : nsISupports // true if this thing is set/valid readonly attribute boolean valid; - // this thing's base PRTime value, either - // as UTC or as local. Setting this - // will explode the PRTime value to - // year/etc. + // this thing's base PRTime value, either as UTC or as timezoneless- + // local. Setting this will explode the PRTime value to year/etc + // based on the current value of timezoneOffset. attribute PRTime nativeTime; // Year, fully exploded (e.g. "1989", "2004") @@ -85,7 +84,8 @@ interface calIDateTime : nsISupports // zone attribute PRBool isUtc; - // if true, this calIDateTime represents a date (whole day), not a specific second + // if true, this calIDateTime represents a date (whole day), not a + // specific second attribute PRBool isDate; // an associated timezone that's the preferred way of representing @@ -93,6 +93,9 @@ interface calIDateTime : nsISupports // timezone, and UTC or localtime is assumed (based on isUtc). attribute AUTF8String timezone; + // the offset in minutes from UTC that this date is stored in. + attribute PRInt32 timezoneOffset; + // // computed values // diff --git a/calendar/base/src/calDateTime.cpp b/calendar/base/src/calDateTime.cpp index 098240cd4a1..3e6825b10a4 100644 --- a/calendar/base/src/calDateTime.cpp +++ b/calendar/base/src/calDateTime.cpp @@ -64,6 +64,7 @@ calDateTime::calDateTime() mIsUtc = PR_FALSE; mWeekday = 0; mYearday = 0; + mTimezoneOffset = 0; } calDateTime::calDateTime(struct icaltimetype *atimeptr) @@ -214,6 +215,10 @@ calDateTime::SetTimeInTimezone(PRTime aTime, const char *aTimezone) struct icaltimetype icalt; time_t tt; + icaltimezone *zone = icaltimezone_get_builtin_timezone_from_tzid(aTimezone); + if (!zone) + return NS_ERROR_FAILURE; + PRInt64 temp, million; LL_I2L(million, PR_USEC_PER_SEC); LL_DIV(temp, aTime, million); @@ -221,10 +226,7 @@ calDateTime::SetTimeInTimezone(PRTime aTime, const char *aTimezone) LL_L2I(sectime, temp); tt = sectime; - icalt = icaltime_from_timet(tt, 0); - if (aTimezone && (strncmp(aTimezone, "UTC", 3) != 0)) - icalt = icaltime_as_utc(icalt, aTimezone); - + icalt = icaltime_from_timet_with_zone(tt, 0, zone); FromIcalTime(&icalt); return NS_OK; @@ -234,12 +236,23 @@ NS_IMETHODIMP calDateTime::GetInTimezone(const char *aTimezone, calIDateTime **aResult) { struct icaltimetype icalt; + icaltimezone *zone, *utc; + ToIcalTime(&icalt); - icalt = icaltime_as_zone(icalt, aTimezone); + utc = icaltimezone_get_utc_timezone(); + zone = icaltimezone_get_builtin_timezone_from_tzid(aTimezone); + if (!zone) + return NS_ERROR_FAILURE; + + icaltimezone_convert_time(&icalt, utc, zone); + calDateTime *cdt = new calDateTime(&icalt); - if (!cdt) - return NS_ERROR_OUT_OF_MEMORY; + if (zone != utc) { + int ignored; + cdt->mIsUtc = PR_FALSE; + cdt->mTimezoneOffset = icaltimezone_get_utc_offset (zone, &icalt, &ignored); + } NS_ADDREF (*aResult = cdt); return NS_OK; @@ -290,7 +303,7 @@ NS_IMETHODIMP_(void) calDateTime::ToIcalTime(icaltimetype *icalt) { icalt->year = mYear; - icalt->month = mMonth; + icalt->month = mMonth + 1; icalt->day = mDay; icalt->hour = mHour; icalt->minute = mMinute; @@ -298,13 +311,17 @@ calDateTime::ToIcalTime(icaltimetype *icalt) icalt->is_utc = mIsUtc ? 1 : 0; icalt->is_date = mIsDate ? 1 : 0; + + icalt->zone = NULL; } void calDateTime::FromIcalTime(icaltimetype *icalt) { + NS_ASSERTION(icalt->zone == NULL, "Got icaltimetype with a non-null zone!"); + mYear = icalt->year; - mMonth = icalt->month; + mMonth = icalt->month - 1; mDay = icalt->day; mHour = icalt->hour; mMinute = icalt->minute; @@ -313,6 +330,9 @@ calDateTime::FromIcalTime(icaltimetype *icalt) mIsUtc = icalt->is_utc ? PR_TRUE : PR_FALSE; mIsDate = icalt->is_date ? PR_TRUE : PR_FALSE; + mTimezoneOffset = 0; + mTimezone.Assign(""); + // reconstruct nativetime time_t tt = icaltime_as_timet(*icalt); PRInt64 temp, million; @@ -401,14 +421,21 @@ calDateTime::SetProperty(nsIXPConnectWrappedNative *wrapper, JSContext * cx, LL_I2L(thousands, 1000); LL_MUL(utcTime, utcTime, thousands); - mIsUtc = PR_FALSE; - mTimezone.AssignLiteral(""); + mIsUtc = PR_TRUE; - nsresult rv = SetNativeTime(utcTime); - if (NS_FAILED(rv)) { + jsval tzoffsetval; + if (!JS_CallFunctionName(cx, dobj, "getTimezoneOffset", 0, nsnull, &tzoffsetval)) { mValid = PR_FALSE; } else { - mValid = PR_TRUE; + JS_ValueToECMAInt32(cx, tzoffsetval, &mTimezoneOffset); + mTimezone.AssignLiteral(""); + nsresult rv = SetNativeTime(utcTime); + + if (NS_FAILED(rv)) { + mValid = PR_FALSE; + } else { + mValid = PR_TRUE; + } } } diff --git a/calendar/base/src/calDateTime.h b/calendar/base/src/calDateTime.h index 7e210008ebc..71e283c88f1 100644 --- a/calendar/base/src/calDateTime.h +++ b/calendar/base/src/calDateTime.h @@ -80,6 +80,7 @@ protected: PRBool mIsUtc; PRBool mIsDate; nsCString mTimezone; + PRInt32 mTimezoneOffset; PRInt16 mWeekday; PRInt16 mYearday;