1ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru/* 2ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru******************************************************************************* 38393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius* Copyright (C) 2007-2013, International Business Machines Corporation and 427f654740f2a26ad62a5c155af9199af9e69b889claireho* others. All Rights Reserved. 5ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru******************************************************************************* 6ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru*/ 7ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 854dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius#include "utypeinfo.h" // for 'typeid' to work 927f654740f2a26ad62a5c155af9199af9e69b889claireho 10ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#include "unicode/utypes.h" 11ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 12ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#if !UCONFIG_NO_FORMATTING 13ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 14ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#include "unicode/vtzone.h" 15ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#include "unicode/rbtz.h" 16ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#include "unicode/ucal.h" 17ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#include "unicode/ures.h" 18ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#include "cmemory.h" 19ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#include "uvector.h" 20ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#include "gregoimp.h" 2159d709d503bab6e2b61931737e662dd293b40578ccornelius#include "uassert.h" 22ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 23ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruU_NAMESPACE_BEGIN 24ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 2585bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho// This is the deleter that will be use to remove TimeZoneRule 2685bf2e2fbc60a9f938064abc8127d61da7d19882Claire HoU_CDECL_BEGIN 2785bf2e2fbc60a9f938064abc8127d61da7d19882Claire Hostatic void U_CALLCONV 2885bf2e2fbc60a9f938064abc8127d61da7d19882Claire HodeleteTimeZoneRule(void* obj) { 2985bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho delete (TimeZoneRule*) obj; 3085bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho} 3185bf2e2fbc60a9f938064abc8127d61da7d19882Claire HoU_CDECL_END 3285bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho 33ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// Smybol characters used by RFC2445 VTIMEZONE 34ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Querustatic const UChar COLON = 0x3A; /* : */ 35ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Querustatic const UChar SEMICOLON = 0x3B; /* ; */ 36ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Querustatic const UChar EQUALS_SIGN = 0x3D; /* = */ 37ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Querustatic const UChar COMMA = 0x2C; /* , */ 38ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Querustatic const UChar PLUS = 0x2B; /* + */ 39ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Querustatic const UChar MINUS = 0x2D; /* - */ 40ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 41ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// RFC2445 VTIMEZONE tokens 42ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Querustatic const UChar ICAL_BEGIN_VTIMEZONE[] = {0x42, 0x45, 0x47, 0x49, 0x4E, 0x3A, 0x56, 0x54, 0x49, 0x4D, 0x45, 0x5A, 0x4F, 0x4E, 0x45, 0}; /* "BEGIN:VTIMEZONE" */ 43ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Querustatic const UChar ICAL_END_VTIMEZONE[] = {0x45, 0x4E, 0x44, 0x3A, 0x56, 0x54, 0x49, 0x4D, 0x45, 0x5A, 0x4F, 0x4E, 0x45, 0}; /* "END:VTIMEZONE" */ 44ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Querustatic const UChar ICAL_BEGIN[] = {0x42, 0x45, 0x47, 0x49, 0x4E, 0}; /* "BEGIN" */ 45ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Querustatic const UChar ICAL_END[] = {0x45, 0x4E, 0x44, 0}; /* "END" */ 46ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Querustatic const UChar ICAL_VTIMEZONE[] = {0x56, 0x54, 0x49, 0x4D, 0x45, 0x5A, 0x4F, 0x4E, 0x45, 0}; /* "VTIMEZONE" */ 47ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Querustatic const UChar ICAL_TZID[] = {0x54, 0x5A, 0x49, 0x44, 0}; /* "TZID" */ 48ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Querustatic const UChar ICAL_STANDARD[] = {0x53, 0x54, 0x41, 0x4E, 0x44, 0x41, 0x52, 0x44, 0}; /* "STANDARD" */ 49ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Querustatic const UChar ICAL_DAYLIGHT[] = {0x44, 0x41, 0x59, 0x4C, 0x49, 0x47, 0x48, 0x54, 0}; /* "DAYLIGHT" */ 50ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Querustatic const UChar ICAL_DTSTART[] = {0x44, 0x54, 0x53, 0x54, 0x41, 0x52, 0x54, 0}; /* "DTSTART" */ 51ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Querustatic const UChar ICAL_TZOFFSETFROM[] = {0x54, 0x5A, 0x4F, 0x46, 0x46, 0x53, 0x45, 0x54, 0x46, 0x52, 0x4F, 0x4D, 0}; /* "TZOFFSETFROM" */ 52ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Querustatic const UChar ICAL_TZOFFSETTO[] = {0x54, 0x5A, 0x4F, 0x46, 0x46, 0x53, 0x45, 0x54, 0x54, 0x4F, 0}; /* "TZOFFSETTO" */ 53ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Querustatic const UChar ICAL_RDATE[] = {0x52, 0x44, 0x41, 0x54, 0x45, 0}; /* "RDATE" */ 54ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Querustatic const UChar ICAL_RRULE[] = {0x52, 0x52, 0x55, 0x4C, 0x45, 0}; /* "RRULE" */ 55ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Querustatic const UChar ICAL_TZNAME[] = {0x54, 0x5A, 0x4E, 0x41, 0x4D, 0x45, 0}; /* "TZNAME" */ 56ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Querustatic const UChar ICAL_TZURL[] = {0x54, 0x5A, 0x55, 0x52, 0x4C, 0}; /* "TZURL" */ 57ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Querustatic const UChar ICAL_LASTMOD[] = {0x4C, 0x41, 0x53, 0x54, 0x2D, 0x4D, 0x4F, 0x44, 0x49, 0x46, 0x49, 0x45, 0x44, 0}; /* "LAST-MODIFIED" */ 58ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 59ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Querustatic const UChar ICAL_FREQ[] = {0x46, 0x52, 0x45, 0x51, 0}; /* "FREQ" */ 60ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Querustatic const UChar ICAL_UNTIL[] = {0x55, 0x4E, 0x54, 0x49, 0x4C, 0}; /* "UNTIL" */ 61ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Querustatic const UChar ICAL_YEARLY[] = {0x59, 0x45, 0x41, 0x52, 0x4C, 0x59, 0}; /* "YEARLY" */ 62ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Querustatic const UChar ICAL_BYMONTH[] = {0x42, 0x59, 0x4D, 0x4F, 0x4E, 0x54, 0x48, 0}; /* "BYMONTH" */ 63ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Querustatic const UChar ICAL_BYDAY[] = {0x42, 0x59, 0x44, 0x41, 0x59, 0}; /* "BYDAY" */ 64ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Querustatic const UChar ICAL_BYMONTHDAY[] = {0x42, 0x59, 0x4D, 0x4F, 0x4E, 0x54, 0x48, 0x44, 0x41, 0x59, 0}; /* "BYMONTHDAY" */ 65ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 66ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Querustatic const UChar ICAL_NEWLINE[] = {0x0D, 0x0A, 0}; /* CRLF */ 67ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 68ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Querustatic const UChar ICAL_DOW_NAMES[7][3] = { 69ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru {0x53, 0x55, 0}, /* "SU" */ 70ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru {0x4D, 0x4F, 0}, /* "MO" */ 71ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru {0x54, 0x55, 0}, /* "TU" */ 72ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru {0x57, 0x45, 0}, /* "WE" */ 73ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru {0x54, 0x48, 0}, /* "TH" */ 74ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru {0x46, 0x52, 0}, /* "FR" */ 75ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru {0x53, 0x41, 0} /* "SA" */}; 76ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 77ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// Month length for non-leap year 78ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Querustatic const int32_t MONTHLENGTH[] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}; 79ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 80ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// ICU custom property 81ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Querustatic const UChar ICU_TZINFO_PROP[] = {0x58, 0x2D, 0x54, 0x5A, 0x49, 0x4E, 0x46, 0x4F, 0x3A, 0}; /* "X-TZINFO:" */ 82ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Querustatic const UChar ICU_TZINFO_PARTIAL[] = {0x2F, 0x50, 0x61, 0x72, 0x74, 0x69, 0x61, 0x6C, 0x40, 0}; /* "/Partial@" */ 83ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Querustatic const UChar ICU_TZINFO_SIMPLE[] = {0x2F, 0x53, 0x69, 0x6D, 0x70, 0x6C, 0x65, 0x40, 0}; /* "/Simple@" */ 84ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 85ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 86ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru/* 87ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * Simple fixed digit ASCII number to integer converter 88ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru */ 89ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Querustatic int32_t parseAsciiDigits(const UnicodeString& str, int32_t start, int32_t length, UErrorCode& status) { 90ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru if (U_FAILURE(status)) { 91ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru return 0; 92ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } 93ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru if (length <= 0 || str.length() < start || (start + length) > str.length()) { 94ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru status = U_INVALID_FORMAT_ERROR; 95ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru return 0; 96ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } 97ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru int32_t sign = 1; 98ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru if (str.charAt(start) == PLUS) { 99ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru start++; 100ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru length--; 101ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } else if (str.charAt(start) == MINUS) { 102ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru sign = -1; 103ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru start++; 104ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru length--; 105ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } 106ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru int32_t num = 0; 107ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru for (int32_t i = 0; i < length; i++) { 108ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru int32_t digit = str.charAt(start + i) - 0x0030; 109ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru if (digit < 0 || digit > 9) { 110ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru status = U_INVALID_FORMAT_ERROR; 111ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru return 0; 112ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } 113ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru num = 10 * num + digit; 114ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } 115ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru return sign * num; 116ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru} 117ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 118ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Querustatic UnicodeString& appendAsciiDigits(int32_t number, uint8_t length, UnicodeString& str) { 119ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru UBool negative = FALSE; 120ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru int32_t digits[10]; // max int32_t is 10 decimal digits 121ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru int32_t i; 122ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 123ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru if (number < 0) { 124ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru negative = TRUE; 125ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru number *= -1; 126ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } 127ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 128ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru length = length > 10 ? 10 : length; 129ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru if (length == 0) { 130ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru // variable length 131ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru i = 0; 132ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru do { 133ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru digits[i++] = number % 10; 134ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru number /= 10; 135ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } while (number != 0); 136ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru length = i; 137ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } else { 138ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru // fixed digits 139ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru for (i = 0; i < length; i++) { 140ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru digits[i] = number % 10; 141ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru number /= 10; 142ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } 143ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } 144ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru if (negative) { 145ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru str.append(MINUS); 146ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } 147ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru for (i = length - 1; i >= 0; i--) { 148ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru str.append((UChar)(digits[i] + 0x0030)); 149ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } 150ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru return str; 151ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru} 152ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 153ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Querustatic UnicodeString& appendMillis(UDate date, UnicodeString& str) { 154ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru UBool negative = FALSE; 155ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru int32_t digits[20]; // max int64_t is 20 decimal digits 156ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru int32_t i; 157ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru int64_t number; 158ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 159ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru if (date < MIN_MILLIS) { 160ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru number = (int64_t)MIN_MILLIS; 161ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } else if (date > MAX_MILLIS) { 162ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru number = (int64_t)MAX_MILLIS; 163ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } else { 164ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru number = (int64_t)date; 165ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } 166ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru if (number < 0) { 167ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru negative = TRUE; 168ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru number *= -1; 169ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } 170ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru i = 0; 171ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru do { 172ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru digits[i++] = (int32_t)(number % 10); 173ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru number /= 10; 174ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } while (number != 0); 175ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 176ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru if (negative) { 177ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru str.append(MINUS); 178ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } 179ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru i--; 180ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru while (i >= 0) { 181ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru str.append((UChar)(digits[i--] + 0x0030)); 182ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } 183ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru return str; 184ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru} 185ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 186ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru/* 187ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * Convert date/time to RFC2445 Date-Time form #1 DATE WITH LOCAL TIME 188ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru */ 189ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Querustatic UnicodeString& getDateTimeString(UDate time, UnicodeString& str) { 190ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru int32_t year, month, dom, dow, doy, mid; 191ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru Grego::timeToFields(time, year, month, dom, dow, doy, mid); 192ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 193ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru str.remove(); 194ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru appendAsciiDigits(year, 4, str); 195ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru appendAsciiDigits(month + 1, 2, str); 196ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru appendAsciiDigits(dom, 2, str); 197ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru str.append((UChar)0x0054 /*'T'*/); 198ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 199ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru int32_t t = mid; 200ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru int32_t hour = t / U_MILLIS_PER_HOUR; 201ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru t %= U_MILLIS_PER_HOUR; 202ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru int32_t min = t / U_MILLIS_PER_MINUTE; 203ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru t %= U_MILLIS_PER_MINUTE; 204ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru int32_t sec = t / U_MILLIS_PER_SECOND; 205ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 206ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru appendAsciiDigits(hour, 2, str); 207ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru appendAsciiDigits(min, 2, str); 208ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru appendAsciiDigits(sec, 2, str); 209ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru return str; 210ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru} 211ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 212ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru/* 213ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * Convert date/time to RFC2445 Date-Time form #2 DATE WITH UTC TIME 214ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru */ 215ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Querustatic UnicodeString& getUTCDateTimeString(UDate time, UnicodeString& str) { 216ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru getDateTimeString(time, str); 217ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru str.append((UChar)0x005A /*'Z'*/); 218ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru return str; 219ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru} 220ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 221ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru/* 222ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * Parse RFC2445 Date-Time form #1 DATE WITH LOCAL TIME and 223ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * #2 DATE WITH UTC TIME 224ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru */ 225ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Querustatic UDate parseDateTimeString(const UnicodeString& str, int32_t offset, UErrorCode& status) { 226ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru if (U_FAILURE(status)) { 227ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru return 0.0; 228ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } 229ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 230ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru int32_t year = 0, month = 0, day = 0, hour = 0, min = 0, sec = 0; 231ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru UBool isUTC = FALSE; 232ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru UBool isValid = FALSE; 233ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru do { 234ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru int length = str.length(); 235ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru if (length != 15 && length != 16) { 236ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru // FORM#1 15 characters, such as "20060317T142115" 237ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru // FORM#2 16 characters, such as "20060317T142115Z" 238ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru break; 239ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } 240ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru if (str.charAt(8) != 0x0054) { 241ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru // charcter "T" must be used for separating date and time 242ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru break; 243ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } 244ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru if (length == 16) { 245ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru if (str.charAt(15) != 0x005A) { 246ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru // invalid format 247ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru break; 248ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } 249ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru isUTC = TRUE; 250ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } 251ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 252ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru year = parseAsciiDigits(str, 0, 4, status); 253ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru month = parseAsciiDigits(str, 4, 2, status) - 1; // 0-based 254ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru day = parseAsciiDigits(str, 6, 2, status); 255ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru hour = parseAsciiDigits(str, 9, 2, status); 256ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru min = parseAsciiDigits(str, 11, 2, status); 257ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru sec = parseAsciiDigits(str, 13, 2, status); 258ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 259ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru if (U_FAILURE(status)) { 260ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru break; 261ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } 262ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 263ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru // check valid range 264ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru int32_t maxDayOfMonth = Grego::monthLength(year, month); 265ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru if (year < 0 || month < 0 || month > 11 || day < 1 || day > maxDayOfMonth || 266ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru hour < 0 || hour >= 24 || min < 0 || min >= 60 || sec < 0 || sec >= 60) { 267ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru break; 268ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } 269ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 270ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru isValid = TRUE; 271ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } while(false); 272ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 273ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru if (!isValid) { 274ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru status = U_INVALID_FORMAT_ERROR; 275ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru return 0.0; 276ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } 277ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru // Calculate the time 278ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru UDate time = Grego::fieldsToDay(year, month, day) * U_MILLIS_PER_DAY; 279ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru time += (hour * U_MILLIS_PER_HOUR + min * U_MILLIS_PER_MINUTE + sec * U_MILLIS_PER_SECOND); 280ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru if (!isUTC) { 281ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru time -= offset; 282ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } 283ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru return time; 284ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru} 285ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 286ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru/* 287ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * Convert RFC2445 utc-offset string to milliseconds 288ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru */ 289ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Querustatic int32_t offsetStrToMillis(const UnicodeString& str, UErrorCode& status) { 290ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru if (U_FAILURE(status)) { 291ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru return 0; 292ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } 293ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 294ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru UBool isValid = FALSE; 295ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru int32_t sign = 0, hour = 0, min = 0, sec = 0; 296ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 297ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru do { 298ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru int length = str.length(); 299ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru if (length != 5 && length != 7) { 300ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru // utf-offset must be 5 or 7 characters 301ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru break; 302ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } 303ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru // sign 304ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru UChar s = str.charAt(0); 305ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru if (s == PLUS) { 306ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru sign = 1; 307ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } else if (s == MINUS) { 308ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru sign = -1; 309ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } else { 310ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru // utf-offset must start with "+" or "-" 311ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru break; 312ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } 313ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru hour = parseAsciiDigits(str, 1, 2, status); 314ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru min = parseAsciiDigits(str, 3, 2, status); 315ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru if (length == 7) { 316ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru sec = parseAsciiDigits(str, 5, 2, status); 317ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } 318ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru if (U_FAILURE(status)) { 319ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru break; 320ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } 321ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru isValid = true; 322ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } while(false); 323ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 324ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru if (!isValid) { 325ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru status = U_INVALID_FORMAT_ERROR; 326ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru return 0; 327ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } 328ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru int32_t millis = sign * ((hour * 60 + min) * 60 + sec) * 1000; 329ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru return millis; 330ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru} 331ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 332ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru/* 333ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * Convert milliseconds to RFC2445 utc-offset string 334ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru */ 335ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Querustatic void millisToOffset(int32_t millis, UnicodeString& str) { 336ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru str.remove(); 337ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru if (millis >= 0) { 338ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru str.append(PLUS); 339ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } else { 340ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru str.append(MINUS); 341ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru millis = -millis; 342ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } 343ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru int32_t hour, min, sec; 344ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru int32_t t = millis / 1000; 345ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 346ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru sec = t % 60; 347ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru t = (t - sec) / 60; 348ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru min = t % 60; 349ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru hour = t / 60; 350ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 351ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru appendAsciiDigits(hour, 2, str); 352ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru appendAsciiDigits(min, 2, str); 353ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru appendAsciiDigits(sec, 2, str); 354ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru} 355ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 356ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru/* 357ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * Create a default TZNAME from TZID 358ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru */ 35985bf2e2fbc60a9f938064abc8127d61da7d19882Claire Hostatic void getDefaultTZName(const UnicodeString tzid, UBool isDST, UnicodeString& zonename) { 36085bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho zonename = tzid; 361ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru if (isDST) { 36285bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho zonename += UNICODE_STRING_SIMPLE("(DST)"); 363ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } else { 36485bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho zonename += UNICODE_STRING_SIMPLE("(STD)"); 365ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } 366ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru} 367ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 368ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru/* 369ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * Parse individual RRULE 370ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * 371ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * On return - 372ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * 373ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * month calculated by BYMONTH-1, or -1 when not found 374ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * dow day of week in BYDAY, or 0 when not found 375ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * wim day of week ordinal number in BYDAY, or 0 when not found 376ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * dom an array of day of month 377ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * domCount number of availble days in dom (domCount is specifying the size of dom on input) 378ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * until time defined by UNTIL attribute or MIN_MILLIS if not available 379ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru */ 380ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Querustatic void parseRRULE(const UnicodeString& rrule, int32_t& month, int32_t& dow, int32_t& wim, 381ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru int32_t* dom, int32_t& domCount, UDate& until, UErrorCode& status) { 382ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru if (U_FAILURE(status)) { 383ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru return; 384ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } 385ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru int32_t numDom = 0; 386ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 387ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru month = -1; 388ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru dow = 0; 389ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru wim = 0; 390ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru until = MIN_MILLIS; 391ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 392ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru UBool yearly = FALSE; 393ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru //UBool parseError = FALSE; 394ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 395ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru int32_t prop_start = 0; 396ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru int32_t prop_end; 397ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru UnicodeString prop, attr, value; 398ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru UBool nextProp = TRUE; 399ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 400ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru while (nextProp) { 401ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru prop_end = rrule.indexOf(SEMICOLON, prop_start); 402ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru if (prop_end == -1) { 403ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru prop.setTo(rrule, prop_start); 404ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru nextProp = FALSE; 405ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } else { 406ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru prop.setTo(rrule, prop_start, prop_end - prop_start); 407ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru prop_start = prop_end + 1; 408ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } 409ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru int32_t eql = prop.indexOf(EQUALS_SIGN); 410ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru if (eql != -1) { 411ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru attr.setTo(prop, 0, eql); 412ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru value.setTo(prop, eql + 1); 413ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } else { 414ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru goto rruleParseError; 415ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } 416ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 417103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius if (attr.compare(ICAL_FREQ, -1) == 0) { 418ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru // only support YEARLY frequency type 419103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius if (value.compare(ICAL_YEARLY, -1) == 0) { 420ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru yearly = TRUE; 421ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } else { 422ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru goto rruleParseError; 423ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } 424103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius } else if (attr.compare(ICAL_UNTIL, -1) == 0) { 425ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru // ISO8601 UTC format, for example, "20060315T020000Z" 426ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru until = parseDateTimeString(value, 0, status); 427ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru if (U_FAILURE(status)) { 428ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru goto rruleParseError; 429ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } 430103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius } else if (attr.compare(ICAL_BYMONTH, -1) == 0) { 431ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru // Note: BYMONTH may contain multiple months, but only single month make sense for 432ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru // VTIMEZONE property. 433ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru if (value.length() > 2) { 434ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru goto rruleParseError; 435ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } 436ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru month = parseAsciiDigits(value, 0, value.length(), status) - 1; 437ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru if (U_FAILURE(status) || month < 0 || month >= 12) { 438ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru goto rruleParseError; 439ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } 440103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius } else if (attr.compare(ICAL_BYDAY, -1) == 0) { 441ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru // Note: BYDAY may contain multiple day of week separated by comma. It is unlikely used for 442ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru // VTIMEZONE property. We do not support the case. 443ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 444ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru // 2-letter format is used just for representing a day of week, for example, "SU" for Sunday 445ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru // 3 or 4-letter format is used for represeinging Nth day of week, for example, "-1SA" for last Saturday 446ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru int32_t length = value.length(); 447ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru if (length < 2 || length > 4) { 448ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru goto rruleParseError; 449ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } 450ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru if (length > 2) { 451ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru // Nth day of week 452ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru int32_t sign = 1; 453ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru if (value.charAt(0) == PLUS) { 454ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru sign = 1; 455ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } else if (value.charAt(0) == MINUS) { 456ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru sign = -1; 457ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } else if (length == 4) { 458ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru goto rruleParseError; 459ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } 460ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru int32_t n = parseAsciiDigits(value, length - 3, 1, status); 461ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru if (U_FAILURE(status) || n == 0 || n > 4) { 462ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru goto rruleParseError; 463ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } 464ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru wim = n * sign; 465ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru value.remove(0, length - 2); 466ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } 467ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru int32_t wday; 468ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru for (wday = 0; wday < 7; wday++) { 469ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru if (value.compare(ICAL_DOW_NAMES[wday], 2) == 0) { 470ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru break; 471ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } 472ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } 473ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru if (wday < 7) { 474ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru // Sunday(1) - Saturday(7) 475ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru dow = wday + 1; 476ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } else { 477ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru goto rruleParseError; 478ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } 479103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius } else if (attr.compare(ICAL_BYMONTHDAY, -1) == 0) { 480ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru // Note: BYMONTHDAY may contain multiple days delimitted by comma 481ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru // 482ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru // A value of BYMONTHDAY could be negative, for example, -1 means 483ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru // the last day in a month 484ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru int32_t dom_idx = 0; 485ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru int32_t dom_start = 0; 486ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru int32_t dom_end; 487ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru UBool nextDOM = TRUE; 488ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru while (nextDOM) { 489ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru dom_end = value.indexOf(COMMA, dom_start); 490ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru if (dom_end == -1) { 491ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru dom_end = value.length(); 492ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru nextDOM = FALSE; 493ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } 494ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru if (dom_idx < domCount) { 495ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru dom[dom_idx] = parseAsciiDigits(value, dom_start, dom_end - dom_start, status); 496ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru if (U_FAILURE(status)) { 497ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru goto rruleParseError; 498ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } 499ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru dom_idx++; 500ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } else { 501ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru status = U_BUFFER_OVERFLOW_ERROR; 502ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru goto rruleParseError; 503ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } 504ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru dom_start = dom_end + 1; 505ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } 506ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru numDom = dom_idx; 507ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } 508ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } 509ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru if (!yearly) { 510ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru // FREQ=YEARLY must be set 511ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru goto rruleParseError; 512ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } 513ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru // Set actual number of parsed DOM (ICAL_BYMONTHDAY) 514ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru domCount = numDom; 515ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru return; 516ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 517ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QuerurruleParseError: 518ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru if (U_SUCCESS(status)) { 519ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru // Set error status 520ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru status = U_INVALID_FORMAT_ERROR; 521ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } 522ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru} 523ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 52485bf2e2fbc60a9f938064abc8127d61da7d19882Claire Hostatic TimeZoneRule* createRuleByRRULE(const UnicodeString& zonename, int rawOffset, int dstSavings, UDate start, 525ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru UVector* dates, int fromOffset, UErrorCode& status) { 526ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru if (U_FAILURE(status)) { 527ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru return NULL; 528ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } 529ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru if (dates == NULL || dates->size() == 0) { 530ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru status = U_ILLEGAL_ARGUMENT_ERROR; 531ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru return NULL; 532ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } 533ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 534ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru int32_t i, j; 535ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru DateTimeRule *adtr = NULL; 536ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 537ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru // Parse the first rule 538ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru UnicodeString rrule = *((UnicodeString*)dates->elementAt(0)); 539ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru int32_t month, dayOfWeek, nthDayOfWeek, dayOfMonth = 0; 540ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru int32_t days[7]; 541ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru int32_t daysCount = sizeof(days)/sizeof(days[0]); 542ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru UDate until; 543ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 544ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru parseRRULE(rrule, month, dayOfWeek, nthDayOfWeek, days, daysCount, until, status); 545ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru if (U_FAILURE(status)) { 546ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru return NULL; 547ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } 548ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 549ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru if (dates->size() == 1) { 550ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru // No more rules 551ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru if (daysCount > 1) { 552ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru // Multiple BYMONTHDAY values 553ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru if (daysCount != 7 || month == -1 || dayOfWeek == 0) { 554ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru // Only support the rule using 7 continuous days 555ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru // BYMONTH and BYDAY must be set at the same time 556ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru goto unsupportedRRule; 557ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } 558ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru int32_t firstDay = 31; // max possible number of dates in a month 559ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru for (i = 0; i < 7; i++) { 560ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru // Resolve negative day numbers. A negative day number should 561ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru // not be used in February, but if we see such case, we use 28 562ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru // as the base. 563ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru if (days[i] < 0) { 564ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru days[i] = MONTHLENGTH[month] + days[i] + 1; 565ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } 566ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru if (days[i] < firstDay) { 567ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru firstDay = days[i]; 568ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } 569ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } 570ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru // Make sure days are continuous 571ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru for (i = 1; i < 7; i++) { 572ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru UBool found = FALSE; 573ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru for (j = 0; j < 7; j++) { 574ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru if (days[j] == firstDay + i) { 575ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru found = TRUE; 576ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru break; 577ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } 578ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } 579ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru if (!found) { 580ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru // days are not continuous 581ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru goto unsupportedRRule; 582ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } 583ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } 584ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru // Use DOW_GEQ_DOM rule with firstDay as the start date 585ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru dayOfMonth = firstDay; 586ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } 587ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } else { 588ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru // Check if BYMONTH + BYMONTHDAY + BYDAY rule with multiple RRULE lines. 589ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru // Otherwise, not supported. 590ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru if (month == -1 || dayOfWeek == 0 || daysCount == 0) { 591ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru // This is not the case 592ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru goto unsupportedRRule; 593ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } 594ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru // Parse the rest of rules if number of rules is not exceeding 7. 595ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru // We can only support 7 continuous days starting from a day of month. 596ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru if (dates->size() > 7) { 597ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru goto unsupportedRRule; 598ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } 599ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 600ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru // Note: To check valid date range across multiple rule is a little 601ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru // bit complicated. For now, this code is not doing strict range 602ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru // checking across month boundary 603ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 604ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru int32_t earliestMonth = month; 605ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru int32_t earliestDay = 31; 606ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru for (i = 0; i < daysCount; i++) { 607ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru int32_t dom = days[i]; 608ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru dom = dom > 0 ? dom : MONTHLENGTH[month] + dom + 1; 609ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru earliestDay = dom < earliestDay ? dom : earliestDay; 610ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } 611ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 612ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru int32_t anotherMonth = -1; 613ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru for (i = 1; i < dates->size(); i++) { 614ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru rrule = *((UnicodeString*)dates->elementAt(i)); 615ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru UDate tmp_until; 616ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru int32_t tmp_month, tmp_dayOfWeek, tmp_nthDayOfWeek; 617ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru int32_t tmp_days[7]; 618ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru int32_t tmp_daysCount = sizeof(tmp_days)/sizeof(tmp_days[0]); 619ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru parseRRULE(rrule, tmp_month, tmp_dayOfWeek, tmp_nthDayOfWeek, tmp_days, tmp_daysCount, tmp_until, status); 620ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru if (U_FAILURE(status)) { 621ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru return NULL; 622ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } 623ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru // If UNTIL is newer than previous one, use the one 624ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru if (tmp_until > until) { 625ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru until = tmp_until; 626ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } 627ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 628ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru // Check if BYMONTH + BYMONTHDAY + BYDAY rule 629ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru if (tmp_month == -1 || tmp_dayOfWeek == 0 || tmp_daysCount == 0) { 630ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru goto unsupportedRRule; 631ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } 632ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru // Count number of BYMONTHDAY 633ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru if (daysCount + tmp_daysCount > 7) { 634ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru // We cannot support BYMONTHDAY more than 7 635ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru goto unsupportedRRule; 636ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } 637ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru // Check if the same BYDAY is used. Otherwise, we cannot 638ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru // support the rule 639ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru if (tmp_dayOfWeek != dayOfWeek) { 640ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru goto unsupportedRRule; 641ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } 642ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru // Check if the month is same or right next to the primary month 643ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru if (tmp_month != month) { 644ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru if (anotherMonth == -1) { 645ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru int32_t diff = tmp_month - month; 646ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru if (diff == -11 || diff == -1) { 647ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru // Previous month 648ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru anotherMonth = tmp_month; 649ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru earliestMonth = anotherMonth; 650ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru // Reset earliest day 651ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru earliestDay = 31; 652ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } else if (diff == 11 || diff == 1) { 653ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru // Next month 654ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru anotherMonth = tmp_month; 655ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } else { 656ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru // The day range cannot exceed more than 2 months 657ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru goto unsupportedRRule; 658ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } 659ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } else if (tmp_month != month && tmp_month != anotherMonth) { 660ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru // The day range cannot exceed more than 2 months 661ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru goto unsupportedRRule; 662ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } 663ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } 664ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru // If ealier month, go through days to find the earliest day 665ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru if (tmp_month == earliestMonth) { 666ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru for (j = 0; j < tmp_daysCount; j++) { 667ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru tmp_days[j] = tmp_days[j] > 0 ? tmp_days[j] : MONTHLENGTH[tmp_month] + tmp_days[j] + 1; 668ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru earliestDay = tmp_days[j] < earliestDay ? tmp_days[j] : earliestDay; 669ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } 670ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } 671ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru daysCount += tmp_daysCount; 672ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } 673ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru if (daysCount != 7) { 674ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru // Number of BYMONTHDAY entries must be 7 675ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru goto unsupportedRRule; 676ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } 677ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru month = earliestMonth; 678ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru dayOfMonth = earliestDay; 679ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } 680ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 681ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru // Calculate start/end year and missing fields 682ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru int32_t startYear, startMonth, startDOM, startDOW, startDOY, startMID; 683ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru Grego::timeToFields(start + fromOffset, startYear, startMonth, startDOM, 684ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru startDOW, startDOY, startMID); 685ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru if (month == -1) { 686ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru // If BYMONTH is not set, use the month of DTSTART 687ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru month = startMonth; 688ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } 689ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru if (dayOfWeek == 0 && nthDayOfWeek == 0 && dayOfMonth == 0) { 690ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru // If only YEARLY is set, use the day of DTSTART as BYMONTHDAY 691ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru dayOfMonth = startDOM; 692ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } 693ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 694ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru int32_t endYear; 695ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru if (until != MIN_MILLIS) { 696ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru int32_t endMonth, endDOM, endDOW, endDOY, endMID; 697ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru Grego::timeToFields(until, endYear, endMonth, endDOM, endDOW, endDOY, endMID); 698ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } else { 699ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru endYear = AnnualTimeZoneRule::MAX_YEAR; 700ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } 701ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 702ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru // Create the AnnualDateTimeRule 703ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru if (dayOfWeek == 0 && nthDayOfWeek == 0 && dayOfMonth != 0) { 704ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru // Day in month rule, for example, 15th day in the month 705ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru adtr = new DateTimeRule(month, dayOfMonth, startMID, DateTimeRule::WALL_TIME); 706ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } else if (dayOfWeek != 0 && nthDayOfWeek != 0 && dayOfMonth == 0) { 707ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru // Nth day of week rule, for example, last Sunday 708ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru adtr = new DateTimeRule(month, nthDayOfWeek, dayOfWeek, startMID, DateTimeRule::WALL_TIME); 709ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } else if (dayOfWeek != 0 && nthDayOfWeek == 0 && dayOfMonth != 0) { 710ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru // First day of week after day of month rule, for example, 711ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru // first Sunday after 15th day in the month 712ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru adtr = new DateTimeRule(month, dayOfMonth, dayOfWeek, TRUE, startMID, DateTimeRule::WALL_TIME); 713ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } 714ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru if (adtr == NULL) { 715ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru goto unsupportedRRule; 716ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } 71785bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho return new AnnualTimeZoneRule(zonename, rawOffset, dstSavings, adtr, startYear, endYear); 718ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 719ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruunsupportedRRule: 720ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru status = U_INVALID_STATE_ERROR; 721ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru return NULL; 722ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru} 723ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 724ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru/* 725ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * Create a TimeZoneRule by the RDATE definition 726ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru */ 72785bf2e2fbc60a9f938064abc8127d61da7d19882Claire Hostatic TimeZoneRule* createRuleByRDATE(const UnicodeString& zonename, int32_t rawOffset, int32_t dstSavings, 728ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru UDate start, UVector* dates, int32_t fromOffset, UErrorCode& status) { 729ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru if (U_FAILURE(status)) { 730ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru return NULL; 731ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } 732ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru TimeArrayTimeZoneRule *retVal = NULL; 733ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru if (dates == NULL || dates->size() == 0) { 734ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru // When no RDATE line is provided, use start (DTSTART) 735ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru // as the transition time 73685bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho retVal = new TimeArrayTimeZoneRule(zonename, rawOffset, dstSavings, 737ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru &start, 1, DateTimeRule::UTC_TIME); 738ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } else { 739ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru // Create an array of transition times 740ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru int32_t size = dates->size(); 741ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru UDate* times = (UDate*)uprv_malloc(sizeof(UDate) * size); 742ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru if (times == NULL) { 743ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru status = U_MEMORY_ALLOCATION_ERROR; 744ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru return NULL; 745ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } 746ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru for (int32_t i = 0; i < size; i++) { 747ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru UnicodeString *datestr = (UnicodeString*)dates->elementAt(i); 748ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru times[i] = parseDateTimeString(*datestr, fromOffset, status); 749ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru if (U_FAILURE(status)) { 750ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru uprv_free(times); 751ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru return NULL; 752ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } 753ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } 75485bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho retVal = new TimeArrayTimeZoneRule(zonename, rawOffset, dstSavings, 755ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru times, size, DateTimeRule::UTC_TIME); 756ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru uprv_free(times); 757ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } 758ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru return retVal; 759ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru} 760ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 761ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru/* 762ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * Check if the DOW rule specified by month, weekInMonth and dayOfWeek is equivalent 763ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * to the DateTimerule. 764ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru */ 765ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Querustatic UBool isEquivalentDateRule(int32_t month, int32_t weekInMonth, int32_t dayOfWeek, const DateTimeRule *dtrule) { 766ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru if (month != dtrule->getRuleMonth() || dayOfWeek != dtrule->getRuleDayOfWeek()) { 767ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru return FALSE; 768ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } 769ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru if (dtrule->getTimeRuleType() != DateTimeRule::WALL_TIME) { 770ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru // Do not try to do more intelligent comparison for now. 771ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru return FALSE; 772ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } 773ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru if (dtrule->getDateRuleType() == DateTimeRule::DOW 774ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru && dtrule->getRuleWeekInMonth() == weekInMonth) { 775ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru return TRUE; 776ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } 777ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru int32_t ruleDOM = dtrule->getRuleDayOfMonth(); 778ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru if (dtrule->getDateRuleType() == DateTimeRule::DOW_GEQ_DOM) { 779ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru if (ruleDOM%7 == 1 && (ruleDOM + 6)/7 == weekInMonth) { 780ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru return TRUE; 781ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } 782ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru if (month != UCAL_FEBRUARY && (MONTHLENGTH[month] - ruleDOM)%7 == 6 783ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru && weekInMonth == -1*((MONTHLENGTH[month]-ruleDOM+1)/7)) { 784ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru return TRUE; 785ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } 786ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } 787ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru if (dtrule->getDateRuleType() == DateTimeRule::DOW_LEQ_DOM) { 788ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru if (ruleDOM%7 == 0 && ruleDOM/7 == weekInMonth) { 789ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru return TRUE; 790ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } 791ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru if (month != UCAL_FEBRUARY && (MONTHLENGTH[month] - ruleDOM)%7 == 0 792ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru && weekInMonth == -1*((MONTHLENGTH[month] - ruleDOM)/7 + 1)) { 793ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru return TRUE; 794ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } 795ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } 796ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru return FALSE; 797ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru} 798ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 799ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru/* 800ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * Convert the rule to its equivalent rule using WALL_TIME mode. 801ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * This function returns NULL when the specified DateTimeRule is already 802ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * using WALL_TIME mode. 803ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru */ 804ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Querustatic DateTimeRule* toWallTimeRule(const DateTimeRule* rule, int32_t rawOffset, int32_t dstSavings) { 805ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru if (rule->getTimeRuleType() == DateTimeRule::WALL_TIME) { 806ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru return NULL; 807ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } 808ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru int32_t wallt = rule->getRuleMillisInDay(); 809ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru if (rule->getTimeRuleType() == DateTimeRule::UTC_TIME) { 810ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru wallt += (rawOffset + dstSavings); 811ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } else if (rule->getTimeRuleType() == DateTimeRule::STANDARD_TIME) { 812ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru wallt += dstSavings; 813ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } 814ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 815ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru int32_t month = -1, dom = 0, dow = 0; 816ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru DateTimeRule::DateRuleType dtype; 817ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru int32_t dshift = 0; 818ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru if (wallt < 0) { 819ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru dshift = -1; 820ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru wallt += U_MILLIS_PER_DAY; 821ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } else if (wallt >= U_MILLIS_PER_DAY) { 822ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru dshift = 1; 823ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru wallt -= U_MILLIS_PER_DAY; 824ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } 825ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 826ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru month = rule->getRuleMonth(); 827ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru dom = rule->getRuleDayOfMonth(); 828ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru dow = rule->getRuleDayOfWeek(); 829ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru dtype = rule->getDateRuleType(); 830ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 831ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru if (dshift != 0) { 832ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru if (dtype == DateTimeRule::DOW) { 833ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru // Convert to DOW_GEW_DOM or DOW_LEQ_DOM rule first 834ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru int32_t wim = rule->getRuleWeekInMonth(); 835ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru if (wim > 0) { 836ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru dtype = DateTimeRule::DOW_GEQ_DOM; 837ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru dom = 7 * (wim - 1) + 1; 838ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } else { 839ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru dtype = DateTimeRule::DOW_LEQ_DOM; 840ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru dom = MONTHLENGTH[month] + 7 * (wim + 1); 841ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } 842ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } 843ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru // Shift one day before or after 844ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru dom += dshift; 845ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru if (dom == 0) { 846ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru month--; 847ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru month = month < UCAL_JANUARY ? UCAL_DECEMBER : month; 848ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru dom = MONTHLENGTH[month]; 849ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } else if (dom > MONTHLENGTH[month]) { 850ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru month++; 851ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru month = month > UCAL_DECEMBER ? UCAL_JANUARY : month; 852ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru dom = 1; 853ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } 854ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru if (dtype != DateTimeRule::DOM) { 855ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru // Adjust day of week 856ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru dow += dshift; 857ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru if (dow < UCAL_SUNDAY) { 858ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru dow = UCAL_SATURDAY; 859ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } else if (dow > UCAL_SATURDAY) { 860ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru dow = UCAL_SUNDAY; 861ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } 862ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } 863ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } 864ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru // Create a new rule 865ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru DateTimeRule *modifiedRule; 866ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru if (dtype == DateTimeRule::DOM) { 867ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru modifiedRule = new DateTimeRule(month, dom, wallt, DateTimeRule::WALL_TIME); 868ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } else { 869ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru modifiedRule = new DateTimeRule(month, dom, dow, 870ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru (dtype == DateTimeRule::DOW_GEQ_DOM), wallt, DateTimeRule::WALL_TIME); 871ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } 872ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru return modifiedRule; 873ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru} 874ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 875ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru/* 876ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * Minumum implementations of stream writer/reader, writing/reading 877ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * UnicodeString. For now, we do not want to introduce the dependency 878ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * on the ICU I/O stream in this module. But we want to keep the code 879ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * equivalent to the ICU4J implementation, which utilizes java.io.Writer/ 880ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * Reader. 881ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru */ 882ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queruclass VTZWriter { 883ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Querupublic: 884ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru VTZWriter(UnicodeString& out); 885ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru ~VTZWriter(); 886ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 887ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru void write(const UnicodeString& str); 888ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru void write(UChar ch); 889103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius void write(const UChar* str); 890ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru //void write(const UChar* str, int32_t length); 891ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queruprivate: 892ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru UnicodeString* out; 893ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}; 894ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 895ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruVTZWriter::VTZWriter(UnicodeString& output) { 896ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru out = &output; 897ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru} 898ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 899ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruVTZWriter::~VTZWriter() { 900ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru} 901ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 902ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queruvoid 903ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruVTZWriter::write(const UnicodeString& str) { 904ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru out->append(str); 905ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru} 906ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 907ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queruvoid 908ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruVTZWriter::write(UChar ch) { 909ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru out->append(ch); 910ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru} 911ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 912103e9ffba2cba345d0078eb8b8db33249f81840aCraig Corneliusvoid 913103e9ffba2cba345d0078eb8b8db33249f81840aCraig CorneliusVTZWriter::write(const UChar* str) { 914103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius out->append(str, -1); 915103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius} 916103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius 917ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru/* 918ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queruvoid 919ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruVTZWriter::write(const UChar* str, int32_t length) { 920ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru out->append(str, length); 921ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru} 922ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru*/ 923ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 924ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queruclass VTZReader { 925ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Querupublic: 926ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru VTZReader(const UnicodeString& input); 927ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru ~VTZReader(); 928ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 929ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru UChar read(void); 930ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queruprivate: 931ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru const UnicodeString* in; 932ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru int32_t index; 933ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}; 934ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 935ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruVTZReader::VTZReader(const UnicodeString& input) { 936ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru in = &input; 937ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru index = 0; 938ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru} 939ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 940ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruVTZReader::~VTZReader() { 941ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru} 942ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 943ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruUChar 944ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruVTZReader::read(void) { 945ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru UChar ch = 0xFFFF; 946ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru if (index < in->length()) { 947ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru ch = in->charAt(index); 948ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } 949ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru index++; 950ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru return ch; 951ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru} 952ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 953ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 954ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruUOBJECT_DEFINE_RTTI_IMPLEMENTATION(VTimeZone) 955ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 956ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruVTimeZone::VTimeZone() 957ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru: BasicTimeZone(), tz(NULL), vtzlines(NULL), 958ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru lastmod(MAX_MILLIS) { 959ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru} 960ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 961ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruVTimeZone::VTimeZone(const VTimeZone& source) 962ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru: BasicTimeZone(source), tz(NULL), vtzlines(NULL), 963ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru tzurl(source.tzurl), lastmod(source.lastmod), 964ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru olsonzid(source.olsonzid), icutzver(source.icutzver) { 965ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru if (source.tz != NULL) { 966ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru tz = (BasicTimeZone*)source.tz->clone(); 967ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } 968ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru if (source.vtzlines != NULL) { 969ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru UErrorCode status = U_ZERO_ERROR; 970ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru int32_t size = source.vtzlines->size(); 971103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius vtzlines = new UVector(uprv_deleteUObject, uhash_compareUnicodeString, size, status); 972ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru if (U_SUCCESS(status)) { 973ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru for (int32_t i = 0; i < size; i++) { 974ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru UnicodeString *line = (UnicodeString*)source.vtzlines->elementAt(i); 975ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru vtzlines->addElement(line->clone(), status); 976ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru if (U_FAILURE(status)) { 977ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru break; 978ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } 979ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } 980ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } 981ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru if (U_FAILURE(status) && vtzlines != NULL) { 982ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru delete vtzlines; 983ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } 984ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } 985ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru} 986ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 987ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruVTimeZone::~VTimeZone() { 988ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru if (tz != NULL) { 989ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru delete tz; 990ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } 991ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru if (vtzlines != NULL) { 992ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru delete vtzlines; 993ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } 994ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru} 995ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 996ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruVTimeZone& 997ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruVTimeZone::operator=(const VTimeZone& right) { 998ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru if (this == &right) { 999ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru return *this; 1000ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } 1001ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru if (*this != right) { 1002ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru BasicTimeZone::operator=(right); 1003ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru if (tz != NULL) { 1004ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru delete tz; 1005ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru tz = NULL; 1006ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } 1007ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru if (right.tz != NULL) { 1008ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru tz = (BasicTimeZone*)right.tz->clone(); 1009ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } 1010ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru if (vtzlines != NULL) { 1011ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru delete vtzlines; 1012ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } 1013ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru if (right.vtzlines != NULL) { 1014ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru UErrorCode status = U_ZERO_ERROR; 1015ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru int32_t size = right.vtzlines->size(); 1016103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius vtzlines = new UVector(uprv_deleteUObject, uhash_compareUnicodeString, size, status); 1017ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru if (U_SUCCESS(status)) { 1018ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru for (int32_t i = 0; i < size; i++) { 1019ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru UnicodeString *line = (UnicodeString*)right.vtzlines->elementAt(i); 1020ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru vtzlines->addElement(line->clone(), status); 1021ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru if (U_FAILURE(status)) { 1022ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru break; 1023ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } 1024ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } 1025ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } 1026ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru if (U_FAILURE(status) && vtzlines != NULL) { 1027ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru delete vtzlines; 1028ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru vtzlines = NULL; 1029ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } 1030ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } 1031ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru tzurl = right.tzurl; 1032ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru lastmod = right.lastmod; 1033ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru olsonzid = right.olsonzid; 1034ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru icutzver = right.icutzver; 1035ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } 1036ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru return *this; 1037ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru} 1038ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 1039ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruUBool 1040ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruVTimeZone::operator==(const TimeZone& that) const { 1041ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru if (this == &that) { 1042ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru return TRUE; 1043ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } 104427f654740f2a26ad62a5c155af9199af9e69b889claireho if (typeid(*this) != typeid(that) || !BasicTimeZone::operator==(that)) { 1045ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru return FALSE; 1046ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } 1047ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru VTimeZone *vtz = (VTimeZone*)&that; 1048ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru if (*tz == *(vtz->tz) 1049ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru && tzurl == vtz->tzurl 1050ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru && lastmod == vtz->lastmod 1051ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru /* && olsonzid = that.olsonzid */ 1052ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru /* && icutzver = that.icutzver */) { 1053ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru return TRUE; 1054ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } 1055ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru return FALSE; 1056ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru} 1057ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 1058ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruUBool 1059ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruVTimeZone::operator!=(const TimeZone& that) const { 1060ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru return !operator==(that); 1061ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru} 1062ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 1063ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruVTimeZone* 1064ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruVTimeZone::createVTimeZoneByID(const UnicodeString& ID) { 1065ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru VTimeZone *vtz = new VTimeZone(); 1066ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru vtz->tz = (BasicTimeZone*)TimeZone::createTimeZone(ID); 1067ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru vtz->tz->getID(vtz->olsonzid); 1068ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 1069ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru // Set ICU tzdata version 1070ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru UErrorCode status = U_ZERO_ERROR; 1071ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru UResourceBundle *bundle = NULL; 1072ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru const UChar* versionStr = NULL; 107327f654740f2a26ad62a5c155af9199af9e69b889claireho int32_t len = 0; 107427f654740f2a26ad62a5c155af9199af9e69b889claireho bundle = ures_openDirect(NULL, "zoneinfo64", &status); 107527f654740f2a26ad62a5c155af9199af9e69b889claireho versionStr = ures_getStringByKey(bundle, "TZVersion", &len, &status); 107627f654740f2a26ad62a5c155af9199af9e69b889claireho if (U_SUCCESS(status)) { 107727f654740f2a26ad62a5c155af9199af9e69b889claireho vtz->icutzver.setTo(versionStr, len); 107827f654740f2a26ad62a5c155af9199af9e69b889claireho } 107927f654740f2a26ad62a5c155af9199af9e69b889claireho ures_close(bundle); 108027f654740f2a26ad62a5c155af9199af9e69b889claireho return vtz; 108127f654740f2a26ad62a5c155af9199af9e69b889claireho} 108227f654740f2a26ad62a5c155af9199af9e69b889claireho 108327f654740f2a26ad62a5c155af9199af9e69b889clairehoVTimeZone* 108427f654740f2a26ad62a5c155af9199af9e69b889clairehoVTimeZone::createVTimeZoneFromBasicTimeZone(const BasicTimeZone& basic_time_zone, UErrorCode &status) { 108527f654740f2a26ad62a5c155af9199af9e69b889claireho if (U_FAILURE(status)) { 108627f654740f2a26ad62a5c155af9199af9e69b889claireho return NULL; 108727f654740f2a26ad62a5c155af9199af9e69b889claireho } 108827f654740f2a26ad62a5c155af9199af9e69b889claireho VTimeZone *vtz = new VTimeZone(); 108927f654740f2a26ad62a5c155af9199af9e69b889claireho if (vtz == NULL) { 109027f654740f2a26ad62a5c155af9199af9e69b889claireho status = U_MEMORY_ALLOCATION_ERROR; 109127f654740f2a26ad62a5c155af9199af9e69b889claireho return NULL; 109227f654740f2a26ad62a5c155af9199af9e69b889claireho } 109327f654740f2a26ad62a5c155af9199af9e69b889claireho vtz->tz = (BasicTimeZone *)basic_time_zone.clone(); 109427f654740f2a26ad62a5c155af9199af9e69b889claireho if (vtz->tz == NULL) { 109527f654740f2a26ad62a5c155af9199af9e69b889claireho status = U_MEMORY_ALLOCATION_ERROR; 109627f654740f2a26ad62a5c155af9199af9e69b889claireho delete vtz; 109727f654740f2a26ad62a5c155af9199af9e69b889claireho return NULL; 109827f654740f2a26ad62a5c155af9199af9e69b889claireho } 109927f654740f2a26ad62a5c155af9199af9e69b889claireho vtz->tz->getID(vtz->olsonzid); 110027f654740f2a26ad62a5c155af9199af9e69b889claireho 110127f654740f2a26ad62a5c155af9199af9e69b889claireho // Set ICU tzdata version 110227f654740f2a26ad62a5c155af9199af9e69b889claireho UResourceBundle *bundle = NULL; 110327f654740f2a26ad62a5c155af9199af9e69b889claireho const UChar* versionStr = NULL; 110427f654740f2a26ad62a5c155af9199af9e69b889claireho int32_t len = 0; 110527f654740f2a26ad62a5c155af9199af9e69b889claireho bundle = ures_openDirect(NULL, "zoneinfo64", &status); 1106ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru versionStr = ures_getStringByKey(bundle, "TZVersion", &len, &status); 1107ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru if (U_SUCCESS(status)) { 1108ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru vtz->icutzver.setTo(versionStr, len); 1109ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } 1110ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru ures_close(bundle); 1111ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru return vtz; 1112ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru} 1113ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 1114ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruVTimeZone* 1115ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruVTimeZone::createVTimeZone(const UnicodeString& vtzdata, UErrorCode& status) { 1116ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru if (U_FAILURE(status)) { 1117ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru return NULL; 1118ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } 1119ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru VTZReader reader(vtzdata); 1120ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru VTimeZone *vtz = new VTimeZone(); 1121ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru vtz->load(reader, status); 1122ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru if (U_FAILURE(status)) { 1123ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru delete vtz; 1124ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru return NULL; 1125ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } 1126ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru return vtz; 1127ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru} 1128ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 1129ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruUBool 1130ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruVTimeZone::getTZURL(UnicodeString& url) const { 1131ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru if (tzurl.length() > 0) { 1132ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru url = tzurl; 1133ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru return TRUE; 1134ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } 1135ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru return FALSE; 1136ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru} 1137ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 1138ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queruvoid 1139ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruVTimeZone::setTZURL(const UnicodeString& url) { 1140ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru tzurl = url; 1141ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru} 1142ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 1143ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruUBool 1144ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruVTimeZone::getLastModified(UDate& lastModified) const { 1145ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru if (lastmod != MAX_MILLIS) { 1146ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru lastModified = lastmod; 1147ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru return TRUE; 1148ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } 1149ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru return FALSE; 1150ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru} 1151ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 1152ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queruvoid 1153ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruVTimeZone::setLastModified(UDate lastModified) { 1154ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru lastmod = lastModified; 1155ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru} 1156ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 1157ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queruvoid 1158ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruVTimeZone::write(UnicodeString& result, UErrorCode& status) const { 1159ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru result.remove(); 1160ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru VTZWriter writer(result); 1161ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru write(writer, status); 1162ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru} 1163ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 1164ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queruvoid 11658393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig CorneliusVTimeZone::write(UDate start, UnicodeString& result, UErrorCode& status) const { 1166ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru result.remove(); 1167ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru VTZWriter writer(result); 1168ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru write(start, writer, status); 1169ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru} 1170ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 1171ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queruvoid 11728393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig CorneliusVTimeZone::writeSimple(UDate time, UnicodeString& result, UErrorCode& status) const { 1173ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru result.remove(); 1174ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru VTZWriter writer(result); 1175ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru writeSimple(time, writer, status); 1176ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru} 1177ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 1178ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruTimeZone* 1179ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruVTimeZone::clone(void) const { 1180ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru return new VTimeZone(*this); 1181ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru} 1182ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 1183ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queruint32_t 1184ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruVTimeZone::getOffset(uint8_t era, int32_t year, int32_t month, int32_t day, 1185ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru uint8_t dayOfWeek, int32_t millis, UErrorCode& status) const { 1186ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru return tz->getOffset(era, year, month, day, dayOfWeek, millis, status); 1187ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru} 1188ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 1189ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queruint32_t 1190ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruVTimeZone::getOffset(uint8_t era, int32_t year, int32_t month, int32_t day, 1191ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru uint8_t dayOfWeek, int32_t millis, 1192ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru int32_t monthLength, UErrorCode& status) const { 1193ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru return tz->getOffset(era, year, month, day, dayOfWeek, millis, monthLength, status); 1194ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru} 1195ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 1196ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queruvoid 1197ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruVTimeZone::getOffset(UDate date, UBool local, int32_t& rawOffset, 1198ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru int32_t& dstOffset, UErrorCode& status) const { 1199ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru return tz->getOffset(date, local, rawOffset, dstOffset, status); 1200ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru} 1201ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 1202ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queruvoid 1203ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruVTimeZone::setRawOffset(int32_t offsetMillis) { 1204ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru tz->setRawOffset(offsetMillis); 1205ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru} 1206ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 1207ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queruint32_t 1208ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruVTimeZone::getRawOffset(void) const { 1209ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru return tz->getRawOffset(); 1210ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru} 1211ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 1212ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruUBool 1213ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruVTimeZone::useDaylightTime(void) const { 1214ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru return tz->useDaylightTime(); 1215ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru} 1216ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 1217ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruUBool 1218ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruVTimeZone::inDaylightTime(UDate date, UErrorCode& status) const { 1219ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru return tz->inDaylightTime(date, status); 1220ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru} 1221ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 1222ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruUBool 1223ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruVTimeZone::hasSameRules(const TimeZone& other) const { 1224ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru return tz->hasSameRules(other); 1225ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru} 1226ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 1227ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruUBool 12288393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig CorneliusVTimeZone::getNextTransition(UDate base, UBool inclusive, TimeZoneTransition& result) const { 1229ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru return tz->getNextTransition(base, inclusive, result); 1230ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru} 1231ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 1232ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruUBool 12338393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig CorneliusVTimeZone::getPreviousTransition(UDate base, UBool inclusive, TimeZoneTransition& result) const { 1234ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru return tz->getPreviousTransition(base, inclusive, result); 1235ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru} 1236ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 1237ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queruint32_t 12388393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig CorneliusVTimeZone::countTransitionRules(UErrorCode& status) const { 1239ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru return tz->countTransitionRules(status); 1240ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru} 1241ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 1242ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queruvoid 1243ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruVTimeZone::getTimeZoneRules(const InitialTimeZoneRule*& initial, 1244ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru const TimeZoneRule* trsrules[], int32_t& trscount, 12458393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius UErrorCode& status) const { 1246ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru tz->getTimeZoneRules(initial, trsrules, trscount, status); 1247ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru} 1248ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 1249ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queruvoid 1250ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruVTimeZone::load(VTZReader& reader, UErrorCode& status) { 1251103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius vtzlines = new UVector(uprv_deleteUObject, uhash_compareUnicodeString, DEFAULT_VTIMEZONE_LINES, status); 1252ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru if (U_FAILURE(status)) { 1253ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru return; 1254ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } 1255ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru UBool eol = FALSE; 1256ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru UBool start = FALSE; 1257ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru UBool success = FALSE; 1258ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru UnicodeString line; 1259ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 1260ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru while (TRUE) { 1261ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru UChar ch = reader.read(); 1262ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru if (ch == 0xFFFF) { 1263ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru // end of file 1264103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius if (start && line.startsWith(ICAL_END_VTIMEZONE, -1)) { 1265ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru vtzlines->addElement(new UnicodeString(line), status); 1266ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru if (U_FAILURE(status)) { 1267ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru goto cleanupVtzlines; 1268ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } 1269ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru success = TRUE; 1270ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } 1271ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru break; 1272ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } 1273ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru if (ch == 0x000D) { 1274ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru // CR, must be followed by LF according to the definition in RFC2445 1275ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru continue; 1276ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } 1277ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru if (eol) { 1278ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru if (ch != 0x0009 && ch != 0x0020) { 1279ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru // NOT followed by TAB/SP -> new line 1280ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru if (start) { 1281ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru if (line.length() > 0) { 1282ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru vtzlines->addElement(new UnicodeString(line), status); 1283ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru if (U_FAILURE(status)) { 1284ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru goto cleanupVtzlines; 1285ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } 1286ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } 1287ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } 1288ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru line.remove(); 1289ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru if (ch != 0x000A) { 1290ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru line.append(ch); 1291ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } 1292ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } 1293ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru eol = FALSE; 1294ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } else { 1295ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru if (ch == 0x000A) { 1296ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru // LF 1297ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru eol = TRUE; 1298ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru if (start) { 1299103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius if (line.startsWith(ICAL_END_VTIMEZONE, -1)) { 1300ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru vtzlines->addElement(new UnicodeString(line), status); 1301ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru if (U_FAILURE(status)) { 1302ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru goto cleanupVtzlines; 1303ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } 1304ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru success = TRUE; 1305ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru break; 1306ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } 1307ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } else { 1308103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius if (line.startsWith(ICAL_BEGIN_VTIMEZONE, -1)) { 1309ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru vtzlines->addElement(new UnicodeString(line), status); 1310ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru if (U_FAILURE(status)) { 1311ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru goto cleanupVtzlines; 1312ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } 1313ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru line.remove(); 1314ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru start = TRUE; 1315ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru eol = FALSE; 1316ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } 1317ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } 1318ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } else { 1319ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru line.append(ch); 1320ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } 1321ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } 1322ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } 1323ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru if (!success) { 1324ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru if (U_SUCCESS(status)) { 1325ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru status = U_INVALID_STATE_ERROR; 1326ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } 1327ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru goto cleanupVtzlines; 1328ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } 1329ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru parse(status); 1330ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru return; 1331ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 1332ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QuerucleanupVtzlines: 1333ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru delete vtzlines; 1334ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru vtzlines = NULL; 1335ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru} 1336ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 1337ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// parser state 1338ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#define INI 0 // Initial state 1339ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#define VTZ 1 // In VTIMEZONE 1340ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#define TZI 2 // In STANDARD or DAYLIGHT 1341ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 1342ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#define DEF_DSTSAVINGS (60*60*1000) 1343ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#define DEF_TZSTARTTIME (0.0) 1344ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 1345ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queruvoid 1346ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruVTimeZone::parse(UErrorCode& status) { 1347ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru if (U_FAILURE(status)) { 1348ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru return; 1349ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } 1350ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru if (vtzlines == NULL || vtzlines->size() == 0) { 1351ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru status = U_INVALID_STATE_ERROR; 1352ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru return; 1353ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } 1354ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru InitialTimeZoneRule *initialRule = NULL; 1355ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru RuleBasedTimeZone *rbtz = NULL; 1356ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 1357ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru // timezone ID 1358ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru UnicodeString tzid; 1359ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 1360ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru int32_t state = INI; 1361ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru int32_t n = 0; 1362ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru UBool dst = FALSE; // current zone type 1363ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru UnicodeString from; // current zone from offset 1364ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru UnicodeString to; // current zone offset 136585bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho UnicodeString zonename; // current zone name 1366ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru UnicodeString dtstart; // current zone starts 1367ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru UBool isRRULE = FALSE; // true if the rule is described by RRULE 1368ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru int32_t initialRawOffset = 0; // initial offset 1369ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru int32_t initialDSTSavings = 0; // initial offset 1370ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru UDate firstStart = MAX_MILLIS; // the earliest rule start time 1371ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru UnicodeString name; // RFC2445 prop name 1372ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru UnicodeString value; // RFC2445 prop value 1373ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 1374ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru UVector *dates = NULL; // list of RDATE or RRULE strings 1375ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru UVector *rules = NULL; // list of TimeZoneRule instances 1376ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 137785bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho int32_t finalRuleIdx = -1; 137885bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho int32_t finalRuleCount = 0; 137985bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho 1380ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru rules = new UVector(status); 1381ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru if (U_FAILURE(status)) { 1382ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru goto cleanupParse; 1383ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } 138485bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho // Set the deleter to remove TimeZoneRule vectors to avoid memory leaks due to unowned TimeZoneRules. 138585bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho rules->setDeleter(deleteTimeZoneRule); 138685bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho 1387103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius dates = new UVector(uprv_deleteUObject, uhash_compareUnicodeString, status); 1388ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru if (U_FAILURE(status)) { 1389ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru goto cleanupParse; 1390ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } 139185bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho if (rules == NULL || dates == NULL) { 139285bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho status = U_MEMORY_ALLOCATION_ERROR; 139385bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho goto cleanupParse; 139485bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho } 1395ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 1396ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru for (n = 0; n < vtzlines->size(); n++) { 1397ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru UnicodeString *line = (UnicodeString*)vtzlines->elementAt(n); 1398ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru int32_t valueSep = line->indexOf(COLON); 1399ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru if (valueSep < 0) { 1400ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru continue; 1401ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } 1402ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru name.setTo(*line, 0, valueSep); 1403ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru value.setTo(*line, valueSep + 1); 1404ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 1405ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru switch (state) { 1406ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru case INI: 1407103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius if (name.compare(ICAL_BEGIN, -1) == 0 1408103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius && value.compare(ICAL_VTIMEZONE, -1) == 0) { 1409ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru state = VTZ; 1410ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } 1411ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru break; 1412ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 1413ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru case VTZ: 1414103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius if (name.compare(ICAL_TZID, -1) == 0) { 1415ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru tzid = value; 1416103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius } else if (name.compare(ICAL_TZURL, -1) == 0) { 1417ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru tzurl = value; 1418103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius } else if (name.compare(ICAL_LASTMOD, -1) == 0) { 1419ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru // Always in 'Z' format, so the offset argument for the parse method 1420ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru // can be any value. 1421ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru lastmod = parseDateTimeString(value, 0, status); 1422ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru if (U_FAILURE(status)) { 1423ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru goto cleanupParse; 1424ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } 1425103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius } else if (name.compare(ICAL_BEGIN, -1) == 0) { 1426103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius UBool isDST = (value.compare(ICAL_DAYLIGHT, -1) == 0); 1427103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius if (value.compare(ICAL_STANDARD, -1) == 0 || isDST) { 1428ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru // tzid must be ready at this point 1429ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru if (tzid.length() == 0) { 1430ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru goto cleanupParse; 1431ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } 1432ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru // initialize current zone properties 1433ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru if (dates->size() != 0) { 1434ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru dates->removeAllElements(); 1435ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } 1436ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru isRRULE = FALSE; 1437ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru from.remove(); 1438ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru to.remove(); 143985bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho zonename.remove(); 1440ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru dst = isDST; 1441ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru state = TZI; 1442ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } else { 1443ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru // BEGIN property other than STANDARD/DAYLIGHT 1444ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru // must not be there. 1445ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru goto cleanupParse; 1446ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } 1447103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius } else if (name.compare(ICAL_END, -1) == 0) { 1448ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru break; 1449ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } 1450ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru break; 1451ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru case TZI: 1452103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius if (name.compare(ICAL_DTSTART, -1) == 0) { 1453ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru dtstart = value; 1454103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius } else if (name.compare(ICAL_TZNAME, -1) == 0) { 145585bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho zonename = value; 1456103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius } else if (name.compare(ICAL_TZOFFSETFROM, -1) == 0) { 1457ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru from = value; 1458103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius } else if (name.compare(ICAL_TZOFFSETTO, -1) == 0) { 1459ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru to = value; 1460103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius } else if (name.compare(ICAL_RDATE, -1) == 0) { 1461ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru // RDATE mixed with RRULE is not supported 1462ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru if (isRRULE) { 1463ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru goto cleanupParse; 1464ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } 1465ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru // RDATE value may contain multiple date delimited 1466ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru // by comma 1467ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru UBool nextDate = TRUE; 1468ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru int32_t dstart = 0; 1469ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru UnicodeString *dstr; 1470ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru while (nextDate) { 1471ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru int32_t dend = value.indexOf(COMMA, dstart); 1472ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru if (dend == -1) { 1473ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru dstr = new UnicodeString(value, dstart); 1474ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru nextDate = FALSE; 1475ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } else { 1476ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru dstr = new UnicodeString(value, dstart, dend - dstart); 1477ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } 1478ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru dates->addElement(dstr, status); 1479ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru if (U_FAILURE(status)) { 1480ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru goto cleanupParse; 1481ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } 1482ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru dstart = dend + 1; 1483ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } 1484103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius } else if (name.compare(ICAL_RRULE, -1) == 0) { 1485ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru // RRULE mixed with RDATE is not supported 1486ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru if (!isRRULE && dates->size() != 0) { 1487ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru goto cleanupParse; 1488ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } 1489ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru isRRULE = true; 1490ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru dates->addElement(new UnicodeString(value), status); 1491ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru if (U_FAILURE(status)) { 1492ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru goto cleanupParse; 1493ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } 1494103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius } else if (name.compare(ICAL_END, -1) == 0) { 1495ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru // Mandatory properties 1496ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru if (dtstart.length() == 0 || from.length() == 0 || to.length() == 0) { 1497ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru goto cleanupParse; 1498ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } 149985bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho // if zonename is not available, create one from tzid 150085bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho if (zonename.length() == 0) { 150185bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho getDefaultTZName(tzid, dst, zonename); 1502ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } 1503ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 1504ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru // create a time zone rule 1505ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru TimeZoneRule *rule = NULL; 1506ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru int32_t fromOffset = 0; 1507ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru int32_t toOffset = 0; 1508ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru int32_t rawOffset = 0; 1509ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru int32_t dstSavings = 0; 1510ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru UDate start = 0; 1511ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 1512ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru // Parse TZOFFSETFROM/TZOFFSETTO 1513ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru fromOffset = offsetStrToMillis(from, status); 1514ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru toOffset = offsetStrToMillis(to, status); 1515ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru if (U_FAILURE(status)) { 1516ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru goto cleanupParse; 1517ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } 1518ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 1519ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru if (dst) { 1520ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru // If daylight, use the previous offset as rawoffset if positive 1521ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru if (toOffset - fromOffset > 0) { 1522ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru rawOffset = fromOffset; 1523ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru dstSavings = toOffset - fromOffset; 1524ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } else { 1525ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru // This is rare case.. just use 1 hour DST savings 1526ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru rawOffset = toOffset - DEF_DSTSAVINGS; 1527ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru dstSavings = DEF_DSTSAVINGS; 1528ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } 1529ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } else { 1530ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru rawOffset = toOffset; 1531ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru dstSavings = 0; 1532ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } 1533ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 1534ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru // start time 1535ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru start = parseDateTimeString(dtstart, fromOffset, status); 1536ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru if (U_FAILURE(status)) { 1537ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru goto cleanupParse; 1538ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } 1539ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 1540ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru // Create the rule 1541ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru UDate actualStart = MAX_MILLIS; 1542ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru if (isRRULE) { 154385bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho rule = createRuleByRRULE(zonename, rawOffset, dstSavings, start, dates, fromOffset, status); 1544ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } else { 154585bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho rule = createRuleByRDATE(zonename, rawOffset, dstSavings, start, dates, fromOffset, status); 1546ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } 1547ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru if (U_FAILURE(status) || rule == NULL) { 1548ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru goto cleanupParse; 1549ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } else { 1550ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru UBool startAvail = rule->getFirstStart(fromOffset, 0, actualStart); 1551ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru if (startAvail && actualStart < firstStart) { 1552ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru // save from offset information for the earliest rule 1553ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru firstStart = actualStart; 1554ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru // If this is STD, assume the time before this transtion 1555ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru // is DST when the difference is 1 hour. This might not be 1556ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru // accurate, but VTIMEZONE data does not have such info. 1557ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru if (dstSavings > 0) { 1558ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru initialRawOffset = fromOffset; 1559ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru initialDSTSavings = 0; 1560ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } else { 1561ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru if (fromOffset - toOffset == DEF_DSTSAVINGS) { 1562ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru initialRawOffset = fromOffset - DEF_DSTSAVINGS; 1563ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru initialDSTSavings = DEF_DSTSAVINGS; 1564ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } else { 1565ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru initialRawOffset = fromOffset; 1566ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru initialDSTSavings = 0; 1567ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } 1568ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } 1569ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } 1570ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } 1571ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru rules->addElement(rule, status); 1572ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru if (U_FAILURE(status)) { 1573ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru goto cleanupParse; 1574ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } 1575ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru state = VTZ; 1576ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } 1577ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru break; 1578ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } 1579ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } 1580ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru // Must have at least one rule 1581ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru if (rules->size() == 0) { 1582ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru goto cleanupParse; 1583ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } 1584ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 1585ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru // Create a initial rule 158685bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho getDefaultTZName(tzid, FALSE, zonename); 158785bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho initialRule = new InitialTimeZoneRule(zonename, 1588ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru initialRawOffset, initialDSTSavings); 158985bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho if (initialRule == NULL) { 159085bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho status = U_MEMORY_ALLOCATION_ERROR; 159185bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho goto cleanupParse; 159285bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho } 1593ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 1594ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru // Finally, create the RuleBasedTimeZone 1595ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru rbtz = new RuleBasedTimeZone(tzid, initialRule); 159685bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho if (rbtz == NULL) { 159785bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho status = U_MEMORY_ALLOCATION_ERROR; 159885bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho goto cleanupParse; 159985bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho } 160085bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho initialRule = NULL; // already adopted by RBTZ, no need to delete 160185bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho 160285bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho for (n = 0; n < rules->size(); n++) { 160385bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho TimeZoneRule *r = (TimeZoneRule*)rules->elementAt(n); 160427f654740f2a26ad62a5c155af9199af9e69b889claireho AnnualTimeZoneRule *atzrule = dynamic_cast<AnnualTimeZoneRule *>(r); 160527f654740f2a26ad62a5c155af9199af9e69b889claireho if (atzrule != NULL) { 160627f654740f2a26ad62a5c155af9199af9e69b889claireho if (atzrule->getEndYear() == AnnualTimeZoneRule::MAX_YEAR) { 160785bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho finalRuleCount++; 160885bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho finalRuleIdx = n; 160985bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho } 161085bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho } 161185bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho } 161285bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho if (finalRuleCount > 2) { 161385bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho // Too many final rules 161485bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho status = U_ILLEGAL_ARGUMENT_ERROR; 161585bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho goto cleanupParse; 161685bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho } 161785bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho 161885bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho if (finalRuleCount == 1) { 161985bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho if (rules->size() == 1) { 162085bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho // Only one final rule, only governs the initial rule, 162185bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho // which is already initialized, thus, we do not need to 162285bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho // add this transition rule 162385bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho rules->removeAllElements(); 162485bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho } else { 162585bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho // Normalize the final rule 162685bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho AnnualTimeZoneRule *finalRule = (AnnualTimeZoneRule*)rules->elementAt(finalRuleIdx); 162785bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho int32_t tmpRaw = finalRule->getRawOffset(); 162885bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho int32_t tmpDST = finalRule->getDSTSavings(); 162985bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho 163085bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho // Find the last non-final rule 163185bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho UDate finalStart, start; 163285bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho finalRule->getFirstStart(initialRawOffset, initialDSTSavings, finalStart); 163385bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho start = finalStart; 163485bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho for (n = 0; n < rules->size(); n++) { 163585bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho if (finalRuleIdx == n) { 163685bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho continue; 163785bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho } 163885bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho TimeZoneRule *r = (TimeZoneRule*)rules->elementAt(n); 163985bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho UDate lastStart; 164085bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho r->getFinalStart(tmpRaw, tmpDST, lastStart); 164185bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho if (lastStart > start) { 164285bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho finalRule->getNextStart(lastStart, 164385bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho r->getRawOffset(), 164485bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho r->getDSTSavings(), 164585bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho FALSE, 164685bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho start); 164785bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho } 164885bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho } 164985bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho 165085bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho TimeZoneRule *newRule; 165185bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho UnicodeString tznam; 165285bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho if (start == finalStart) { 165385bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho // Transform this into a single transition 165485bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho newRule = new TimeArrayTimeZoneRule( 165585bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho finalRule->getName(tznam), 165685bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho finalRule->getRawOffset(), 165785bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho finalRule->getDSTSavings(), 165885bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho &finalStart, 165985bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho 1, 166085bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho DateTimeRule::UTC_TIME); 166185bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho } else { 166285bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho // Update the end year 166385bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho int32_t y, m, d, dow, doy, mid; 166485bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho Grego::timeToFields(start, y, m, d, dow, doy, mid); 166585bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho newRule = new AnnualTimeZoneRule( 166685bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho finalRule->getName(tznam), 166785bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho finalRule->getRawOffset(), 166885bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho finalRule->getDSTSavings(), 166985bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho *(finalRule->getRule()), 167085bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho finalRule->getStartYear(), 167185bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho y); 167285bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho } 167385bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho if (newRule == NULL) { 167485bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho status = U_MEMORY_ALLOCATION_ERROR; 167585bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho goto cleanupParse; 167685bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho } 167785bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho rules->removeElementAt(finalRuleIdx); 167885bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho rules->addElement(newRule, status); 167985bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho if (U_FAILURE(status)) { 168085bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho delete newRule; 168185bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho goto cleanupParse; 168285bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho } 168385bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho } 168485bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho } 168585bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho 1686ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru while (!rules->isEmpty()) { 1687ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru TimeZoneRule *tzr = (TimeZoneRule*)rules->orphanElementAt(0); 1688ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru rbtz->addTransitionRule(tzr, status); 1689ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru if (U_FAILURE(status)) { 1690ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru goto cleanupParse; 1691ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } 1692ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } 1693ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru rbtz->complete(status); 1694ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru if (U_FAILURE(status)) { 1695ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru goto cleanupParse; 1696ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } 1697ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru delete rules; 1698ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru delete dates; 1699ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 1700ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru tz = rbtz; 1701ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru setID(tzid); 1702ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru return; 1703ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 1704ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QuerucleanupParse: 1705ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru if (rules != NULL) { 1706ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru while (!rules->isEmpty()) { 1707ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru TimeZoneRule *r = (TimeZoneRule*)rules->orphanElementAt(0); 1708ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru delete r; 1709ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } 1710ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru delete rules; 1711ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } 1712ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru if (dates != NULL) { 1713ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru delete dates; 1714ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } 1715ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru if (initialRule != NULL) { 1716ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru delete initialRule; 1717ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } 1718ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru if (rbtz != NULL) { 1719ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru delete rbtz; 1720ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } 1721ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru return; 1722ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru} 1723ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 1724ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queruvoid 1725ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruVTimeZone::write(VTZWriter& writer, UErrorCode& status) const { 1726ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru if (vtzlines != NULL) { 1727ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru for (int32_t i = 0; i < vtzlines->size(); i++) { 1728ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru UnicodeString *line = (UnicodeString*)vtzlines->elementAt(i); 1729103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius if (line->startsWith(ICAL_TZURL, -1) 1730ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru && line->charAt(u_strlen(ICAL_TZURL)) == COLON) { 1731ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru writer.write(ICAL_TZURL); 1732ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru writer.write(COLON); 1733ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru writer.write(tzurl); 1734ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru writer.write(ICAL_NEWLINE); 1735103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius } else if (line->startsWith(ICAL_LASTMOD, -1) 1736ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru && line->charAt(u_strlen(ICAL_LASTMOD)) == COLON) { 1737ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru UnicodeString utcString; 1738ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru writer.write(ICAL_LASTMOD); 1739ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru writer.write(COLON); 1740ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru writer.write(getUTCDateTimeString(lastmod, utcString)); 1741ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru writer.write(ICAL_NEWLINE); 1742ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } else { 1743ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru writer.write(*line); 1744ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru writer.write(ICAL_NEWLINE); 1745ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } 1746ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } 1747ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } else { 1748ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru UVector *customProps = NULL; 1749ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru if (olsonzid.length() > 0 && icutzver.length() > 0) { 1750103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius customProps = new UVector(uprv_deleteUObject, uhash_compareUnicodeString, status); 1751ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru if (U_FAILURE(status)) { 1752ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru return; 1753ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } 1754ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru UnicodeString *icutzprop = new UnicodeString(ICU_TZINFO_PROP); 1755ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru icutzprop->append(olsonzid); 1756ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru icutzprop->append((UChar)0x005B/*'['*/); 1757ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru icutzprop->append(icutzver); 1758ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru icutzprop->append((UChar)0x005D/*']'*/); 1759ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru customProps->addElement(icutzprop, status); 1760ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru if (U_FAILURE(status)) { 1761ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru delete icutzprop; 1762ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru delete customProps; 1763ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru return; 1764ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } 1765ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } 1766ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru writeZone(writer, *tz, customProps, status); 1767ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru delete customProps; 1768ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } 1769ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru} 1770ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 1771ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queruvoid 17728393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig CorneliusVTimeZone::write(UDate start, VTZWriter& writer, UErrorCode& status) const { 1773ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru if (U_FAILURE(status)) { 1774ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru return; 1775ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } 1776ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru InitialTimeZoneRule *initial = NULL; 1777ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru UVector *transitionRules = NULL; 1778103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius UVector customProps(uprv_deleteUObject, uhash_compareUnicodeString, status); 1779ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru UnicodeString tzid; 1780ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 1781ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru // Extract rules applicable to dates after the start time 1782ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru getTimeZoneRulesAfter(start, initial, transitionRules, status); 1783ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru if (U_FAILURE(status)) { 1784ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru return; 1785ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } 1786ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 1787ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru // Create a RuleBasedTimeZone with the subset rule 1788ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru getID(tzid); 1789ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru RuleBasedTimeZone rbtz(tzid, initial); 1790ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru if (transitionRules != NULL) { 1791ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru while (!transitionRules->isEmpty()) { 1792ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru TimeZoneRule *tr = (TimeZoneRule*)transitionRules->orphanElementAt(0); 1793ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru rbtz.addTransitionRule(tr, status); 1794ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru if (U_FAILURE(status)) { 1795ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru goto cleanupWritePartial; 1796ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } 1797ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } 1798ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru delete transitionRules; 1799ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru transitionRules = NULL; 1800ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } 1801ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru rbtz.complete(status); 1802ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru if (U_FAILURE(status)) { 1803ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru goto cleanupWritePartial; 1804ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } 1805ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 1806ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru if (olsonzid.length() > 0 && icutzver.length() > 0) { 1807ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru UnicodeString *icutzprop = new UnicodeString(ICU_TZINFO_PROP); 1808ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru icutzprop->append(olsonzid); 1809ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru icutzprop->append((UChar)0x005B/*'['*/); 1810ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru icutzprop->append(icutzver); 1811103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius icutzprop->append(ICU_TZINFO_PARTIAL, -1); 1812ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru appendMillis(start, *icutzprop); 1813ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru icutzprop->append((UChar)0x005D/*']'*/); 1814ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru customProps.addElement(icutzprop, status); 1815ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru if (U_FAILURE(status)) { 1816ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru delete icutzprop; 1817ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru goto cleanupWritePartial; 1818ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } 1819ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } 1820ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru writeZone(writer, rbtz, &customProps, status); 1821ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru return; 1822ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 1823ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QuerucleanupWritePartial: 1824ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru if (initial != NULL) { 1825ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru delete initial; 1826ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } 1827ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru if (transitionRules != NULL) { 1828ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru while (!transitionRules->isEmpty()) { 1829ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru TimeZoneRule *tr = (TimeZoneRule*)transitionRules->orphanElementAt(0); 1830ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru delete tr; 1831ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } 1832ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru delete transitionRules; 1833ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } 1834ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru} 1835ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 1836ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queruvoid 18378393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig CorneliusVTimeZone::writeSimple(UDate time, VTZWriter& writer, UErrorCode& status) const { 1838ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru if (U_FAILURE(status)) { 1839ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru return; 1840ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } 1841ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 1842103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius UVector customProps(uprv_deleteUObject, uhash_compareUnicodeString, status); 1843ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru UnicodeString tzid; 1844ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 1845ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru // Extract simple rules 1846ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru InitialTimeZoneRule *initial = NULL; 1847ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru AnnualTimeZoneRule *std = NULL, *dst = NULL; 1848ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru getSimpleRulesNear(time, initial, std, dst, status); 1849ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru if (U_SUCCESS(status)) { 1850ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru // Create a RuleBasedTimeZone with the subset rule 1851ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru getID(tzid); 1852ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru RuleBasedTimeZone rbtz(tzid, initial); 1853ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru if (std != NULL && dst != NULL) { 1854ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru rbtz.addTransitionRule(std, status); 1855ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru rbtz.addTransitionRule(dst, status); 1856ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } 1857ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru if (U_FAILURE(status)) { 1858ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru goto cleanupWriteSimple; 1859ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } 1860ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 1861ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru if (olsonzid.length() > 0 && icutzver.length() > 0) { 1862ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru UnicodeString *icutzprop = new UnicodeString(ICU_TZINFO_PROP); 1863ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru icutzprop->append(olsonzid); 1864ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru icutzprop->append((UChar)0x005B/*'['*/); 1865ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru icutzprop->append(icutzver); 1866103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius icutzprop->append(ICU_TZINFO_SIMPLE, -1); 1867ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru appendMillis(time, *icutzprop); 1868ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru icutzprop->append((UChar)0x005D/*']'*/); 1869ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru customProps.addElement(icutzprop, status); 1870ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru if (U_FAILURE(status)) { 1871ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru delete icutzprop; 1872ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru goto cleanupWriteSimple; 1873ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } 1874ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } 1875ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru writeZone(writer, rbtz, &customProps, status); 1876ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } 1877ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru return; 1878ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 1879ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QuerucleanupWriteSimple: 1880ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru if (initial != NULL) { 1881ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru delete initial; 1882ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } 1883ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru if (std != NULL) { 1884ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru delete std; 1885ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } 1886ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru if (dst != NULL) { 1887ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru delete dst; 1888ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } 1889ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru} 1890ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 1891ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queruvoid 1892ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruVTimeZone::writeZone(VTZWriter& w, BasicTimeZone& basictz, 1893ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru UVector* customProps, UErrorCode& status) const { 1894ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru if (U_FAILURE(status)) { 1895ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru return; 1896ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } 1897ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru writeHeaders(w, status); 1898ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru if (U_FAILURE(status)) { 1899ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru return; 1900ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } 1901ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 1902ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru if (customProps != NULL) { 1903ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru for (int32_t i = 0; i < customProps->size(); i++) { 1904ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru UnicodeString *custprop = (UnicodeString*)customProps->elementAt(i); 1905ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru w.write(*custprop); 1906ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru w.write(ICAL_NEWLINE); 1907ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } 1908ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } 1909ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 1910ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru UDate t = MIN_MILLIS; 1911ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru UnicodeString dstName; 1912ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru int32_t dstFromOffset = 0; 1913ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru int32_t dstFromDSTSavings = 0; 1914ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru int32_t dstToOffset = 0; 1915ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru int32_t dstStartYear = 0; 1916ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru int32_t dstMonth = 0; 1917ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru int32_t dstDayOfWeek = 0; 1918ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru int32_t dstWeekInMonth = 0; 1919ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru int32_t dstMillisInDay = 0; 1920ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru UDate dstStartTime = 0.0; 1921ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru UDate dstUntilTime = 0.0; 1922ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru int32_t dstCount = 0; 1923ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru AnnualTimeZoneRule *finalDstRule = NULL; 1924ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 1925ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru UnicodeString stdName; 1926ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru int32_t stdFromOffset = 0; 1927ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru int32_t stdFromDSTSavings = 0; 1928ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru int32_t stdToOffset = 0; 1929ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru int32_t stdStartYear = 0; 1930ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru int32_t stdMonth = 0; 1931ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru int32_t stdDayOfWeek = 0; 1932ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru int32_t stdWeekInMonth = 0; 1933ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru int32_t stdMillisInDay = 0; 1934ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru UDate stdStartTime = 0.0; 1935ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru UDate stdUntilTime = 0.0; 1936ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru int32_t stdCount = 0; 1937ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru AnnualTimeZoneRule *finalStdRule = NULL; 1938ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 1939ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru int32_t year, month, dom, dow, doy, mid; 1940ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru UBool hasTransitions = FALSE; 1941ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru TimeZoneTransition tzt; 1942ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru UBool tztAvail; 1943ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru UnicodeString name; 1944ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru UBool isDst; 1945ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 1946ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru // Going through all transitions 1947ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru while (TRUE) { 1948ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru tztAvail = basictz.getNextTransition(t, FALSE, tzt); 1949ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru if (!tztAvail) { 1950ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru break; 1951ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } 1952ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru hasTransitions = TRUE; 1953ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru t = tzt.getTime(); 1954ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru tzt.getTo()->getName(name); 1955ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru isDst = (tzt.getTo()->getDSTSavings() != 0); 1956ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru int32_t fromOffset = tzt.getFrom()->getRawOffset() + tzt.getFrom()->getDSTSavings(); 1957ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru int32_t fromDSTSavings = tzt.getFrom()->getDSTSavings(); 1958ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru int32_t toOffset = tzt.getTo()->getRawOffset() + tzt.getTo()->getDSTSavings(); 1959ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru Grego::timeToFields(tzt.getTime() + fromOffset, year, month, dom, dow, doy, mid); 1960ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru int32_t weekInMonth = Grego::dayOfWeekInMonth(year, month, dom); 1961ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru UBool sameRule = FALSE; 196227f654740f2a26ad62a5c155af9199af9e69b889claireho const AnnualTimeZoneRule *atzrule; 1963ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru if (isDst) { 1964ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru if (finalDstRule == NULL 196527f654740f2a26ad62a5c155af9199af9e69b889claireho && (atzrule = dynamic_cast<const AnnualTimeZoneRule *>(tzt.getTo())) != NULL 196627f654740f2a26ad62a5c155af9199af9e69b889claireho && atzrule->getEndYear() == AnnualTimeZoneRule::MAX_YEAR 196727f654740f2a26ad62a5c155af9199af9e69b889claireho ) { 196827f654740f2a26ad62a5c155af9199af9e69b889claireho finalDstRule = (AnnualTimeZoneRule*)tzt.getTo()->clone(); 1969ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } 1970ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru if (dstCount > 0) { 1971ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru if (year == dstStartYear + dstCount 1972ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru && name.compare(dstName) == 0 1973ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru && dstFromOffset == fromOffset 1974ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru && dstToOffset == toOffset 1975ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru && dstMonth == month 1976ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru && dstDayOfWeek == dow 1977ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru && dstWeekInMonth == weekInMonth 1978ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru && dstMillisInDay == mid) { 1979ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru // Update until time 1980ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru dstUntilTime = t; 1981ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru dstCount++; 1982ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru sameRule = TRUE; 1983ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } 1984ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru if (!sameRule) { 1985ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru if (dstCount == 1) { 1986ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru writeZonePropsByTime(w, TRUE, dstName, dstFromOffset, dstToOffset, dstStartTime, 1987ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru TRUE, status); 1988ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } else { 1989ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru writeZonePropsByDOW(w, TRUE, dstName, dstFromOffset, dstToOffset, 1990ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru dstMonth, dstWeekInMonth, dstDayOfWeek, dstStartTime, dstUntilTime, status); 1991ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } 1992ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru if (U_FAILURE(status)) { 1993ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru goto cleanupWriteZone; 1994ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } 1995ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } 1996ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } 1997ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru if (!sameRule) { 1998ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru // Reset this DST information 1999ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru dstName = name; 2000ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru dstFromOffset = fromOffset; 2001ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru dstFromDSTSavings = fromDSTSavings; 2002ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru dstToOffset = toOffset; 2003ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru dstStartYear = year; 2004ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru dstMonth = month; 2005ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru dstDayOfWeek = dow; 2006ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru dstWeekInMonth = weekInMonth; 2007ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru dstMillisInDay = mid; 2008ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru dstStartTime = dstUntilTime = t; 2009ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru dstCount = 1; 2010ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } 2011ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru if (finalStdRule != NULL && finalDstRule != NULL) { 2012ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru break; 2013ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } 2014ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } else { 2015ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru if (finalStdRule == NULL 201627f654740f2a26ad62a5c155af9199af9e69b889claireho && (atzrule = dynamic_cast<const AnnualTimeZoneRule *>(tzt.getTo())) != NULL 201727f654740f2a26ad62a5c155af9199af9e69b889claireho && atzrule->getEndYear() == AnnualTimeZoneRule::MAX_YEAR 201827f654740f2a26ad62a5c155af9199af9e69b889claireho ) { 201927f654740f2a26ad62a5c155af9199af9e69b889claireho finalStdRule = (AnnualTimeZoneRule*)tzt.getTo()->clone(); 2020ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } 2021ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru if (stdCount > 0) { 2022ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru if (year == stdStartYear + stdCount 2023ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru && name.compare(stdName) == 0 2024ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru && stdFromOffset == fromOffset 2025ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru && stdToOffset == toOffset 2026ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru && stdMonth == month 2027ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru && stdDayOfWeek == dow 2028ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru && stdWeekInMonth == weekInMonth 2029ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru && stdMillisInDay == mid) { 2030ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru // Update until time 2031ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru stdUntilTime = t; 2032ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru stdCount++; 2033ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru sameRule = TRUE; 2034ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } 2035ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru if (!sameRule) { 2036ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru if (stdCount == 1) { 2037ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru writeZonePropsByTime(w, FALSE, stdName, stdFromOffset, stdToOffset, stdStartTime, 2038ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru TRUE, status); 2039ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } else { 2040ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru writeZonePropsByDOW(w, FALSE, stdName, stdFromOffset, stdToOffset, 2041ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru stdMonth, stdWeekInMonth, stdDayOfWeek, stdStartTime, stdUntilTime, status); 2042ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } 2043ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru if (U_FAILURE(status)) { 2044ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru goto cleanupWriteZone; 2045ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } 2046ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } 2047ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } 2048ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru if (!sameRule) { 2049ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru // Reset this STD information 2050ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru stdName = name; 2051ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru stdFromOffset = fromOffset; 2052ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru stdFromDSTSavings = fromDSTSavings; 2053ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru stdToOffset = toOffset; 2054ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru stdStartYear = year; 2055ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru stdMonth = month; 2056ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru stdDayOfWeek = dow; 2057ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru stdWeekInMonth = weekInMonth; 2058ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru stdMillisInDay = mid; 2059ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru stdStartTime = stdUntilTime = t; 2060ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru stdCount = 1; 2061ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } 2062ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru if (finalStdRule != NULL && finalDstRule != NULL) { 2063ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru break; 2064ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } 2065ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } 2066ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } 2067ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru if (!hasTransitions) { 2068ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru // No transition - put a single non transition RDATE 2069ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru int32_t raw, dst, offset; 2070ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru basictz.getOffset(0.0/*any time*/, FALSE, raw, dst, status); 2071ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru if (U_FAILURE(status)) { 2072ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru goto cleanupWriteZone; 2073ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } 2074ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru offset = raw + dst; 2075ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru isDst = (dst != 0); 2076ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru UnicodeString tzid; 2077ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru basictz.getID(tzid); 2078ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru getDefaultTZName(tzid, isDst, name); 2079ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru writeZonePropsByTime(w, isDst, name, 2080ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru offset, offset, DEF_TZSTARTTIME - offset, FALSE, status); 2081ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru if (U_FAILURE(status)) { 2082ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru goto cleanupWriteZone; 2083ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } 2084ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } else { 2085ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru if (dstCount > 0) { 2086ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru if (finalDstRule == NULL) { 2087ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru if (dstCount == 1) { 2088ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru writeZonePropsByTime(w, TRUE, dstName, dstFromOffset, dstToOffset, dstStartTime, 2089ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru TRUE, status); 2090ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } else { 2091ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru writeZonePropsByDOW(w, TRUE, dstName, dstFromOffset, dstToOffset, 2092ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru dstMonth, dstWeekInMonth, dstDayOfWeek, dstStartTime, dstUntilTime, status); 2093ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } 2094ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru if (U_FAILURE(status)) { 2095ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru goto cleanupWriteZone; 2096ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } 2097ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } else { 2098ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru if (dstCount == 1) { 2099ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru writeFinalRule(w, TRUE, finalDstRule, 2100ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru dstFromOffset - dstFromDSTSavings, dstFromDSTSavings, dstStartTime, status); 2101ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } else { 2102ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru // Use a single rule if possible 2103ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru if (isEquivalentDateRule(dstMonth, dstWeekInMonth, dstDayOfWeek, finalDstRule->getRule())) { 2104ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru writeZonePropsByDOW(w, TRUE, dstName, dstFromOffset, dstToOffset, 2105ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru dstMonth, dstWeekInMonth, dstDayOfWeek, dstStartTime, MAX_MILLIS, status); 2106ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } else { 2107ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru // Not equivalent rule - write out two different rules 2108ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru writeZonePropsByDOW(w, TRUE, dstName, dstFromOffset, dstToOffset, 2109ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru dstMonth, dstWeekInMonth, dstDayOfWeek, dstStartTime, dstUntilTime, status); 2110ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru if (U_FAILURE(status)) { 2111ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru goto cleanupWriteZone; 2112ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } 211359d709d503bab6e2b61931737e662dd293b40578ccornelius UDate nextStart; 211459d709d503bab6e2b61931737e662dd293b40578ccornelius UBool nextStartAvail = finalDstRule->getNextStart(dstUntilTime, dstFromOffset - dstFromDSTSavings, dstFromDSTSavings, false, nextStart); 211559d709d503bab6e2b61931737e662dd293b40578ccornelius U_ASSERT(nextStartAvail); 211659d709d503bab6e2b61931737e662dd293b40578ccornelius if (nextStartAvail) { 211759d709d503bab6e2b61931737e662dd293b40578ccornelius writeFinalRule(w, TRUE, finalDstRule, 211859d709d503bab6e2b61931737e662dd293b40578ccornelius dstFromOffset - dstFromDSTSavings, dstFromDSTSavings, nextStart, status); 211959d709d503bab6e2b61931737e662dd293b40578ccornelius } 2120ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } 2121ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } 2122ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru if (U_FAILURE(status)) { 2123ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru goto cleanupWriteZone; 2124ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } 2125ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } 2126ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } 2127ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru if (stdCount > 0) { 2128ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru if (finalStdRule == NULL) { 2129ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru if (stdCount == 1) { 2130ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru writeZonePropsByTime(w, FALSE, stdName, stdFromOffset, stdToOffset, stdStartTime, 2131ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru TRUE, status); 2132ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } else { 2133ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru writeZonePropsByDOW(w, FALSE, stdName, stdFromOffset, stdToOffset, 2134ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru stdMonth, stdWeekInMonth, stdDayOfWeek, stdStartTime, stdUntilTime, status); 2135ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } 2136ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru if (U_FAILURE(status)) { 2137ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru goto cleanupWriteZone; 2138ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } 2139ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } else { 2140ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru if (stdCount == 1) { 2141ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru writeFinalRule(w, FALSE, finalStdRule, 2142ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru stdFromOffset - stdFromDSTSavings, stdFromDSTSavings, stdStartTime, status); 2143ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } else { 2144ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru // Use a single rule if possible 2145ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru if (isEquivalentDateRule(stdMonth, stdWeekInMonth, stdDayOfWeek, finalStdRule->getRule())) { 2146ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru writeZonePropsByDOW(w, FALSE, stdName, stdFromOffset, stdToOffset, 214759d709d503bab6e2b61931737e662dd293b40578ccornelius stdMonth, stdWeekInMonth, stdDayOfWeek, stdStartTime, MAX_MILLIS, status); 2148ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } else { 2149ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru // Not equivalent rule - write out two different rules 2150ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru writeZonePropsByDOW(w, FALSE, stdName, stdFromOffset, stdToOffset, 2151ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru stdMonth, stdWeekInMonth, stdDayOfWeek, stdStartTime, stdUntilTime, status); 2152ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru if (U_FAILURE(status)) { 2153ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru goto cleanupWriteZone; 2154ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } 215559d709d503bab6e2b61931737e662dd293b40578ccornelius UDate nextStart; 215659d709d503bab6e2b61931737e662dd293b40578ccornelius UBool nextStartAvail = finalStdRule->getNextStart(stdUntilTime, stdFromOffset - stdFromDSTSavings, stdFromDSTSavings, false, nextStart); 215759d709d503bab6e2b61931737e662dd293b40578ccornelius U_ASSERT(nextStartAvail); 215859d709d503bab6e2b61931737e662dd293b40578ccornelius if (nextStartAvail) { 215959d709d503bab6e2b61931737e662dd293b40578ccornelius writeFinalRule(w, FALSE, finalStdRule, 216059d709d503bab6e2b61931737e662dd293b40578ccornelius stdFromOffset - stdFromDSTSavings, stdFromDSTSavings, nextStart, status); 216159d709d503bab6e2b61931737e662dd293b40578ccornelius } 2162ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } 2163ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } 2164ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru if (U_FAILURE(status)) { 2165ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru goto cleanupWriteZone; 2166ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } 2167ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } 2168ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } 2169ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } 2170ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru writeFooter(w, status); 2171ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 2172ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QuerucleanupWriteZone: 2173ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 2174ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru if (finalStdRule != NULL) { 2175ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru delete finalStdRule; 2176ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } 2177ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru if (finalDstRule != NULL) { 2178ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru delete finalDstRule; 2179ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } 2180ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru} 2181ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 2182ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queruvoid 2183ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruVTimeZone::writeHeaders(VTZWriter& writer, UErrorCode& status) const { 2184ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru if (U_FAILURE(status)) { 2185ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru return; 2186ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } 2187ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru UnicodeString tzid; 2188ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru tz->getID(tzid); 2189ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 2190ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru writer.write(ICAL_BEGIN); 2191ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru writer.write(COLON); 2192ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru writer.write(ICAL_VTIMEZONE); 2193ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru writer.write(ICAL_NEWLINE); 2194ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru writer.write(ICAL_TZID); 2195ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru writer.write(COLON); 2196ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru writer.write(tzid); 2197ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru writer.write(ICAL_NEWLINE); 2198ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru if (tzurl.length() != 0) { 2199ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru writer.write(ICAL_TZURL); 2200ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru writer.write(COLON); 2201ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru writer.write(tzurl); 2202ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru writer.write(ICAL_NEWLINE); 2203ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } 2204ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru if (lastmod != MAX_MILLIS) { 2205ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru UnicodeString lastmodStr; 2206ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru writer.write(ICAL_LASTMOD); 2207ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru writer.write(COLON); 2208ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru writer.write(getUTCDateTimeString(lastmod, lastmodStr)); 2209ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru writer.write(ICAL_NEWLINE); 2210ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } 2211ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru} 2212ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 2213ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru/* 2214ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * Write the closing section of the VTIMEZONE definition block 2215ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru */ 2216ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queruvoid 2217ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruVTimeZone::writeFooter(VTZWriter& writer, UErrorCode& status) const { 2218ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru if (U_FAILURE(status)) { 2219ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru return; 2220ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } 2221ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru writer.write(ICAL_END); 2222ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru writer.write(COLON); 2223ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru writer.write(ICAL_VTIMEZONE); 2224ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru writer.write(ICAL_NEWLINE); 2225ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru} 2226ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 2227ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru/* 2228ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * Write a single start time 2229ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru */ 2230ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queruvoid 223185bf2e2fbc60a9f938064abc8127d61da7d19882Claire HoVTimeZone::writeZonePropsByTime(VTZWriter& writer, UBool isDst, const UnicodeString& zonename, 2232ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru int32_t fromOffset, int32_t toOffset, UDate time, UBool withRDATE, 2233ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru UErrorCode& status) const { 2234ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru if (U_FAILURE(status)) { 2235ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru return; 2236ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } 223785bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho beginZoneProps(writer, isDst, zonename, fromOffset, toOffset, time, status); 2238ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru if (U_FAILURE(status)) { 2239ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru return; 2240ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } 2241ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru if (withRDATE) { 2242ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru writer.write(ICAL_RDATE); 2243ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru writer.write(COLON); 2244ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru UnicodeString timestr; 2245ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru writer.write(getDateTimeString(time + fromOffset, timestr)); 2246ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru writer.write(ICAL_NEWLINE); 2247ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } 2248ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru endZoneProps(writer, isDst, status); 2249ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru if (U_FAILURE(status)) { 2250ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru return; 2251ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } 2252ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru} 2253ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 2254ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru/* 2255ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * Write start times defined by a DOM rule using VTIMEZONE RRULE 2256ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru */ 2257ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queruvoid 225885bf2e2fbc60a9f938064abc8127d61da7d19882Claire HoVTimeZone::writeZonePropsByDOM(VTZWriter& writer, UBool isDst, const UnicodeString& zonename, 2259ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru int32_t fromOffset, int32_t toOffset, 2260ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru int32_t month, int32_t dayOfMonth, UDate startTime, UDate untilTime, 2261ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru UErrorCode& status) const { 2262ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru if (U_FAILURE(status)) { 2263ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru return; 2264ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } 226585bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho beginZoneProps(writer, isDst, zonename, fromOffset, toOffset, startTime, status); 2266ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru if (U_FAILURE(status)) { 2267ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru return; 2268ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } 2269ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru beginRRULE(writer, month, status); 2270ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru if (U_FAILURE(status)) { 2271ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru return; 2272ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } 2273ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru writer.write(ICAL_BYMONTHDAY); 2274ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru writer.write(EQUALS_SIGN); 2275ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru UnicodeString dstr; 2276ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru appendAsciiDigits(dayOfMonth, 0, dstr); 2277ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru writer.write(dstr); 2278ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru if (untilTime != MAX_MILLIS) { 2279ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru appendUNTIL(writer, getDateTimeString(untilTime + fromOffset, dstr), status); 2280ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru if (U_FAILURE(status)) { 2281ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru return; 2282ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } 2283ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } 2284ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru writer.write(ICAL_NEWLINE); 2285ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru endZoneProps(writer, isDst, status); 2286ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru} 2287ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 2288ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru/* 2289ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * Write start times defined by a DOW rule using VTIMEZONE RRULE 2290ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru */ 2291ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queruvoid 229285bf2e2fbc60a9f938064abc8127d61da7d19882Claire HoVTimeZone::writeZonePropsByDOW(VTZWriter& writer, UBool isDst, const UnicodeString& zonename, 2293ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru int32_t fromOffset, int32_t toOffset, 2294ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru int32_t month, int32_t weekInMonth, int32_t dayOfWeek, 2295ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru UDate startTime, UDate untilTime, UErrorCode& status) const { 2296ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru if (U_FAILURE(status)) { 2297ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru return; 2298ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } 229985bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho beginZoneProps(writer, isDst, zonename, fromOffset, toOffset, startTime, status); 2300ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru if (U_FAILURE(status)) { 2301ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru return; 2302ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } 2303ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru beginRRULE(writer, month, status); 2304ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru if (U_FAILURE(status)) { 2305ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru return; 2306ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } 2307ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru writer.write(ICAL_BYDAY); 2308ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru writer.write(EQUALS_SIGN); 2309ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru UnicodeString dstr; 2310ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru appendAsciiDigits(weekInMonth, 0, dstr); 2311ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru writer.write(dstr); // -4, -3, -2, -1, 1, 2, 3, 4 2312ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru writer.write(ICAL_DOW_NAMES[dayOfWeek - 1]); // SU, MO, TU... 2313ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 2314ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru if (untilTime != MAX_MILLIS) { 2315ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru appendUNTIL(writer, getDateTimeString(untilTime + fromOffset, dstr), status); 2316ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru if (U_FAILURE(status)) { 2317ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru return; 2318ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } 2319ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } 2320ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru writer.write(ICAL_NEWLINE); 2321ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru endZoneProps(writer, isDst, status); 2322ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru} 2323ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 2324ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru/* 2325ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * Write start times defined by a DOW_GEQ_DOM rule using VTIMEZONE RRULE 2326ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru */ 2327ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queruvoid 232885bf2e2fbc60a9f938064abc8127d61da7d19882Claire HoVTimeZone::writeZonePropsByDOW_GEQ_DOM(VTZWriter& writer, UBool isDst, const UnicodeString& zonename, 2329ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru int32_t fromOffset, int32_t toOffset, 2330ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru int32_t month, int32_t dayOfMonth, int32_t dayOfWeek, 2331ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru UDate startTime, UDate untilTime, UErrorCode& status) const { 2332ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru if (U_FAILURE(status)) { 2333ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru return; 2334ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } 2335ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru // Check if this rule can be converted to DOW rule 2336ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru if (dayOfMonth%7 == 1) { 2337ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru // Can be represented by DOW rule 233885bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho writeZonePropsByDOW(writer, isDst, zonename, fromOffset, toOffset, 2339ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru month, (dayOfMonth + 6)/7, dayOfWeek, startTime, untilTime, status); 2340ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru if (U_FAILURE(status)) { 2341ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru return; 2342ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } 2343ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } else if (month != UCAL_FEBRUARY && (MONTHLENGTH[month] - dayOfMonth)%7 == 6) { 2344ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru // Can be represented by DOW rule with negative week number 234585bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho writeZonePropsByDOW(writer, isDst, zonename, fromOffset, toOffset, 2346ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru month, -1*((MONTHLENGTH[month] - dayOfMonth + 1)/7), dayOfWeek, startTime, untilTime, status); 2347ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru if (U_FAILURE(status)) { 2348ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru return; 2349ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } 2350ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } else { 2351ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru // Otherwise, use BYMONTHDAY to include all possible dates 235285bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho beginZoneProps(writer, isDst, zonename, fromOffset, toOffset, startTime, status); 2353ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru if (U_FAILURE(status)) { 2354ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru return; 2355ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } 2356ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru // Check if all days are in the same month 2357ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru int32_t startDay = dayOfMonth; 2358ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru int32_t currentMonthDays = 7; 2359ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 2360ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru if (dayOfMonth <= 0) { 2361ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru // The start day is in previous month 2362ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru int32_t prevMonthDays = 1 - dayOfMonth; 2363ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru currentMonthDays -= prevMonthDays; 2364ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 2365ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru int32_t prevMonth = (month - 1) < 0 ? 11 : month - 1; 2366ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 2367ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru // Note: When a rule is separated into two, UNTIL attribute needs to be 2368ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru // calculated for each of them. For now, we skip this, because we basically use this method 2369ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru // only for final rules, which does not have the UNTIL attribute 2370ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru writeZonePropsByDOW_GEQ_DOM_sub(writer, prevMonth, -prevMonthDays, dayOfWeek, prevMonthDays, 2371ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru MAX_MILLIS /* Do not use UNTIL */, fromOffset, status); 2372ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru if (U_FAILURE(status)) { 2373ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru return; 2374ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } 2375ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 2376ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru // Start from 1 for the rest 2377ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru startDay = 1; 2378ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } else if (dayOfMonth + 6 > MONTHLENGTH[month]) { 2379ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru // Note: This code does not actually work well in February. For now, days in month in 2380ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru // non-leap year. 2381ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru int32_t nextMonthDays = dayOfMonth + 6 - MONTHLENGTH[month]; 2382ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru currentMonthDays -= nextMonthDays; 2383ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 2384ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru int32_t nextMonth = (month + 1) > 11 ? 0 : month + 1; 2385ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 2386ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru writeZonePropsByDOW_GEQ_DOM_sub(writer, nextMonth, 1, dayOfWeek, nextMonthDays, 2387ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru MAX_MILLIS /* Do not use UNTIL */, fromOffset, status); 2388ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru if (U_FAILURE(status)) { 2389ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru return; 2390ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } 2391ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } 2392ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru writeZonePropsByDOW_GEQ_DOM_sub(writer, month, startDay, dayOfWeek, currentMonthDays, 2393ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru untilTime, fromOffset, status); 2394ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru if (U_FAILURE(status)) { 2395ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru return; 2396ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } 2397ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru endZoneProps(writer, isDst, status); 2398ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } 2399ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru} 2400ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 2401ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru/* 2402ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * Called from writeZonePropsByDOW_GEQ_DOM 2403ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru */ 2404ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queruvoid 2405ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruVTimeZone::writeZonePropsByDOW_GEQ_DOM_sub(VTZWriter& writer, int32_t month, int32_t dayOfMonth, 2406ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru int32_t dayOfWeek, int32_t numDays, 2407ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru UDate untilTime, int32_t fromOffset, UErrorCode& status) const { 2408ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 2409ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru if (U_FAILURE(status)) { 2410ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru return; 2411ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } 2412ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru int32_t startDayNum = dayOfMonth; 2413ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru UBool isFeb = (month == UCAL_FEBRUARY); 2414ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru if (dayOfMonth < 0 && !isFeb) { 2415ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru // Use positive number if possible 2416ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru startDayNum = MONTHLENGTH[month] + dayOfMonth + 1; 2417ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } 2418ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru beginRRULE(writer, month, status); 2419ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru if (U_FAILURE(status)) { 2420ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru return; 2421ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } 2422ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru writer.write(ICAL_BYDAY); 2423ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru writer.write(EQUALS_SIGN); 2424ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru writer.write(ICAL_DOW_NAMES[dayOfWeek - 1]); // SU, MO, TU... 2425ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru writer.write(SEMICOLON); 2426ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru writer.write(ICAL_BYMONTHDAY); 2427ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru writer.write(EQUALS_SIGN); 2428ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 2429ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru UnicodeString dstr; 2430ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru appendAsciiDigits(startDayNum, 0, dstr); 2431ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru writer.write(dstr); 2432ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru for (int32_t i = 1; i < numDays; i++) { 2433ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru writer.write(COMMA); 2434ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru dstr.remove(); 2435ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru appendAsciiDigits(startDayNum + i, 0, dstr); 2436ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru writer.write(dstr); 2437ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } 2438ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 2439ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru if (untilTime != MAX_MILLIS) { 2440ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru appendUNTIL(writer, getDateTimeString(untilTime + fromOffset, dstr), status); 2441ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru if (U_FAILURE(status)) { 2442ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru return; 2443ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } 2444ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } 2445ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru writer.write(ICAL_NEWLINE); 2446ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru} 2447ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 2448ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru/* 2449ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * Write start times defined by a DOW_LEQ_DOM rule using VTIMEZONE RRULE 2450ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru */ 2451ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queruvoid 245285bf2e2fbc60a9f938064abc8127d61da7d19882Claire HoVTimeZone::writeZonePropsByDOW_LEQ_DOM(VTZWriter& writer, UBool isDst, const UnicodeString& zonename, 2453ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru int32_t fromOffset, int32_t toOffset, 2454ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru int32_t month, int32_t dayOfMonth, int32_t dayOfWeek, 2455ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru UDate startTime, UDate untilTime, UErrorCode& status) const { 2456ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru if (U_FAILURE(status)) { 2457ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru return; 2458ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } 2459ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru // Check if this rule can be converted to DOW rule 2460ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru if (dayOfMonth%7 == 0) { 2461ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru // Can be represented by DOW rule 246285bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho writeZonePropsByDOW(writer, isDst, zonename, fromOffset, toOffset, 2463ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru month, dayOfMonth/7, dayOfWeek, startTime, untilTime, status); 2464ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } else if (month != UCAL_FEBRUARY && (MONTHLENGTH[month] - dayOfMonth)%7 == 0){ 2465ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru // Can be represented by DOW rule with negative week number 246685bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho writeZonePropsByDOW(writer, isDst, zonename, fromOffset, toOffset, 2467ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru month, -1*((MONTHLENGTH[month] - dayOfMonth)/7 + 1), dayOfWeek, startTime, untilTime, status); 2468ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } else if (month == UCAL_FEBRUARY && dayOfMonth == 29) { 2469ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru // Specical case for February 247085bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho writeZonePropsByDOW(writer, isDst, zonename, fromOffset, toOffset, 2471ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru UCAL_FEBRUARY, -1, dayOfWeek, startTime, untilTime, status); 2472ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } else { 2473ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru // Otherwise, convert this to DOW_GEQ_DOM rule 247485bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho writeZonePropsByDOW_GEQ_DOM(writer, isDst, zonename, fromOffset, toOffset, 2475ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru month, dayOfMonth - 6, dayOfWeek, startTime, untilTime, status); 2476ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } 2477ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru} 2478ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 2479ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru/* 2480ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * Write the final time zone rule using RRULE, with no UNTIL attribute 2481ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru */ 2482ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queruvoid 2483ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruVTimeZone::writeFinalRule(VTZWriter& writer, UBool isDst, const AnnualTimeZoneRule* rule, 2484ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru int32_t fromRawOffset, int32_t fromDSTSavings, 2485ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru UDate startTime, UErrorCode& status) const { 2486ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru if (U_FAILURE(status)) { 2487ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru return; 2488ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } 2489ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru UBool modifiedRule = TRUE; 2490ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru const DateTimeRule *dtrule = toWallTimeRule(rule->getRule(), fromRawOffset, fromDSTSavings); 2491ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru if (dtrule == NULL) { 2492ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru modifiedRule = FALSE; 2493ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru dtrule = rule->getRule(); 2494ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } 249527f654740f2a26ad62a5c155af9199af9e69b889claireho 249627f654740f2a26ad62a5c155af9199af9e69b889claireho // If the rule's mills in a day is out of range, adjust start time. 249727f654740f2a26ad62a5c155af9199af9e69b889claireho // Olson tzdata supports 24:00 of a day, but VTIMEZONE does not. 249827f654740f2a26ad62a5c155af9199af9e69b889claireho // See ticket#7008/#7518 249927f654740f2a26ad62a5c155af9199af9e69b889claireho 250027f654740f2a26ad62a5c155af9199af9e69b889claireho int32_t timeInDay = dtrule->getRuleMillisInDay(); 250127f654740f2a26ad62a5c155af9199af9e69b889claireho if (timeInDay < 0) { 250227f654740f2a26ad62a5c155af9199af9e69b889claireho startTime = startTime + (0 - timeInDay); 250327f654740f2a26ad62a5c155af9199af9e69b889claireho } else if (timeInDay >= U_MILLIS_PER_DAY) { 250427f654740f2a26ad62a5c155af9199af9e69b889claireho startTime = startTime - (timeInDay - (U_MILLIS_PER_DAY - 1)); 250527f654740f2a26ad62a5c155af9199af9e69b889claireho } 250627f654740f2a26ad62a5c155af9199af9e69b889claireho 2507ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru int32_t toOffset = rule->getRawOffset() + rule->getDSTSavings(); 2508ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru UnicodeString name; 2509ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru rule->getName(name); 2510ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru switch (dtrule->getDateRuleType()) { 2511ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru case DateTimeRule::DOM: 2512ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru writeZonePropsByDOM(writer, isDst, name, fromRawOffset + fromDSTSavings, toOffset, 2513ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru dtrule->getRuleMonth(), dtrule->getRuleDayOfMonth(), startTime, MAX_MILLIS, status); 2514ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru break; 2515ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru case DateTimeRule::DOW: 2516ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru writeZonePropsByDOW(writer, isDst, name, fromRawOffset + fromDSTSavings, toOffset, 2517ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru dtrule->getRuleMonth(), dtrule->getRuleWeekInMonth(), dtrule->getRuleDayOfWeek(), startTime, MAX_MILLIS, status); 2518ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru break; 2519ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru case DateTimeRule::DOW_GEQ_DOM: 2520ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru writeZonePropsByDOW_GEQ_DOM(writer, isDst, name, fromRawOffset + fromDSTSavings, toOffset, 2521ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru dtrule->getRuleMonth(), dtrule->getRuleDayOfMonth(), dtrule->getRuleDayOfWeek(), startTime, MAX_MILLIS, status); 2522ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru break; 2523ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru case DateTimeRule::DOW_LEQ_DOM: 2524ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru writeZonePropsByDOW_LEQ_DOM(writer, isDst, name, fromRawOffset + fromDSTSavings, toOffset, 2525ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru dtrule->getRuleMonth(), dtrule->getRuleDayOfMonth(), dtrule->getRuleDayOfWeek(), startTime, MAX_MILLIS, status); 2526ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru break; 2527ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } 2528ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru if (modifiedRule) { 2529ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru delete dtrule; 2530ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } 2531ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru} 2532ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 2533ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru/* 2534ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * Write the opening section of zone properties 2535ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru */ 2536ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queruvoid 253785bf2e2fbc60a9f938064abc8127d61da7d19882Claire HoVTimeZone::beginZoneProps(VTZWriter& writer, UBool isDst, const UnicodeString& zonename, 2538ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru int32_t fromOffset, int32_t toOffset, UDate startTime, UErrorCode& status) const { 2539ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru if (U_FAILURE(status)) { 2540ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru return; 2541ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } 2542ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru writer.write(ICAL_BEGIN); 2543ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru writer.write(COLON); 2544ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru if (isDst) { 2545ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru writer.write(ICAL_DAYLIGHT); 2546ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } else { 2547ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru writer.write(ICAL_STANDARD); 2548ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } 2549ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru writer.write(ICAL_NEWLINE); 2550ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 2551ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru UnicodeString dstr; 2552ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 2553ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru // TZOFFSETTO 2554ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru writer.write(ICAL_TZOFFSETTO); 2555ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru writer.write(COLON); 2556ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru millisToOffset(toOffset, dstr); 2557ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru writer.write(dstr); 2558ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru writer.write(ICAL_NEWLINE); 2559ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 2560ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru // TZOFFSETFROM 2561ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru writer.write(ICAL_TZOFFSETFROM); 2562ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru writer.write(COLON); 2563ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru millisToOffset(fromOffset, dstr); 2564ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru writer.write(dstr); 2565ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru writer.write(ICAL_NEWLINE); 2566ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 2567ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru // TZNAME 2568ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru writer.write(ICAL_TZNAME); 2569ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru writer.write(COLON); 257085bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho writer.write(zonename); 2571ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru writer.write(ICAL_NEWLINE); 2572ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 2573ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru // DTSTART 2574ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru writer.write(ICAL_DTSTART); 2575ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru writer.write(COLON); 2576ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru writer.write(getDateTimeString(startTime + fromOffset, dstr)); 2577ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru writer.write(ICAL_NEWLINE); 2578ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru} 2579ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 2580ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru/* 2581ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * Writes the closing section of zone properties 2582ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru */ 2583ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queruvoid 2584ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruVTimeZone::endZoneProps(VTZWriter& writer, UBool isDst, UErrorCode& status) const { 2585ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru if (U_FAILURE(status)) { 2586ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru return; 2587ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } 2588ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru // END:STANDARD or END:DAYLIGHT 2589ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru writer.write(ICAL_END); 2590ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru writer.write(COLON); 2591ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru if (isDst) { 2592ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru writer.write(ICAL_DAYLIGHT); 2593ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } else { 2594ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru writer.write(ICAL_STANDARD); 2595ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } 2596ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru writer.write(ICAL_NEWLINE); 2597ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru} 2598ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 2599ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru/* 2600ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * Write the beggining part of RRULE line 2601ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru */ 2602ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queruvoid 2603ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruVTimeZone::beginRRULE(VTZWriter& writer, int32_t month, UErrorCode& status) const { 2604ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru if (U_FAILURE(status)) { 2605ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru return; 2606ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } 2607ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru UnicodeString dstr; 2608ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru writer.write(ICAL_RRULE); 2609ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru writer.write(COLON); 2610ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru writer.write(ICAL_FREQ); 2611ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru writer.write(EQUALS_SIGN); 2612ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru writer.write(ICAL_YEARLY); 2613ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru writer.write(SEMICOLON); 2614ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru writer.write(ICAL_BYMONTH); 2615ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru writer.write(EQUALS_SIGN); 2616ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru appendAsciiDigits(month + 1, 0, dstr); 2617ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru writer.write(dstr); 2618ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru writer.write(SEMICOLON); 2619ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru} 2620ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 2621ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru/* 2622ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * Append the UNTIL attribute after RRULE line 2623ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru */ 2624ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queruvoid 2625ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruVTimeZone::appendUNTIL(VTZWriter& writer, const UnicodeString& until, UErrorCode& status) const { 2626ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru if (U_FAILURE(status)) { 2627ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru return; 2628ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } 2629ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru if (until.length() > 0) { 2630ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru writer.write(SEMICOLON); 2631ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru writer.write(ICAL_UNTIL); 2632ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru writer.write(EQUALS_SIGN); 2633ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru writer.write(until); 2634ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } 2635ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru} 2636ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 2637ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruU_NAMESPACE_END 2638ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 2639ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#endif /* #if !UCONFIG_NO_FORMATTING */ 2640ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 2641ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru//eof 2642