UnicodeString& TimeZone::getDisplayName(UBool daylight, EDisplayType style, const Locale& locale, UnicodeString& result) const { // SRL TODO: cache the SDF, just like java. UErrorCode status = U_ZERO_ERROR; SimpleDateFormat format(style == LONG ? "zzzz" : "z",locale,status); if(!U_SUCCESS(status)) { // *** SRL what do I do here?!! return result.remove(); } // Create a new SimpleTimeZone as a stand-in for this zone; the // stand-in will have no DST, or all DST, but the same ID and offset, // and hence the same display name. // We don't cache these because they're small and cheap to create. UnicodeString tempID; SimpleTimeZone *tz = daylight ? // For the pure-DST zone, we use JANUARY and DECEMBER new SimpleTimeZone(getRawOffset(), getID(tempID), UCAL_JANUARY , 1, 0, 0, UCAL_DECEMBER , 31, 0, U_MILLIS_PER_DAY, status) : new SimpleTimeZone(getRawOffset(), getID(tempID)); format.applyPattern(style == LONG ? "zzzz" : "z"); Calendar *myCalendar = (Calendar*)format.getCalendar(); myCalendar->setTimeZone(*tz); // copy delete tz; FieldPosition pos(FieldPosition::DONT_CARE); return format.format(UDate(196262345678.), result, pos); // Must use a valid date here. }
void SimpleTimeZone::getOffsetFromLocal(UDate date, int32_t nonExistingTimeOpt, int32_t duplicatedTimeOpt, int32_t& rawOffsetGMT, int32_t& savingsDST, UErrorCode& status) const { if (U_FAILURE(status)) { return; } rawOffsetGMT = getRawOffset(); int32_t year, month, dom, dow; double day = uprv_floor(date / U_MILLIS_PER_DAY); int32_t millis = (int32_t) (date - day * U_MILLIS_PER_DAY); Grego::dayToFields(day, year, month, dom, dow); savingsDST = getOffset(GregorianCalendar::AD, year, month, dom, (uint8_t) dow, millis, Grego::monthLength(year, month), status) - rawOffsetGMT; if (U_FAILURE(status)) { return; } UBool recalc = FALSE; // Now we need some adjustment if (savingsDST > 0) { if ((nonExistingTimeOpt & kStdDstMask) == kStandard || ((nonExistingTimeOpt & kStdDstMask) != kDaylight && (nonExistingTimeOpt & kFormerLatterMask) != kLatter)) { date -= getDSTSavings(); recalc = TRUE; } } else { if ((duplicatedTimeOpt & kStdDstMask) == kDaylight || ((duplicatedTimeOpt & kStdDstMask) != kStandard && (duplicatedTimeOpt & kFormerLatterMask) == kFormer)) { date -= getDSTSavings(); recalc = TRUE; } } if (recalc) { day = uprv_floor(date / U_MILLIS_PER_DAY); millis = (int32_t) (date - day * U_MILLIS_PER_DAY); Grego::dayToFields(day, year, month, dom, dow); savingsDST = getOffset(GregorianCalendar::AD, year, month, dom, (uint8_t) dow, millis, Grego::monthLength(year, month), status) - rawOffsetGMT; } }
void TimeZone::getOffset(UDate date, UBool local, int32_t& rawOffset, int32_t& dstOffset, UErrorCode& ec) const { if (U_FAILURE(ec)) { return; } rawOffset = getRawOffset(); if (!local) { date += rawOffset; // now in local standard millis } // When local == TRUE, date might not be in local standard // millis. getOffset taking 7 parameters used here assume // the given time in day is local standard time. // At STD->DST transition, there is a range of time which // does not exist. When 'date' is in this time range // (and local == TRUE), this method interprets the specified // local time as DST. At DST->STD transition, there is a // range of time which occurs twice. In this case, this // method interprets the specified local time as STD. // To support the behavior above, we need to call getOffset // (with 7 args) twice when local == true and DST is // detected in the initial call. for (int32_t pass=0; ; ++pass) { int32_t year, month, dom, dow; double day = uprv_floor(date / U_MILLIS_PER_DAY); int32_t millis = (int32_t) (date - day * U_MILLIS_PER_DAY); Grego::dayToFields(day, year, month, dom, dow); dstOffset = getOffset(GregorianCalendar::AD, year, month, dom, (uint8_t) dow, millis, Grego::monthLength(year, month), ec) - rawOffset; // Recompute if local==TRUE, dstOffset!=0. if (pass!=0 || !local || dstOffset == 0) { break; } // adjust to local standard millis date -= dstOffset; } }
void SimpleTimeZone::initTransitionRules(UErrorCode& status) { if (U_FAILURE(status)) { return; } if (transitionRulesInitialized) { return; } deleteTransitionRules(); UnicodeString tzid; getID(tzid); if (useDaylight) { DateTimeRule* dtRule; DateTimeRule::TimeRuleType timeRuleType; UDate firstStdStart, firstDstStart; // Create a TimeZoneRule for daylight saving time timeRuleType = (startTimeMode == STANDARD_TIME) ? DateTimeRule::STANDARD_TIME : ((startTimeMode == UTC_TIME) ? DateTimeRule::UTC_TIME : DateTimeRule::WALL_TIME); switch (startMode) { case DOM_MODE: dtRule = new DateTimeRule(startMonth, startDay, startTime, timeRuleType); break; case DOW_IN_MONTH_MODE: dtRule = new DateTimeRule(startMonth, startDay, startDayOfWeek, startTime, timeRuleType); break; case DOW_GE_DOM_MODE: dtRule = new DateTimeRule(startMonth, startDay, startDayOfWeek, true, startTime, timeRuleType); break; case DOW_LE_DOM_MODE: dtRule = new DateTimeRule(startMonth, startDay, startDayOfWeek, false, startTime, timeRuleType); break; default: status = U_INVALID_STATE_ERROR; return; } // Check for Null pointer if (dtRule == NULL) { status = U_MEMORY_ALLOCATION_ERROR; return; } // For now, use ID + "(DST)" as the name dstRule = new AnnualTimeZoneRule(tzid+UnicodeString(DST_STR), getRawOffset(), getDSTSavings(), dtRule, startYear, AnnualTimeZoneRule::MAX_YEAR); // Check for Null pointer if (dstRule == NULL) { status = U_MEMORY_ALLOCATION_ERROR; deleteTransitionRules(); return; } // Calculate the first DST start time dstRule->getFirstStart(getRawOffset(), 0, firstDstStart); // Create a TimeZoneRule for standard time timeRuleType = (endTimeMode == STANDARD_TIME) ? DateTimeRule::STANDARD_TIME : ((endTimeMode == UTC_TIME) ? DateTimeRule::UTC_TIME : DateTimeRule::WALL_TIME); switch (endMode) { case DOM_MODE: dtRule = new DateTimeRule(endMonth, endDay, endTime, timeRuleType); break; case DOW_IN_MONTH_MODE: dtRule = new DateTimeRule(endMonth, endDay, endDayOfWeek, endTime, timeRuleType); break; case DOW_GE_DOM_MODE: dtRule = new DateTimeRule(endMonth, endDay, endDayOfWeek, true, endTime, timeRuleType); break; case DOW_LE_DOM_MODE: dtRule = new DateTimeRule(endMonth, endDay, endDayOfWeek, false, endTime, timeRuleType); break; } // Check for Null pointer if (dtRule == NULL) { status = U_MEMORY_ALLOCATION_ERROR; deleteTransitionRules(); return; } // For now, use ID + "(STD)" as the name stdRule = new AnnualTimeZoneRule(tzid+UnicodeString(STD_STR), getRawOffset(), 0, dtRule, startYear, AnnualTimeZoneRule::MAX_YEAR); //Check for Null pointer if (stdRule == NULL) { status = U_MEMORY_ALLOCATION_ERROR; deleteTransitionRules(); return; } // Calculate the first STD start time stdRule->getFirstStart(getRawOffset(), dstRule->getDSTSavings(), firstStdStart); // Create a TimeZoneRule for initial time if (firstStdStart < firstDstStart) { initialRule = new InitialTimeZoneRule(tzid+UnicodeString(DST_STR), getRawOffset(), dstRule->getDSTSavings()); firstTransition = new TimeZoneTransition(firstStdStart, *initialRule, *stdRule); } else { initialRule = new InitialTimeZoneRule(tzid+UnicodeString(STD_STR), getRawOffset(), 0); firstTransition = new TimeZoneTransition(firstDstStart, *initialRule, *dstRule); } // Check for null pointers. if (initialRule == NULL || firstTransition == NULL) { status = U_MEMORY_ALLOCATION_ERROR; deleteTransitionRules(); return; } } else { // Create a TimeZoneRule for initial time initialRule = new InitialTimeZoneRule(tzid, getRawOffset(), 0); // Check for null pointer. if (initialRule == NULL) { status = U_MEMORY_ALLOCATION_ERROR; deleteTransitionRules(); return; } } transitionRulesInitialized = TRUE; }
UBool TimeZone::hasSameRules(const TimeZone& other) const { return (getRawOffset() == other.getRawOffset() && useDaylightTime() == other.useDaylightTime()); }