]>
Commit | Line | Data |
---|---|---|
f3c0d7a5 A |
1 | // © 2016 and later: Unicode, Inc. and others. |
2 | // License & terms of use: http://www.unicode.org/copyright.html | |
b75a7d8f A |
3 | /* |
4 | ******************************************************************************* | |
2ca993e8 | 5 | * Copyright (C) 1996-2016, International Business Machines |
b75a7d8f A |
6 | * Corporation and others. All Rights Reserved. |
7 | ******************************************************************************* | |
8 | */ | |
9 | ||
51004dcb | 10 | #include "utypeinfo.h" // for 'typeid' to work |
729e4ab9 | 11 | |
b75a7d8f A |
12 | #include "unicode/utypes.h" |
13 | ||
14 | #if !UCONFIG_NO_FORMATTING | |
15 | ||
b331163b A |
16 | #include <stdlib.h> // Apple addition for uacal_getDayPeriod |
17 | ||
b75a7d8f A |
18 | #include "unicode/ucal.h" |
19 | #include "unicode/uloc.h" | |
20 | #include "unicode/calendar.h" | |
21 | #include "unicode/timezone.h" | |
73c04bcf | 22 | #include "unicode/gregocal.h" |
b75a7d8f A |
23 | #include "unicode/simpletz.h" |
24 | #include "unicode/ustring.h" | |
25 | #include "unicode/strenum.h" | |
51004dcb | 26 | #include "unicode/localpointer.h" |
b75a7d8f | 27 | #include "cmemory.h" |
46f4442e | 28 | #include "cstring.h" |
b75a7d8f | 29 | #include "ustrenum.h" |
729e4ab9 A |
30 | #include "uenumimp.h" |
31 | #include "ulist.h" | |
2ca993e8 | 32 | #include "ulocimp.h" |
b75a7d8f A |
33 | |
34 | U_NAMESPACE_USE | |
35 | ||
36 | static TimeZone* | |
37 | _createTimeZone(const UChar* zoneID, int32_t len, UErrorCode* ec) { | |
38 | TimeZone* zone = NULL; | |
39 | if (ec!=NULL && U_SUCCESS(*ec)) { | |
40 | // Note that if zoneID is invalid, we get back GMT. This odd | |
41 | // behavior is by design and goes back to the JDK. The only | |
42 | // failure we will see is a memory allocation failure. | |
43 | int32_t l = (len<0 ? u_strlen(zoneID) : len); | |
374ca955 A |
44 | UnicodeString zoneStrID; |
45 | zoneStrID.setTo((UBool)(len < 0), zoneID, l); /* temporary read-only alias */ | |
46 | zone = TimeZone::createTimeZone(zoneStrID); | |
b75a7d8f A |
47 | if (zone == NULL) { |
48 | *ec = U_MEMORY_ALLOCATION_ERROR; | |
49 | } | |
50 | } | |
51 | return zone; | |
52 | } | |
53 | ||
4388f060 A |
54 | U_CAPI UEnumeration* U_EXPORT2 |
55 | ucal_openTimeZoneIDEnumeration(USystemTimeZoneType zoneType, const char* region, | |
56 | const int32_t* rawOffset, UErrorCode* ec) { | |
57 | return uenum_openFromStringEnumeration(TimeZone::createTimeZoneIDEnumeration( | |
58 | zoneType, region, rawOffset, *ec), ec); | |
59 | } | |
60 | ||
b75a7d8f A |
61 | U_CAPI UEnumeration* U_EXPORT2 |
62 | ucal_openTimeZones(UErrorCode* ec) { | |
729e4ab9 | 63 | return uenum_openFromStringEnumeration(TimeZone::createEnumeration(), ec); |
b75a7d8f A |
64 | } |
65 | ||
66 | U_CAPI UEnumeration* U_EXPORT2 | |
67 | ucal_openCountryTimeZones(const char* country, UErrorCode* ec) { | |
729e4ab9 | 68 | return uenum_openFromStringEnumeration(TimeZone::createEnumeration(country), ec); |
b75a7d8f A |
69 | } |
70 | ||
71 | U_CAPI int32_t U_EXPORT2 | |
72 | ucal_getDefaultTimeZone(UChar* result, int32_t resultCapacity, UErrorCode* ec) { | |
73 | int32_t len = 0; | |
74 | if (ec!=NULL && U_SUCCESS(*ec)) { | |
75 | TimeZone* zone = TimeZone::createDefault(); | |
76 | if (zone == NULL) { | |
77 | *ec = U_MEMORY_ALLOCATION_ERROR; | |
78 | } else { | |
79 | UnicodeString id; | |
80 | zone->getID(id); | |
81 | delete zone; | |
82 | len = id.extract(result, resultCapacity, *ec); | |
83 | } | |
84 | } | |
85 | return len; | |
86 | } | |
87 | ||
88 | U_CAPI void U_EXPORT2 | |
89 | ucal_setDefaultTimeZone(const UChar* zoneID, UErrorCode* ec) { | |
90 | TimeZone* zone = _createTimeZone(zoneID, -1, ec); | |
91 | if (zone != NULL) { | |
92 | TimeZone::adoptDefault(zone); | |
93 | } | |
94 | } | |
95 | ||
96 | U_CAPI int32_t U_EXPORT2 | |
97 | ucal_getDSTSavings(const UChar* zoneID, UErrorCode* ec) { | |
98 | int32_t result = 0; | |
99 | TimeZone* zone = _createTimeZone(zoneID, -1, ec); | |
374ca955 | 100 | if (U_SUCCESS(*ec)) { |
729e4ab9 A |
101 | SimpleTimeZone* stz = dynamic_cast<SimpleTimeZone*>(zone); |
102 | if (stz != NULL) { | |
103 | result = stz->getDSTSavings(); | |
374ca955 A |
104 | } else { |
105 | // Since there is no getDSTSavings on TimeZone, we use a | |
106 | // heuristic: Starting with the current time, march | |
107 | // forwards for one year, looking for DST savings. | |
108 | // Stepping by weeks is sufficient. | |
109 | UDate d = Calendar::getNow(); | |
110 | for (int32_t i=0; i<53; ++i, d+=U_MILLIS_PER_DAY*7.0) { | |
111 | int32_t raw, dst; | |
112 | zone->getOffset(d, FALSE, raw, dst, *ec); | |
113 | if (U_FAILURE(*ec)) { | |
114 | break; | |
115 | } else if (dst != 0) { | |
116 | result = dst; | |
117 | break; | |
118 | } | |
119 | } | |
120 | } | |
b75a7d8f A |
121 | } |
122 | delete zone; | |
123 | return result; | |
124 | } | |
125 | ||
b75a7d8f A |
126 | U_CAPI UDate U_EXPORT2 |
127 | ucal_getNow() | |
128 | { | |
129 | ||
130 | return Calendar::getNow(); | |
131 | } | |
132 | ||
46f4442e A |
133 | #define ULOC_LOCALE_IDENTIFIER_CAPACITY (ULOC_FULLNAME_CAPACITY + 1 + ULOC_KEYWORD_AND_VALUES_CAPACITY) |
134 | ||
b75a7d8f | 135 | U_CAPI UCalendar* U_EXPORT2 |
46f4442e A |
136 | ucal_open( const UChar* zoneID, |
137 | int32_t len, | |
138 | const char* locale, | |
139 | UCalendarType caltype, | |
140 | UErrorCode* status) | |
b75a7d8f A |
141 | { |
142 | ||
143 | if(U_FAILURE(*status)) return 0; | |
144 | ||
145 | TimeZone* zone = (zoneID==NULL) ? TimeZone::createDefault() | |
146 | : _createTimeZone(zoneID, len, status); | |
147 | ||
148 | if (U_FAILURE(*status)) { | |
149 | return NULL; | |
150 | } | |
46f4442e A |
151 | |
152 | if ( caltype == UCAL_GREGORIAN ) { | |
153 | char localeBuf[ULOC_LOCALE_IDENTIFIER_CAPACITY]; | |
729e4ab9 A |
154 | if ( locale == NULL ) { |
155 | locale = uloc_getDefault(); | |
156 | } | |
46f4442e A |
157 | uprv_strncpy(localeBuf, locale, ULOC_LOCALE_IDENTIFIER_CAPACITY); |
158 | uloc_setKeywordValue("calendar", "gregorian", localeBuf, ULOC_LOCALE_IDENTIFIER_CAPACITY, status); | |
159 | if (U_FAILURE(*status)) { | |
160 | return NULL; | |
161 | } | |
162 | return (UCalendar*)Calendar::createInstance(zone, Locale(localeBuf), *status); | |
163 | } | |
b75a7d8f A |
164 | return (UCalendar*)Calendar::createInstance(zone, Locale(locale), *status); |
165 | } | |
166 | ||
167 | U_CAPI void U_EXPORT2 | |
168 | ucal_close(UCalendar *cal) | |
169 | { | |
170 | ||
171 | delete (Calendar*) cal; | |
172 | } | |
173 | ||
46f4442e A |
174 | U_CAPI UCalendar* U_EXPORT2 |
175 | ucal_clone(const UCalendar* cal, | |
176 | UErrorCode* status) | |
177 | { | |
178 | if(U_FAILURE(*status)) return 0; | |
179 | ||
180 | Calendar* res = ((Calendar*)cal)->clone(); | |
181 | ||
182 | if(res == 0) { | |
183 | *status = U_MEMORY_ALLOCATION_ERROR; | |
184 | return 0; | |
185 | } | |
186 | ||
187 | return (UCalendar*) res; | |
188 | } | |
189 | ||
b75a7d8f A |
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; | |
0f5d89e8 A |
199 | |
200 | TimeZone* zone; | |
201 | if (zoneID==NULL) { | |
202 | zone = TimeZone::createDefault(); | |
203 | } else { | |
204 | UnicodeString zoneStrID, id; | |
205 | zoneStrID.setTo(len < 0, zoneID, len); /* aliasing assignment, avoids copy */ | |
206 | ((Calendar*)cal)->getTimeZone().getID(id); | |
207 | if (id == zoneStrID) { | |
208 | return; | |
209 | } | |
210 | zone = TimeZone::createTimeZone(zoneStrID); | |
211 | } | |
b75a7d8f A |
212 | |
213 | if (zone != NULL) { | |
214 | ((Calendar*)cal)->adoptTimeZone(zone); | |
0f5d89e8 A |
215 | } else { |
216 | *status = U_MEMORY_ALLOCATION_ERROR; | |
b75a7d8f A |
217 | } |
218 | } | |
219 | ||
51004dcb A |
220 | U_CAPI int32_t U_EXPORT2 |
221 | ucal_getTimeZoneID(const UCalendar *cal, | |
222 | UChar *result, | |
223 | int32_t resultLength, | |
224 | UErrorCode *status) | |
225 | { | |
226 | if (U_FAILURE(*status)) { | |
227 | return 0; | |
228 | } | |
229 | const TimeZone& tz = ((Calendar*)cal)->getTimeZone(); | |
230 | UnicodeString id; | |
231 | tz.getID(id); | |
232 | return id.extract(result, resultLength, *status); | |
233 | } | |
234 | ||
b75a7d8f A |
235 | U_CAPI int32_t U_EXPORT2 |
236 | ucal_getTimeZoneDisplayName(const UCalendar* cal, | |
237 | UCalendarDisplayNameType type, | |
238 | const char *locale, | |
239 | UChar* result, | |
240 | int32_t resultLength, | |
241 | UErrorCode* status) | |
242 | { | |
243 | ||
46f4442e | 244 | if(U_FAILURE(*status)) return -1; |
b75a7d8f | 245 | |
46f4442e A |
246 | const TimeZone& tz = ((Calendar*)cal)->getTimeZone(); |
247 | UnicodeString id; | |
248 | if(!(result==NULL && resultLength==0)) { | |
249 | // NULL destination for pure preflighting: empty dummy string | |
250 | // otherwise, alias the destination buffer | |
251 | id.setTo(result, 0, resultLength); | |
252 | } | |
b75a7d8f | 253 | |
46f4442e | 254 | switch(type) { |
b75a7d8f | 255 | case UCAL_STANDARD: |
46f4442e A |
256 | tz.getDisplayName(FALSE, TimeZone::LONG, Locale(locale), id); |
257 | break; | |
b75a7d8f A |
258 | |
259 | case UCAL_SHORT_STANDARD: | |
46f4442e A |
260 | tz.getDisplayName(FALSE, TimeZone::SHORT, Locale(locale), id); |
261 | break; | |
b75a7d8f A |
262 | |
263 | case UCAL_DST: | |
46f4442e A |
264 | tz.getDisplayName(TRUE, TimeZone::LONG, Locale(locale), id); |
265 | break; | |
b75a7d8f A |
266 | |
267 | case UCAL_SHORT_DST: | |
46f4442e A |
268 | tz.getDisplayName(TRUE, TimeZone::SHORT, Locale(locale), id); |
269 | break; | |
270 | } | |
b75a7d8f | 271 | |
46f4442e | 272 | return id.extract(result, resultLength, *status); |
b75a7d8f A |
273 | } |
274 | ||
275 | U_CAPI UBool U_EXPORT2 | |
276 | ucal_inDaylightTime( const UCalendar* cal, | |
46f4442e | 277 | UErrorCode* status ) |
b75a7d8f A |
278 | { |
279 | ||
46f4442e A |
280 | if(U_FAILURE(*status)) return (UBool) -1; |
281 | return ((Calendar*)cal)->inDaylightTime(*status); | |
b75a7d8f A |
282 | } |
283 | ||
46f4442e | 284 | U_CAPI void U_EXPORT2 |
73c04bcf | 285 | ucal_setGregorianChange(UCalendar *cal, UDate date, UErrorCode *pErrorCode) { |
46f4442e A |
286 | if(U_FAILURE(*pErrorCode)) { |
287 | return; | |
288 | } | |
289 | Calendar *cpp_cal = (Calendar *)cal; | |
729e4ab9 A |
290 | GregorianCalendar *gregocal = dynamic_cast<GregorianCalendar *>(cpp_cal); |
291 | // Not if(gregocal == NULL) { | |
292 | // because we really want to work only with a GregorianCalendar, not with | |
293 | // its subclasses like BuddhistCalendar. | |
4388f060 A |
294 | if (cpp_cal == NULL) { |
295 | // We normally don't check "this" pointers for NULL, but this here avoids | |
296 | // compiler-generated exception-throwing code in case cal == NULL. | |
297 | *pErrorCode = U_ILLEGAL_ARGUMENT_ERROR; | |
298 | return; | |
299 | } | |
729e4ab9 | 300 | if(typeid(*cpp_cal) != typeid(GregorianCalendar)) { |
46f4442e A |
301 | *pErrorCode = U_UNSUPPORTED_ERROR; |
302 | return; | |
303 | } | |
729e4ab9 | 304 | gregocal->setGregorianChange(date, *pErrorCode); |
73c04bcf A |
305 | } |
306 | ||
46f4442e | 307 | U_CAPI UDate U_EXPORT2 |
73c04bcf | 308 | ucal_getGregorianChange(const UCalendar *cal, UErrorCode *pErrorCode) { |
46f4442e A |
309 | if(U_FAILURE(*pErrorCode)) { |
310 | return (UDate)0; | |
311 | } | |
729e4ab9 A |
312 | const Calendar *cpp_cal = (const Calendar *)cal; |
313 | const GregorianCalendar *gregocal = dynamic_cast<const GregorianCalendar *>(cpp_cal); | |
314 | // Not if(gregocal == NULL) { | |
315 | // see comments in ucal_setGregorianChange(). | |
4388f060 A |
316 | if (cpp_cal == NULL) { |
317 | // We normally don't check "this" pointers for NULL, but this here avoids | |
318 | // compiler-generated exception-throwing code in case cal == NULL. | |
319 | *pErrorCode = U_ILLEGAL_ARGUMENT_ERROR; | |
320 | return (UDate)0; | |
321 | } | |
729e4ab9 | 322 | if(typeid(*cpp_cal) != typeid(GregorianCalendar)) { |
46f4442e A |
323 | *pErrorCode = U_UNSUPPORTED_ERROR; |
324 | return (UDate)0; | |
325 | } | |
729e4ab9 | 326 | return gregocal->getGregorianChange(); |
73c04bcf A |
327 | } |
328 | ||
b75a7d8f A |
329 | U_CAPI int32_t U_EXPORT2 |
330 | ucal_getAttribute( const UCalendar* cal, | |
46f4442e | 331 | UCalendarAttribute attr) |
b75a7d8f A |
332 | { |
333 | ||
46f4442e | 334 | switch(attr) { |
b75a7d8f | 335 | case UCAL_LENIENT: |
46f4442e A |
336 | return ((Calendar*)cal)->isLenient(); |
337 | ||
b75a7d8f | 338 | case UCAL_FIRST_DAY_OF_WEEK: |
46f4442e A |
339 | return ((Calendar*)cal)->getFirstDayOfWeek(); |
340 | ||
b75a7d8f | 341 | case UCAL_MINIMAL_DAYS_IN_FIRST_WEEK: |
46f4442e | 342 | return ((Calendar*)cal)->getMinimalDaysInFirstWeek(); |
b75a7d8f | 343 | |
4388f060 A |
344 | case UCAL_REPEATED_WALL_TIME: |
345 | return ((Calendar*)cal)->getRepeatedWallTimeOption(); | |
346 | ||
347 | case UCAL_SKIPPED_WALL_TIME: | |
348 | return ((Calendar*)cal)->getSkippedWallTimeOption(); | |
349 | ||
b75a7d8f | 350 | default: |
46f4442e A |
351 | break; |
352 | } | |
353 | return -1; | |
b75a7d8f A |
354 | } |
355 | ||
356 | U_CAPI void U_EXPORT2 | |
357 | ucal_setAttribute( UCalendar* cal, | |
46f4442e A |
358 | UCalendarAttribute attr, |
359 | int32_t newValue) | |
b75a7d8f A |
360 | { |
361 | ||
46f4442e | 362 | switch(attr) { |
b75a7d8f | 363 | case UCAL_LENIENT: |
46f4442e A |
364 | ((Calendar*)cal)->setLenient((UBool)newValue); |
365 | break; | |
366 | ||
b75a7d8f | 367 | case UCAL_FIRST_DAY_OF_WEEK: |
46f4442e A |
368 | ((Calendar*)cal)->setFirstDayOfWeek((UCalendarDaysOfWeek)newValue); |
369 | break; | |
370 | ||
b75a7d8f | 371 | case UCAL_MINIMAL_DAYS_IN_FIRST_WEEK: |
46f4442e A |
372 | ((Calendar*)cal)->setMinimalDaysInFirstWeek((uint8_t)newValue); |
373 | break; | |
4388f060 A |
374 | |
375 | case UCAL_REPEATED_WALL_TIME: | |
376 | ((Calendar*)cal)->setRepeatedWallTimeOption((UCalendarWallTimeOption)newValue); | |
377 | break; | |
378 | ||
379 | case UCAL_SKIPPED_WALL_TIME: | |
380 | ((Calendar*)cal)->setSkippedWallTimeOption((UCalendarWallTimeOption)newValue); | |
381 | break; | |
46f4442e | 382 | } |
b75a7d8f A |
383 | } |
384 | ||
385 | U_CAPI const char* U_EXPORT2 | |
386 | ucal_getAvailable(int32_t index) | |
387 | { | |
388 | ||
46f4442e | 389 | return uloc_getAvailable(index); |
b75a7d8f A |
390 | } |
391 | ||
392 | U_CAPI int32_t U_EXPORT2 | |
393 | ucal_countAvailable() | |
394 | { | |
395 | ||
46f4442e | 396 | return uloc_countAvailable(); |
b75a7d8f A |
397 | } |
398 | ||
399 | U_CAPI UDate U_EXPORT2 | |
400 | ucal_getMillis( const UCalendar* cal, | |
46f4442e | 401 | UErrorCode* status) |
b75a7d8f A |
402 | { |
403 | ||
46f4442e | 404 | if(U_FAILURE(*status)) return (UDate) 0; |
b75a7d8f | 405 | |
46f4442e | 406 | return ((Calendar*)cal)->getTime(*status); |
b75a7d8f A |
407 | } |
408 | ||
409 | U_CAPI void U_EXPORT2 | |
410 | ucal_setMillis( UCalendar* cal, | |
46f4442e A |
411 | UDate dateTime, |
412 | UErrorCode* status ) | |
b75a7d8f | 413 | { |
46f4442e | 414 | if(U_FAILURE(*status)) return; |
b75a7d8f | 415 | |
46f4442e | 416 | ((Calendar*)cal)->setTime(dateTime, *status); |
b75a7d8f A |
417 | } |
418 | ||
419 | // TBD: why does this take an UErrorCode? | |
420 | U_CAPI void U_EXPORT2 | |
421 | ucal_setDate( UCalendar* cal, | |
46f4442e A |
422 | int32_t year, |
423 | int32_t month, | |
424 | int32_t date, | |
425 | UErrorCode *status) | |
b75a7d8f A |
426 | { |
427 | ||
46f4442e | 428 | if(U_FAILURE(*status)) return; |
b75a7d8f | 429 | |
46f4442e | 430 | ((Calendar*)cal)->set(year, month, date); |
b75a7d8f A |
431 | } |
432 | ||
433 | // TBD: why does this take an UErrorCode? | |
434 | U_CAPI void U_EXPORT2 | |
435 | ucal_setDateTime( UCalendar* cal, | |
46f4442e A |
436 | int32_t year, |
437 | int32_t month, | |
438 | int32_t date, | |
439 | int32_t hour, | |
440 | int32_t minute, | |
441 | int32_t second, | |
442 | UErrorCode *status) | |
b75a7d8f | 443 | { |
46f4442e | 444 | if(U_FAILURE(*status)) return; |
b75a7d8f | 445 | |
46f4442e | 446 | ((Calendar*)cal)->set(year, month, date, hour, minute, second); |
b75a7d8f A |
447 | } |
448 | ||
449 | U_CAPI UBool U_EXPORT2 | |
450 | ucal_equivalentTo( const UCalendar* cal1, | |
46f4442e | 451 | const UCalendar* cal2) |
b75a7d8f A |
452 | { |
453 | ||
46f4442e | 454 | return ((Calendar*)cal1)->isEquivalentTo(*((Calendar*)cal2)); |
b75a7d8f A |
455 | } |
456 | ||
457 | U_CAPI void U_EXPORT2 | |
458 | ucal_add( UCalendar* cal, | |
46f4442e A |
459 | UCalendarDateFields field, |
460 | int32_t amount, | |
461 | UErrorCode* status) | |
b75a7d8f A |
462 | { |
463 | ||
46f4442e | 464 | if(U_FAILURE(*status)) return; |
b75a7d8f | 465 | |
46f4442e | 466 | ((Calendar*)cal)->add(field, amount, *status); |
b75a7d8f A |
467 | } |
468 | ||
469 | U_CAPI void U_EXPORT2 | |
470 | ucal_roll( UCalendar* cal, | |
46f4442e A |
471 | UCalendarDateFields field, |
472 | int32_t amount, | |
473 | UErrorCode* status) | |
b75a7d8f A |
474 | { |
475 | ||
46f4442e | 476 | if(U_FAILURE(*status)) return; |
b75a7d8f | 477 | |
46f4442e | 478 | ((Calendar*)cal)->roll(field, amount, *status); |
b75a7d8f A |
479 | } |
480 | ||
481 | U_CAPI int32_t U_EXPORT2 | |
482 | ucal_get( const UCalendar* cal, | |
46f4442e A |
483 | UCalendarDateFields field, |
484 | UErrorCode* status ) | |
b75a7d8f A |
485 | { |
486 | ||
46f4442e | 487 | if(U_FAILURE(*status)) return -1; |
b75a7d8f | 488 | |
46f4442e | 489 | return ((Calendar*)cal)->get(field, *status); |
b75a7d8f A |
490 | } |
491 | ||
492 | U_CAPI void U_EXPORT2 | |
493 | ucal_set( UCalendar* cal, | |
46f4442e A |
494 | UCalendarDateFields field, |
495 | int32_t value) | |
b75a7d8f A |
496 | { |
497 | ||
46f4442e | 498 | ((Calendar*)cal)->set(field, value); |
b75a7d8f A |
499 | } |
500 | ||
501 | U_CAPI UBool U_EXPORT2 | |
502 | ucal_isSet( const UCalendar* cal, | |
46f4442e | 503 | UCalendarDateFields field) |
b75a7d8f A |
504 | { |
505 | ||
46f4442e | 506 | return ((Calendar*)cal)->isSet(field); |
b75a7d8f A |
507 | } |
508 | ||
509 | U_CAPI void U_EXPORT2 | |
510 | ucal_clearField( UCalendar* cal, | |
46f4442e | 511 | UCalendarDateFields field) |
b75a7d8f A |
512 | { |
513 | ||
46f4442e | 514 | ((Calendar*)cal)->clear(field); |
b75a7d8f A |
515 | } |
516 | ||
517 | U_CAPI void U_EXPORT2 | |
518 | ucal_clear(UCalendar* calendar) | |
519 | { | |
520 | ||
46f4442e | 521 | ((Calendar*)calendar)->clear(); |
b75a7d8f A |
522 | } |
523 | ||
524 | U_CAPI int32_t U_EXPORT2 | |
525 | ucal_getLimit( const UCalendar* cal, | |
46f4442e A |
526 | UCalendarDateFields field, |
527 | UCalendarLimitType type, | |
528 | UErrorCode *status) | |
b75a7d8f A |
529 | { |
530 | ||
46f4442e A |
531 | if(status==0 || U_FAILURE(*status)) { |
532 | return -1; | |
533 | } | |
534 | ||
535 | switch(type) { | |
b75a7d8f | 536 | case UCAL_MINIMUM: |
46f4442e | 537 | return ((Calendar*)cal)->getMinimum(field); |
b75a7d8f A |
538 | |
539 | case UCAL_MAXIMUM: | |
46f4442e | 540 | return ((Calendar*)cal)->getMaximum(field); |
b75a7d8f A |
541 | |
542 | case UCAL_GREATEST_MINIMUM: | |
46f4442e | 543 | return ((Calendar*)cal)->getGreatestMinimum(field); |
b75a7d8f A |
544 | |
545 | case UCAL_LEAST_MAXIMUM: | |
46f4442e | 546 | return ((Calendar*)cal)->getLeastMaximum(field); |
b75a7d8f A |
547 | |
548 | case UCAL_ACTUAL_MINIMUM: | |
46f4442e A |
549 | return ((Calendar*)cal)->getActualMinimum(field, |
550 | *status); | |
b75a7d8f A |
551 | |
552 | case UCAL_ACTUAL_MAXIMUM: | |
46f4442e A |
553 | return ((Calendar*)cal)->getActualMaximum(field, |
554 | *status); | |
b75a7d8f A |
555 | |
556 | default: | |
46f4442e A |
557 | break; |
558 | } | |
559 | return -1; | |
b75a7d8f A |
560 | } |
561 | ||
374ca955 A |
562 | U_CAPI const char * U_EXPORT2 |
563 | ucal_getLocaleByType(const UCalendar *cal, ULocDataLocaleType type, UErrorCode* status) | |
564 | { | |
565 | if (cal == NULL) { | |
566 | if (U_SUCCESS(*status)) { | |
567 | *status = U_ILLEGAL_ARGUMENT_ERROR; | |
568 | } | |
569 | return NULL; | |
570 | } | |
571 | return ((Calendar*)cal)->getLocaleID(type, *status); | |
572 | } | |
573 | ||
46f4442e A |
574 | U_CAPI const char * U_EXPORT2 |
575 | ucal_getTZDataVersion(UErrorCode* status) | |
576 | { | |
577 | return TimeZone::getTZDataVersion(*status); | |
578 | } | |
579 | ||
580 | U_CAPI int32_t U_EXPORT2 | |
581 | ucal_getCanonicalTimeZoneID(const UChar* id, int32_t len, | |
582 | UChar* result, int32_t resultCapacity, UBool *isSystemID, UErrorCode* status) { | |
583 | if(status == 0 || U_FAILURE(*status)) { | |
584 | return 0; | |
585 | } | |
586 | if (isSystemID) { | |
587 | *isSystemID = FALSE; | |
588 | } | |
589 | if (id == 0 || len == 0 || result == 0 || resultCapacity <= 0) { | |
590 | *status = U_ILLEGAL_ARGUMENT_ERROR; | |
591 | return 0; | |
592 | } | |
593 | int32_t reslen = 0; | |
594 | UnicodeString canonical; | |
595 | UBool systemID = FALSE; | |
596 | TimeZone::getCanonicalID(UnicodeString(id, len), canonical, systemID, *status); | |
597 | if (U_SUCCESS(*status)) { | |
598 | if (isSystemID) { | |
599 | *isSystemID = systemID; | |
600 | } | |
601 | reslen = canonical.extract(result, resultCapacity, *status); | |
602 | } | |
603 | return reslen; | |
604 | } | |
605 | ||
606 | U_CAPI const char * U_EXPORT2 | |
607 | ucal_getType(const UCalendar *cal, UErrorCode* status) | |
608 | { | |
609 | if (U_FAILURE(*status)) { | |
610 | return NULL; | |
611 | } | |
612 | return ((Calendar*)cal)->getType(); | |
613 | } | |
614 | ||
729e4ab9 A |
615 | U_CAPI UCalendarWeekdayType U_EXPORT2 |
616 | ucal_getDayOfWeekType(const UCalendar *cal, UCalendarDaysOfWeek dayOfWeek, UErrorCode* status) | |
617 | { | |
618 | if (U_FAILURE(*status)) { | |
619 | return UCAL_WEEKDAY; | |
620 | } | |
621 | return ((Calendar*)cal)->getDayOfWeekType(dayOfWeek, *status); | |
622 | } | |
623 | ||
624 | U_CAPI int32_t U_EXPORT2 | |
625 | ucal_getWeekendTransition(const UCalendar *cal, UCalendarDaysOfWeek dayOfWeek, UErrorCode *status) | |
626 | { | |
627 | if (U_FAILURE(*status)) { | |
628 | return 0; | |
629 | } | |
630 | return ((Calendar*)cal)->getWeekendTransition(dayOfWeek, *status); | |
631 | } | |
632 | ||
633 | U_CAPI UBool U_EXPORT2 | |
634 | ucal_isWeekend(const UCalendar *cal, UDate date, UErrorCode *status) | |
46f4442e | 635 | { |
729e4ab9 A |
636 | if (U_FAILURE(*status)) { |
637 | return FALSE; | |
638 | } | |
639 | return ((Calendar*)cal)->isWeekend(date, *status); | |
640 | } | |
641 | ||
642 | U_CAPI int32_t U_EXPORT2 | |
643 | ucal_getFieldDifference(UCalendar* cal, UDate target, | |
644 | UCalendarDateFields field, | |
645 | UErrorCode* status ) | |
646 | { | |
647 | if (U_FAILURE(*status)) { | |
648 | return 0; | |
649 | } | |
650 | return ((Calendar*)cal)->fieldDifference(target, field, *status); | |
651 | } | |
652 | ||
653 | ||
654 | static const UEnumeration defaultKeywordValues = { | |
655 | NULL, | |
656 | NULL, | |
657 | ulist_close_keyword_values_iterator, | |
658 | ulist_count_keyword_values, | |
659 | uenum_unextDefault, | |
660 | ulist_next_keyword_value, | |
661 | ulist_reset_keyword_values_iterator | |
662 | }; | |
663 | ||
664 | static const char * const CAL_TYPES[] = { | |
665 | "gregorian", | |
666 | "japanese", | |
667 | "buddhist", | |
668 | "roc", | |
669 | "persian", | |
670 | "islamic-civil", | |
671 | "islamic", | |
672 | "hebrew", | |
673 | "chinese", | |
674 | "indian", | |
675 | "coptic", | |
676 | "ethiopic", | |
677 | "ethiopic-amete-alem", | |
57a6839d A |
678 | "iso8601", |
679 | "dangi", | |
680 | "islamic-umalqura", | |
681 | "islamic-tbla", | |
682 | "islamic-rgsa", | |
729e4ab9 A |
683 | NULL |
684 | }; | |
685 | ||
686 | U_CAPI UEnumeration* U_EXPORT2 | |
687 | ucal_getKeywordValuesForLocale(const char * /* key */, const char* locale, UBool commonlyUsed, UErrorCode *status) { | |
688 | // Resolve region | |
2ca993e8 A |
689 | char prefRegion[ULOC_COUNTRY_CAPACITY]; |
690 | (void)ulocimp_getRegionForSupplementalData(locale, TRUE, prefRegion, sizeof(prefRegion), status); | |
729e4ab9 A |
691 | |
692 | // Read preferred calendar values from supplementalData calendarPreference | |
693 | UResourceBundle *rb = ures_openDirect(NULL, "supplementalData", status); | |
694 | ures_getByKey(rb, "calendarPreferenceData", rb, status); | |
695 | UResourceBundle *order = ures_getByKey(rb, prefRegion, NULL, status); | |
696 | if (*status == U_MISSING_RESOURCE_ERROR && rb != NULL) { | |
697 | *status = U_ZERO_ERROR; | |
698 | order = ures_getByKey(rb, "001", NULL, status); | |
699 | } | |
700 | ||
701 | // Create a list of calendar type strings | |
702 | UList *values = NULL; | |
703 | if (U_SUCCESS(*status)) { | |
704 | values = ulist_createEmptyList(status); | |
705 | if (U_SUCCESS(*status)) { | |
706 | for (int i = 0; i < ures_getSize(order); i++) { | |
707 | int32_t len; | |
708 | const UChar *type = ures_getStringByIndex(order, i, &len, status); | |
709 | char *caltype = (char*)uprv_malloc(len + 1); | |
710 | if (caltype == NULL) { | |
711 | *status = U_MEMORY_ALLOCATION_ERROR; | |
712 | break; | |
713 | } | |
714 | u_UCharsToChars(type, caltype, len); | |
715 | *(caltype + len) = 0; | |
716 | ||
717 | ulist_addItemEndList(values, caltype, TRUE, status); | |
718 | if (U_FAILURE(*status)) { | |
719 | break; | |
720 | } | |
721 | } | |
722 | ||
723 | if (U_SUCCESS(*status) && !commonlyUsed) { | |
724 | // If not commonlyUsed, add other available values | |
725 | for (int32_t i = 0; CAL_TYPES[i] != NULL; i++) { | |
726 | if (!ulist_containsString(values, CAL_TYPES[i], (int32_t)uprv_strlen(CAL_TYPES[i]))) { | |
727 | ulist_addItemEndList(values, CAL_TYPES[i], FALSE, status); | |
728 | if (U_FAILURE(*status)) { | |
729 | break; | |
730 | } | |
731 | } | |
732 | } | |
733 | } | |
734 | if (U_FAILURE(*status)) { | |
735 | ulist_deleteList(values); | |
736 | values = NULL; | |
737 | } | |
738 | } | |
739 | } | |
740 | ||
741 | ures_close(order); | |
742 | ures_close(rb); | |
743 | ||
744 | if (U_FAILURE(*status) || values == NULL) { | |
745 | return NULL; | |
746 | } | |
747 | ||
748 | // Create string enumeration | |
749 | UEnumeration *en = (UEnumeration*)uprv_malloc(sizeof(UEnumeration)); | |
750 | if (en == NULL) { | |
751 | *status = U_MEMORY_ALLOCATION_ERROR; | |
752 | ulist_deleteList(values); | |
753 | return NULL; | |
754 | } | |
755 | ulist_resetList(values); | |
756 | memcpy(en, &defaultKeywordValues, sizeof(UEnumeration)); | |
757 | en->context = values; | |
758 | return en; | |
46f4442e A |
759 | } |
760 | ||
51004dcb A |
761 | U_CAPI UBool U_EXPORT2 |
762 | ucal_getTimeZoneTransitionDate(const UCalendar* cal, UTimeZoneTransitionType type, | |
763 | UDate* transition, UErrorCode* status) | |
764 | { | |
765 | if (U_FAILURE(*status)) { | |
766 | return FALSE; | |
767 | } | |
768 | UDate base = ((Calendar*)cal)->getTime(*status); | |
769 | const TimeZone& tz = ((Calendar*)cal)->getTimeZone(); | |
770 | const BasicTimeZone * btz = dynamic_cast<const BasicTimeZone *>(&tz); | |
771 | if (btz != NULL && U_SUCCESS(*status)) { | |
772 | TimeZoneTransition tzt; | |
773 | UBool inclusive = (type == UCAL_TZ_TRANSITION_NEXT_INCLUSIVE || type == UCAL_TZ_TRANSITION_PREVIOUS_INCLUSIVE); | |
774 | UBool result = (type == UCAL_TZ_TRANSITION_NEXT || type == UCAL_TZ_TRANSITION_NEXT_INCLUSIVE)? | |
775 | btz->getNextTransition(base, inclusive, tzt): | |
776 | btz->getPreviousTransition(base, inclusive, tzt); | |
777 | if (result) { | |
778 | *transition = tzt.getTime(); | |
779 | return TRUE; | |
780 | } | |
781 | } | |
782 | return FALSE; | |
783 | } | |
784 | ||
57a6839d A |
785 | U_CAPI int32_t U_EXPORT2 |
786 | ucal_getWindowsTimeZoneID(const UChar* id, int32_t len, UChar* winid, int32_t winidCapacity, UErrorCode* status) { | |
787 | if (U_FAILURE(*status)) { | |
788 | return 0; | |
789 | } | |
790 | ||
791 | int32_t resultLen = 0; | |
792 | UnicodeString resultWinID; | |
793 | ||
794 | TimeZone::getWindowsID(UnicodeString(id, len), resultWinID, *status); | |
795 | if (U_SUCCESS(*status) && resultWinID.length() > 0) { | |
796 | resultLen = resultWinID.length(); | |
797 | resultWinID.extract(winid, winidCapacity, *status); | |
798 | } | |
799 | ||
800 | return resultLen; | |
801 | } | |
802 | ||
803 | U_CAPI int32_t U_EXPORT2 | |
804 | ucal_getTimeZoneIDForWindowsID(const UChar* winid, int32_t len, const char* region, UChar* id, int32_t idCapacity, UErrorCode* status) { | |
805 | if (U_FAILURE(*status)) { | |
806 | return 0; | |
807 | } | |
808 | ||
809 | int32_t resultLen = 0; | |
810 | UnicodeString resultID; | |
811 | ||
812 | TimeZone::getIDForWindowsID(UnicodeString(winid, len), region, resultID, *status); | |
813 | if (U_SUCCESS(*status) && resultID.length() > 0) { | |
814 | resultLen = resultID.length(); | |
815 | resultID.extract(id, idCapacity, *status); | |
816 | } | |
817 | ||
818 | return resultLen; | |
819 | } | |
820 | ||
b331163b A |
821 | // Apple-specific function uacal_getDayPeriod and helper functions/data |
822 | typedef struct { | |
823 | const char* name; | |
824 | UADayPeriod value; | |
825 | } DayPeriodNameToValue; | |
826 | ||
827 | static const DayPeriodNameToValue dpNameToValue[] = { | |
828 | { "afternoon1", UADAYPERIOD_AFTERNOON1 }, | |
829 | { "afternoon2", UADAYPERIOD_AFTERNOON2 }, | |
830 | { "evening1", UADAYPERIOD_EVENING1 }, | |
831 | { "evening2", UADAYPERIOD_EVENING2 }, | |
832 | { "midnight", UADAYPERIOD_MIDNIGHT }, | |
833 | { "morning1", UADAYPERIOD_MORNING1 }, | |
834 | { "morning2", UADAYPERIOD_MORNING2 }, | |
835 | { "night1", UADAYPERIOD_NIGHT1 }, | |
836 | { "night2", UADAYPERIOD_NIGHT2 }, | |
837 | { "noon", UADAYPERIOD_NOON }, | |
838 | }; | |
839 | ||
840 | static UADayPeriod dayPeriodFromName(const char* name) { | |
841 | const DayPeriodNameToValue * dpNameToValuePtr = dpNameToValue; | |
842 | const DayPeriodNameToValue * dpNameToValueLim = dpNameToValue + UPRV_LENGTHOF(dpNameToValue); | |
843 | // simple linear search, dpNameToValue is small enough | |
844 | for (; dpNameToValuePtr < dpNameToValueLim; dpNameToValuePtr++) { | |
845 | if (uprv_strcmp(name, dpNameToValuePtr->name) == 0) { | |
846 | return dpNameToValuePtr->value; | |
847 | } | |
848 | } | |
849 | return UADAYPERIOD_UNKNOWN; | |
850 | } | |
851 | ||
852 | typedef struct { | |
853 | int32_t startHour; | |
854 | int32_t startMin; | |
855 | UADayPeriod value; | |
856 | } DayPeriodEntry; | |
857 | ||
858 | int CompareDayPeriodEntries(const void* entry1Ptr, const void* entry2Ptr) { | |
859 | const DayPeriodEntry * dpEntry1Ptr = (const DayPeriodEntry *)entry1Ptr; | |
860 | const DayPeriodEntry * dpEntry2Ptr = (const DayPeriodEntry *)entry2Ptr; | |
861 | if (dpEntry1Ptr->startHour < dpEntry2Ptr->startHour) return -1; | |
862 | if (dpEntry1Ptr->startHour > dpEntry2Ptr->startHour) return 1; | |
863 | // here hours are equal | |
864 | if (dpEntry1Ptr->startMin < dpEntry2Ptr->startMin) return -1; | |
865 | if (dpEntry1Ptr->startMin > dpEntry2Ptr->startMin) return 1; | |
866 | return 0; | |
867 | } | |
868 | ||
869 | enum { kSetNameMaxLen = 8, kBoundaryTimeMaxLen = 6, kDayPeriodEntriesMax = 12 }; | |
870 | ||
871 | U_CAPI UADayPeriod U_EXPORT2 | |
872 | uacal_getDayPeriod( const char* locale, | |
873 | int32_t hour, | |
874 | int32_t minute, | |
875 | UBool formatStyle, | |
876 | UErrorCode* status ) { | |
877 | UADayPeriod dayPeriod = UADAYPERIOD_UNKNOWN; | |
878 | DayPeriodEntry dpEntries[kDayPeriodEntriesMax]; | |
879 | int32_t dpEntriesCount = 0; | |
880 | ||
881 | if (U_FAILURE(*status)) { | |
882 | return dayPeriod; | |
883 | } | |
884 | if (hour < 0 || hour > 23 || minute < 0 || minute > 59) { | |
885 | *status = U_ILLEGAL_ARGUMENT_ERROR; | |
886 | return dayPeriod; | |
887 | } | |
888 | // get dayPeriods bundle | |
889 | LocalUResourceBundlePointer rb(ures_openDirect(NULL, "dayPeriods", status)); | |
890 | if (U_FAILURE(*status)) { | |
891 | return dayPeriod; | |
892 | } | |
893 | // get locales/locales_selection subbundle | |
894 | LocalUResourceBundlePointer rbSub(ures_getByKey(rb.getAlias(), formatStyle? "locales": "locales_selection", NULL, status)); | |
895 | if (U_FAILURE(*status)) { | |
896 | return dayPeriod; | |
897 | } | |
898 | // get bundle for language (maps to setName) | |
899 | char lang[ULOC_LANG_CAPACITY] = {0}; | |
900 | if (locale != NULL) { | |
901 | UErrorCode tempStatus = U_ZERO_ERROR; | |
902 | uloc_getLanguage(locale, lang, ULOC_LANG_CAPACITY, &tempStatus); | |
903 | if (U_FAILURE(*status) || *status == U_STRING_NOT_TERMINATED_WARNING) { | |
904 | lang[0] = 0; | |
905 | } | |
906 | } | |
907 | if (lang[0] == 0) { | |
2ca993e8 | 908 | uprv_strcpy(lang, "en"); // should be "root" but the data for root was missing |
b331163b A |
909 | } |
910 | LocalUResourceBundlePointer rbLang(ures_getByKey(rbSub.getAlias(), lang, NULL, status)); | |
911 | if (U_FAILURE(*status)) { | |
912 | // should only happen if lang was not [root] en | |
2ca993e8 | 913 | // fallback should be "root" but the data for root was missing, use "en" |
b331163b A |
914 | *status = U_ZERO_ERROR; |
915 | rbLang.adoptInstead(ures_getByKey(rbSub.getAlias(), "en", rbLang.orphan(), status)); | |
916 | } | |
917 | if (U_FAILURE(*status)) { | |
918 | return dayPeriod; | |
919 | } | |
920 | // get setName from language bundle | |
921 | char setName[kSetNameMaxLen] = {0}; | |
922 | int32_t setNameLen = kSetNameMaxLen; | |
923 | ures_getUTF8String(rbLang.getAlias(), setName, &setNameLen, TRUE, status); | |
924 | if (U_FAILURE(*status)) { | |
925 | return dayPeriod; | |
926 | } | |
927 | // get rules subbundle | |
928 | rbSub.adoptInstead(ures_getByKey(rb.getAlias(), "rules", rbSub.orphan(), status)); | |
929 | if (U_FAILURE(*status)) { | |
930 | return dayPeriod; | |
931 | } | |
932 | // get ruleset from rules subbundle | |
933 | rb.adoptInstead(ures_getByKey(rbSub.getAlias(), setName, rb.orphan(), status)); | |
934 | if (U_FAILURE(*status)) { | |
935 | return dayPeriod; | |
936 | } | |
937 | // OK, we should finally have a ruleset (works to here). | |
938 | // Iterate over it to collect entries | |
939 | LocalUResourceBundlePointer rbBound; | |
940 | while (ures_hasNext(rb.getAlias())) { | |
941 | rbSub.adoptInstead(ures_getNextResource(rb.getAlias(), rbSub.orphan(), status)); | |
942 | if (U_FAILURE(*status)) { | |
943 | return dayPeriod; | |
944 | } | |
945 | // rbSub now has the bundle for a particular dayPeriod such as morning1, afternoon2, noon | |
946 | UADayPeriod dpForBundle = dayPeriodFromName(ures_getKey(rbSub.getAlias())); | |
2ca993e8 | 947 | int32_t dpLimit = 24; |
b331163b A |
948 | while (ures_hasNext(rbSub.getAlias())) { |
949 | rbBound.adoptInstead(ures_getNextResource(rbSub.getAlias(), rbBound.orphan(), status)); | |
950 | if (U_FAILURE(*status)) { | |
951 | return dayPeriod; | |
952 | } | |
2ca993e8 | 953 | // rbBound now has the bundle for a particular time period boundary such as at, from, before. |
b331163b A |
954 | // This is either of type URES_STRING (size=1) or of type URES_ARRAY (size > 1) |
955 | const char *boundaryType = ures_getKey(rbBound.getAlias()); | |
2ca993e8 A |
956 | char boundaryTimeStr[kBoundaryTimeMaxLen]; |
957 | int32_t boundaryTimeStrLen = kBoundaryTimeMaxLen; | |
958 | ures_getUTF8String(rbBound.getAlias(), boundaryTimeStr, &boundaryTimeStrLen, TRUE, status); | |
959 | if (U_FAILURE(*status)) { | |
960 | return dayPeriod; | |
961 | } | |
962 | int32_t startHour = atoi(boundaryTimeStr); // can depend on POSIX locale (fortunately no decimal sep here) | |
b331163b | 963 | if (uprv_strcmp(boundaryType, "before") == 0) { |
2ca993e8 | 964 | dpLimit = startHour; |
b331163b A |
965 | continue; |
966 | } | |
2ca993e8 A |
967 | int32_t startMinute = 0; |
968 | if (uprv_strcmp(boundaryType, "from") == 0) { | |
969 | startMinute = 1; | |
970 | if (startHour > dpLimit && dpEntriesCount < kDayPeriodEntriesMax) { | |
971 | dpEntries[dpEntriesCount].startHour = 0; | |
972 | dpEntries[dpEntriesCount].startMin = startMinute; | |
b331163b A |
973 | dpEntries[dpEntriesCount].value = dpForBundle; |
974 | dpEntriesCount++; | |
975 | } | |
976 | } | |
2ca993e8 A |
977 | if (dpEntriesCount < kDayPeriodEntriesMax) { |
978 | dpEntries[dpEntriesCount].startHour = startHour; | |
979 | dpEntries[dpEntriesCount].startMin = startMinute; | |
980 | dpEntries[dpEntriesCount].value = dpForBundle; | |
981 | dpEntriesCount++; | |
982 | } | |
b331163b A |
983 | } |
984 | } | |
985 | if (dpEntriesCount < kDayPeriodEntriesMax) { | |
986 | dpEntries[dpEntriesCount].startHour = 24; | |
987 | dpEntries[dpEntriesCount].startMin = 0; | |
988 | dpEntries[dpEntriesCount].value = UADAYPERIOD_UNKNOWN; | |
989 | dpEntriesCount++; | |
990 | } | |
991 | // We have collected all of the rule data, now sort by time | |
992 | qsort(dpEntries, dpEntriesCount, sizeof(DayPeriodEntry), CompareDayPeriodEntries); | |
2ca993e8 A |
993 | |
994 | // now fix start minute for the non-"at" entries | |
995 | int32_t dpIndex; | |
996 | for (dpIndex = 0; dpIndex < dpEntriesCount; dpIndex++) { | |
997 | if (dpIndex == 0 || (dpEntries[dpIndex-1].value != UADAYPERIOD_MIDNIGHT && dpEntries[dpIndex-1].value != UADAYPERIOD_NOON)) { | |
998 | dpEntries[dpIndex].startMin = 0; | |
999 | } | |
1000 | } | |
1001 | ||
b331163b A |
1002 | // OK, all of the above is what we would do in an "open" function if we were using an |
1003 | // open/use/close model for this; the object would just have the sorted array above. | |
1004 | ||
1005 | // Now we use the sorted array to find the dayPeriod matching the supplied time. | |
1006 | // Only a few entries, linear search OK | |
1007 | DayPeriodEntry entryToMatch = { hour, minute, UADAYPERIOD_UNKNOWN }; | |
2ca993e8 | 1008 | dpIndex = 0; |
b331163b A |
1009 | while (dpIndex < dpEntriesCount - 1 && CompareDayPeriodEntries(&entryToMatch, &dpEntries[dpIndex + 1]) >= 0) { |
1010 | dpIndex++; | |
1011 | } | |
1012 | if (CompareDayPeriodEntries(&entryToMatch, &dpEntries[dpIndex]) >= 0) { | |
1013 | dayPeriod = dpEntries[dpIndex].value; | |
1014 | } | |
1015 | ||
1016 | return dayPeriod; | |
1017 | } | |
1018 | ||
1019 | ||
57a6839d | 1020 | |
b75a7d8f | 1021 | #endif /* #if !UCONFIG_NO_FORMATTING */ |