xref: /haiku/src/kits/locale/TimeZone.cpp (revision 1bad1ff34a3e132a8816d2ac7ba9722d3a5249a9)
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