]> git.saurik.com Git - apple/icu.git/blob - icuSources/i18n/ucal.cpp
ICU-8.11.4.tar.gz
[apple/icu.git] / icuSources / i18n / ucal.cpp
1 /*
2 *******************************************************************************
3 * Copyright (C) 1996-2006, 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 "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);
33 UnicodeString zoneStrID;
34 zoneStrID.setTo((UBool)(len < 0), zoneID, l); /* temporary read-only alias */
35 zone = TimeZone::createTimeZone(zoneStrID);
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);
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 }
102 }
103 delete zone;
104 return result;
105 }
106
107 #ifdef U_USE_UCAL_OBSOLETE_2_8
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 }
153 #endif
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
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
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
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
514 #endif /* #if !UCONFIG_NO_FORMATTING */