2 *******************************************************************************
3 * Copyright (C) 1996-2008, International Business Machines
4 * Corporation and others. All Rights Reserved.
5 *******************************************************************************
8 #include "unicode/utypes.h"
10 #if !UCONFIG_NO_FORMATTING
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"
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
);
38 *ec
= U_MEMORY_ALLOCATION_ERROR
;
44 U_CAPI UEnumeration
* U_EXPORT2
45 ucal_openTimeZones(UErrorCode
* ec
) {
46 return uenum_openStringEnumeration(TimeZone::createEnumeration(), ec
);
49 U_CAPI UEnumeration
* U_EXPORT2
50 ucal_openCountryTimeZones(const char* country
, UErrorCode
* ec
) {
51 return uenum_openStringEnumeration(TimeZone::createEnumeration(country
), ec
);
54 U_CAPI
int32_t U_EXPORT2
55 ucal_getDefaultTimeZone(UChar
* result
, int32_t resultCapacity
, UErrorCode
* ec
) {
57 if (ec
!=NULL
&& U_SUCCESS(*ec
)) {
58 TimeZone
* zone
= TimeZone::createDefault();
60 *ec
= U_MEMORY_ALLOCATION_ERROR
;
65 len
= id
.extract(result
, resultCapacity
, *ec
);
72 ucal_setDefaultTimeZone(const UChar
* zoneID
, UErrorCode
* ec
) {
73 TimeZone
* zone
= _createTimeZone(zoneID
, -1, ec
);
75 TimeZone::adoptDefault(zone
);
79 U_CAPI
int32_t U_EXPORT2
80 ucal_getDSTSavings(const UChar
* zoneID
, UErrorCode
* ec
) {
82 TimeZone
* zone
= _createTimeZone(zoneID
, -1, ec
);
84 if (zone
->getDynamicClassID() == SimpleTimeZone::getStaticClassID()) {
85 result
= ((SimpleTimeZone
*) zone
)->getDSTSavings();
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) {
94 zone
->getOffset(d
, FALSE
, raw
, dst
, *ec
);
97 } else if (dst
!= 0) {
108 U_CAPI UDate U_EXPORT2
112 return Calendar::getNow();
115 #define ULOC_LOCALE_IDENTIFIER_CAPACITY (ULOC_FULLNAME_CAPACITY + 1 + ULOC_KEYWORD_AND_VALUES_CAPACITY)
117 U_CAPI UCalendar
* U_EXPORT2
118 ucal_open( const UChar
* zoneID
,
121 UCalendarType caltype
,
125 if(U_FAILURE(*status
)) return 0;
127 TimeZone
* zone
= (zoneID
==NULL
) ? TimeZone::createDefault()
128 : _createTimeZone(zoneID
, len
, status
);
130 if (U_FAILURE(*status
)) {
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
)) {
141 return (UCalendar
*)Calendar::createInstance(zone
, Locale(localeBuf
), *status
);
143 return (UCalendar
*)Calendar::createInstance(zone
, Locale(locale
), *status
);
146 U_CAPI
void U_EXPORT2
147 ucal_close(UCalendar
*cal
)
150 delete (Calendar
*) cal
;
153 U_CAPI UCalendar
* U_EXPORT2
154 ucal_clone(const UCalendar
* cal
,
157 if(U_FAILURE(*status
)) return 0;
159 Calendar
* res
= ((Calendar
*)cal
)->clone();
162 *status
= U_MEMORY_ALLOCATION_ERROR
;
166 return (UCalendar
*) res
;
169 U_CAPI
void U_EXPORT2
170 ucal_setTimeZone( UCalendar
* cal
,
176 if(U_FAILURE(*status
))
179 TimeZone
* zone
= (zoneID
==NULL
) ? TimeZone::createDefault()
180 : _createTimeZone(zoneID
, len
, status
);
183 ((Calendar
*)cal
)->adoptTimeZone(zone
);
187 U_CAPI
int32_t U_EXPORT2
188 ucal_getTimeZoneDisplayName(const UCalendar
* cal
,
189 UCalendarDisplayNameType type
,
192 int32_t resultLength
,
196 if(U_FAILURE(*status
)) return -1;
198 const TimeZone
& tz
= ((Calendar
*)cal
)->getTimeZone();
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
);
208 tz
.getDisplayName(FALSE
, TimeZone::LONG
, Locale(locale
), id
);
211 case UCAL_SHORT_STANDARD
:
212 tz
.getDisplayName(FALSE
, TimeZone::SHORT
, Locale(locale
), id
);
216 tz
.getDisplayName(TRUE
, TimeZone::LONG
, Locale(locale
), id
);
220 tz
.getDisplayName(TRUE
, TimeZone::SHORT
, Locale(locale
), id
);
224 return id
.extract(result
, resultLength
, *status
);
227 U_CAPI UBool U_EXPORT2
228 ucal_inDaylightTime( const UCalendar
* cal
,
232 if(U_FAILURE(*status
)) return (UBool
) -1;
233 return ((Calendar
*)cal
)->inDaylightTime(*status
);
236 U_CAPI
void U_EXPORT2
237 ucal_setGregorianChange(UCalendar
*cal
, UDate date
, UErrorCode
*pErrorCode
) {
238 if(U_FAILURE(*pErrorCode
)) {
241 Calendar
*cpp_cal
= (Calendar
*)cal
;
242 if(cpp_cal
->getDynamicClassID() != GregorianCalendar::getStaticClassID()) {
243 *pErrorCode
= U_UNSUPPORTED_ERROR
;
246 ((GregorianCalendar
*)cpp_cal
)->setGregorianChange(date
, *pErrorCode
);
249 U_CAPI UDate U_EXPORT2
250 ucal_getGregorianChange(const UCalendar
*cal
, UErrorCode
*pErrorCode
) {
251 if(U_FAILURE(*pErrorCode
)) {
254 Calendar
*cpp_cal
= (Calendar
*)cal
;
255 if(cpp_cal
->getDynamicClassID() != GregorianCalendar::getStaticClassID()) {
256 *pErrorCode
= U_UNSUPPORTED_ERROR
;
259 return ((GregorianCalendar
*)cpp_cal
)->getGregorianChange();
262 U_CAPI
int32_t U_EXPORT2
263 ucal_getAttribute( const UCalendar
* cal
,
264 UCalendarAttribute attr
)
269 return ((Calendar
*)cal
)->isLenient();
271 case UCAL_FIRST_DAY_OF_WEEK
:
272 return ((Calendar
*)cal
)->getFirstDayOfWeek();
274 case UCAL_MINIMAL_DAYS_IN_FIRST_WEEK
:
275 return ((Calendar
*)cal
)->getMinimalDaysInFirstWeek();
283 U_CAPI
void U_EXPORT2
284 ucal_setAttribute( UCalendar
* cal
,
285 UCalendarAttribute attr
,
291 ((Calendar
*)cal
)->setLenient((UBool
)newValue
);
294 case UCAL_FIRST_DAY_OF_WEEK
:
295 ((Calendar
*)cal
)->setFirstDayOfWeek((UCalendarDaysOfWeek
)newValue
);
298 case UCAL_MINIMAL_DAYS_IN_FIRST_WEEK
:
299 ((Calendar
*)cal
)->setMinimalDaysInFirstWeek((uint8_t)newValue
);
304 U_CAPI
const char* U_EXPORT2
305 ucal_getAvailable(int32_t index
)
308 return uloc_getAvailable(index
);
311 U_CAPI
int32_t U_EXPORT2
312 ucal_countAvailable()
315 return uloc_countAvailable();
318 U_CAPI UDate U_EXPORT2
319 ucal_getMillis( const UCalendar
* cal
,
323 if(U_FAILURE(*status
)) return (UDate
) 0;
325 return ((Calendar
*)cal
)->getTime(*status
);
328 U_CAPI
void U_EXPORT2
329 ucal_setMillis( UCalendar
* cal
,
333 if(U_FAILURE(*status
)) return;
335 ((Calendar
*)cal
)->setTime(dateTime
, *status
);
338 // TBD: why does this take an UErrorCode?
339 U_CAPI
void U_EXPORT2
340 ucal_setDate( UCalendar
* cal
,
347 if(U_FAILURE(*status
)) return;
349 ((Calendar
*)cal
)->set(year
, month
, date
);
352 // TBD: why does this take an UErrorCode?
353 U_CAPI
void U_EXPORT2
354 ucal_setDateTime( UCalendar
* cal
,
363 if(U_FAILURE(*status
)) return;
365 ((Calendar
*)cal
)->set(year
, month
, date
, hour
, minute
, second
);
368 U_CAPI UBool U_EXPORT2
369 ucal_equivalentTo( const UCalendar
* cal1
,
370 const UCalendar
* cal2
)
373 return ((Calendar
*)cal1
)->isEquivalentTo(*((Calendar
*)cal2
));
376 U_CAPI
void U_EXPORT2
377 ucal_add( UCalendar
* cal
,
378 UCalendarDateFields field
,
383 if(U_FAILURE(*status
)) return;
385 ((Calendar
*)cal
)->add(field
, amount
, *status
);
388 U_CAPI
void U_EXPORT2
389 ucal_roll( UCalendar
* cal
,
390 UCalendarDateFields field
,
395 if(U_FAILURE(*status
)) return;
397 ((Calendar
*)cal
)->roll(field
, amount
, *status
);
400 U_CAPI
int32_t U_EXPORT2
401 ucal_get( const UCalendar
* cal
,
402 UCalendarDateFields field
,
406 if(U_FAILURE(*status
)) return -1;
408 return ((Calendar
*)cal
)->get(field
, *status
);
411 U_CAPI
void U_EXPORT2
412 ucal_set( UCalendar
* cal
,
413 UCalendarDateFields field
,
417 ((Calendar
*)cal
)->set(field
, value
);
420 U_CAPI UBool U_EXPORT2
421 ucal_isSet( const UCalendar
* cal
,
422 UCalendarDateFields field
)
425 return ((Calendar
*)cal
)->isSet(field
);
428 U_CAPI
void U_EXPORT2
429 ucal_clearField( UCalendar
* cal
,
430 UCalendarDateFields field
)
433 ((Calendar
*)cal
)->clear(field
);
436 U_CAPI
void U_EXPORT2
437 ucal_clear(UCalendar
* calendar
)
440 ((Calendar
*)calendar
)->clear();
443 U_CAPI
int32_t U_EXPORT2
444 ucal_getLimit( const UCalendar
* cal
,
445 UCalendarDateFields field
,
446 UCalendarLimitType type
,
450 if(status
==0 || U_FAILURE(*status
)) {
456 return ((Calendar
*)cal
)->getMinimum(field
);
459 return ((Calendar
*)cal
)->getMaximum(field
);
461 case UCAL_GREATEST_MINIMUM
:
462 return ((Calendar
*)cal
)->getGreatestMinimum(field
);
464 case UCAL_LEAST_MAXIMUM
:
465 return ((Calendar
*)cal
)->getLeastMaximum(field
);
467 case UCAL_ACTUAL_MINIMUM
:
468 return ((Calendar
*)cal
)->getActualMinimum(field
,
471 case UCAL_ACTUAL_MAXIMUM
:
472 return ((Calendar
*)cal
)->getActualMaximum(field
,
481 U_CAPI
const char * U_EXPORT2
482 ucal_getLocaleByType(const UCalendar
*cal
, ULocDataLocaleType type
, UErrorCode
* status
)
485 if (U_SUCCESS(*status
)) {
486 *status
= U_ILLEGAL_ARGUMENT_ERROR
;
490 return ((Calendar
*)cal
)->getLocaleID(type
, *status
);
493 U_CAPI
const char * U_EXPORT2
494 ucal_getTZDataVersion(UErrorCode
* status
)
496 return TimeZone::getTZDataVersion(*status
);
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
)) {
508 if (id
== 0 || len
== 0 || result
== 0 || resultCapacity
<= 0) {
509 *status
= U_ILLEGAL_ARGUMENT_ERROR
;
513 UnicodeString canonical
;
514 UBool systemID
= FALSE
;
515 TimeZone::getCanonicalID(UnicodeString(id
, len
), canonical
, systemID
, *status
);
516 if (U_SUCCESS(*status
)) {
518 *isSystemID
= systemID
;
520 reslen
= canonical
.extract(result
, resultCapacity
, *status
);
525 U_CAPI
const char * U_EXPORT2
526 ucal_getType(const UCalendar
*cal
, UErrorCode
* status
)
528 if (U_FAILURE(*status
)) {
531 return ((Calendar
*)cal
)->getType();
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
)
539 return ucal_getType(cal
, status
);
542 #endif /* #if !UCONFIG_NO_FORMATTING */