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