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