Index: base/time/time_mac.cc |
diff --git a/base/time/time_mac.cc b/base/time/time_mac.cc |
index 139e0c9e297ad7ec3d95e61447c801c8689a45bc..7d83f9d8081ae2bb14bec995cc0316f31a0e122a 100644 |
--- a/base/time/time_mac.cc |
+++ b/base/time/time_mac.cc |
@@ -165,19 +165,27 @@ Time Time::NowFromSystemTime() { |
// static |
Time Time::FromExploded(bool is_local, const Exploded& exploded) { |
- CFGregorianDate date; |
- date.second = exploded.second + |
- exploded.millisecond / static_cast<double>(kMillisecondsPerSecond); |
- date.minute = exploded.minute; |
- date.hour = exploded.hour; |
- date.day = exploded.day_of_month; |
- date.month = exploded.month; |
- date.year = exploded.year; |
- |
base::ScopedCFTypeRef<CFTimeZoneRef> time_zone( |
- is_local ? CFTimeZoneCopySystem() : NULL); |
- CFAbsoluteTime seconds = CFGregorianDateGetAbsoluteTime(date, time_zone) + |
- kCFAbsoluteTimeIntervalSince1970; |
+ is_local ? CFTimeZoneCopySystem() : |
+ CFTimeZoneCreateWithTimeIntervalFromGMT(kCFAllocatorDefault, 0)); |
+ base::ScopedCFTypeRef<CFCalendarRef> gregorian( |
+ CFCalendarCreateWithIdentifier(kCFAllocatorDefault, |
+ kCFGregorianCalendar)); |
+ CFCalendarSetTimeZone(gregorian, time_zone); |
+ CFAbsoluteTime absolute_time; |
+ CFCalendarComposeAbsoluteTime(gregorian, &absolute_time, "yMdHms", |
+ static_cast<int>(exploded.year), |
+ static_cast<int>(exploded.month), |
+ static_cast<int>(exploded.day_of_month), |
+ static_cast<int>(exploded.hour), |
+ static_cast<int>(exploded.minute), |
+ static_cast<int>(exploded.second)); |
+ // Milliseconds from |exploded| is added back to |absolute_time| here |
+ // because CFCalendar parameters are integer values. |
+ double milliseconds = |
+ exploded.millisecond / static_cast<double>(kMillisecondsPerSecond); |
+ CFAbsoluteTime seconds = |
+ absolute_time + milliseconds + kCFAbsoluteTimeIntervalSince1970; |
return Time(static_cast<int64>(seconds * kMicrosecondsPerSecond) + |
kWindowsEpochDeltaMicroseconds); |
} |
@@ -193,19 +201,29 @@ void Time::Explode(bool is_local, Exploded* exploded) const { |
kCFAbsoluteTimeIntervalSince1970; |
base::ScopedCFTypeRef<CFTimeZoneRef> time_zone( |
- is_local ? CFTimeZoneCopySystem() : NULL); |
- CFGregorianDate date = CFAbsoluteTimeGetGregorianDate(seconds, time_zone); |
- // 1 = Monday, ..., 7 = Sunday. |
- int cf_day_of_week = CFAbsoluteTimeGetDayOfWeek(seconds, time_zone); |
- |
- exploded->year = date.year; |
- exploded->month = date.month; |
- exploded->day_of_week = cf_day_of_week % 7; |
- exploded->day_of_month = date.day; |
- exploded->hour = date.hour; |
- exploded->minute = date.minute; |
+ is_local ? CFTimeZoneCopySystem() : |
+ CFTimeZoneCreateWithTimeIntervalFromGMT(kCFAllocatorDefault, 0)); |
+ base::ScopedCFTypeRef<CFCalendarRef> gregorian( |
+ CFCalendarCreateWithIdentifier(kCFAllocatorDefault, |
+ kCFGregorianCalendar)); |
+ CFCalendarSetTimeZone(gregorian, time_zone); |
+ int year, month, day, hour, minute, second; |
+ CFCalendarDecomposeAbsoluteTime(gregorian, seconds, "yMdHms", &year, &month, |
+ &day, &hour, &minute, &second); |
+ |
+ // Calculate the day of week using CFCalendar, which returns 1 = Sunday, |
+ // 2 = Monday, etc., then convert to |Exploded|'s 0 = Sunday convention. |
+ CFIndex cf_day_of_week = CFCalendarGetOrdinalityOfUnit( |
+ gregorian, kCFCalendarUnitWeekday, kCFCalendarUnitWeekOfMonth, seconds); |
+ |
+ exploded->year = year; |
+ exploded->month = month; |
+ exploded->day_of_week = (cf_day_of_week - 1) % 7; |
+ exploded->day_of_month = day; |
+ exploded->hour = hour; |
+ exploded->minute = minute; |
// Make sure seconds are rounded down towards -infinity. |
- exploded->second = floor(date.second); |
+ exploded->second = floor(second); |
// Calculate milliseconds ourselves, since we rounded the |seconds|, making |
// sure to round towards -infinity. |
exploded->millisecond = |