]>
Commit | Line | Data |
---|---|---|
b75a7d8f A |
1 | /* |
2 | ******************************************************************************* | |
73c04bcf | 3 | * Copyright (C) 1996-2006, International Business Machines |
b75a7d8f A |
4 | * Corporation and others. All Rights Reserved. |
5 | ******************************************************************************* | |
6 | */ | |
7 | ||
8 | #include "unicode/utypes.h" | |
9 | ||
10 | #if !UCONFIG_NO_FORMATTING | |
11 | ||
12 | #include "unicode/ucal.h" | |
13 | #include "unicode/uloc.h" | |
14 | #include "unicode/calendar.h" | |
15 | #include "unicode/timezone.h" | |
73c04bcf | 16 | #include "unicode/gregocal.h" |
b75a7d8f A |
17 | #include "unicode/simpletz.h" |
18 | #include "unicode/ustring.h" | |
19 | #include "unicode/strenum.h" | |
20 | #include "cmemory.h" | |
21 | #include "ustrenum.h" | |
22 | ||
23 | U_NAMESPACE_USE | |
24 | ||
25 | static TimeZone* | |
26 | _createTimeZone(const UChar* zoneID, int32_t len, UErrorCode* ec) { | |
27 | TimeZone* zone = NULL; | |
28 | if (ec!=NULL && U_SUCCESS(*ec)) { | |
29 | // Note that if zoneID is invalid, we get back GMT. This odd | |
30 | // behavior is by design and goes back to the JDK. The only | |
31 | // failure we will see is a memory allocation failure. | |
32 | int32_t l = (len<0 ? u_strlen(zoneID) : len); | |
374ca955 A |
33 | UnicodeString zoneStrID; |
34 | zoneStrID.setTo((UBool)(len < 0), zoneID, l); /* temporary read-only alias */ | |
35 | zone = TimeZone::createTimeZone(zoneStrID); | |
b75a7d8f A |
36 | if (zone == NULL) { |
37 | *ec = U_MEMORY_ALLOCATION_ERROR; | |
38 | } | |
39 | } | |
40 | return zone; | |
41 | } | |
42 | ||
43 | U_CAPI UEnumeration* U_EXPORT2 | |
44 | ucal_openTimeZones(UErrorCode* ec) { | |
45 | return uenum_openStringEnumeration(TimeZone::createEnumeration(), ec); | |
46 | } | |
47 | ||
48 | U_CAPI UEnumeration* U_EXPORT2 | |
49 | ucal_openCountryTimeZones(const char* country, UErrorCode* ec) { | |
50 | return uenum_openStringEnumeration(TimeZone::createEnumeration(country), ec); | |
51 | } | |
52 | ||
53 | U_CAPI int32_t U_EXPORT2 | |
54 | ucal_getDefaultTimeZone(UChar* result, int32_t resultCapacity, UErrorCode* ec) { | |
55 | int32_t len = 0; | |
56 | if (ec!=NULL && U_SUCCESS(*ec)) { | |
57 | TimeZone* zone = TimeZone::createDefault(); | |
58 | if (zone == NULL) { | |
59 | *ec = U_MEMORY_ALLOCATION_ERROR; | |
60 | } else { | |
61 | UnicodeString id; | |
62 | zone->getID(id); | |
63 | delete zone; | |
64 | len = id.extract(result, resultCapacity, *ec); | |
65 | } | |
66 | } | |
67 | return len; | |
68 | } | |
69 | ||
70 | U_CAPI void U_EXPORT2 | |
71 | ucal_setDefaultTimeZone(const UChar* zoneID, UErrorCode* ec) { | |
72 | TimeZone* zone = _createTimeZone(zoneID, -1, ec); | |
73 | if (zone != NULL) { | |
74 | TimeZone::adoptDefault(zone); | |
75 | } | |
76 | } | |
77 | ||
78 | U_CAPI int32_t U_EXPORT2 | |
79 | ucal_getDSTSavings(const UChar* zoneID, UErrorCode* ec) { | |
80 | int32_t result = 0; | |
81 | TimeZone* zone = _createTimeZone(zoneID, -1, ec); | |
374ca955 A |
82 | if (U_SUCCESS(*ec)) { |
83 | if (zone->getDynamicClassID() == SimpleTimeZone::getStaticClassID()) { | |
84 | result = ((SimpleTimeZone*) zone)->getDSTSavings(); | |
85 | } else { | |
86 | // Since there is no getDSTSavings on TimeZone, we use a | |
87 | // heuristic: Starting with the current time, march | |
88 | // forwards for one year, looking for DST savings. | |
89 | // Stepping by weeks is sufficient. | |
90 | UDate d = Calendar::getNow(); | |
91 | for (int32_t i=0; i<53; ++i, d+=U_MILLIS_PER_DAY*7.0) { | |
92 | int32_t raw, dst; | |
93 | zone->getOffset(d, FALSE, raw, dst, *ec); | |
94 | if (U_FAILURE(*ec)) { | |
95 | break; | |
96 | } else if (dst != 0) { | |
97 | result = dst; | |
98 | break; | |
99 | } | |
100 | } | |
101 | } | |
b75a7d8f A |
102 | } |
103 | delete zone; | |
104 | return result; | |
105 | } | |
106 | ||
374ca955 | 107 | #ifdef U_USE_UCAL_OBSOLETE_2_8 |
b75a7d8f A |
108 | U_CAPI const UChar* U_EXPORT2 |
109 | ucal_getAvailableTZIDs( int32_t rawOffset, | |
110 | int32_t index, | |
111 | UErrorCode* status) | |
112 | { | |
113 | ||
114 | if(U_FAILURE(*status)) return 0; | |
115 | ||
116 | int32_t count = 0; | |
117 | const UChar *retVal = 0; | |
118 | ||
119 | const UnicodeString** tzs = TimeZone::createAvailableIDs(rawOffset, | |
120 | count); | |
121 | ||
122 | if(tzs == 0) { | |
123 | *status = U_MEMORY_ALLOCATION_ERROR; | |
124 | return 0; | |
125 | } | |
126 | ||
127 | if(index < count) | |
128 | retVal = tzs[index]->getBuffer(); | |
129 | else | |
130 | *status = U_INDEX_OUTOFBOUNDS_ERROR; | |
131 | ||
132 | uprv_free(tzs); | |
133 | return retVal; | |
134 | } | |
135 | ||
136 | U_CAPI int32_t U_EXPORT2 | |
137 | ucal_countAvailableTZIDs(int32_t rawOffset) | |
138 | { | |
139 | ||
140 | int32_t count = 0; | |
141 | ||
142 | const UnicodeString** tzs = TimeZone::createAvailableIDs(rawOffset, | |
143 | count); | |
144 | ||
145 | if(tzs == 0) { | |
146 | // TBD: U_MEMORY_ALLOCATION_ERROR | |
147 | return 0; | |
148 | } | |
149 | ||
150 | uprv_free(tzs); | |
151 | return count; | |
152 | } | |
374ca955 | 153 | #endif |
b75a7d8f A |
154 | |
155 | U_CAPI UDate U_EXPORT2 | |
156 | ucal_getNow() | |
157 | { | |
158 | ||
159 | return Calendar::getNow(); | |
160 | } | |
161 | ||
162 | // ignore type until we add more subclasses | |
163 | U_CAPI UCalendar* U_EXPORT2 | |
164 | ucal_open( const UChar* zoneID, | |
165 | int32_t len, | |
166 | const char* locale, | |
167 | UCalendarType /*type*/, | |
168 | UErrorCode* status) | |
169 | { | |
170 | ||
171 | if(U_FAILURE(*status)) return 0; | |
172 | ||
173 | TimeZone* zone = (zoneID==NULL) ? TimeZone::createDefault() | |
174 | : _createTimeZone(zoneID, len, status); | |
175 | ||
176 | if (U_FAILURE(*status)) { | |
177 | return NULL; | |
178 | } | |
179 | ||
180 | return (UCalendar*)Calendar::createInstance(zone, Locale(locale), *status); | |
181 | } | |
182 | ||
183 | U_CAPI void U_EXPORT2 | |
184 | ucal_close(UCalendar *cal) | |
185 | { | |
186 | ||
187 | delete (Calendar*) cal; | |
188 | } | |
189 | ||
190 | U_CAPI void U_EXPORT2 | |
191 | ucal_setTimeZone( UCalendar* cal, | |
192 | const UChar* zoneID, | |
193 | int32_t len, | |
194 | UErrorCode *status) | |
195 | { | |
196 | ||
197 | if(U_FAILURE(*status)) | |
198 | return; | |
199 | ||
200 | TimeZone* zone = (zoneID==NULL) ? TimeZone::createDefault() | |
201 | : _createTimeZone(zoneID, len, status); | |
202 | ||
203 | if (zone != NULL) { | |
204 | ((Calendar*)cal)->adoptTimeZone(zone); | |
205 | } | |
206 | } | |
207 | ||
208 | U_CAPI int32_t U_EXPORT2 | |
209 | ucal_getTimeZoneDisplayName(const UCalendar* cal, | |
210 | UCalendarDisplayNameType type, | |
211 | const char *locale, | |
212 | UChar* result, | |
213 | int32_t resultLength, | |
214 | UErrorCode* status) | |
215 | { | |
216 | ||
217 | if(U_FAILURE(*status)) return -1; | |
218 | ||
219 | const TimeZone& tz = ((Calendar*)cal)->getTimeZone(); | |
220 | UnicodeString id; | |
221 | if(!(result==NULL && resultLength==0)) { | |
222 | // NULL destination for pure preflighting: empty dummy string | |
223 | // otherwise, alias the destination buffer | |
224 | id.setTo(result, 0, resultLength); | |
225 | } | |
226 | ||
227 | switch(type) { | |
228 | case UCAL_STANDARD: | |
229 | tz.getDisplayName(FALSE, TimeZone::LONG, Locale(locale), id); | |
230 | break; | |
231 | ||
232 | case UCAL_SHORT_STANDARD: | |
233 | tz.getDisplayName(FALSE, TimeZone::SHORT, Locale(locale), id); | |
234 | break; | |
235 | ||
236 | case UCAL_DST: | |
237 | tz.getDisplayName(TRUE, TimeZone::LONG, Locale(locale), id); | |
238 | break; | |
239 | ||
240 | case UCAL_SHORT_DST: | |
241 | tz.getDisplayName(TRUE, TimeZone::SHORT, Locale(locale), id); | |
242 | break; | |
243 | } | |
244 | ||
245 | return id.extract(result, resultLength, *status); | |
246 | } | |
247 | ||
248 | U_CAPI UBool U_EXPORT2 | |
249 | ucal_inDaylightTime( const UCalendar* cal, | |
250 | UErrorCode* status ) | |
251 | { | |
252 | ||
253 | if(U_FAILURE(*status)) return (UBool) -1; | |
254 | return ((Calendar*)cal)->inDaylightTime(*status); | |
255 | } | |
256 | ||
73c04bcf A |
257 | U_DRAFT void U_EXPORT2 |
258 | ucal_setGregorianChange(UCalendar *cal, UDate date, UErrorCode *pErrorCode) { | |
259 | if(U_FAILURE(*pErrorCode)) { | |
260 | return; | |
261 | } | |
262 | Calendar *cpp_cal = (Calendar *)cal; | |
263 | if(cpp_cal->getDynamicClassID() != GregorianCalendar::getStaticClassID()) { | |
264 | *pErrorCode = U_UNSUPPORTED_ERROR; | |
265 | return; | |
266 | } | |
267 | ((GregorianCalendar *)cpp_cal)->setGregorianChange(date, *pErrorCode); | |
268 | } | |
269 | ||
270 | U_DRAFT UDate U_EXPORT2 | |
271 | ucal_getGregorianChange(const UCalendar *cal, UErrorCode *pErrorCode) { | |
272 | if(U_FAILURE(*pErrorCode)) { | |
273 | return (UDate)0; | |
274 | } | |
275 | Calendar *cpp_cal = (Calendar *)cal; | |
276 | if(cpp_cal->getDynamicClassID() != GregorianCalendar::getStaticClassID()) { | |
277 | *pErrorCode = U_UNSUPPORTED_ERROR; | |
278 | return (UDate)0; | |
279 | } | |
280 | return ((GregorianCalendar *)cpp_cal)->getGregorianChange(); | |
281 | } | |
282 | ||
b75a7d8f A |
283 | U_CAPI int32_t U_EXPORT2 |
284 | ucal_getAttribute( const UCalendar* cal, | |
285 | UCalendarAttribute attr) | |
286 | { | |
287 | ||
288 | switch(attr) { | |
289 | case UCAL_LENIENT: | |
290 | return ((Calendar*)cal)->isLenient(); | |
291 | ||
292 | case UCAL_FIRST_DAY_OF_WEEK: | |
293 | return ((Calendar*)cal)->getFirstDayOfWeek(); | |
294 | ||
295 | case UCAL_MINIMAL_DAYS_IN_FIRST_WEEK: | |
296 | return ((Calendar*)cal)->getMinimalDaysInFirstWeek(); | |
297 | ||
298 | default: | |
299 | break; | |
300 | } | |
301 | return -1; | |
302 | } | |
303 | ||
304 | U_CAPI void U_EXPORT2 | |
305 | ucal_setAttribute( UCalendar* cal, | |
306 | UCalendarAttribute attr, | |
307 | int32_t newValue) | |
308 | { | |
309 | ||
310 | switch(attr) { | |
311 | case UCAL_LENIENT: | |
312 | ((Calendar*)cal)->setLenient((UBool)newValue); | |
313 | break; | |
314 | ||
315 | case UCAL_FIRST_DAY_OF_WEEK: | |
316 | ((Calendar*)cal)->setFirstDayOfWeek((UCalendarDaysOfWeek)newValue); | |
317 | break; | |
318 | ||
319 | case UCAL_MINIMAL_DAYS_IN_FIRST_WEEK: | |
320 | ((Calendar*)cal)->setMinimalDaysInFirstWeek((uint8_t)newValue); | |
321 | break; | |
322 | } | |
323 | } | |
324 | ||
325 | U_CAPI const char* U_EXPORT2 | |
326 | ucal_getAvailable(int32_t index) | |
327 | { | |
328 | ||
329 | return uloc_getAvailable(index); | |
330 | } | |
331 | ||
332 | U_CAPI int32_t U_EXPORT2 | |
333 | ucal_countAvailable() | |
334 | { | |
335 | ||
336 | return uloc_countAvailable(); | |
337 | } | |
338 | ||
339 | U_CAPI UDate U_EXPORT2 | |
340 | ucal_getMillis( const UCalendar* cal, | |
341 | UErrorCode* status) | |
342 | { | |
343 | ||
344 | if(U_FAILURE(*status)) return (UDate) 0; | |
345 | ||
346 | return ((Calendar*)cal)->getTime(*status); | |
347 | } | |
348 | ||
349 | U_CAPI void U_EXPORT2 | |
350 | ucal_setMillis( UCalendar* cal, | |
351 | UDate dateTime, | |
352 | UErrorCode* status ) | |
353 | { | |
354 | if(U_FAILURE(*status)) return; | |
355 | ||
356 | ((Calendar*)cal)->setTime(dateTime, *status); | |
357 | } | |
358 | ||
359 | // TBD: why does this take an UErrorCode? | |
360 | U_CAPI void U_EXPORT2 | |
361 | ucal_setDate( UCalendar* cal, | |
362 | int32_t year, | |
363 | int32_t month, | |
364 | int32_t date, | |
365 | UErrorCode *status) | |
366 | { | |
367 | ||
368 | if(U_FAILURE(*status)) return; | |
369 | ||
370 | ((Calendar*)cal)->set(year, month, date); | |
371 | } | |
372 | ||
373 | // TBD: why does this take an UErrorCode? | |
374 | U_CAPI void U_EXPORT2 | |
375 | ucal_setDateTime( UCalendar* cal, | |
376 | int32_t year, | |
377 | int32_t month, | |
378 | int32_t date, | |
379 | int32_t hour, | |
380 | int32_t minute, | |
381 | int32_t second, | |
382 | UErrorCode *status) | |
383 | { | |
384 | if(U_FAILURE(*status)) return; | |
385 | ||
386 | ((Calendar*)cal)->set(year, month, date, hour, minute, second); | |
387 | } | |
388 | ||
389 | U_CAPI UBool U_EXPORT2 | |
390 | ucal_equivalentTo( const UCalendar* cal1, | |
391 | const UCalendar* cal2) | |
392 | { | |
393 | ||
394 | return ((Calendar*)cal1)->isEquivalentTo(*((Calendar*)cal2)); | |
395 | } | |
396 | ||
397 | U_CAPI void U_EXPORT2 | |
398 | ucal_add( UCalendar* cal, | |
399 | UCalendarDateFields field, | |
400 | int32_t amount, | |
401 | UErrorCode* status) | |
402 | { | |
403 | ||
404 | if(U_FAILURE(*status)) return; | |
405 | ||
406 | ((Calendar*)cal)->add(field, amount, *status); | |
407 | } | |
408 | ||
409 | U_CAPI void U_EXPORT2 | |
410 | ucal_roll( UCalendar* cal, | |
411 | UCalendarDateFields field, | |
412 | int32_t amount, | |
413 | UErrorCode* status) | |
414 | { | |
415 | ||
416 | if(U_FAILURE(*status)) return; | |
417 | ||
418 | ((Calendar*)cal)->roll(field, amount, *status); | |
419 | } | |
420 | ||
421 | U_CAPI int32_t U_EXPORT2 | |
422 | ucal_get( const UCalendar* cal, | |
423 | UCalendarDateFields field, | |
424 | UErrorCode* status ) | |
425 | { | |
426 | ||
427 | if(U_FAILURE(*status)) return -1; | |
428 | ||
429 | return ((Calendar*)cal)->get(field, *status); | |
430 | } | |
431 | ||
432 | U_CAPI void U_EXPORT2 | |
433 | ucal_set( UCalendar* cal, | |
434 | UCalendarDateFields field, | |
435 | int32_t value) | |
436 | { | |
437 | ||
438 | ((Calendar*)cal)->set(field, value); | |
439 | } | |
440 | ||
441 | U_CAPI UBool U_EXPORT2 | |
442 | ucal_isSet( const UCalendar* cal, | |
443 | UCalendarDateFields field) | |
444 | { | |
445 | ||
446 | return ((Calendar*)cal)->isSet(field); | |
447 | } | |
448 | ||
449 | U_CAPI void U_EXPORT2 | |
450 | ucal_clearField( UCalendar* cal, | |
451 | UCalendarDateFields field) | |
452 | { | |
453 | ||
454 | ((Calendar*)cal)->clear(field); | |
455 | } | |
456 | ||
457 | U_CAPI void U_EXPORT2 | |
458 | ucal_clear(UCalendar* calendar) | |
459 | { | |
460 | ||
461 | ((Calendar*)calendar)->clear(); | |
462 | } | |
463 | ||
464 | U_CAPI int32_t U_EXPORT2 | |
465 | ucal_getLimit( const UCalendar* cal, | |
466 | UCalendarDateFields field, | |
467 | UCalendarLimitType type, | |
468 | UErrorCode *status) | |
469 | { | |
470 | ||
471 | if(status==0 || U_FAILURE(*status)) { | |
472 | return -1; | |
473 | } | |
474 | ||
475 | switch(type) { | |
476 | case UCAL_MINIMUM: | |
477 | return ((Calendar*)cal)->getMinimum(field); | |
478 | ||
479 | case UCAL_MAXIMUM: | |
480 | return ((Calendar*)cal)->getMaximum(field); | |
481 | ||
482 | case UCAL_GREATEST_MINIMUM: | |
483 | return ((Calendar*)cal)->getGreatestMinimum(field); | |
484 | ||
485 | case UCAL_LEAST_MAXIMUM: | |
486 | return ((Calendar*)cal)->getLeastMaximum(field); | |
487 | ||
488 | case UCAL_ACTUAL_MINIMUM: | |
489 | return ((Calendar*)cal)->getActualMinimum(field, | |
490 | *status); | |
491 | ||
492 | case UCAL_ACTUAL_MAXIMUM: | |
493 | return ((Calendar*)cal)->getActualMaximum(field, | |
494 | *status); | |
495 | ||
496 | default: | |
497 | break; | |
498 | } | |
499 | return -1; | |
500 | } | |
501 | ||
374ca955 A |
502 | U_CAPI const char * U_EXPORT2 |
503 | ucal_getLocaleByType(const UCalendar *cal, ULocDataLocaleType type, UErrorCode* status) | |
504 | { | |
505 | if (cal == NULL) { | |
506 | if (U_SUCCESS(*status)) { | |
507 | *status = U_ILLEGAL_ARGUMENT_ERROR; | |
508 | } | |
509 | return NULL; | |
510 | } | |
511 | return ((Calendar*)cal)->getLocaleID(type, *status); | |
512 | } | |
513 | ||
b75a7d8f | 514 | #endif /* #if !UCONFIG_NO_FORMATTING */ |