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