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