void BasicTimeZone::getTimeZoneRulesAfter(UDate start, InitialTimeZoneRule*& initial, UVector*& transitionRules, UErrorCode& status) /*const*/ { if (U_FAILURE(status)) { return; } const InitialTimeZoneRule *orgini; const TimeZoneRule **orgtrs = NULL; TimeZoneTransition tzt; UBool avail; UVector *orgRules = NULL; int32_t ruleCount; TimeZoneRule *r = NULL; UBool *done = NULL; InitialTimeZoneRule *res_initial = NULL; UVector *filteredRules = NULL; UnicodeString name; int32_t i; UDate time, t; UDate *newTimes = NULL; UDate firstStart; UBool bFinalStd = FALSE, bFinalDst = FALSE; // Original transition rules ruleCount = countTransitionRules(status); if (U_FAILURE(status)) { return; } orgRules = new UVector(ruleCount, status); if (U_FAILURE(status)) { return; } orgtrs = (const TimeZoneRule**)uprv_malloc(sizeof(TimeZoneRule*)*ruleCount); if (orgtrs == NULL) { status = U_MEMORY_ALLOCATION_ERROR; goto error; } getTimeZoneRules(orgini, orgtrs, ruleCount, status); if (U_FAILURE(status)) { goto error; } for (i = 0; i < ruleCount; i++) { orgRules->addElement(orgtrs[i]->clone(), status); if (U_FAILURE(status)) { goto error; } } uprv_free(orgtrs); orgtrs = NULL; avail = getPreviousTransition(start, TRUE, tzt); if (!avail) { // No need to filter out rules only applicable to time before the start initial = orgini->clone(); transitionRules = orgRules; return; } done = (UBool*)uprv_malloc(sizeof(UBool)*ruleCount); if (done == NULL) { status = U_MEMORY_ALLOCATION_ERROR; goto error; } filteredRules = new UVector(status); if (U_FAILURE(status)) { goto error; } // Create initial rule tzt.getTo()->getName(name); res_initial = new InitialTimeZoneRule(name, tzt.getTo()->getRawOffset(), tzt.getTo()->getDSTSavings()); // Mark rules which does not need to be processed for (i = 0; i < ruleCount; i++) { r = (TimeZoneRule*)orgRules->elementAt(i); avail = r->getNextStart(start, res_initial->getRawOffset(), res_initial->getDSTSavings(), FALSE, time); done[i] = !avail; } time = start; while (!bFinalStd || !bFinalDst) { avail = getNextTransition(time, FALSE, tzt); if (!avail) { break; } time = tzt.getTime(); const TimeZoneRule *toRule = tzt.getTo(); for (i = 0; i < ruleCount; i++) { r = (TimeZoneRule*)orgRules->elementAt(i); if (*r == *toRule) { break; } } if (i >= ruleCount) { // This case should never happen status = U_INVALID_STATE_ERROR; goto error; } if (done[i]) { continue; } if (toRule->getDynamicClassID() == TimeArrayTimeZoneRule::getStaticClassID()) { TimeArrayTimeZoneRule *tar = (TimeArrayTimeZoneRule*)toRule; // Get the previous raw offset and DST savings before the very first start time TimeZoneTransition tzt0; t = start; while (TRUE) { avail = getNextTransition(t, FALSE, tzt0); if (!avail) { break; } if (*(tzt0.getTo()) == *tar) { break; } t = tzt0.getTime(); } if (avail) { // Check if the entire start times to be added tar->getFirstStart(tzt.getFrom()->getRawOffset(), tzt.getFrom()->getDSTSavings(), firstStart); if (firstStart > start) { // Just add the rule as is filteredRules->addElement(tar->clone(), status); if (U_FAILURE(status)) { goto error; } } else { // Colllect transitions after the start time int32_t startTimes; DateTimeRule::TimeRuleType timeType; int32_t idx; startTimes = tar->countStartTimes(); timeType = tar->getTimeType(); for (idx = 0; idx < startTimes; idx++) { tar->getStartTimeAt(idx, t); if (timeType == DateTimeRule::STANDARD_TIME) { t -= tzt.getFrom()->getRawOffset(); } if (timeType == DateTimeRule::WALL_TIME) { t -= tzt.getFrom()->getDSTSavings(); } if (t > start) { break; } } int32_t asize = startTimes - idx; if (asize > 0) { newTimes = (UDate*)uprv_malloc(sizeof(UDate) * asize); if (newTimes == NULL) { status = U_MEMORY_ALLOCATION_ERROR; goto error; } for (int32_t newidx = 0; newidx < asize; newidx++) { tar->getStartTimeAt(idx + newidx, newTimes[newidx]); if (U_FAILURE(status)) { uprv_free(newTimes); newTimes = NULL; goto error; } } tar->getName(name); TimeArrayTimeZoneRule *newTar = new TimeArrayTimeZoneRule(name, tar->getRawOffset(), tar->getDSTSavings(), newTimes, asize, timeType); uprv_free(newTimes); filteredRules->addElement(newTar, status); if (U_FAILURE(status)) { goto error; } } } } } else if (toRule->getDynamicClassID() == AnnualTimeZoneRule::getStaticClassID()) { AnnualTimeZoneRule *ar = (AnnualTimeZoneRule*)toRule; ar->getFirstStart(tzt.getFrom()->getRawOffset(), tzt.getFrom()->getDSTSavings(), firstStart); if (firstStart == tzt.getTime()) { // Just add the rule as is filteredRules->addElement(ar->clone(), status); if (U_FAILURE(status)) { goto error; } } else { // Calculate the transition year int32_t year, month, dom, dow, doy, mid; Grego::timeToFields(tzt.getTime(), year, month, dom, dow, doy, mid); // Re-create the rule ar->getName(name); AnnualTimeZoneRule *newAr = new AnnualTimeZoneRule(name, ar->getRawOffset(), ar->getDSTSavings(), *(ar->getRule()), year, ar->getEndYear()); filteredRules->addElement(newAr, status); if (U_FAILURE(status)) { goto error; } } // check if this is a final rule if (ar->getEndYear() == AnnualTimeZoneRule::MAX_YEAR) { // After bot final standard and dst rules are processed, // exit this while loop. if (ar->getDSTSavings() == 0) { bFinalStd = TRUE; } else { bFinalDst = TRUE; } } } done[i] = TRUE; } // Set the results if (orgRules != NULL) { while (!orgRules->isEmpty()) { r = (TimeZoneRule*)orgRules->orphanElementAt(0); delete r; } delete orgRules; } if (done != NULL) { uprv_free(done); } initial = res_initial; transitionRules = filteredRules; return; error: if (orgtrs != NULL) { uprv_free(orgtrs); } if (orgRules != NULL) { while (!orgRules->isEmpty()) { r = (TimeZoneRule*)orgRules->orphanElementAt(0); delete r; } delete orgRules; } if (done != NULL) { uprv_free(done); } initial = NULL; transitionRules = NULL; }
static UBool getSystemTimeInformation(TimeZone *tz, SYSTEMTIME &daylightDate, SYSTEMTIME &standardDate, int32_t &bias, int32_t &daylightBias, int32_t &standardBias) { UErrorCode status = U_ZERO_ERROR; UBool result = TRUE; BasicTimeZone *btz = (BasicTimeZone*)tz; // we should check type InitialTimeZoneRule *initial = NULL; AnnualTimeZoneRule *std = NULL, *dst = NULL; btz->getSimpleRulesNear(uprv_getUTCtime(), initial, std, dst, status); if (U_SUCCESS(status)) { if (std == NULL || dst == NULL) { bias = -1 * (initial->getRawOffset()/60000); daylightBias = 0; // Do not use DST. Set 0 to all stadardDate/daylightDate fields standardDate.wYear = standardDate.wMonth = standardDate.wDayOfWeek = standardDate.wDay = standardDate.wHour = standardDate.wMinute = standardDate.wSecond = standardDate.wMilliseconds = 0; daylightDate.wYear = daylightDate.wMonth = daylightDate.wDayOfWeek = daylightDate.wDay = daylightDate.wHour = daylightDate.wMinute = daylightDate.wSecond = daylightDate.wMilliseconds = 0; } else { U_ASSERT(std->getRule()->getDateRuleType() == DateTimeRule::DOW); U_ASSERT(dst->getRule()->getDateRuleType() == DateTimeRule::DOW); bias = -1 * (std->getRawOffset()/60000); daylightBias = -1 * (dst->getDSTSavings()/60000); // Always use DOW type rule int32_t hour, min, sec, mil; standardDate.wYear = 0; standardDate.wMonth = std->getRule()->getRuleMonth() + 1; standardDate.wDay = std->getRule()->getRuleWeekInMonth(); if (standardDate.wDay < 0) { standardDate.wDay = 5; } standardDate.wDayOfWeek = std->getRule()->getRuleDayOfWeek() - 1; mil = std->getRule()->getRuleMillisInDay(); hour = mil/3600000; mil %= 3600000; min = mil/60000; mil %= 60000; sec = mil/1000; mil %= 1000; standardDate.wHour = hour; standardDate.wMinute = min; standardDate.wSecond = sec; standardDate.wMilliseconds = mil; daylightDate.wYear = 0; daylightDate.wMonth = dst->getRule()->getRuleMonth() + 1; daylightDate.wDay = dst->getRule()->getRuleWeekInMonth(); if (daylightDate.wDay < 0) { daylightDate.wDay = 5; } daylightDate.wDayOfWeek = dst->getRule()->getRuleDayOfWeek() - 1; mil = dst->getRule()->getRuleMillisInDay(); hour = mil/3600000; mil %= 3600000; min = mil/60000; mil %= 60000; sec = mil/1000; mil %= 1000; daylightDate.wHour = hour; daylightDate.wMinute = min; daylightDate.wSecond = sec; daylightDate.wMilliseconds = mil; } } else { result = FALSE; } delete initial; delete std; delete dst; return result; }