static OSStatus DER_CFDateToUTCTime(CFAbsoluteTime date, CSSM_DATA_PTR utcTime) { CFGregorianDate gdate = CFAbsoluteTimeGetGregorianDate(date, NULL /* GMT */); unsigned char *d; SInt8 second; utcTime->Length = 13; utcTime->Data = d = PORT_Alloc(13); if (!utcTime->Data) return SECFailure; /* UTC time does not handle the years before 1950 */ if (gdate.year < 1950) return SECFailure; /* remove the century since it's added to the year by the CFAbsoluteTimeGetGregorianDate routine, but is not needed for UTC time */ gdate.year %= 100; second = gdate.second + 0.5; d[0] = HIDIGIT(gdate.year); d[1] = LODIGIT(gdate.year); d[2] = HIDIGIT(gdate.month); d[3] = LODIGIT(gdate.month); d[4] = HIDIGIT(gdate.day); d[5] = LODIGIT(gdate.day); d[6] = HIDIGIT(gdate.hour); d[7] = LODIGIT(gdate.hour); d[8] = HIDIGIT(gdate.minute); d[9] = LODIGIT(gdate.minute); d[10] = HIDIGIT(second); d[11] = LODIGIT(second); d[12] = 'Z'; return SECSuccess; }
Gregorian(CFAbsoluteTime ref) { static_cast<CFGregorianDate &>(*this) = CFAbsoluteTimeGetGregorianDate(ref, NULL); }
/* Note that the units of years and months are not equal length, but are treated as such. */ CFAbsoluteTime CFAbsoluteTimeAddGregorianUnits(CFAbsoluteTime at, CFTimeZoneRef tz, CFGregorianUnits units) { CFGregorianDate gdate; CFGregorianUnits working; CFAbsoluteTime candidate_at0, candidate_at1; uint8_t monthdays; /* Most people seem to expect years, then months, then days, etc. * to be added in that order. Thus, 27 April + (4 days, 1 month) * = 31 May, and not 1 June. This is also relatively predictable. * * On another issue, months not being equal length, people also * seem to expect late day-of-month clamping (don't clamp as you * go through months), but clamp before adding in the days. Late * clamping is also more predictable given random starting points * and random numbers of months added (ie Jan 31 + 2 months could * be March 28 or March 29 in different years with aggressive * clamping). Proportionality (28 Feb + 1 month = 31 March) is * also not expected. * * Also, people don't expect time zone transitions to have any * effect when adding years and/or months and/or days, only. * Hours, minutes, and seconds, though, are added in as humans * would experience the passing of that time. What this means * is that if the date, after adding years, months, and days * lands on some date, and then adding hours, minutes, and * seconds crosses a time zone transition, the time zone * transition is accounted for. If adding years, months, and * days gets the date into a different time zone offset period, * that transition is not taken into account. */ gdate = CFAbsoluteTimeGetGregorianDate(at, tz); // We must work in a CFGregorianUnits, because the fields // in the CFGregorianDate can easily overflow. working.years = gdate.year; working.months = gdate.month; working.days = gdate.day; working.years += units.years; working.months += units.months; while (12 < working.months) { working.months -= 12; working.years += 1; } while (working.months < 1) { working.months += 12; working.years -= 1; } monthdays = __CFDaysInMonth(working.months, working.years - 2001); if (monthdays < working.days) { // Clamp day to new month working.days = monthdays; } working.days += units.days; while (monthdays < working.days) { working.months += 1; if (12 < working.months) { working.months -= 12; working.years += 1; } working.days -= monthdays; monthdays = __CFDaysInMonth(working.months, working.years - 2001); } while (working.days < 1) { working.months -= 1; if (working.months < 1) { working.months += 12; working.years -= 1; } monthdays = __CFDaysInMonth(working.months, working.years - 2001); working.days += monthdays; } gdate.year = working.years; gdate.month = working.months; gdate.day = working.days; /* Roll in hours, minutes, and seconds */ candidate_at0 = CFGregorianDateGetAbsoluteTime(gdate, tz); candidate_at1 = candidate_at0 + 3600.0 * units.hours + 60.0 * units.minutes + units.seconds; /* If summing in the hours, minutes, and seconds delta pushes us * into a new time zone offset, that will automatically be taken * care of by the fact that we just add the raw time above. To * undo that effect, we'd have to get the time zone offsets for * candidate_at0 and candidate_at1 here, and subtract the * difference (offset1 - offset0) from candidate_at1. */ return candidate_at1; }
/* * Returns a copy of repeat event after changing the repeat date * into next event date. * * Caller is responsible for releasing the copy after use. */ __private_extern__ CFDictionaryRef copyNextRepeatingEvent(CFStringRef type) { CFDictionaryRef repeatDict = NULL; CFStringRef repeatDictType = NULL; CFMutableDictionaryRef repeatDictCopy = NULL; CFGregorianDate greg; CFTimeZoneRef tizzy; CFAbsoluteTime ev_time; CFDateRef ev_date; int days; int minutes_scheduled; int cf_day_of_week; /* * 'WakeOrPowerOn' repeat events are returned when caller asks * for 'Wake' events or 'PowerOn' events. * Don't bother to return anything if caller is looking specifically for * WakeOrPowerOn type repeat events. */ if( CFEqual(type, CFSTR(kIOPMAutoSleep)) || CFEqual(type, CFSTR(kIOPMAutoShutdown)) || CFEqual(type, CFSTR(kIOPMAutoRestart)) ) { repeatDict = repeatingPowerOff; } else if ( CFEqual(type, CFSTR(kIOPMAutoPowerOn)) || CFEqual(type, CFSTR(kIOPMAutoWake)) ) { repeatDict = repeatingPowerOn; } else return NULL; repeatDictType = getRepeatingDictionaryType(repeatDict); if (CFEqual(type, repeatDictType) || ( (CFEqual(repeatDictType, CFSTR(kIOPMAutoWakeOrPowerOn))) && (CFEqual(type, CFSTR(kIOPMAutoPowerOn)) || CFEqual(type, CFSTR(kIOPMAutoWake))) ) ) { repeatDictCopy = CFDictionaryCreateMutableCopy(0,0,repeatDict); tizzy = CFTimeZoneCopySystem(); // Massage the scheduled time into today's date cf_day_of_week = CFAbsoluteTimeGetDayOfWeek( CFAbsoluteTimeGetCurrent(), tizzy); days = daysUntil(repeatDict, cf_day_of_week); greg = CFAbsoluteTimeGetGregorianDate( CFAbsoluteTimeGetCurrent() + days*(60*60*24), tizzy); minutes_scheduled = getRepeatingDictionaryMinutes(repeatDict); greg.hour = minutes_scheduled/60; greg.minute = minutes_scheduled%60; greg.second = 0.0; ev_time = CFGregorianDateGetAbsoluteTime(greg, tizzy); ev_date = CFDateCreate(kCFAllocatorDefault, ev_time); CFDictionarySetValue(repeatDictCopy, CFSTR(kIOPMPowerEventTimeKey), ev_date); /* Set 'AppNameKey' to 'Repeating' */ CFDictionarySetValue(repeatDictCopy, CFSTR(kIOPMPowerEventAppNameKey), CFSTR(kIOPMRepeatingAppName)); CFRelease(ev_date); CFRelease(tizzy); } return repeatDictCopy; }