1 /* 2 * Copyright (c) 2010, Haiku, Inc. 3 * Distributed under the terms of the MIT license. 4 * 5 * Authors: 6 * Adrien Destugues <pulkomandy@pulkomandy.ath.cx> 7 * Oliver Tappe <zooey@hirschkaefer.de> 8 */ 9 10 11 #include <unicode/uversion.h> 12 #include <TimeZone.h> 13 14 #include <new> 15 16 #include <unicode/locid.h> 17 #include <unicode/timezone.h> 18 #include <ICUWrapper.h> 19 20 #include <Language.h> 21 22 23 const char* BTimeZone::kNameOfGmtZone = "GMT"; 24 25 26 static const BString skEmptyString; 27 28 29 static const uint32 skNameField = 1U << 0; 30 static const uint32 skDaylightSavingNameField = 1U << 1; 31 static const uint32 skShortNameField = 1U << 2; 32 static const uint32 skShortDaylightSavingNameField = 1U << 3; 33 static const uint32 skLongGenericNameField = 1U << 4; 34 static const uint32 skGenericLocationNameField = 1U << 5; 35 static const uint32 skShortCommonlyUsedNameField = 1U << 6; 36 static const uint32 skSupportsDaylightSavingField = 1U << 7; 37 static const uint32 skOffsetFromGMTField = 1U << 8; 38 39 40 BTimeZone::BTimeZone(const char* zoneID, const BLanguage* language) 41 : 42 fICUTimeZone(NULL), 43 fICULocale(NULL), 44 fInitStatus(B_NO_INIT), 45 fInitializedFields(0) 46 { 47 SetTo(zoneID, language); 48 } 49 50 51 BTimeZone::BTimeZone(const BTimeZone& other) 52 : 53 fICUTimeZone(other.fICUTimeZone == NULL 54 ? NULL 55 : other.fICUTimeZone->clone()), 56 fICULocale(other.fICULocale == NULL 57 ? NULL 58 : other.fICULocale->clone()), 59 fInitStatus(other.fInitStatus), 60 fInitializedFields(other.fInitializedFields), 61 fZoneID(other.fZoneID), 62 fName(other.fName), 63 fDaylightSavingName(other.fDaylightSavingName), 64 fShortName(other.fShortName), 65 fShortDaylightSavingName(other.fShortDaylightSavingName), 66 fOffsetFromGMT(other.fOffsetFromGMT), 67 fSupportsDaylightSaving(other.fSupportsDaylightSaving) 68 { 69 } 70 71 72 BTimeZone::~BTimeZone() 73 { 74 delete fICULocale; 75 delete fICUTimeZone; 76 } 77 78 79 BTimeZone& BTimeZone::operator=(const BTimeZone& source) 80 { 81 delete fICUTimeZone; 82 fICUTimeZone = source.fICUTimeZone == NULL 83 ? NULL 84 : source.fICUTimeZone->clone(); 85 fICULocale = source.fICULocale == NULL 86 ? NULL 87 : source.fICULocale->clone(); 88 fInitStatus = source.fInitStatus; 89 fInitializedFields = source.fInitializedFields; 90 fZoneID = source.fZoneID; 91 fName = source.fName; 92 fDaylightSavingName = source.fDaylightSavingName; 93 fShortName = source.fShortName; 94 fShortDaylightSavingName = source.fShortDaylightSavingName; 95 fOffsetFromGMT = source.fOffsetFromGMT; 96 fSupportsDaylightSaving = source.fSupportsDaylightSaving; 97 98 return *this; 99 } 100 101 102 const BString& 103 BTimeZone::ID() const 104 { 105 return fZoneID; 106 } 107 108 109 const BString& 110 BTimeZone::Name() const 111 { 112 if ((fInitializedFields & skNameField) == 0) { 113 UnicodeString unicodeString; 114 if (fICULocale != NULL) { 115 fICUTimeZone->getDisplayName(false, TimeZone::GENERIC_LOCATION, 116 *fICULocale, unicodeString); 117 } else { 118 fICUTimeZone->getDisplayName(false, TimeZone::GENERIC_LOCATION, 119 unicodeString); 120 } 121 BStringByteSink sink(&fName); 122 unicodeString.toUTF8(sink); 123 fInitializedFields |= skNameField; 124 } 125 126 return fName; 127 } 128 129 130 const BString& 131 BTimeZone::DaylightSavingName() const 132 { 133 if ((fInitializedFields & skDaylightSavingNameField) == 0) { 134 UnicodeString unicodeString; 135 if (fICULocale != NULL) { 136 fICUTimeZone->getDisplayName(true, TimeZone::GENERIC_LOCATION, 137 *fICULocale, unicodeString); 138 } else { 139 fICUTimeZone->getDisplayName(true, TimeZone::GENERIC_LOCATION, 140 unicodeString); 141 } 142 BStringByteSink sink(&fDaylightSavingName); 143 unicodeString.toUTF8(sink); 144 fInitializedFields |= skDaylightSavingNameField; 145 } 146 147 return fDaylightSavingName; 148 } 149 150 151 const BString& 152 BTimeZone::ShortName() const 153 { 154 if ((fInitializedFields & skShortNameField) == 0) { 155 UnicodeString unicodeString; 156 if (fICULocale != NULL) { 157 fICUTimeZone->getDisplayName(false, TimeZone::SHORT, *fICULocale, 158 unicodeString); 159 } else { 160 fICUTimeZone->getDisplayName(false, TimeZone::SHORT, unicodeString); 161 } 162 BStringByteSink sink(&fShortName); 163 unicodeString.toUTF8(sink); 164 fInitializedFields |= skShortNameField; 165 } 166 167 return fShortName; 168 } 169 170 171 const BString& 172 BTimeZone::ShortDaylightSavingName() const 173 { 174 if ((fInitializedFields & skShortDaylightSavingNameField) == 0) { 175 UnicodeString unicodeString; 176 if (fICULocale != NULL) { 177 fICUTimeZone->getDisplayName(true, TimeZone::SHORT, *fICULocale, 178 unicodeString); 179 } else { 180 fICUTimeZone->getDisplayName(true, TimeZone::SHORT, unicodeString); 181 } 182 BStringByteSink sink(&fShortDaylightSavingName); 183 unicodeString.toUTF8(sink); 184 fInitializedFields |= skShortDaylightSavingNameField; 185 } 186 187 return fShortDaylightSavingName; 188 } 189 190 191 int 192 BTimeZone::OffsetFromGMT() const 193 { 194 if ((fInitializedFields & skOffsetFromGMTField) == 0) { 195 int32_t rawOffset; 196 int32_t dstOffset; 197 UDate nowMillis = 1000 * (double)time(NULL); 198 199 UErrorCode error = U_ZERO_ERROR; 200 fICUTimeZone->getOffset(nowMillis, FALSE, rawOffset, dstOffset, error); 201 if (!U_SUCCESS(error)) 202 fOffsetFromGMT = 0; 203 else { 204 fOffsetFromGMT = (rawOffset + dstOffset) / 1000; 205 // we want seconds, not ms (which ICU gives us) 206 } 207 fInitializedFields |= skOffsetFromGMTField; 208 } 209 210 return fOffsetFromGMT; 211 } 212 213 214 bool 215 BTimeZone::SupportsDaylightSaving() const 216 { 217 if ((fInitializedFields & skSupportsDaylightSavingField) == 0) { 218 fSupportsDaylightSaving = fICUTimeZone->useDaylightTime(); 219 fInitializedFields |= skSupportsDaylightSavingField; 220 } 221 222 return fSupportsDaylightSaving; 223 } 224 225 226 status_t 227 BTimeZone::InitCheck() const 228 { 229 return fInitStatus; 230 } 231 232 233 status_t 234 BTimeZone::SetLanguage(const BLanguage* language) 235 { 236 return SetTo(fZoneID, language); 237 } 238 239 240 status_t 241 BTimeZone::SetTo(const char* zoneID, const BLanguage* language) 242 { 243 delete fICULocale; 244 fICULocale = NULL; 245 delete fICUTimeZone; 246 fInitializedFields = 0; 247 248 if (zoneID == NULL || zoneID[0] == '\0') 249 fICUTimeZone = TimeZone::createDefault(); 250 else 251 fICUTimeZone = TimeZone::createTimeZone(zoneID); 252 253 if (fICUTimeZone == NULL) { 254 fInitStatus = B_NAME_NOT_FOUND; 255 return fInitStatus; 256 } 257 258 if (language != NULL) { 259 fICULocale = new Locale(language->Code()); 260 if (fICULocale == NULL) { 261 fInitStatus = B_NO_MEMORY; 262 return fInitStatus; 263 } 264 } 265 266 UnicodeString unicodeString; 267 fICUTimeZone->getID(unicodeString); 268 BStringByteSink sink(&fZoneID); 269 unicodeString.toUTF8(sink); 270 271 fInitStatus = B_OK; 272 273 return fInitStatus; 274 } 275