]> git.saurik.com Git - apple/icu.git/blame - icuSources/i18n/ucal.cpp
ICU-400.39.tar.gz
[apple/icu.git] / icuSources / i18n / ucal.cpp
CommitLineData
b75a7d8f
A
1/*
2*******************************************************************************
46f4442e 3* Copyright (C) 1996-2008, 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"
46f4442e 21#include "cstring.h"
b75a7d8f
A
22#include "ustrenum.h"
23
24U_NAMESPACE_USE
25
26static 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);
374ca955
A
34 UnicodeString zoneStrID;
35 zoneStrID.setTo((UBool)(len < 0), zoneID, l); /* temporary read-only alias */
36 zone = TimeZone::createTimeZone(zoneStrID);
b75a7d8f
A
37 if (zone == NULL) {
38 *ec = U_MEMORY_ALLOCATION_ERROR;
39 }
40 }
41 return zone;
42}
43
44U_CAPI UEnumeration* U_EXPORT2
45ucal_openTimeZones(UErrorCode* ec) {
46 return uenum_openStringEnumeration(TimeZone::createEnumeration(), ec);
47}
48
49U_CAPI UEnumeration* U_EXPORT2
50ucal_openCountryTimeZones(const char* country, UErrorCode* ec) {
51 return uenum_openStringEnumeration(TimeZone::createEnumeration(country), ec);
52}
53
54U_CAPI int32_t U_EXPORT2
55ucal_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
71U_CAPI void U_EXPORT2
72ucal_setDefaultTimeZone(const UChar* zoneID, UErrorCode* ec) {
73 TimeZone* zone = _createTimeZone(zoneID, -1, ec);
74 if (zone != NULL) {
75 TimeZone::adoptDefault(zone);
76 }
77}
78
79U_CAPI int32_t U_EXPORT2
80ucal_getDSTSavings(const UChar* zoneID, UErrorCode* ec) {
81 int32_t result = 0;
82 TimeZone* zone = _createTimeZone(zoneID, -1, ec);
374ca955
A
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 }
b75a7d8f
A
103 }
104 delete zone;
105 return result;
106}
107
b75a7d8f
A
108U_CAPI UDate U_EXPORT2
109ucal_getNow()
110{
111
112 return Calendar::getNow();
113}
114
46f4442e
A
115#define ULOC_LOCALE_IDENTIFIER_CAPACITY (ULOC_FULLNAME_CAPACITY + 1 + ULOC_KEYWORD_AND_VALUES_CAPACITY)
116
b75a7d8f 117U_CAPI UCalendar* U_EXPORT2
46f4442e
A
118ucal_open( const UChar* zoneID,
119 int32_t len,
120 const char* locale,
121 UCalendarType caltype,
122 UErrorCode* status)
b75a7d8f
A
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 }
46f4442e
A
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 }
b75a7d8f
A
143 return (UCalendar*)Calendar::createInstance(zone, Locale(locale), *status);
144}
145
146U_CAPI void U_EXPORT2
147ucal_close(UCalendar *cal)
148{
149
150 delete (Calendar*) cal;
151}
152
46f4442e
A
153U_CAPI UCalendar* U_EXPORT2
154ucal_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
b75a7d8f
A
169U_CAPI void U_EXPORT2
170ucal_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
187U_CAPI int32_t U_EXPORT2
188ucal_getTimeZoneDisplayName(const UCalendar* cal,
189 UCalendarDisplayNameType type,
190 const char *locale,
191 UChar* result,
192 int32_t resultLength,
193 UErrorCode* status)
194{
195
46f4442e 196 if(U_FAILURE(*status)) return -1;
b75a7d8f 197
46f4442e
A
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 }
b75a7d8f 205
46f4442e 206 switch(type) {
b75a7d8f 207 case UCAL_STANDARD:
46f4442e
A
208 tz.getDisplayName(FALSE, TimeZone::LONG, Locale(locale), id);
209 break;
b75a7d8f
A
210
211 case UCAL_SHORT_STANDARD:
46f4442e
A
212 tz.getDisplayName(FALSE, TimeZone::SHORT, Locale(locale), id);
213 break;
b75a7d8f
A
214
215 case UCAL_DST:
46f4442e
A
216 tz.getDisplayName(TRUE, TimeZone::LONG, Locale(locale), id);
217 break;
b75a7d8f
A
218
219 case UCAL_SHORT_DST:
46f4442e
A
220 tz.getDisplayName(TRUE, TimeZone::SHORT, Locale(locale), id);
221 break;
222 }
b75a7d8f 223
46f4442e 224 return id.extract(result, resultLength, *status);
b75a7d8f
A
225}
226
227U_CAPI UBool U_EXPORT2
228ucal_inDaylightTime( const UCalendar* cal,
46f4442e 229 UErrorCode* status )
b75a7d8f
A
230{
231
46f4442e
A
232 if(U_FAILURE(*status)) return (UBool) -1;
233 return ((Calendar*)cal)->inDaylightTime(*status);
b75a7d8f
A
234}
235
46f4442e 236U_CAPI void U_EXPORT2
73c04bcf 237ucal_setGregorianChange(UCalendar *cal, UDate date, UErrorCode *pErrorCode) {
46f4442e
A
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);
73c04bcf
A
247}
248
46f4442e 249U_CAPI UDate U_EXPORT2
73c04bcf 250ucal_getGregorianChange(const UCalendar *cal, UErrorCode *pErrorCode) {
46f4442e
A
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();
73c04bcf
A
260}
261
b75a7d8f
A
262U_CAPI int32_t U_EXPORT2
263ucal_getAttribute( const UCalendar* cal,
46f4442e 264 UCalendarAttribute attr)
b75a7d8f
A
265{
266
46f4442e 267 switch(attr) {
b75a7d8f 268 case UCAL_LENIENT:
46f4442e
A
269 return ((Calendar*)cal)->isLenient();
270
b75a7d8f 271 case UCAL_FIRST_DAY_OF_WEEK:
46f4442e
A
272 return ((Calendar*)cal)->getFirstDayOfWeek();
273
b75a7d8f 274 case UCAL_MINIMAL_DAYS_IN_FIRST_WEEK:
46f4442e 275 return ((Calendar*)cal)->getMinimalDaysInFirstWeek();
b75a7d8f
A
276
277 default:
46f4442e
A
278 break;
279 }
280 return -1;
b75a7d8f
A
281}
282
283U_CAPI void U_EXPORT2
284ucal_setAttribute( UCalendar* cal,
46f4442e
A
285 UCalendarAttribute attr,
286 int32_t newValue)
b75a7d8f
A
287{
288
46f4442e 289 switch(attr) {
b75a7d8f 290 case UCAL_LENIENT:
46f4442e
A
291 ((Calendar*)cal)->setLenient((UBool)newValue);
292 break;
293
b75a7d8f 294 case UCAL_FIRST_DAY_OF_WEEK:
46f4442e
A
295 ((Calendar*)cal)->setFirstDayOfWeek((UCalendarDaysOfWeek)newValue);
296 break;
297
b75a7d8f 298 case UCAL_MINIMAL_DAYS_IN_FIRST_WEEK:
46f4442e
A
299 ((Calendar*)cal)->setMinimalDaysInFirstWeek((uint8_t)newValue);
300 break;
301 }
b75a7d8f
A
302}
303
304U_CAPI const char* U_EXPORT2
305ucal_getAvailable(int32_t index)
306{
307
46f4442e 308 return uloc_getAvailable(index);
b75a7d8f
A
309}
310
311U_CAPI int32_t U_EXPORT2
312ucal_countAvailable()
313{
314
46f4442e 315 return uloc_countAvailable();
b75a7d8f
A
316}
317
318U_CAPI UDate U_EXPORT2
319ucal_getMillis( const UCalendar* cal,
46f4442e 320 UErrorCode* status)
b75a7d8f
A
321{
322
46f4442e 323 if(U_FAILURE(*status)) return (UDate) 0;
b75a7d8f 324
46f4442e 325 return ((Calendar*)cal)->getTime(*status);
b75a7d8f
A
326}
327
328U_CAPI void U_EXPORT2
329ucal_setMillis( UCalendar* cal,
46f4442e
A
330 UDate dateTime,
331 UErrorCode* status )
b75a7d8f 332{
46f4442e 333 if(U_FAILURE(*status)) return;
b75a7d8f 334
46f4442e 335 ((Calendar*)cal)->setTime(dateTime, *status);
b75a7d8f
A
336}
337
338// TBD: why does this take an UErrorCode?
339U_CAPI void U_EXPORT2
340ucal_setDate( UCalendar* cal,
46f4442e
A
341 int32_t year,
342 int32_t month,
343 int32_t date,
344 UErrorCode *status)
b75a7d8f
A
345{
346
46f4442e 347 if(U_FAILURE(*status)) return;
b75a7d8f 348
46f4442e 349 ((Calendar*)cal)->set(year, month, date);
b75a7d8f
A
350}
351
352// TBD: why does this take an UErrorCode?
353U_CAPI void U_EXPORT2
354ucal_setDateTime( UCalendar* cal,
46f4442e
A
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)
b75a7d8f 362{
46f4442e 363 if(U_FAILURE(*status)) return;
b75a7d8f 364
46f4442e 365 ((Calendar*)cal)->set(year, month, date, hour, minute, second);
b75a7d8f
A
366}
367
368U_CAPI UBool U_EXPORT2
369ucal_equivalentTo( const UCalendar* cal1,
46f4442e 370 const UCalendar* cal2)
b75a7d8f
A
371{
372
46f4442e 373 return ((Calendar*)cal1)->isEquivalentTo(*((Calendar*)cal2));
b75a7d8f
A
374}
375
376U_CAPI void U_EXPORT2
377ucal_add( UCalendar* cal,
46f4442e
A
378 UCalendarDateFields field,
379 int32_t amount,
380 UErrorCode* status)
b75a7d8f
A
381{
382
46f4442e 383 if(U_FAILURE(*status)) return;
b75a7d8f 384
46f4442e 385 ((Calendar*)cal)->add(field, amount, *status);
b75a7d8f
A
386}
387
388U_CAPI void U_EXPORT2
389ucal_roll( UCalendar* cal,
46f4442e
A
390 UCalendarDateFields field,
391 int32_t amount,
392 UErrorCode* status)
b75a7d8f
A
393{
394
46f4442e 395 if(U_FAILURE(*status)) return;
b75a7d8f 396
46f4442e 397 ((Calendar*)cal)->roll(field, amount, *status);
b75a7d8f
A
398}
399
400U_CAPI int32_t U_EXPORT2
401ucal_get( const UCalendar* cal,
46f4442e
A
402 UCalendarDateFields field,
403 UErrorCode* status )
b75a7d8f
A
404{
405
46f4442e 406 if(U_FAILURE(*status)) return -1;
b75a7d8f 407
46f4442e 408 return ((Calendar*)cal)->get(field, *status);
b75a7d8f
A
409}
410
411U_CAPI void U_EXPORT2
412ucal_set( UCalendar* cal,
46f4442e
A
413 UCalendarDateFields field,
414 int32_t value)
b75a7d8f
A
415{
416
46f4442e 417 ((Calendar*)cal)->set(field, value);
b75a7d8f
A
418}
419
420U_CAPI UBool U_EXPORT2
421ucal_isSet( const UCalendar* cal,
46f4442e 422 UCalendarDateFields field)
b75a7d8f
A
423{
424
46f4442e 425 return ((Calendar*)cal)->isSet(field);
b75a7d8f
A
426}
427
428U_CAPI void U_EXPORT2
429ucal_clearField( UCalendar* cal,
46f4442e 430 UCalendarDateFields field)
b75a7d8f
A
431{
432
46f4442e 433 ((Calendar*)cal)->clear(field);
b75a7d8f
A
434}
435
436U_CAPI void U_EXPORT2
437ucal_clear(UCalendar* calendar)
438{
439
46f4442e 440 ((Calendar*)calendar)->clear();
b75a7d8f
A
441}
442
443U_CAPI int32_t U_EXPORT2
444ucal_getLimit( const UCalendar* cal,
46f4442e
A
445 UCalendarDateFields field,
446 UCalendarLimitType type,
447 UErrorCode *status)
b75a7d8f
A
448{
449
46f4442e
A
450 if(status==0 || U_FAILURE(*status)) {
451 return -1;
452 }
453
454 switch(type) {
b75a7d8f 455 case UCAL_MINIMUM:
46f4442e 456 return ((Calendar*)cal)->getMinimum(field);
b75a7d8f
A
457
458 case UCAL_MAXIMUM:
46f4442e 459 return ((Calendar*)cal)->getMaximum(field);
b75a7d8f
A
460
461 case UCAL_GREATEST_MINIMUM:
46f4442e 462 return ((Calendar*)cal)->getGreatestMinimum(field);
b75a7d8f
A
463
464 case UCAL_LEAST_MAXIMUM:
46f4442e 465 return ((Calendar*)cal)->getLeastMaximum(field);
b75a7d8f
A
466
467 case UCAL_ACTUAL_MINIMUM:
46f4442e
A
468 return ((Calendar*)cal)->getActualMinimum(field,
469 *status);
b75a7d8f
A
470
471 case UCAL_ACTUAL_MAXIMUM:
46f4442e
A
472 return ((Calendar*)cal)->getActualMaximum(field,
473 *status);
b75a7d8f
A
474
475 default:
46f4442e
A
476 break;
477 }
478 return -1;
b75a7d8f
A
479}
480
374ca955
A
481U_CAPI const char * U_EXPORT2
482ucal_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
46f4442e
A
493U_CAPI const char * U_EXPORT2
494ucal_getTZDataVersion(UErrorCode* status)
495{
496 return TimeZone::getTZDataVersion(*status);
497}
498
499U_CAPI int32_t U_EXPORT2
500ucal_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
525U_CAPI const char * U_EXPORT2
526ucal_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.
536U_CAPI const char * U_EXPORT2
537ucal_getTypeWithError(const UCalendar *cal, UErrorCode* status)
538{
539 return ucal_getType(cal, status);
540}
541
b75a7d8f 542#endif /* #if !UCONFIG_NO_FORMATTING */