]>
Commit | Line | Data |
---|---|---|
b75a7d8f A |
1 | /* |
2 | ******************************************************************************* | |
51004dcb | 3 | * Copyright (C) 1996-2013, International Business Machines |
b75a7d8f A |
4 | * Corporation and others. All Rights Reserved. |
5 | ******************************************************************************* | |
6 | */ | |
7 | ||
51004dcb | 8 | #include "utypeinfo.h" // for 'typeid' to work |
729e4ab9 | 9 | |
b75a7d8f A |
10 | #include "unicode/utypes.h" |
11 | ||
12 | #if !UCONFIG_NO_FORMATTING | |
13 | ||
14 | #include "unicode/ucal.h" | |
15 | #include "unicode/uloc.h" | |
16 | #include "unicode/calendar.h" | |
17 | #include "unicode/timezone.h" | |
73c04bcf | 18 | #include "unicode/gregocal.h" |
b75a7d8f A |
19 | #include "unicode/simpletz.h" |
20 | #include "unicode/ustring.h" | |
21 | #include "unicode/strenum.h" | |
51004dcb | 22 | #include "unicode/localpointer.h" |
b75a7d8f | 23 | #include "cmemory.h" |
46f4442e | 24 | #include "cstring.h" |
b75a7d8f | 25 | #include "ustrenum.h" |
729e4ab9 A |
26 | #include "uenumimp.h" |
27 | #include "ulist.h" | |
b75a7d8f A |
28 | |
29 | U_NAMESPACE_USE | |
30 | ||
31 | static TimeZone* | |
32 | _createTimeZone(const UChar* zoneID, int32_t len, UErrorCode* ec) { | |
33 | TimeZone* zone = NULL; | |
34 | if (ec!=NULL && U_SUCCESS(*ec)) { | |
35 | // Note that if zoneID is invalid, we get back GMT. This odd | |
36 | // behavior is by design and goes back to the JDK. The only | |
37 | // failure we will see is a memory allocation failure. | |
38 | int32_t l = (len<0 ? u_strlen(zoneID) : len); | |
374ca955 A |
39 | UnicodeString zoneStrID; |
40 | zoneStrID.setTo((UBool)(len < 0), zoneID, l); /* temporary read-only alias */ | |
41 | zone = TimeZone::createTimeZone(zoneStrID); | |
b75a7d8f A |
42 | if (zone == NULL) { |
43 | *ec = U_MEMORY_ALLOCATION_ERROR; | |
44 | } | |
45 | } | |
46 | return zone; | |
47 | } | |
48 | ||
4388f060 A |
49 | U_CAPI UEnumeration* U_EXPORT2 |
50 | ucal_openTimeZoneIDEnumeration(USystemTimeZoneType zoneType, const char* region, | |
51 | const int32_t* rawOffset, UErrorCode* ec) { | |
52 | return uenum_openFromStringEnumeration(TimeZone::createTimeZoneIDEnumeration( | |
53 | zoneType, region, rawOffset, *ec), ec); | |
54 | } | |
55 | ||
b75a7d8f A |
56 | U_CAPI UEnumeration* U_EXPORT2 |
57 | ucal_openTimeZones(UErrorCode* ec) { | |
729e4ab9 | 58 | return uenum_openFromStringEnumeration(TimeZone::createEnumeration(), ec); |
b75a7d8f A |
59 | } |
60 | ||
61 | U_CAPI UEnumeration* U_EXPORT2 | |
62 | ucal_openCountryTimeZones(const char* country, UErrorCode* ec) { | |
729e4ab9 | 63 | return uenum_openFromStringEnumeration(TimeZone::createEnumeration(country), ec); |
b75a7d8f A |
64 | } |
65 | ||
66 | U_CAPI int32_t U_EXPORT2 | |
67 | ucal_getDefaultTimeZone(UChar* result, int32_t resultCapacity, UErrorCode* ec) { | |
68 | int32_t len = 0; | |
69 | if (ec!=NULL && U_SUCCESS(*ec)) { | |
70 | TimeZone* zone = TimeZone::createDefault(); | |
71 | if (zone == NULL) { | |
72 | *ec = U_MEMORY_ALLOCATION_ERROR; | |
73 | } else { | |
74 | UnicodeString id; | |
75 | zone->getID(id); | |
76 | delete zone; | |
77 | len = id.extract(result, resultCapacity, *ec); | |
78 | } | |
79 | } | |
80 | return len; | |
81 | } | |
82 | ||
83 | U_CAPI void U_EXPORT2 | |
84 | ucal_setDefaultTimeZone(const UChar* zoneID, UErrorCode* ec) { | |
85 | TimeZone* zone = _createTimeZone(zoneID, -1, ec); | |
86 | if (zone != NULL) { | |
87 | TimeZone::adoptDefault(zone); | |
88 | } | |
89 | } | |
90 | ||
91 | U_CAPI int32_t U_EXPORT2 | |
92 | ucal_getDSTSavings(const UChar* zoneID, UErrorCode* ec) { | |
93 | int32_t result = 0; | |
94 | TimeZone* zone = _createTimeZone(zoneID, -1, ec); | |
374ca955 | 95 | if (U_SUCCESS(*ec)) { |
729e4ab9 A |
96 | SimpleTimeZone* stz = dynamic_cast<SimpleTimeZone*>(zone); |
97 | if (stz != NULL) { | |
98 | result = stz->getDSTSavings(); | |
374ca955 A |
99 | } else { |
100 | // Since there is no getDSTSavings on TimeZone, we use a | |
101 | // heuristic: Starting with the current time, march | |
102 | // forwards for one year, looking for DST savings. | |
103 | // Stepping by weeks is sufficient. | |
104 | UDate d = Calendar::getNow(); | |
105 | for (int32_t i=0; i<53; ++i, d+=U_MILLIS_PER_DAY*7.0) { | |
106 | int32_t raw, dst; | |
107 | zone->getOffset(d, FALSE, raw, dst, *ec); | |
108 | if (U_FAILURE(*ec)) { | |
109 | break; | |
110 | } else if (dst != 0) { | |
111 | result = dst; | |
112 | break; | |
113 | } | |
114 | } | |
115 | } | |
b75a7d8f A |
116 | } |
117 | delete zone; | |
118 | return result; | |
119 | } | |
120 | ||
b75a7d8f A |
121 | U_CAPI UDate U_EXPORT2 |
122 | ucal_getNow() | |
123 | { | |
124 | ||
125 | return Calendar::getNow(); | |
126 | } | |
127 | ||
46f4442e A |
128 | #define ULOC_LOCALE_IDENTIFIER_CAPACITY (ULOC_FULLNAME_CAPACITY + 1 + ULOC_KEYWORD_AND_VALUES_CAPACITY) |
129 | ||
b75a7d8f | 130 | U_CAPI UCalendar* U_EXPORT2 |
46f4442e A |
131 | ucal_open( const UChar* zoneID, |
132 | int32_t len, | |
133 | const char* locale, | |
134 | UCalendarType caltype, | |
135 | UErrorCode* status) | |
b75a7d8f A |
136 | { |
137 | ||
138 | if(U_FAILURE(*status)) return 0; | |
139 | ||
140 | TimeZone* zone = (zoneID==NULL) ? TimeZone::createDefault() | |
141 | : _createTimeZone(zoneID, len, status); | |
142 | ||
143 | if (U_FAILURE(*status)) { | |
144 | return NULL; | |
145 | } | |
46f4442e A |
146 | |
147 | if ( caltype == UCAL_GREGORIAN ) { | |
148 | char localeBuf[ULOC_LOCALE_IDENTIFIER_CAPACITY]; | |
729e4ab9 A |
149 | if ( locale == NULL ) { |
150 | locale = uloc_getDefault(); | |
151 | } | |
46f4442e A |
152 | uprv_strncpy(localeBuf, locale, ULOC_LOCALE_IDENTIFIER_CAPACITY); |
153 | uloc_setKeywordValue("calendar", "gregorian", localeBuf, ULOC_LOCALE_IDENTIFIER_CAPACITY, status); | |
154 | if (U_FAILURE(*status)) { | |
155 | return NULL; | |
156 | } | |
157 | return (UCalendar*)Calendar::createInstance(zone, Locale(localeBuf), *status); | |
158 | } | |
b75a7d8f A |
159 | return (UCalendar*)Calendar::createInstance(zone, Locale(locale), *status); |
160 | } | |
161 | ||
162 | U_CAPI void U_EXPORT2 | |
163 | ucal_close(UCalendar *cal) | |
164 | { | |
165 | ||
166 | delete (Calendar*) cal; | |
167 | } | |
168 | ||
46f4442e A |
169 | U_CAPI UCalendar* U_EXPORT2 |
170 | ucal_clone(const UCalendar* cal, | |
171 | UErrorCode* status) | |
172 | { | |
173 | if(U_FAILURE(*status)) return 0; | |
174 | ||
175 | Calendar* res = ((Calendar*)cal)->clone(); | |
176 | ||
177 | if(res == 0) { | |
178 | *status = U_MEMORY_ALLOCATION_ERROR; | |
179 | return 0; | |
180 | } | |
181 | ||
182 | return (UCalendar*) res; | |
183 | } | |
184 | ||
b75a7d8f A |
185 | U_CAPI void U_EXPORT2 |
186 | ucal_setTimeZone( UCalendar* cal, | |
187 | const UChar* zoneID, | |
188 | int32_t len, | |
189 | UErrorCode *status) | |
190 | { | |
191 | ||
192 | if(U_FAILURE(*status)) | |
193 | return; | |
194 | ||
195 | TimeZone* zone = (zoneID==NULL) ? TimeZone::createDefault() | |
196 | : _createTimeZone(zoneID, len, status); | |
197 | ||
198 | if (zone != NULL) { | |
199 | ((Calendar*)cal)->adoptTimeZone(zone); | |
200 | } | |
201 | } | |
202 | ||
51004dcb A |
203 | U_CAPI int32_t U_EXPORT2 |
204 | ucal_getTimeZoneID(const UCalendar *cal, | |
205 | UChar *result, | |
206 | int32_t resultLength, | |
207 | UErrorCode *status) | |
208 | { | |
209 | if (U_FAILURE(*status)) { | |
210 | return 0; | |
211 | } | |
212 | const TimeZone& tz = ((Calendar*)cal)->getTimeZone(); | |
213 | UnicodeString id; | |
214 | tz.getID(id); | |
215 | return id.extract(result, resultLength, *status); | |
216 | } | |
217 | ||
b75a7d8f A |
218 | U_CAPI int32_t U_EXPORT2 |
219 | ucal_getTimeZoneDisplayName(const UCalendar* cal, | |
220 | UCalendarDisplayNameType type, | |
221 | const char *locale, | |
222 | UChar* result, | |
223 | int32_t resultLength, | |
224 | UErrorCode* status) | |
225 | { | |
226 | ||
46f4442e | 227 | if(U_FAILURE(*status)) return -1; |
b75a7d8f | 228 | |
46f4442e A |
229 | const TimeZone& tz = ((Calendar*)cal)->getTimeZone(); |
230 | UnicodeString id; | |
231 | if(!(result==NULL && resultLength==0)) { | |
232 | // NULL destination for pure preflighting: empty dummy string | |
233 | // otherwise, alias the destination buffer | |
234 | id.setTo(result, 0, resultLength); | |
235 | } | |
b75a7d8f | 236 | |
46f4442e | 237 | switch(type) { |
b75a7d8f | 238 | case UCAL_STANDARD: |
46f4442e A |
239 | tz.getDisplayName(FALSE, TimeZone::LONG, Locale(locale), id); |
240 | break; | |
b75a7d8f A |
241 | |
242 | case UCAL_SHORT_STANDARD: | |
46f4442e A |
243 | tz.getDisplayName(FALSE, TimeZone::SHORT, Locale(locale), id); |
244 | break; | |
b75a7d8f A |
245 | |
246 | case UCAL_DST: | |
46f4442e A |
247 | tz.getDisplayName(TRUE, TimeZone::LONG, Locale(locale), id); |
248 | break; | |
b75a7d8f A |
249 | |
250 | case UCAL_SHORT_DST: | |
46f4442e A |
251 | tz.getDisplayName(TRUE, TimeZone::SHORT, Locale(locale), id); |
252 | break; | |
253 | } | |
b75a7d8f | 254 | |
46f4442e | 255 | return id.extract(result, resultLength, *status); |
b75a7d8f A |
256 | } |
257 | ||
258 | U_CAPI UBool U_EXPORT2 | |
259 | ucal_inDaylightTime( const UCalendar* cal, | |
46f4442e | 260 | UErrorCode* status ) |
b75a7d8f A |
261 | { |
262 | ||
46f4442e A |
263 | if(U_FAILURE(*status)) return (UBool) -1; |
264 | return ((Calendar*)cal)->inDaylightTime(*status); | |
b75a7d8f A |
265 | } |
266 | ||
46f4442e | 267 | U_CAPI void U_EXPORT2 |
73c04bcf | 268 | ucal_setGregorianChange(UCalendar *cal, UDate date, UErrorCode *pErrorCode) { |
46f4442e A |
269 | if(U_FAILURE(*pErrorCode)) { |
270 | return; | |
271 | } | |
272 | Calendar *cpp_cal = (Calendar *)cal; | |
729e4ab9 A |
273 | GregorianCalendar *gregocal = dynamic_cast<GregorianCalendar *>(cpp_cal); |
274 | // Not if(gregocal == NULL) { | |
275 | // because we really want to work only with a GregorianCalendar, not with | |
276 | // its subclasses like BuddhistCalendar. | |
4388f060 A |
277 | if (cpp_cal == NULL) { |
278 | // We normally don't check "this" pointers for NULL, but this here avoids | |
279 | // compiler-generated exception-throwing code in case cal == NULL. | |
280 | *pErrorCode = U_ILLEGAL_ARGUMENT_ERROR; | |
281 | return; | |
282 | } | |
729e4ab9 | 283 | if(typeid(*cpp_cal) != typeid(GregorianCalendar)) { |
46f4442e A |
284 | *pErrorCode = U_UNSUPPORTED_ERROR; |
285 | return; | |
286 | } | |
729e4ab9 | 287 | gregocal->setGregorianChange(date, *pErrorCode); |
73c04bcf A |
288 | } |
289 | ||
46f4442e | 290 | U_CAPI UDate U_EXPORT2 |
73c04bcf | 291 | ucal_getGregorianChange(const UCalendar *cal, UErrorCode *pErrorCode) { |
46f4442e A |
292 | if(U_FAILURE(*pErrorCode)) { |
293 | return (UDate)0; | |
294 | } | |
729e4ab9 A |
295 | const Calendar *cpp_cal = (const Calendar *)cal; |
296 | const GregorianCalendar *gregocal = dynamic_cast<const GregorianCalendar *>(cpp_cal); | |
297 | // Not if(gregocal == NULL) { | |
298 | // see comments in ucal_setGregorianChange(). | |
4388f060 A |
299 | if (cpp_cal == NULL) { |
300 | // We normally don't check "this" pointers for NULL, but this here avoids | |
301 | // compiler-generated exception-throwing code in case cal == NULL. | |
302 | *pErrorCode = U_ILLEGAL_ARGUMENT_ERROR; | |
303 | return (UDate)0; | |
304 | } | |
729e4ab9 | 305 | if(typeid(*cpp_cal) != typeid(GregorianCalendar)) { |
46f4442e A |
306 | *pErrorCode = U_UNSUPPORTED_ERROR; |
307 | return (UDate)0; | |
308 | } | |
729e4ab9 | 309 | return gregocal->getGregorianChange(); |
73c04bcf A |
310 | } |
311 | ||
b75a7d8f A |
312 | U_CAPI int32_t U_EXPORT2 |
313 | ucal_getAttribute( const UCalendar* cal, | |
46f4442e | 314 | UCalendarAttribute attr) |
b75a7d8f A |
315 | { |
316 | ||
46f4442e | 317 | switch(attr) { |
b75a7d8f | 318 | case UCAL_LENIENT: |
46f4442e A |
319 | return ((Calendar*)cal)->isLenient(); |
320 | ||
b75a7d8f | 321 | case UCAL_FIRST_DAY_OF_WEEK: |
46f4442e A |
322 | return ((Calendar*)cal)->getFirstDayOfWeek(); |
323 | ||
b75a7d8f | 324 | case UCAL_MINIMAL_DAYS_IN_FIRST_WEEK: |
46f4442e | 325 | return ((Calendar*)cal)->getMinimalDaysInFirstWeek(); |
b75a7d8f | 326 | |
4388f060 A |
327 | case UCAL_REPEATED_WALL_TIME: |
328 | return ((Calendar*)cal)->getRepeatedWallTimeOption(); | |
329 | ||
330 | case UCAL_SKIPPED_WALL_TIME: | |
331 | return ((Calendar*)cal)->getSkippedWallTimeOption(); | |
332 | ||
b75a7d8f | 333 | default: |
46f4442e A |
334 | break; |
335 | } | |
336 | return -1; | |
b75a7d8f A |
337 | } |
338 | ||
339 | U_CAPI void U_EXPORT2 | |
340 | ucal_setAttribute( UCalendar* cal, | |
46f4442e A |
341 | UCalendarAttribute attr, |
342 | int32_t newValue) | |
b75a7d8f A |
343 | { |
344 | ||
46f4442e | 345 | switch(attr) { |
b75a7d8f | 346 | case UCAL_LENIENT: |
46f4442e A |
347 | ((Calendar*)cal)->setLenient((UBool)newValue); |
348 | break; | |
349 | ||
b75a7d8f | 350 | case UCAL_FIRST_DAY_OF_WEEK: |
46f4442e A |
351 | ((Calendar*)cal)->setFirstDayOfWeek((UCalendarDaysOfWeek)newValue); |
352 | break; | |
353 | ||
b75a7d8f | 354 | case UCAL_MINIMAL_DAYS_IN_FIRST_WEEK: |
46f4442e A |
355 | ((Calendar*)cal)->setMinimalDaysInFirstWeek((uint8_t)newValue); |
356 | break; | |
4388f060 A |
357 | |
358 | case UCAL_REPEATED_WALL_TIME: | |
359 | ((Calendar*)cal)->setRepeatedWallTimeOption((UCalendarWallTimeOption)newValue); | |
360 | break; | |
361 | ||
362 | case UCAL_SKIPPED_WALL_TIME: | |
363 | ((Calendar*)cal)->setSkippedWallTimeOption((UCalendarWallTimeOption)newValue); | |
364 | break; | |
46f4442e | 365 | } |
b75a7d8f A |
366 | } |
367 | ||
368 | U_CAPI const char* U_EXPORT2 | |
369 | ucal_getAvailable(int32_t index) | |
370 | { | |
371 | ||
46f4442e | 372 | return uloc_getAvailable(index); |
b75a7d8f A |
373 | } |
374 | ||
375 | U_CAPI int32_t U_EXPORT2 | |
376 | ucal_countAvailable() | |
377 | { | |
378 | ||
46f4442e | 379 | return uloc_countAvailable(); |
b75a7d8f A |
380 | } |
381 | ||
382 | U_CAPI UDate U_EXPORT2 | |
383 | ucal_getMillis( const UCalendar* cal, | |
46f4442e | 384 | UErrorCode* status) |
b75a7d8f A |
385 | { |
386 | ||
46f4442e | 387 | if(U_FAILURE(*status)) return (UDate) 0; |
b75a7d8f | 388 | |
46f4442e | 389 | return ((Calendar*)cal)->getTime(*status); |
b75a7d8f A |
390 | } |
391 | ||
392 | U_CAPI void U_EXPORT2 | |
393 | ucal_setMillis( UCalendar* cal, | |
46f4442e A |
394 | UDate dateTime, |
395 | UErrorCode* status ) | |
b75a7d8f | 396 | { |
46f4442e | 397 | if(U_FAILURE(*status)) return; |
b75a7d8f | 398 | |
46f4442e | 399 | ((Calendar*)cal)->setTime(dateTime, *status); |
b75a7d8f A |
400 | } |
401 | ||
402 | // TBD: why does this take an UErrorCode? | |
403 | U_CAPI void U_EXPORT2 | |
404 | ucal_setDate( UCalendar* cal, | |
46f4442e A |
405 | int32_t year, |
406 | int32_t month, | |
407 | int32_t date, | |
408 | UErrorCode *status) | |
b75a7d8f A |
409 | { |
410 | ||
46f4442e | 411 | if(U_FAILURE(*status)) return; |
b75a7d8f | 412 | |
46f4442e | 413 | ((Calendar*)cal)->set(year, month, date); |
b75a7d8f A |
414 | } |
415 | ||
416 | // TBD: why does this take an UErrorCode? | |
417 | U_CAPI void U_EXPORT2 | |
418 | ucal_setDateTime( UCalendar* cal, | |
46f4442e A |
419 | int32_t year, |
420 | int32_t month, | |
421 | int32_t date, | |
422 | int32_t hour, | |
423 | int32_t minute, | |
424 | int32_t second, | |
425 | UErrorCode *status) | |
b75a7d8f | 426 | { |
46f4442e | 427 | if(U_FAILURE(*status)) return; |
b75a7d8f | 428 | |
46f4442e | 429 | ((Calendar*)cal)->set(year, month, date, hour, minute, second); |
b75a7d8f A |
430 | } |
431 | ||
432 | U_CAPI UBool U_EXPORT2 | |
433 | ucal_equivalentTo( const UCalendar* cal1, | |
46f4442e | 434 | const UCalendar* cal2) |
b75a7d8f A |
435 | { |
436 | ||
46f4442e | 437 | return ((Calendar*)cal1)->isEquivalentTo(*((Calendar*)cal2)); |
b75a7d8f A |
438 | } |
439 | ||
440 | U_CAPI void U_EXPORT2 | |
441 | ucal_add( UCalendar* cal, | |
46f4442e A |
442 | UCalendarDateFields field, |
443 | int32_t amount, | |
444 | UErrorCode* status) | |
b75a7d8f A |
445 | { |
446 | ||
46f4442e | 447 | if(U_FAILURE(*status)) return; |
b75a7d8f | 448 | |
46f4442e | 449 | ((Calendar*)cal)->add(field, amount, *status); |
b75a7d8f A |
450 | } |
451 | ||
452 | U_CAPI void U_EXPORT2 | |
453 | ucal_roll( UCalendar* cal, | |
46f4442e A |
454 | UCalendarDateFields field, |
455 | int32_t amount, | |
456 | UErrorCode* status) | |
b75a7d8f A |
457 | { |
458 | ||
46f4442e | 459 | if(U_FAILURE(*status)) return; |
b75a7d8f | 460 | |
46f4442e | 461 | ((Calendar*)cal)->roll(field, amount, *status); |
b75a7d8f A |
462 | } |
463 | ||
464 | U_CAPI int32_t U_EXPORT2 | |
465 | ucal_get( const UCalendar* cal, | |
46f4442e A |
466 | UCalendarDateFields field, |
467 | UErrorCode* status ) | |
b75a7d8f A |
468 | { |
469 | ||
46f4442e | 470 | if(U_FAILURE(*status)) return -1; |
b75a7d8f | 471 | |
46f4442e | 472 | return ((Calendar*)cal)->get(field, *status); |
b75a7d8f A |
473 | } |
474 | ||
475 | U_CAPI void U_EXPORT2 | |
476 | ucal_set( UCalendar* cal, | |
46f4442e A |
477 | UCalendarDateFields field, |
478 | int32_t value) | |
b75a7d8f A |
479 | { |
480 | ||
46f4442e | 481 | ((Calendar*)cal)->set(field, value); |
b75a7d8f A |
482 | } |
483 | ||
484 | U_CAPI UBool U_EXPORT2 | |
485 | ucal_isSet( const UCalendar* cal, | |
46f4442e | 486 | UCalendarDateFields field) |
b75a7d8f A |
487 | { |
488 | ||
46f4442e | 489 | return ((Calendar*)cal)->isSet(field); |
b75a7d8f A |
490 | } |
491 | ||
492 | U_CAPI void U_EXPORT2 | |
493 | ucal_clearField( UCalendar* cal, | |
46f4442e | 494 | UCalendarDateFields field) |
b75a7d8f A |
495 | { |
496 | ||
46f4442e | 497 | ((Calendar*)cal)->clear(field); |
b75a7d8f A |
498 | } |
499 | ||
500 | U_CAPI void U_EXPORT2 | |
501 | ucal_clear(UCalendar* calendar) | |
502 | { | |
503 | ||
46f4442e | 504 | ((Calendar*)calendar)->clear(); |
b75a7d8f A |
505 | } |
506 | ||
507 | U_CAPI int32_t U_EXPORT2 | |
508 | ucal_getLimit( const UCalendar* cal, | |
46f4442e A |
509 | UCalendarDateFields field, |
510 | UCalendarLimitType type, | |
511 | UErrorCode *status) | |
b75a7d8f A |
512 | { |
513 | ||
46f4442e A |
514 | if(status==0 || U_FAILURE(*status)) { |
515 | return -1; | |
516 | } | |
517 | ||
518 | switch(type) { | |
b75a7d8f | 519 | case UCAL_MINIMUM: |
46f4442e | 520 | return ((Calendar*)cal)->getMinimum(field); |
b75a7d8f A |
521 | |
522 | case UCAL_MAXIMUM: | |
46f4442e | 523 | return ((Calendar*)cal)->getMaximum(field); |
b75a7d8f A |
524 | |
525 | case UCAL_GREATEST_MINIMUM: | |
46f4442e | 526 | return ((Calendar*)cal)->getGreatestMinimum(field); |
b75a7d8f A |
527 | |
528 | case UCAL_LEAST_MAXIMUM: | |
46f4442e | 529 | return ((Calendar*)cal)->getLeastMaximum(field); |
b75a7d8f A |
530 | |
531 | case UCAL_ACTUAL_MINIMUM: | |
46f4442e A |
532 | return ((Calendar*)cal)->getActualMinimum(field, |
533 | *status); | |
b75a7d8f A |
534 | |
535 | case UCAL_ACTUAL_MAXIMUM: | |
46f4442e A |
536 | return ((Calendar*)cal)->getActualMaximum(field, |
537 | *status); | |
b75a7d8f A |
538 | |
539 | default: | |
46f4442e A |
540 | break; |
541 | } | |
542 | return -1; | |
b75a7d8f A |
543 | } |
544 | ||
374ca955 A |
545 | U_CAPI const char * U_EXPORT2 |
546 | ucal_getLocaleByType(const UCalendar *cal, ULocDataLocaleType type, UErrorCode* status) | |
547 | { | |
548 | if (cal == NULL) { | |
549 | if (U_SUCCESS(*status)) { | |
550 | *status = U_ILLEGAL_ARGUMENT_ERROR; | |
551 | } | |
552 | return NULL; | |
553 | } | |
554 | return ((Calendar*)cal)->getLocaleID(type, *status); | |
555 | } | |
556 | ||
46f4442e A |
557 | U_CAPI const char * U_EXPORT2 |
558 | ucal_getTZDataVersion(UErrorCode* status) | |
559 | { | |
560 | return TimeZone::getTZDataVersion(*status); | |
561 | } | |
562 | ||
563 | U_CAPI int32_t U_EXPORT2 | |
564 | ucal_getCanonicalTimeZoneID(const UChar* id, int32_t len, | |
565 | UChar* result, int32_t resultCapacity, UBool *isSystemID, UErrorCode* status) { | |
566 | if(status == 0 || U_FAILURE(*status)) { | |
567 | return 0; | |
568 | } | |
569 | if (isSystemID) { | |
570 | *isSystemID = FALSE; | |
571 | } | |
572 | if (id == 0 || len == 0 || result == 0 || resultCapacity <= 0) { | |
573 | *status = U_ILLEGAL_ARGUMENT_ERROR; | |
574 | return 0; | |
575 | } | |
576 | int32_t reslen = 0; | |
577 | UnicodeString canonical; | |
578 | UBool systemID = FALSE; | |
579 | TimeZone::getCanonicalID(UnicodeString(id, len), canonical, systemID, *status); | |
580 | if (U_SUCCESS(*status)) { | |
581 | if (isSystemID) { | |
582 | *isSystemID = systemID; | |
583 | } | |
584 | reslen = canonical.extract(result, resultCapacity, *status); | |
585 | } | |
586 | return reslen; | |
587 | } | |
588 | ||
589 | U_CAPI const char * U_EXPORT2 | |
590 | ucal_getType(const UCalendar *cal, UErrorCode* status) | |
591 | { | |
592 | if (U_FAILURE(*status)) { | |
593 | return NULL; | |
594 | } | |
595 | return ((Calendar*)cal)->getType(); | |
596 | } | |
597 | ||
729e4ab9 A |
598 | U_CAPI UCalendarWeekdayType U_EXPORT2 |
599 | ucal_getDayOfWeekType(const UCalendar *cal, UCalendarDaysOfWeek dayOfWeek, UErrorCode* status) | |
600 | { | |
601 | if (U_FAILURE(*status)) { | |
602 | return UCAL_WEEKDAY; | |
603 | } | |
604 | return ((Calendar*)cal)->getDayOfWeekType(dayOfWeek, *status); | |
605 | } | |
606 | ||
607 | U_CAPI int32_t U_EXPORT2 | |
608 | ucal_getWeekendTransition(const UCalendar *cal, UCalendarDaysOfWeek dayOfWeek, UErrorCode *status) | |
609 | { | |
610 | if (U_FAILURE(*status)) { | |
611 | return 0; | |
612 | } | |
613 | return ((Calendar*)cal)->getWeekendTransition(dayOfWeek, *status); | |
614 | } | |
615 | ||
616 | U_CAPI UBool U_EXPORT2 | |
617 | ucal_isWeekend(const UCalendar *cal, UDate date, UErrorCode *status) | |
46f4442e | 618 | { |
729e4ab9 A |
619 | if (U_FAILURE(*status)) { |
620 | return FALSE; | |
621 | } | |
622 | return ((Calendar*)cal)->isWeekend(date, *status); | |
623 | } | |
624 | ||
625 | U_CAPI int32_t U_EXPORT2 | |
626 | ucal_getFieldDifference(UCalendar* cal, UDate target, | |
627 | UCalendarDateFields field, | |
628 | UErrorCode* status ) | |
629 | { | |
630 | if (U_FAILURE(*status)) { | |
631 | return 0; | |
632 | } | |
633 | return ((Calendar*)cal)->fieldDifference(target, field, *status); | |
634 | } | |
635 | ||
636 | ||
637 | static const UEnumeration defaultKeywordValues = { | |
638 | NULL, | |
639 | NULL, | |
640 | ulist_close_keyword_values_iterator, | |
641 | ulist_count_keyword_values, | |
642 | uenum_unextDefault, | |
643 | ulist_next_keyword_value, | |
644 | ulist_reset_keyword_values_iterator | |
645 | }; | |
646 | ||
647 | static const char * const CAL_TYPES[] = { | |
648 | "gregorian", | |
649 | "japanese", | |
650 | "buddhist", | |
651 | "roc", | |
652 | "persian", | |
653 | "islamic-civil", | |
654 | "islamic", | |
655 | "hebrew", | |
656 | "chinese", | |
657 | "indian", | |
658 | "coptic", | |
659 | "ethiopic", | |
660 | "ethiopic-amete-alem", | |
57a6839d A |
661 | "iso8601", |
662 | "dangi", | |
663 | "islamic-umalqura", | |
664 | "islamic-tbla", | |
665 | "islamic-rgsa", | |
729e4ab9 A |
666 | NULL |
667 | }; | |
668 | ||
669 | U_CAPI UEnumeration* U_EXPORT2 | |
670 | ucal_getKeywordValuesForLocale(const char * /* key */, const char* locale, UBool commonlyUsed, UErrorCode *status) { | |
671 | // Resolve region | |
672 | char prefRegion[ULOC_FULLNAME_CAPACITY] = ""; | |
673 | int32_t prefRegionLength = 0; | |
674 | prefRegionLength = uloc_getCountry(locale, prefRegion, sizeof(prefRegion), status); | |
675 | if (prefRegionLength == 0) { | |
676 | char loc[ULOC_FULLNAME_CAPACITY] = ""; | |
4388f060 | 677 | uloc_addLikelySubtags(locale, loc, sizeof(loc), status); |
729e4ab9 A |
678 | |
679 | prefRegionLength = uloc_getCountry(loc, prefRegion, sizeof(prefRegion), status); | |
680 | } | |
681 | ||
682 | // Read preferred calendar values from supplementalData calendarPreference | |
683 | UResourceBundle *rb = ures_openDirect(NULL, "supplementalData", status); | |
684 | ures_getByKey(rb, "calendarPreferenceData", rb, status); | |
685 | UResourceBundle *order = ures_getByKey(rb, prefRegion, NULL, status); | |
686 | if (*status == U_MISSING_RESOURCE_ERROR && rb != NULL) { | |
687 | *status = U_ZERO_ERROR; | |
688 | order = ures_getByKey(rb, "001", NULL, status); | |
689 | } | |
690 | ||
691 | // Create a list of calendar type strings | |
692 | UList *values = NULL; | |
693 | if (U_SUCCESS(*status)) { | |
694 | values = ulist_createEmptyList(status); | |
695 | if (U_SUCCESS(*status)) { | |
696 | for (int i = 0; i < ures_getSize(order); i++) { | |
697 | int32_t len; | |
698 | const UChar *type = ures_getStringByIndex(order, i, &len, status); | |
699 | char *caltype = (char*)uprv_malloc(len + 1); | |
700 | if (caltype == NULL) { | |
701 | *status = U_MEMORY_ALLOCATION_ERROR; | |
702 | break; | |
703 | } | |
704 | u_UCharsToChars(type, caltype, len); | |
705 | *(caltype + len) = 0; | |
706 | ||
707 | ulist_addItemEndList(values, caltype, TRUE, status); | |
708 | if (U_FAILURE(*status)) { | |
709 | break; | |
710 | } | |
711 | } | |
712 | ||
713 | if (U_SUCCESS(*status) && !commonlyUsed) { | |
714 | // If not commonlyUsed, add other available values | |
715 | for (int32_t i = 0; CAL_TYPES[i] != NULL; i++) { | |
716 | if (!ulist_containsString(values, CAL_TYPES[i], (int32_t)uprv_strlen(CAL_TYPES[i]))) { | |
717 | ulist_addItemEndList(values, CAL_TYPES[i], FALSE, status); | |
718 | if (U_FAILURE(*status)) { | |
719 | break; | |
720 | } | |
721 | } | |
722 | } | |
723 | } | |
724 | if (U_FAILURE(*status)) { | |
725 | ulist_deleteList(values); | |
726 | values = NULL; | |
727 | } | |
728 | } | |
729 | } | |
730 | ||
731 | ures_close(order); | |
732 | ures_close(rb); | |
733 | ||
734 | if (U_FAILURE(*status) || values == NULL) { | |
735 | return NULL; | |
736 | } | |
737 | ||
738 | // Create string enumeration | |
739 | UEnumeration *en = (UEnumeration*)uprv_malloc(sizeof(UEnumeration)); | |
740 | if (en == NULL) { | |
741 | *status = U_MEMORY_ALLOCATION_ERROR; | |
742 | ulist_deleteList(values); | |
743 | return NULL; | |
744 | } | |
745 | ulist_resetList(values); | |
746 | memcpy(en, &defaultKeywordValues, sizeof(UEnumeration)); | |
747 | en->context = values; | |
748 | return en; | |
46f4442e A |
749 | } |
750 | ||
51004dcb A |
751 | U_CAPI UBool U_EXPORT2 |
752 | ucal_getTimeZoneTransitionDate(const UCalendar* cal, UTimeZoneTransitionType type, | |
753 | UDate* transition, UErrorCode* status) | |
754 | { | |
755 | if (U_FAILURE(*status)) { | |
756 | return FALSE; | |
757 | } | |
758 | UDate base = ((Calendar*)cal)->getTime(*status); | |
759 | const TimeZone& tz = ((Calendar*)cal)->getTimeZone(); | |
760 | const BasicTimeZone * btz = dynamic_cast<const BasicTimeZone *>(&tz); | |
761 | if (btz != NULL && U_SUCCESS(*status)) { | |
762 | TimeZoneTransition tzt; | |
763 | UBool inclusive = (type == UCAL_TZ_TRANSITION_NEXT_INCLUSIVE || type == UCAL_TZ_TRANSITION_PREVIOUS_INCLUSIVE); | |
764 | UBool result = (type == UCAL_TZ_TRANSITION_NEXT || type == UCAL_TZ_TRANSITION_NEXT_INCLUSIVE)? | |
765 | btz->getNextTransition(base, inclusive, tzt): | |
766 | btz->getPreviousTransition(base, inclusive, tzt); | |
767 | if (result) { | |
768 | *transition = tzt.getTime(); | |
769 | return TRUE; | |
770 | } | |
771 | } | |
772 | return FALSE; | |
773 | } | |
774 | ||
57a6839d A |
775 | #ifndef U_HIDE_DRAFT_API |
776 | U_CAPI int32_t U_EXPORT2 | |
777 | ucal_getWindowsTimeZoneID(const UChar* id, int32_t len, UChar* winid, int32_t winidCapacity, UErrorCode* status) { | |
778 | if (U_FAILURE(*status)) { | |
779 | return 0; | |
780 | } | |
781 | ||
782 | int32_t resultLen = 0; | |
783 | UnicodeString resultWinID; | |
784 | ||
785 | TimeZone::getWindowsID(UnicodeString(id, len), resultWinID, *status); | |
786 | if (U_SUCCESS(*status) && resultWinID.length() > 0) { | |
787 | resultLen = resultWinID.length(); | |
788 | resultWinID.extract(winid, winidCapacity, *status); | |
789 | } | |
790 | ||
791 | return resultLen; | |
792 | } | |
793 | ||
794 | U_CAPI int32_t U_EXPORT2 | |
795 | ucal_getTimeZoneIDForWindowsID(const UChar* winid, int32_t len, const char* region, UChar* id, int32_t idCapacity, UErrorCode* status) { | |
796 | if (U_FAILURE(*status)) { | |
797 | return 0; | |
798 | } | |
799 | ||
800 | int32_t resultLen = 0; | |
801 | UnicodeString resultID; | |
802 | ||
803 | TimeZone::getIDForWindowsID(UnicodeString(winid, len), region, resultID, *status); | |
804 | if (U_SUCCESS(*status) && resultID.length() > 0) { | |
805 | resultLen = resultID.length(); | |
806 | resultID.extract(id, idCapacity, *status); | |
807 | } | |
808 | ||
809 | return resultLen; | |
810 | } | |
811 | ||
812 | #endif /* U_HIDE_DRAFT_API */ | |
813 | ||
b75a7d8f | 814 | #endif /* #if !UCONFIG_NO_FORMATTING */ |