1b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru/* 2b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru******************************************************************************* 38393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius* Copyright (C) 2007-2013, International Business Machines Corporation and 427f654740f2a26ad62a5c155af9199af9e69b889claireho* others. All Rights Reserved. 5b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru******************************************************************************* 6b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru*/ 7b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 8b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#include "unicode/utypes.h" 9b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 10b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#if !UCONFIG_NO_FORMATTING 11b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 12b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#include "unicode/basictz.h" 13b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#include "gregoimp.h" 14b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#include "uvector.h" 15b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#include "cmemory.h" 16b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 17b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruU_NAMESPACE_BEGIN 18b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 19b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#define MILLIS_PER_YEAR (365*24*60*60*1000.0) 20b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 21b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruBasicTimeZone::BasicTimeZone() 22b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru: TimeZone() { 23b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru} 24b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 25b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruBasicTimeZone::BasicTimeZone(const UnicodeString &id) 26b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru: TimeZone(id) { 27b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru} 28b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 29b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruBasicTimeZone::BasicTimeZone(const BasicTimeZone& source) 30b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru: TimeZone(source) { 31b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru} 32b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 33b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruBasicTimeZone::~BasicTimeZone() { 34b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru} 35b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 36b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruUBool 378393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig CorneliusBasicTimeZone::hasEquivalentTransitions(const BasicTimeZone& tz, UDate start, UDate end, 388393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius UBool ignoreDstAmount, UErrorCode& status) const { 39b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (U_FAILURE(status)) { 40b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru return FALSE; 41b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 42b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (hasSameRules(tz)) { 43b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru return TRUE; 44b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 45b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // Check the offsets at the start time 46b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru int32_t raw1, raw2, dst1, dst2; 47b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru getOffset(start, FALSE, raw1, dst1, status); 48b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (U_FAILURE(status)) { 49b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru return FALSE; 50b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 51b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru tz.getOffset(start, FALSE, raw2, dst2, status); 52b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (U_FAILURE(status)) { 53b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru return FALSE; 54b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 55b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (ignoreDstAmount) { 56b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if ((raw1 + dst1 != raw2 + dst2) 57b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru || (dst1 != 0 && dst2 == 0) 58b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru || (dst1 == 0 && dst2 != 0)) { 59b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru return FALSE; 60b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 61b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } else { 62b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (raw1 != raw2 || dst1 != dst2) { 63b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru return FALSE; 64b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 65b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 66b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // Check transitions in the range 67b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru UDate time = start; 68b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru TimeZoneTransition tr1, tr2; 69b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru while (TRUE) { 70b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru UBool avail1 = getNextTransition(time, FALSE, tr1); 71b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru UBool avail2 = tz.getNextTransition(time, FALSE, tr2); 72b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 73b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (ignoreDstAmount) { 74b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // Skip a transition which only differ the amount of DST savings 7527f654740f2a26ad62a5c155af9199af9e69b889claireho while (TRUE) { 7627f654740f2a26ad62a5c155af9199af9e69b889claireho if (avail1 7727f654740f2a26ad62a5c155af9199af9e69b889claireho && tr1.getTime() <= end 7827f654740f2a26ad62a5c155af9199af9e69b889claireho && (tr1.getFrom()->getRawOffset() + tr1.getFrom()->getDSTSavings() 7927f654740f2a26ad62a5c155af9199af9e69b889claireho == tr1.getTo()->getRawOffset() + tr1.getTo()->getDSTSavings()) 8027f654740f2a26ad62a5c155af9199af9e69b889claireho && (tr1.getFrom()->getDSTSavings() != 0 && tr1.getTo()->getDSTSavings() != 0)) { 8127f654740f2a26ad62a5c155af9199af9e69b889claireho getNextTransition(tr1.getTime(), FALSE, tr1); 8227f654740f2a26ad62a5c155af9199af9e69b889claireho } else { 8327f654740f2a26ad62a5c155af9199af9e69b889claireho break; 8427f654740f2a26ad62a5c155af9199af9e69b889claireho } 85b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 8627f654740f2a26ad62a5c155af9199af9e69b889claireho while (TRUE) { 8727f654740f2a26ad62a5c155af9199af9e69b889claireho if (avail2 8827f654740f2a26ad62a5c155af9199af9e69b889claireho && tr2.getTime() <= end 8927f654740f2a26ad62a5c155af9199af9e69b889claireho && (tr2.getFrom()->getRawOffset() + tr2.getFrom()->getDSTSavings() 9027f654740f2a26ad62a5c155af9199af9e69b889claireho == tr2.getTo()->getRawOffset() + tr2.getTo()->getDSTSavings()) 9127f654740f2a26ad62a5c155af9199af9e69b889claireho && (tr2.getFrom()->getDSTSavings() != 0 && tr2.getTo()->getDSTSavings() != 0)) { 9227f654740f2a26ad62a5c155af9199af9e69b889claireho tz.getNextTransition(tr2.getTime(), FALSE, tr2); 9327f654740f2a26ad62a5c155af9199af9e69b889claireho } else { 9427f654740f2a26ad62a5c155af9199af9e69b889claireho break; 9527f654740f2a26ad62a5c155af9199af9e69b889claireho } 96b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 97b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 98b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 99b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru UBool inRange1 = (avail1 && tr1.getTime() <= end); 100b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru UBool inRange2 = (avail2 && tr2.getTime() <= end); 101b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (!inRange1 && !inRange2) { 102b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // No more transition in the range 103b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru break; 104b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 105b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (!inRange1 || !inRange2) { 106b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru return FALSE; 107b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 108b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (tr1.getTime() != tr2.getTime()) { 109b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru return FALSE; 110b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 111b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (ignoreDstAmount) { 112b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (tr1.getTo()->getRawOffset() + tr1.getTo()->getDSTSavings() 113b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru != tr2.getTo()->getRawOffset() + tr2.getTo()->getDSTSavings() 11427f654740f2a26ad62a5c155af9199af9e69b889claireho || (tr1.getTo()->getDSTSavings() != 0 && tr2.getTo()->getDSTSavings() == 0) 11527f654740f2a26ad62a5c155af9199af9e69b889claireho || (tr1.getTo()->getDSTSavings() == 0 && tr2.getTo()->getDSTSavings() != 0)) { 116b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru return FALSE; 117b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 118b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } else { 119b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (tr1.getTo()->getRawOffset() != tr2.getTo()->getRawOffset() || 120b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru tr1.getTo()->getDSTSavings() != tr2.getTo()->getDSTSavings()) { 121b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru return FALSE; 122b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 123b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 124b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru time = tr1.getTime(); 125b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 126b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru return TRUE; 127b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru} 128b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 129b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruvoid 130b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruBasicTimeZone::getSimpleRulesNear(UDate date, InitialTimeZoneRule*& initial, 1318393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius AnnualTimeZoneRule*& std, AnnualTimeZoneRule*& dst, UErrorCode& status) const { 132b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru initial = NULL; 133b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru std = NULL; 134b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru dst = NULL; 135b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (U_FAILURE(status)) { 136b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru return; 137b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 138b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru int32_t initialRaw, initialDst; 139b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru UnicodeString initialName; 140b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 141b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru AnnualTimeZoneRule *ar1 = NULL; 142b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru AnnualTimeZoneRule *ar2 = NULL; 143b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru UnicodeString name; 144b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 145b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru UBool avail; 146b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru TimeZoneTransition tr; 147b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // Get the next transition 148b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru avail = getNextTransition(date, FALSE, tr); 149b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (avail) { 150b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru tr.getFrom()->getName(initialName); 151b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru initialRaw = tr.getFrom()->getRawOffset(); 152b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru initialDst = tr.getFrom()->getDSTSavings(); 153b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 154b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // Check if the next transition is either DST->STD or STD->DST and 155b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // within roughly 1 year from the specified date 156b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru UDate nextTransitionTime = tr.getTime(); 157b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (((tr.getFrom()->getDSTSavings() == 0 && tr.getTo()->getDSTSavings() != 0) 158b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru || (tr.getFrom()->getDSTSavings() != 0 && tr.getTo()->getDSTSavings() == 0)) 159b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru && (date + MILLIS_PER_YEAR > nextTransitionTime)) { 160b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 161b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru int32_t year, month, dom, dow, doy, mid; 162b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru UDate d; 163b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 164b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // Get local wall time for the next transition time 165b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru Grego::timeToFields(nextTransitionTime + initialRaw + initialDst, 166b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru year, month, dom, dow, doy, mid); 167b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru int32_t weekInMonth = Grego::dayOfWeekInMonth(year, month, dom); 168b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // Create DOW rule 169b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru DateTimeRule *dtr = new DateTimeRule(month, weekInMonth, dow, mid, DateTimeRule::WALL_TIME); 170b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru tr.getTo()->getName(name); 17150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 17250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho // Note: SimpleTimeZone does not support raw offset change. 17350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho // So we always use raw offset of the given time for the rule, 17450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho // even raw offset is changed. This will result that the result 17550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho // zone to return wrong offset after the transition. 17650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho // When we encounter such case, we do not inspect next next 17750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho // transition for another rule. 17850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho ar1 = new AnnualTimeZoneRule(name, initialRaw, tr.getTo()->getDSTSavings(), 179b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru dtr, year, AnnualTimeZoneRule::MAX_YEAR); 180b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 18150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (tr.getTo()->getRawOffset() == initialRaw) { 18250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho // Get the next next transition 18350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho avail = getNextTransition(nextTransitionTime, FALSE, tr); 18450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (avail) { 18550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho // Check if the next next transition is either DST->STD or STD->DST 18650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho // and within roughly 1 year from the next transition 18750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (((tr.getFrom()->getDSTSavings() == 0 && tr.getTo()->getDSTSavings() != 0) 18850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho || (tr.getFrom()->getDSTSavings() != 0 && tr.getTo()->getDSTSavings() == 0)) 18950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho && nextTransitionTime + MILLIS_PER_YEAR > tr.getTime()) { 19050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 19150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho // Get local wall time for the next transition time 19250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho Grego::timeToFields(tr.getTime() + tr.getFrom()->getRawOffset() + tr.getFrom()->getDSTSavings(), 19350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho year, month, dom, dow, doy, mid); 19450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho weekInMonth = Grego::dayOfWeekInMonth(year, month, dom); 19550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho // Generate another DOW rule 19650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho dtr = new DateTimeRule(month, weekInMonth, dow, mid, DateTimeRule::WALL_TIME); 19750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho tr.getTo()->getName(name); 19850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho ar2 = new AnnualTimeZoneRule(name, tr.getTo()->getRawOffset(), tr.getTo()->getDSTSavings(), 19950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho dtr, year - 1, AnnualTimeZoneRule::MAX_YEAR); 20050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 20150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho // Make sure this rule can be applied to the specified date 20250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho avail = ar2->getPreviousStart(date, tr.getFrom()->getRawOffset(), tr.getFrom()->getDSTSavings(), TRUE, d); 20350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (!avail || d > date 20450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho || initialRaw != tr.getTo()->getRawOffset() 20550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho || initialDst != tr.getTo()->getDSTSavings()) { 20650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho // We cannot use this rule as the second transition rule 20750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho delete ar2; 20850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho ar2 = NULL; 20950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 210b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 211b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 212b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 213b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (ar2 == NULL) { 214b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // Try previous transition 215b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru avail = getPreviousTransition(date, TRUE, tr); 216b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (avail) { 217b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // Check if the previous transition is either DST->STD or STD->DST. 218b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // The actual transition time does not matter here. 219b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if ((tr.getFrom()->getDSTSavings() == 0 && tr.getTo()->getDSTSavings() != 0) 220b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru || (tr.getFrom()->getDSTSavings() != 0 && tr.getTo()->getDSTSavings() == 0)) { 221b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 222b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // Generate another DOW rule 223b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru Grego::timeToFields(tr.getTime() + tr.getFrom()->getRawOffset() + tr.getFrom()->getDSTSavings(), 224b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru year, month, dom, dow, doy, mid); 225b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru weekInMonth = Grego::dayOfWeekInMonth(year, month, dom); 226b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru dtr = new DateTimeRule(month, weekInMonth, dow, mid, DateTimeRule::WALL_TIME); 227b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru tr.getTo()->getName(name); 22850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 22950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho // second rule raw/dst offsets should match raw/dst offsets 23050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho // at the given time 23150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho ar2 = new AnnualTimeZoneRule(name, initialRaw, initialDst, 232b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru dtr, ar1->getStartYear() - 1, AnnualTimeZoneRule::MAX_YEAR); 233b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 234b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // Check if this rule start after the first rule after the specified date 235b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru avail = ar2->getNextStart(date, tr.getFrom()->getRawOffset(), tr.getFrom()->getDSTSavings(), FALSE, d); 236b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (!avail || d <= nextTransitionTime) { 237b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // We cannot use this rule as the second transition rule 238b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru delete ar2; 239b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru ar2 = NULL; 240b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 241b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 242b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 243b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 244b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (ar2 == NULL) { 245b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // Cannot find a good pair of AnnualTimeZoneRule 246b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru delete ar1; 247b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru ar1 = NULL; 248b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } else { 249b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // The initial rule should represent the rule before the previous transition 250b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru ar1->getName(initialName); 251b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru initialRaw = ar1->getRawOffset(); 252b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru initialDst = ar1->getDSTSavings(); 253b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 254b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 255c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru } 256c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru else { 257b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // Try the previous one 258b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru avail = getPreviousTransition(date, TRUE, tr); 259b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (avail) { 260b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru tr.getTo()->getName(initialName); 261b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru initialRaw = tr.getTo()->getRawOffset(); 262b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru initialDst = tr.getTo()->getDSTSavings(); 263b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } else { 264b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // No transitions in the past. Just use the current offsets 265b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru getOffset(date, FALSE, initialRaw, initialDst, status); 266b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (U_FAILURE(status)) { 267b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru return; 268b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 269b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 270b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 271b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // Set the initial rule 272b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru initial = new InitialTimeZoneRule(initialName, initialRaw, initialDst); 273b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 274b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // Set the standard and daylight saving rules 275b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (ar1 != NULL && ar2 != NULL) { 276b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (ar1->getDSTSavings() != 0) { 277b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru dst = ar1; 278b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru std = ar2; 279b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } else { 280b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru std = ar1; 281b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru dst = ar2; 282b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 283b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 284b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru} 285b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 286b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruvoid 287b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruBasicTimeZone::getTimeZoneRulesAfter(UDate start, InitialTimeZoneRule*& initial, 2888393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius UVector*& transitionRules, UErrorCode& status) const { 289b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (U_FAILURE(status)) { 290b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru return; 291b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 292b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 293b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru const InitialTimeZoneRule *orgini; 294b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru const TimeZoneRule **orgtrs = NULL; 295b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru TimeZoneTransition tzt; 296b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru UBool avail; 297b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru UVector *orgRules = NULL; 298b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru int32_t ruleCount; 299b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru TimeZoneRule *r = NULL; 300b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru UBool *done = NULL; 301b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru InitialTimeZoneRule *res_initial = NULL; 302b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru UVector *filteredRules = NULL; 303b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru UnicodeString name; 304b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru int32_t i; 305b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru UDate time, t; 306b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru UDate *newTimes = NULL; 307b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru UDate firstStart; 308b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru UBool bFinalStd = FALSE, bFinalDst = FALSE; 309b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 310b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // Original transition rules 311b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru ruleCount = countTransitionRules(status); 312b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (U_FAILURE(status)) { 313b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru return; 314b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 315b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru orgRules = new UVector(ruleCount, status); 316b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (U_FAILURE(status)) { 317b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru return; 318b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 319b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru orgtrs = (const TimeZoneRule**)uprv_malloc(sizeof(TimeZoneRule*)*ruleCount); 320b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (orgtrs == NULL) { 321b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru status = U_MEMORY_ALLOCATION_ERROR; 322b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru goto error; 323b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 324b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru getTimeZoneRules(orgini, orgtrs, ruleCount, status); 325b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (U_FAILURE(status)) { 326b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru goto error; 327b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 328b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru for (i = 0; i < ruleCount; i++) { 329b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru orgRules->addElement(orgtrs[i]->clone(), status); 330b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (U_FAILURE(status)) { 331b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru goto error; 332b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 333b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 334b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru uprv_free(orgtrs); 335b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru orgtrs = NULL; 336b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 337b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru avail = getPreviousTransition(start, TRUE, tzt); 338b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (!avail) { 339b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // No need to filter out rules only applicable to time before the start 340b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru initial = orgini->clone(); 341b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru transitionRules = orgRules; 342b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru return; 343b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 344b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 345b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru done = (UBool*)uprv_malloc(sizeof(UBool)*ruleCount); 346b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (done == NULL) { 347b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru status = U_MEMORY_ALLOCATION_ERROR; 348b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru goto error; 349b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 350b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru filteredRules = new UVector(status); 351b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (U_FAILURE(status)) { 352b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru goto error; 353b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 354b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 355b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // Create initial rule 356b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru tzt.getTo()->getName(name); 357b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru res_initial = new InitialTimeZoneRule(name, tzt.getTo()->getRawOffset(), 358b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru tzt.getTo()->getDSTSavings()); 359b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 360b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // Mark rules which does not need to be processed 361b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru for (i = 0; i < ruleCount; i++) { 362b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru r = (TimeZoneRule*)orgRules->elementAt(i); 363b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru avail = r->getNextStart(start, res_initial->getRawOffset(), res_initial->getDSTSavings(), FALSE, time); 364b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru done[i] = !avail; 365b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 366b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 367b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru time = start; 368b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru while (!bFinalStd || !bFinalDst) { 369b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru avail = getNextTransition(time, FALSE, tzt); 370b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (!avail) { 371b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru break; 372b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 37327f654740f2a26ad62a5c155af9199af9e69b889claireho UDate updatedTime = tzt.getTime(); 37427f654740f2a26ad62a5c155af9199af9e69b889claireho if (updatedTime == time) { 37527f654740f2a26ad62a5c155af9199af9e69b889claireho // Can get here if rules for start & end of daylight time have exactly 37627f654740f2a26ad62a5c155af9199af9e69b889claireho // the same time. 37727f654740f2a26ad62a5c155af9199af9e69b889claireho // TODO: fix getNextTransition() to prevent it? 37827f654740f2a26ad62a5c155af9199af9e69b889claireho status = U_INVALID_STATE_ERROR; 37927f654740f2a26ad62a5c155af9199af9e69b889claireho goto error; 38027f654740f2a26ad62a5c155af9199af9e69b889claireho } 38127f654740f2a26ad62a5c155af9199af9e69b889claireho time = updatedTime; 382b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 383b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru const TimeZoneRule *toRule = tzt.getTo(); 384b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru for (i = 0; i < ruleCount; i++) { 385b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru r = (TimeZoneRule*)orgRules->elementAt(i); 386b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (*r == *toRule) { 387b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru break; 388b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 389b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 390b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (i >= ruleCount) { 391b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // This case should never happen 392b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru status = U_INVALID_STATE_ERROR; 393b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru goto error; 394b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 395b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (done[i]) { 396b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru continue; 397b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 39827f654740f2a26ad62a5c155af9199af9e69b889claireho const TimeArrayTimeZoneRule *tar = dynamic_cast<const TimeArrayTimeZoneRule *>(toRule); 39927f654740f2a26ad62a5c155af9199af9e69b889claireho const AnnualTimeZoneRule *ar; 40027f654740f2a26ad62a5c155af9199af9e69b889claireho if (tar != NULL) { 401b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // Get the previous raw offset and DST savings before the very first start time 402b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru TimeZoneTransition tzt0; 403b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru t = start; 404b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru while (TRUE) { 405b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru avail = getNextTransition(t, FALSE, tzt0); 406b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (!avail) { 407b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru break; 408b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 409b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (*(tzt0.getTo()) == *tar) { 410b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru break; 411b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 412b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru t = tzt0.getTime(); 413b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 414b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (avail) { 415b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // Check if the entire start times to be added 416b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru tar->getFirstStart(tzt.getFrom()->getRawOffset(), tzt.getFrom()->getDSTSavings(), firstStart); 417b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (firstStart > start) { 418b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // Just add the rule as is 419b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru filteredRules->addElement(tar->clone(), status); 420b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (U_FAILURE(status)) { 421b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru goto error; 422b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 423b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } else { 424b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // Colllect transitions after the start time 425b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru int32_t startTimes; 426b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru DateTimeRule::TimeRuleType timeType; 427b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru int32_t idx; 428b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 429b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru startTimes = tar->countStartTimes(); 430b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru timeType = tar->getTimeType(); 431b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru for (idx = 0; idx < startTimes; idx++) { 432b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru tar->getStartTimeAt(idx, t); 433b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (timeType == DateTimeRule::STANDARD_TIME) { 434b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru t -= tzt.getFrom()->getRawOffset(); 435b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 436b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (timeType == DateTimeRule::WALL_TIME) { 437b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru t -= tzt.getFrom()->getDSTSavings(); 438b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 439b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (t > start) { 440b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru break; 441b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 442b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 443b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru int32_t asize = startTimes - idx; 444b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (asize > 0) { 445b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru newTimes = (UDate*)uprv_malloc(sizeof(UDate) * asize); 446b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (newTimes == NULL) { 447b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru status = U_MEMORY_ALLOCATION_ERROR; 448b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru goto error; 449b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 450b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru for (int32_t newidx = 0; newidx < asize; newidx++) { 451b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru tar->getStartTimeAt(idx + newidx, newTimes[newidx]); 452b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (U_FAILURE(status)) { 453b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru uprv_free(newTimes); 454b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru newTimes = NULL; 455b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru goto error; 456b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 457b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 458b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru tar->getName(name); 459b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru TimeArrayTimeZoneRule *newTar = new TimeArrayTimeZoneRule(name, 460b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru tar->getRawOffset(), tar->getDSTSavings(), newTimes, asize, timeType); 461b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru uprv_free(newTimes); 462b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru filteredRules->addElement(newTar, status); 463b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (U_FAILURE(status)) { 464b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru goto error; 465b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 466b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 467b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 468b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 46927f654740f2a26ad62a5c155af9199af9e69b889claireho } else if ((ar = dynamic_cast<const AnnualTimeZoneRule *>(toRule)) != NULL) { 470b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru ar->getFirstStart(tzt.getFrom()->getRawOffset(), tzt.getFrom()->getDSTSavings(), firstStart); 471b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (firstStart == tzt.getTime()) { 472b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // Just add the rule as is 473b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru filteredRules->addElement(ar->clone(), status); 474b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (U_FAILURE(status)) { 475b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru goto error; 476b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 477b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } else { 478b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // Calculate the transition year 479b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru int32_t year, month, dom, dow, doy, mid; 480b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru Grego::timeToFields(tzt.getTime(), year, month, dom, dow, doy, mid); 481b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // Re-create the rule 482b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru ar->getName(name); 483b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru AnnualTimeZoneRule *newAr = new AnnualTimeZoneRule(name, ar->getRawOffset(), ar->getDSTSavings(), 484b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru *(ar->getRule()), year, ar->getEndYear()); 485b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru filteredRules->addElement(newAr, status); 486b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (U_FAILURE(status)) { 487b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru goto error; 488b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 489b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 490b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // check if this is a final rule 491b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (ar->getEndYear() == AnnualTimeZoneRule::MAX_YEAR) { 492b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // After bot final standard and dst rules are processed, 493b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // exit this while loop. 494b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (ar->getDSTSavings() == 0) { 495b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru bFinalStd = TRUE; 496b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } else { 497b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru bFinalDst = TRUE; 498b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 499b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 500b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 501b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru done[i] = TRUE; 502b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 503b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 504b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // Set the results 505b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (orgRules != NULL) { 506b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru while (!orgRules->isEmpty()) { 507b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru r = (TimeZoneRule*)orgRules->orphanElementAt(0); 508b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru delete r; 509b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 510b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru delete orgRules; 511b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 512b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (done != NULL) { 513b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru uprv_free(done); 514b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 515b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 516b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru initial = res_initial; 517b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru transitionRules = filteredRules; 518b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru return; 519b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 520b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruerror: 521b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (orgtrs != NULL) { 522b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru uprv_free(orgtrs); 523b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 524b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (orgRules != NULL) { 525b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru while (!orgRules->isEmpty()) { 526b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru r = (TimeZoneRule*)orgRules->orphanElementAt(0); 527b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru delete r; 528b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 529b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru delete orgRules; 530b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 531b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (done != NULL) { 53227f654740f2a26ad62a5c155af9199af9e69b889claireho if (filteredRules != NULL) { 53327f654740f2a26ad62a5c155af9199af9e69b889claireho while (!filteredRules->isEmpty()) { 53427f654740f2a26ad62a5c155af9199af9e69b889claireho r = (TimeZoneRule*)filteredRules->orphanElementAt(0); 53527f654740f2a26ad62a5c155af9199af9e69b889claireho delete r; 53627f654740f2a26ad62a5c155af9199af9e69b889claireho } 53727f654740f2a26ad62a5c155af9199af9e69b889claireho delete filteredRules; 53827f654740f2a26ad62a5c155af9199af9e69b889claireho } 53927f654740f2a26ad62a5c155af9199af9e69b889claireho delete res_initial; 540b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru uprv_free(done); 541b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 542b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 543b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru initial = NULL; 544b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru transitionRules = NULL; 545b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru} 546b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 547b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruvoid 548b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste QueruBasicTimeZone::getOffsetFromLocal(UDate /*date*/, int32_t /*nonExistingTimeOpt*/, int32_t /*duplicatedTimeOpt*/, 5498393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius int32_t& /*rawOffset*/, int32_t& /*dstOffset*/, UErrorCode& status) const { 550b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (U_FAILURE(status)) { 551b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru return; 552b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 553b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru status = U_UNSUPPORTED_ERROR; 554b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru} 555b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 556b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruU_NAMESPACE_END 557b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 558b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#endif /* #if !UCONFIG_NO_FORMATTING */ 559b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 560b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru//eof 561