]>
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; | |
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 | ||
51004dcb A |
208 | U_CAPI int32_t U_EXPORT2 |
209 | ucal_getTimeZoneID(const UCalendar *cal, | |
210 | UChar *result, | |
211 | int32_t resultLength, | |
212 | UErrorCode *status) | |
213 | { | |
214 | if (U_FAILURE(*status)) { | |
215 | return 0; | |
216 | } | |
217 | const TimeZone& tz = ((Calendar*)cal)->getTimeZone(); | |
218 | UnicodeString id; | |
219 | tz.getID(id); | |
220 | return id.extract(result, resultLength, *status); | |
221 | } | |
222 | ||
b75a7d8f A |
223 | U_CAPI int32_t U_EXPORT2 |
224 | ucal_getTimeZoneDisplayName(const UCalendar* cal, | |
225 | UCalendarDisplayNameType type, | |
226 | const char *locale, | |
227 | UChar* result, | |
228 | int32_t resultLength, | |
229 | UErrorCode* status) | |
230 | { | |
231 | ||
46f4442e | 232 | if(U_FAILURE(*status)) return -1; |
b75a7d8f | 233 | |
46f4442e A |
234 | const TimeZone& tz = ((Calendar*)cal)->getTimeZone(); |
235 | UnicodeString id; | |
236 | if(!(result==NULL && resultLength==0)) { | |
237 | // NULL destination for pure preflighting: empty dummy string | |
238 | // otherwise, alias the destination buffer | |
239 | id.setTo(result, 0, resultLength); | |
240 | } | |
b75a7d8f | 241 | |
46f4442e | 242 | switch(type) { |
b75a7d8f | 243 | case UCAL_STANDARD: |
46f4442e A |
244 | tz.getDisplayName(FALSE, TimeZone::LONG, Locale(locale), id); |
245 | break; | |
b75a7d8f A |
246 | |
247 | case UCAL_SHORT_STANDARD: | |
46f4442e A |
248 | tz.getDisplayName(FALSE, TimeZone::SHORT, Locale(locale), id); |
249 | break; | |
b75a7d8f A |
250 | |
251 | case UCAL_DST: | |
46f4442e A |
252 | tz.getDisplayName(TRUE, TimeZone::LONG, Locale(locale), id); |
253 | break; | |
b75a7d8f A |
254 | |
255 | case UCAL_SHORT_DST: | |
46f4442e A |
256 | tz.getDisplayName(TRUE, TimeZone::SHORT, Locale(locale), id); |
257 | break; | |
258 | } | |
b75a7d8f | 259 | |
46f4442e | 260 | return id.extract(result, resultLength, *status); |
b75a7d8f A |
261 | } |
262 | ||
263 | U_CAPI UBool U_EXPORT2 | |
264 | ucal_inDaylightTime( const UCalendar* cal, | |
46f4442e | 265 | UErrorCode* status ) |
b75a7d8f A |
266 | { |
267 | ||
46f4442e A |
268 | if(U_FAILURE(*status)) return (UBool) -1; |
269 | return ((Calendar*)cal)->inDaylightTime(*status); | |
b75a7d8f A |
270 | } |
271 | ||
46f4442e | 272 | U_CAPI void U_EXPORT2 |
73c04bcf | 273 | ucal_setGregorianChange(UCalendar *cal, UDate date, UErrorCode *pErrorCode) { |
46f4442e A |
274 | if(U_FAILURE(*pErrorCode)) { |
275 | return; | |
276 | } | |
277 | Calendar *cpp_cal = (Calendar *)cal; | |
729e4ab9 A |
278 | GregorianCalendar *gregocal = dynamic_cast<GregorianCalendar *>(cpp_cal); |
279 | // Not if(gregocal == NULL) { | |
280 | // because we really want to work only with a GregorianCalendar, not with | |
281 | // its subclasses like BuddhistCalendar. | |
4388f060 A |
282 | if (cpp_cal == NULL) { |
283 | // We normally don't check "this" pointers for NULL, but this here avoids | |
284 | // compiler-generated exception-throwing code in case cal == NULL. | |
285 | *pErrorCode = U_ILLEGAL_ARGUMENT_ERROR; | |
286 | return; | |
287 | } | |
729e4ab9 | 288 | if(typeid(*cpp_cal) != typeid(GregorianCalendar)) { |
46f4442e A |
289 | *pErrorCode = U_UNSUPPORTED_ERROR; |
290 | return; | |
291 | } | |
729e4ab9 | 292 | gregocal->setGregorianChange(date, *pErrorCode); |
73c04bcf A |
293 | } |
294 | ||
46f4442e | 295 | U_CAPI UDate U_EXPORT2 |
73c04bcf | 296 | ucal_getGregorianChange(const UCalendar *cal, UErrorCode *pErrorCode) { |
46f4442e A |
297 | if(U_FAILURE(*pErrorCode)) { |
298 | return (UDate)0; | |
299 | } | |
729e4ab9 A |
300 | const Calendar *cpp_cal = (const Calendar *)cal; |
301 | const GregorianCalendar *gregocal = dynamic_cast<const GregorianCalendar *>(cpp_cal); | |
302 | // Not if(gregocal == NULL) { | |
303 | // see comments in ucal_setGregorianChange(). | |
4388f060 A |
304 | if (cpp_cal == NULL) { |
305 | // We normally don't check "this" pointers for NULL, but this here avoids | |
306 | // compiler-generated exception-throwing code in case cal == NULL. | |
307 | *pErrorCode = U_ILLEGAL_ARGUMENT_ERROR; | |
308 | return (UDate)0; | |
309 | } | |
729e4ab9 | 310 | if(typeid(*cpp_cal) != typeid(GregorianCalendar)) { |
46f4442e A |
311 | *pErrorCode = U_UNSUPPORTED_ERROR; |
312 | return (UDate)0; | |
313 | } | |
729e4ab9 | 314 | return gregocal->getGregorianChange(); |
73c04bcf A |
315 | } |
316 | ||
b75a7d8f A |
317 | U_CAPI int32_t U_EXPORT2 |
318 | ucal_getAttribute( const UCalendar* cal, | |
46f4442e | 319 | UCalendarAttribute attr) |
b75a7d8f A |
320 | { |
321 | ||
46f4442e | 322 | switch(attr) { |
b75a7d8f | 323 | case UCAL_LENIENT: |
46f4442e A |
324 | return ((Calendar*)cal)->isLenient(); |
325 | ||
b75a7d8f | 326 | case UCAL_FIRST_DAY_OF_WEEK: |
46f4442e A |
327 | return ((Calendar*)cal)->getFirstDayOfWeek(); |
328 | ||
b75a7d8f | 329 | case UCAL_MINIMAL_DAYS_IN_FIRST_WEEK: |
46f4442e | 330 | return ((Calendar*)cal)->getMinimalDaysInFirstWeek(); |
b75a7d8f | 331 | |
4388f060 A |
332 | case UCAL_REPEATED_WALL_TIME: |
333 | return ((Calendar*)cal)->getRepeatedWallTimeOption(); | |
334 | ||
335 | case UCAL_SKIPPED_WALL_TIME: | |
336 | return ((Calendar*)cal)->getSkippedWallTimeOption(); | |
337 | ||
b75a7d8f | 338 | default: |
46f4442e A |
339 | break; |
340 | } | |
341 | return -1; | |
b75a7d8f A |
342 | } |
343 | ||
344 | U_CAPI void U_EXPORT2 | |
345 | ucal_setAttribute( UCalendar* cal, | |
46f4442e A |
346 | UCalendarAttribute attr, |
347 | int32_t newValue) | |
b75a7d8f A |
348 | { |
349 | ||
46f4442e | 350 | switch(attr) { |
b75a7d8f | 351 | case UCAL_LENIENT: |
46f4442e A |
352 | ((Calendar*)cal)->setLenient((UBool)newValue); |
353 | break; | |
354 | ||
b75a7d8f | 355 | case UCAL_FIRST_DAY_OF_WEEK: |
46f4442e A |
356 | ((Calendar*)cal)->setFirstDayOfWeek((UCalendarDaysOfWeek)newValue); |
357 | break; | |
358 | ||
b75a7d8f | 359 | case UCAL_MINIMAL_DAYS_IN_FIRST_WEEK: |
46f4442e A |
360 | ((Calendar*)cal)->setMinimalDaysInFirstWeek((uint8_t)newValue); |
361 | break; | |
4388f060 A |
362 | |
363 | case UCAL_REPEATED_WALL_TIME: | |
364 | ((Calendar*)cal)->setRepeatedWallTimeOption((UCalendarWallTimeOption)newValue); | |
365 | break; | |
366 | ||
367 | case UCAL_SKIPPED_WALL_TIME: | |
368 | ((Calendar*)cal)->setSkippedWallTimeOption((UCalendarWallTimeOption)newValue); | |
369 | break; | |
46f4442e | 370 | } |
b75a7d8f A |
371 | } |
372 | ||
373 | U_CAPI const char* U_EXPORT2 | |
374 | ucal_getAvailable(int32_t index) | |
375 | { | |
376 | ||
46f4442e | 377 | return uloc_getAvailable(index); |
b75a7d8f A |
378 | } |
379 | ||
380 | U_CAPI int32_t U_EXPORT2 | |
381 | ucal_countAvailable() | |
382 | { | |
383 | ||
46f4442e | 384 | return uloc_countAvailable(); |
b75a7d8f A |
385 | } |
386 | ||
387 | U_CAPI UDate U_EXPORT2 | |
388 | ucal_getMillis( const UCalendar* cal, | |
46f4442e | 389 | UErrorCode* status) |
b75a7d8f A |
390 | { |
391 | ||
46f4442e | 392 | if(U_FAILURE(*status)) return (UDate) 0; |
b75a7d8f | 393 | |
46f4442e | 394 | return ((Calendar*)cal)->getTime(*status); |
b75a7d8f A |
395 | } |
396 | ||
397 | U_CAPI void U_EXPORT2 | |
398 | ucal_setMillis( UCalendar* cal, | |
46f4442e A |
399 | UDate dateTime, |
400 | UErrorCode* status ) | |
b75a7d8f | 401 | { |
46f4442e | 402 | if(U_FAILURE(*status)) return; |
b75a7d8f | 403 | |
46f4442e | 404 | ((Calendar*)cal)->setTime(dateTime, *status); |
b75a7d8f A |
405 | } |
406 | ||
407 | // TBD: why does this take an UErrorCode? | |
408 | U_CAPI void U_EXPORT2 | |
409 | ucal_setDate( UCalendar* cal, | |
46f4442e A |
410 | int32_t year, |
411 | int32_t month, | |
412 | int32_t date, | |
413 | UErrorCode *status) | |
b75a7d8f A |
414 | { |
415 | ||
46f4442e | 416 | if(U_FAILURE(*status)) return; |
b75a7d8f | 417 | |
46f4442e | 418 | ((Calendar*)cal)->set(year, month, date); |
b75a7d8f A |
419 | } |
420 | ||
421 | // TBD: why does this take an UErrorCode? | |
422 | U_CAPI void U_EXPORT2 | |
423 | ucal_setDateTime( UCalendar* cal, | |
46f4442e A |
424 | int32_t year, |
425 | int32_t month, | |
426 | int32_t date, | |
427 | int32_t hour, | |
428 | int32_t minute, | |
429 | int32_t second, | |
430 | UErrorCode *status) | |
b75a7d8f | 431 | { |
46f4442e | 432 | if(U_FAILURE(*status)) return; |
b75a7d8f | 433 | |
46f4442e | 434 | ((Calendar*)cal)->set(year, month, date, hour, minute, second); |
b75a7d8f A |
435 | } |
436 | ||
437 | U_CAPI UBool U_EXPORT2 | |
438 | ucal_equivalentTo( const UCalendar* cal1, | |
46f4442e | 439 | const UCalendar* cal2) |
b75a7d8f A |
440 | { |
441 | ||
46f4442e | 442 | return ((Calendar*)cal1)->isEquivalentTo(*((Calendar*)cal2)); |
b75a7d8f A |
443 | } |
444 | ||
445 | U_CAPI void U_EXPORT2 | |
446 | ucal_add( UCalendar* cal, | |
46f4442e A |
447 | UCalendarDateFields field, |
448 | int32_t amount, | |
449 | UErrorCode* status) | |
b75a7d8f A |
450 | { |
451 | ||
46f4442e | 452 | if(U_FAILURE(*status)) return; |
b75a7d8f | 453 | |
46f4442e | 454 | ((Calendar*)cal)->add(field, amount, *status); |
b75a7d8f A |
455 | } |
456 | ||
457 | U_CAPI void U_EXPORT2 | |
458 | ucal_roll( 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)->roll(field, amount, *status); |
b75a7d8f A |
467 | } |
468 | ||
469 | U_CAPI int32_t U_EXPORT2 | |
470 | ucal_get( const UCalendar* cal, | |
46f4442e A |
471 | UCalendarDateFields field, |
472 | UErrorCode* status ) | |
b75a7d8f A |
473 | { |
474 | ||
46f4442e | 475 | if(U_FAILURE(*status)) return -1; |
b75a7d8f | 476 | |
46f4442e | 477 | return ((Calendar*)cal)->get(field, *status); |
b75a7d8f A |
478 | } |
479 | ||
480 | U_CAPI void U_EXPORT2 | |
481 | ucal_set( UCalendar* cal, | |
46f4442e A |
482 | UCalendarDateFields field, |
483 | int32_t value) | |
b75a7d8f A |
484 | { |
485 | ||
46f4442e | 486 | ((Calendar*)cal)->set(field, value); |
b75a7d8f A |
487 | } |
488 | ||
489 | U_CAPI UBool U_EXPORT2 | |
490 | ucal_isSet( const UCalendar* cal, | |
46f4442e | 491 | UCalendarDateFields field) |
b75a7d8f A |
492 | { |
493 | ||
46f4442e | 494 | return ((Calendar*)cal)->isSet(field); |
b75a7d8f A |
495 | } |
496 | ||
497 | U_CAPI void U_EXPORT2 | |
498 | ucal_clearField( UCalendar* cal, | |
46f4442e | 499 | UCalendarDateFields field) |
b75a7d8f A |
500 | { |
501 | ||
46f4442e | 502 | ((Calendar*)cal)->clear(field); |
b75a7d8f A |
503 | } |
504 | ||
505 | U_CAPI void U_EXPORT2 | |
506 | ucal_clear(UCalendar* calendar) | |
507 | { | |
508 | ||
46f4442e | 509 | ((Calendar*)calendar)->clear(); |
b75a7d8f A |
510 | } |
511 | ||
512 | U_CAPI int32_t U_EXPORT2 | |
513 | ucal_getLimit( const UCalendar* cal, | |
46f4442e A |
514 | UCalendarDateFields field, |
515 | UCalendarLimitType type, | |
516 | UErrorCode *status) | |
b75a7d8f A |
517 | { |
518 | ||
46f4442e A |
519 | if(status==0 || U_FAILURE(*status)) { |
520 | return -1; | |
521 | } | |
522 | ||
523 | switch(type) { | |
b75a7d8f | 524 | case UCAL_MINIMUM: |
46f4442e | 525 | return ((Calendar*)cal)->getMinimum(field); |
b75a7d8f A |
526 | |
527 | case UCAL_MAXIMUM: | |
46f4442e | 528 | return ((Calendar*)cal)->getMaximum(field); |
b75a7d8f A |
529 | |
530 | case UCAL_GREATEST_MINIMUM: | |
46f4442e | 531 | return ((Calendar*)cal)->getGreatestMinimum(field); |
b75a7d8f A |
532 | |
533 | case UCAL_LEAST_MAXIMUM: | |
46f4442e | 534 | return ((Calendar*)cal)->getLeastMaximum(field); |
b75a7d8f A |
535 | |
536 | case UCAL_ACTUAL_MINIMUM: | |
46f4442e A |
537 | return ((Calendar*)cal)->getActualMinimum(field, |
538 | *status); | |
b75a7d8f A |
539 | |
540 | case UCAL_ACTUAL_MAXIMUM: | |
46f4442e A |
541 | return ((Calendar*)cal)->getActualMaximum(field, |
542 | *status); | |
b75a7d8f A |
543 | |
544 | default: | |
46f4442e A |
545 | break; |
546 | } | |
547 | return -1; | |
b75a7d8f A |
548 | } |
549 | ||
374ca955 A |
550 | U_CAPI const char * U_EXPORT2 |
551 | ucal_getLocaleByType(const UCalendar *cal, ULocDataLocaleType type, UErrorCode* status) | |
552 | { | |
553 | if (cal == NULL) { | |
554 | if (U_SUCCESS(*status)) { | |
555 | *status = U_ILLEGAL_ARGUMENT_ERROR; | |
556 | } | |
557 | return NULL; | |
558 | } | |
559 | return ((Calendar*)cal)->getLocaleID(type, *status); | |
560 | } | |
561 | ||
46f4442e A |
562 | U_CAPI const char * U_EXPORT2 |
563 | ucal_getTZDataVersion(UErrorCode* status) | |
564 | { | |
565 | return TimeZone::getTZDataVersion(*status); | |
566 | } | |
567 | ||
568 | U_CAPI int32_t U_EXPORT2 | |
569 | ucal_getCanonicalTimeZoneID(const UChar* id, int32_t len, | |
570 | UChar* result, int32_t resultCapacity, UBool *isSystemID, UErrorCode* status) { | |
571 | if(status == 0 || U_FAILURE(*status)) { | |
572 | return 0; | |
573 | } | |
574 | if (isSystemID) { | |
575 | *isSystemID = FALSE; | |
576 | } | |
577 | if (id == 0 || len == 0 || result == 0 || resultCapacity <= 0) { | |
578 | *status = U_ILLEGAL_ARGUMENT_ERROR; | |
579 | return 0; | |
580 | } | |
581 | int32_t reslen = 0; | |
582 | UnicodeString canonical; | |
583 | UBool systemID = FALSE; | |
584 | TimeZone::getCanonicalID(UnicodeString(id, len), canonical, systemID, *status); | |
585 | if (U_SUCCESS(*status)) { | |
586 | if (isSystemID) { | |
587 | *isSystemID = systemID; | |
588 | } | |
589 | reslen = canonical.extract(result, resultCapacity, *status); | |
590 | } | |
591 | return reslen; | |
592 | } | |
593 | ||
594 | U_CAPI const char * U_EXPORT2 | |
595 | ucal_getType(const UCalendar *cal, UErrorCode* status) | |
596 | { | |
597 | if (U_FAILURE(*status)) { | |
598 | return NULL; | |
599 | } | |
600 | return ((Calendar*)cal)->getType(); | |
601 | } | |
602 | ||
729e4ab9 A |
603 | U_CAPI UCalendarWeekdayType U_EXPORT2 |
604 | ucal_getDayOfWeekType(const UCalendar *cal, UCalendarDaysOfWeek dayOfWeek, UErrorCode* status) | |
605 | { | |
606 | if (U_FAILURE(*status)) { | |
607 | return UCAL_WEEKDAY; | |
608 | } | |
609 | return ((Calendar*)cal)->getDayOfWeekType(dayOfWeek, *status); | |
610 | } | |
611 | ||
612 | U_CAPI int32_t U_EXPORT2 | |
613 | ucal_getWeekendTransition(const UCalendar *cal, UCalendarDaysOfWeek dayOfWeek, UErrorCode *status) | |
614 | { | |
615 | if (U_FAILURE(*status)) { | |
616 | return 0; | |
617 | } | |
618 | return ((Calendar*)cal)->getWeekendTransition(dayOfWeek, *status); | |
619 | } | |
620 | ||
621 | U_CAPI UBool U_EXPORT2 | |
622 | ucal_isWeekend(const UCalendar *cal, UDate date, UErrorCode *status) | |
46f4442e | 623 | { |
729e4ab9 A |
624 | if (U_FAILURE(*status)) { |
625 | return FALSE; | |
626 | } | |
627 | return ((Calendar*)cal)->isWeekend(date, *status); | |
628 | } | |
629 | ||
630 | U_CAPI int32_t U_EXPORT2 | |
631 | ucal_getFieldDifference(UCalendar* cal, UDate target, | |
632 | UCalendarDateFields field, | |
633 | UErrorCode* status ) | |
634 | { | |
635 | if (U_FAILURE(*status)) { | |
636 | return 0; | |
637 | } | |
638 | return ((Calendar*)cal)->fieldDifference(target, field, *status); | |
639 | } | |
640 | ||
641 | ||
642 | static const UEnumeration defaultKeywordValues = { | |
643 | NULL, | |
644 | NULL, | |
645 | ulist_close_keyword_values_iterator, | |
646 | ulist_count_keyword_values, | |
647 | uenum_unextDefault, | |
648 | ulist_next_keyword_value, | |
649 | ulist_reset_keyword_values_iterator | |
650 | }; | |
651 | ||
652 | static const char * const CAL_TYPES[] = { | |
653 | "gregorian", | |
654 | "japanese", | |
655 | "buddhist", | |
656 | "roc", | |
657 | "persian", | |
658 | "islamic-civil", | |
659 | "islamic", | |
660 | "hebrew", | |
661 | "chinese", | |
662 | "indian", | |
663 | "coptic", | |
664 | "ethiopic", | |
665 | "ethiopic-amete-alem", | |
57a6839d A |
666 | "iso8601", |
667 | "dangi", | |
668 | "islamic-umalqura", | |
669 | "islamic-tbla", | |
670 | "islamic-rgsa", | |
729e4ab9 A |
671 | NULL |
672 | }; | |
673 | ||
674 | U_CAPI UEnumeration* U_EXPORT2 | |
675 | ucal_getKeywordValuesForLocale(const char * /* key */, const char* locale, UBool commonlyUsed, UErrorCode *status) { | |
676 | // Resolve region | |
2ca993e8 A |
677 | char prefRegion[ULOC_COUNTRY_CAPACITY]; |
678 | (void)ulocimp_getRegionForSupplementalData(locale, TRUE, prefRegion, sizeof(prefRegion), status); | |
729e4ab9 A |
679 | |
680 | // Read preferred calendar values from supplementalData calendarPreference | |
681 | UResourceBundle *rb = ures_openDirect(NULL, "supplementalData", status); | |
682 | ures_getByKey(rb, "calendarPreferenceData", rb, status); | |
683 | UResourceBundle *order = ures_getByKey(rb, prefRegion, NULL, status); | |
684 | if (*status == U_MISSING_RESOURCE_ERROR && rb != NULL) { | |
685 | *status = U_ZERO_ERROR; | |
686 | order = ures_getByKey(rb, "001", NULL, status); | |
687 | } | |
688 | ||
689 | // Create a list of calendar type strings | |
690 | UList *values = NULL; | |
691 | if (U_SUCCESS(*status)) { | |
692 | values = ulist_createEmptyList(status); | |
693 | if (U_SUCCESS(*status)) { | |
694 | for (int i = 0; i < ures_getSize(order); i++) { | |
695 | int32_t len; | |
696 | const UChar *type = ures_getStringByIndex(order, i, &len, status); | |
697 | char *caltype = (char*)uprv_malloc(len + 1); | |
698 | if (caltype == NULL) { | |
699 | *status = U_MEMORY_ALLOCATION_ERROR; | |
700 | break; | |
701 | } | |
702 | u_UCharsToChars(type, caltype, len); | |
703 | *(caltype + len) = 0; | |
704 | ||
705 | ulist_addItemEndList(values, caltype, TRUE, status); | |
706 | if (U_FAILURE(*status)) { | |
707 | break; | |
708 | } | |
709 | } | |
710 | ||
711 | if (U_SUCCESS(*status) && !commonlyUsed) { | |
712 | // If not commonlyUsed, add other available values | |
713 | for (int32_t i = 0; CAL_TYPES[i] != NULL; i++) { | |
714 | if (!ulist_containsString(values, CAL_TYPES[i], (int32_t)uprv_strlen(CAL_TYPES[i]))) { | |
715 | ulist_addItemEndList(values, CAL_TYPES[i], FALSE, status); | |
716 | if (U_FAILURE(*status)) { | |
717 | break; | |
718 | } | |
719 | } | |
720 | } | |
721 | } | |
722 | if (U_FAILURE(*status)) { | |
723 | ulist_deleteList(values); | |
724 | values = NULL; | |
725 | } | |
726 | } | |
727 | } | |
728 | ||
729 | ures_close(order); | |
730 | ures_close(rb); | |
731 | ||
732 | if (U_FAILURE(*status) || values == NULL) { | |
733 | return NULL; | |
734 | } | |
735 | ||
736 | // Create string enumeration | |
737 | UEnumeration *en = (UEnumeration*)uprv_malloc(sizeof(UEnumeration)); | |
738 | if (en == NULL) { | |
739 | *status = U_MEMORY_ALLOCATION_ERROR; | |
740 | ulist_deleteList(values); | |
741 | return NULL; | |
742 | } | |
743 | ulist_resetList(values); | |
744 | memcpy(en, &defaultKeywordValues, sizeof(UEnumeration)); | |
745 | en->context = values; | |
746 | return en; | |
46f4442e A |
747 | } |
748 | ||
51004dcb A |
749 | U_CAPI UBool U_EXPORT2 |
750 | ucal_getTimeZoneTransitionDate(const UCalendar* cal, UTimeZoneTransitionType type, | |
751 | UDate* transition, UErrorCode* status) | |
752 | { | |
753 | if (U_FAILURE(*status)) { | |
754 | return FALSE; | |
755 | } | |
756 | UDate base = ((Calendar*)cal)->getTime(*status); | |
757 | const TimeZone& tz = ((Calendar*)cal)->getTimeZone(); | |
758 | const BasicTimeZone * btz = dynamic_cast<const BasicTimeZone *>(&tz); | |
759 | if (btz != NULL && U_SUCCESS(*status)) { | |
760 | TimeZoneTransition tzt; | |
761 | UBool inclusive = (type == UCAL_TZ_TRANSITION_NEXT_INCLUSIVE || type == UCAL_TZ_TRANSITION_PREVIOUS_INCLUSIVE); | |
762 | UBool result = (type == UCAL_TZ_TRANSITION_NEXT || type == UCAL_TZ_TRANSITION_NEXT_INCLUSIVE)? | |
763 | btz->getNextTransition(base, inclusive, tzt): | |
764 | btz->getPreviousTransition(base, inclusive, tzt); | |
765 | if (result) { | |
766 | *transition = tzt.getTime(); | |
767 | return TRUE; | |
768 | } | |
769 | } | |
770 | return FALSE; | |
771 | } | |
772 | ||
57a6839d A |
773 | U_CAPI int32_t U_EXPORT2 |
774 | ucal_getWindowsTimeZoneID(const UChar* id, int32_t len, UChar* winid, int32_t winidCapacity, UErrorCode* status) { | |
775 | if (U_FAILURE(*status)) { | |
776 | return 0; | |
777 | } | |
778 | ||
779 | int32_t resultLen = 0; | |
780 | UnicodeString resultWinID; | |
781 | ||
782 | TimeZone::getWindowsID(UnicodeString(id, len), resultWinID, *status); | |
783 | if (U_SUCCESS(*status) && resultWinID.length() > 0) { | |
784 | resultLen = resultWinID.length(); | |
785 | resultWinID.extract(winid, winidCapacity, *status); | |
786 | } | |
787 | ||
788 | return resultLen; | |
789 | } | |
790 | ||
791 | U_CAPI int32_t U_EXPORT2 | |
792 | ucal_getTimeZoneIDForWindowsID(const UChar* winid, int32_t len, const char* region, UChar* id, int32_t idCapacity, UErrorCode* status) { | |
793 | if (U_FAILURE(*status)) { | |
794 | return 0; | |
795 | } | |
796 | ||
797 | int32_t resultLen = 0; | |
798 | UnicodeString resultID; | |
799 | ||
800 | TimeZone::getIDForWindowsID(UnicodeString(winid, len), region, resultID, *status); | |
801 | if (U_SUCCESS(*status) && resultID.length() > 0) { | |
802 | resultLen = resultID.length(); | |
803 | resultID.extract(id, idCapacity, *status); | |
804 | } | |
805 | ||
806 | return resultLen; | |
807 | } | |
808 | ||
b331163b A |
809 | // Apple-specific function uacal_getDayPeriod and helper functions/data |
810 | typedef struct { | |
811 | const char* name; | |
812 | UADayPeriod value; | |
813 | } DayPeriodNameToValue; | |
814 | ||
815 | static const DayPeriodNameToValue dpNameToValue[] = { | |
816 | { "afternoon1", UADAYPERIOD_AFTERNOON1 }, | |
817 | { "afternoon2", UADAYPERIOD_AFTERNOON2 }, | |
818 | { "evening1", UADAYPERIOD_EVENING1 }, | |
819 | { "evening2", UADAYPERIOD_EVENING2 }, | |
820 | { "midnight", UADAYPERIOD_MIDNIGHT }, | |
821 | { "morning1", UADAYPERIOD_MORNING1 }, | |
822 | { "morning2", UADAYPERIOD_MORNING2 }, | |
823 | { "night1", UADAYPERIOD_NIGHT1 }, | |
824 | { "night2", UADAYPERIOD_NIGHT2 }, | |
825 | { "noon", UADAYPERIOD_NOON }, | |
826 | }; | |
827 | ||
828 | static UADayPeriod dayPeriodFromName(const char* name) { | |
829 | const DayPeriodNameToValue * dpNameToValuePtr = dpNameToValue; | |
830 | const DayPeriodNameToValue * dpNameToValueLim = dpNameToValue + UPRV_LENGTHOF(dpNameToValue); | |
831 | // simple linear search, dpNameToValue is small enough | |
832 | for (; dpNameToValuePtr < dpNameToValueLim; dpNameToValuePtr++) { | |
833 | if (uprv_strcmp(name, dpNameToValuePtr->name) == 0) { | |
834 | return dpNameToValuePtr->value; | |
835 | } | |
836 | } | |
837 | return UADAYPERIOD_UNKNOWN; | |
838 | } | |
839 | ||
840 | typedef struct { | |
841 | int32_t startHour; | |
842 | int32_t startMin; | |
843 | UADayPeriod value; | |
844 | } DayPeriodEntry; | |
845 | ||
846 | int CompareDayPeriodEntries(const void* entry1Ptr, const void* entry2Ptr) { | |
847 | const DayPeriodEntry * dpEntry1Ptr = (const DayPeriodEntry *)entry1Ptr; | |
848 | const DayPeriodEntry * dpEntry2Ptr = (const DayPeriodEntry *)entry2Ptr; | |
849 | if (dpEntry1Ptr->startHour < dpEntry2Ptr->startHour) return -1; | |
850 | if (dpEntry1Ptr->startHour > dpEntry2Ptr->startHour) return 1; | |
851 | // here hours are equal | |
852 | if (dpEntry1Ptr->startMin < dpEntry2Ptr->startMin) return -1; | |
853 | if (dpEntry1Ptr->startMin > dpEntry2Ptr->startMin) return 1; | |
854 | return 0; | |
855 | } | |
856 | ||
857 | enum { kSetNameMaxLen = 8, kBoundaryTimeMaxLen = 6, kDayPeriodEntriesMax = 12 }; | |
858 | ||
859 | U_CAPI UADayPeriod U_EXPORT2 | |
860 | uacal_getDayPeriod( const char* locale, | |
861 | int32_t hour, | |
862 | int32_t minute, | |
863 | UBool formatStyle, | |
864 | UErrorCode* status ) { | |
865 | UADayPeriod dayPeriod = UADAYPERIOD_UNKNOWN; | |
866 | DayPeriodEntry dpEntries[kDayPeriodEntriesMax]; | |
867 | int32_t dpEntriesCount = 0; | |
868 | ||
869 | if (U_FAILURE(*status)) { | |
870 | return dayPeriod; | |
871 | } | |
872 | if (hour < 0 || hour > 23 || minute < 0 || minute > 59) { | |
873 | *status = U_ILLEGAL_ARGUMENT_ERROR; | |
874 | return dayPeriod; | |
875 | } | |
876 | // get dayPeriods bundle | |
877 | LocalUResourceBundlePointer rb(ures_openDirect(NULL, "dayPeriods", status)); | |
878 | if (U_FAILURE(*status)) { | |
879 | return dayPeriod; | |
880 | } | |
881 | // get locales/locales_selection subbundle | |
882 | LocalUResourceBundlePointer rbSub(ures_getByKey(rb.getAlias(), formatStyle? "locales": "locales_selection", NULL, status)); | |
883 | if (U_FAILURE(*status)) { | |
884 | return dayPeriod; | |
885 | } | |
886 | // get bundle for language (maps to setName) | |
887 | char lang[ULOC_LANG_CAPACITY] = {0}; | |
888 | if (locale != NULL) { | |
889 | UErrorCode tempStatus = U_ZERO_ERROR; | |
890 | uloc_getLanguage(locale, lang, ULOC_LANG_CAPACITY, &tempStatus); | |
891 | if (U_FAILURE(*status) || *status == U_STRING_NOT_TERMINATED_WARNING) { | |
892 | lang[0] = 0; | |
893 | } | |
894 | } | |
895 | if (lang[0] == 0) { | |
2ca993e8 | 896 | uprv_strcpy(lang, "en"); // should be "root" but the data for root was missing |
b331163b A |
897 | } |
898 | LocalUResourceBundlePointer rbLang(ures_getByKey(rbSub.getAlias(), lang, NULL, status)); | |
899 | if (U_FAILURE(*status)) { | |
900 | // should only happen if lang was not [root] en | |
2ca993e8 | 901 | // fallback should be "root" but the data for root was missing, use "en" |
b331163b A |
902 | *status = U_ZERO_ERROR; |
903 | rbLang.adoptInstead(ures_getByKey(rbSub.getAlias(), "en", rbLang.orphan(), status)); | |
904 | } | |
905 | if (U_FAILURE(*status)) { | |
906 | return dayPeriod; | |
907 | } | |
908 | // get setName from language bundle | |
909 | char setName[kSetNameMaxLen] = {0}; | |
910 | int32_t setNameLen = kSetNameMaxLen; | |
911 | ures_getUTF8String(rbLang.getAlias(), setName, &setNameLen, TRUE, status); | |
912 | if (U_FAILURE(*status)) { | |
913 | return dayPeriod; | |
914 | } | |
915 | // get rules subbundle | |
916 | rbSub.adoptInstead(ures_getByKey(rb.getAlias(), "rules", rbSub.orphan(), status)); | |
917 | if (U_FAILURE(*status)) { | |
918 | return dayPeriod; | |
919 | } | |
920 | // get ruleset from rules subbundle | |
921 | rb.adoptInstead(ures_getByKey(rbSub.getAlias(), setName, rb.orphan(), status)); | |
922 | if (U_FAILURE(*status)) { | |
923 | return dayPeriod; | |
924 | } | |
925 | // OK, we should finally have a ruleset (works to here). | |
926 | // Iterate over it to collect entries | |
927 | LocalUResourceBundlePointer rbBound; | |
928 | while (ures_hasNext(rb.getAlias())) { | |
929 | rbSub.adoptInstead(ures_getNextResource(rb.getAlias(), rbSub.orphan(), status)); | |
930 | if (U_FAILURE(*status)) { | |
931 | return dayPeriod; | |
932 | } | |
933 | // rbSub now has the bundle for a particular dayPeriod such as morning1, afternoon2, noon | |
934 | UADayPeriod dpForBundle = dayPeriodFromName(ures_getKey(rbSub.getAlias())); | |
2ca993e8 | 935 | int32_t dpLimit = 24; |
b331163b A |
936 | while (ures_hasNext(rbSub.getAlias())) { |
937 | rbBound.adoptInstead(ures_getNextResource(rbSub.getAlias(), rbBound.orphan(), status)); | |
938 | if (U_FAILURE(*status)) { | |
939 | return dayPeriod; | |
940 | } | |
2ca993e8 | 941 | // rbBound now has the bundle for a particular time period boundary such as at, from, before. |
b331163b A |
942 | // This is either of type URES_STRING (size=1) or of type URES_ARRAY (size > 1) |
943 | const char *boundaryType = ures_getKey(rbBound.getAlias()); | |
2ca993e8 A |
944 | char boundaryTimeStr[kBoundaryTimeMaxLen]; |
945 | int32_t boundaryTimeStrLen = kBoundaryTimeMaxLen; | |
946 | ures_getUTF8String(rbBound.getAlias(), boundaryTimeStr, &boundaryTimeStrLen, TRUE, status); | |
947 | if (U_FAILURE(*status)) { | |
948 | return dayPeriod; | |
949 | } | |
950 | int32_t startHour = atoi(boundaryTimeStr); // can depend on POSIX locale (fortunately no decimal sep here) | |
b331163b | 951 | if (uprv_strcmp(boundaryType, "before") == 0) { |
2ca993e8 | 952 | dpLimit = startHour; |
b331163b A |
953 | continue; |
954 | } | |
2ca993e8 A |
955 | int32_t startMinute = 0; |
956 | if (uprv_strcmp(boundaryType, "from") == 0) { | |
957 | startMinute = 1; | |
958 | if (startHour > dpLimit && dpEntriesCount < kDayPeriodEntriesMax) { | |
959 | dpEntries[dpEntriesCount].startHour = 0; | |
960 | dpEntries[dpEntriesCount].startMin = startMinute; | |
b331163b A |
961 | dpEntries[dpEntriesCount].value = dpForBundle; |
962 | dpEntriesCount++; | |
963 | } | |
964 | } | |
2ca993e8 A |
965 | if (dpEntriesCount < kDayPeriodEntriesMax) { |
966 | dpEntries[dpEntriesCount].startHour = startHour; | |
967 | dpEntries[dpEntriesCount].startMin = startMinute; | |
968 | dpEntries[dpEntriesCount].value = dpForBundle; | |
969 | dpEntriesCount++; | |
970 | } | |
b331163b A |
971 | } |
972 | } | |
973 | if (dpEntriesCount < kDayPeriodEntriesMax) { | |
974 | dpEntries[dpEntriesCount].startHour = 24; | |
975 | dpEntries[dpEntriesCount].startMin = 0; | |
976 | dpEntries[dpEntriesCount].value = UADAYPERIOD_UNKNOWN; | |
977 | dpEntriesCount++; | |
978 | } | |
979 | // We have collected all of the rule data, now sort by time | |
980 | qsort(dpEntries, dpEntriesCount, sizeof(DayPeriodEntry), CompareDayPeriodEntries); | |
2ca993e8 A |
981 | |
982 | // now fix start minute for the non-"at" entries | |
983 | int32_t dpIndex; | |
984 | for (dpIndex = 0; dpIndex < dpEntriesCount; dpIndex++) { | |
985 | if (dpIndex == 0 || (dpEntries[dpIndex-1].value != UADAYPERIOD_MIDNIGHT && dpEntries[dpIndex-1].value != UADAYPERIOD_NOON)) { | |
986 | dpEntries[dpIndex].startMin = 0; | |
987 | } | |
988 | } | |
989 | ||
b331163b A |
990 | // OK, all of the above is what we would do in an "open" function if we were using an |
991 | // open/use/close model for this; the object would just have the sorted array above. | |
992 | ||
993 | // Now we use the sorted array to find the dayPeriod matching the supplied time. | |
994 | // Only a few entries, linear search OK | |
995 | DayPeriodEntry entryToMatch = { hour, minute, UADAYPERIOD_UNKNOWN }; | |
2ca993e8 | 996 | dpIndex = 0; |
b331163b A |
997 | while (dpIndex < dpEntriesCount - 1 && CompareDayPeriodEntries(&entryToMatch, &dpEntries[dpIndex + 1]) >= 0) { |
998 | dpIndex++; | |
999 | } | |
1000 | if (CompareDayPeriodEntries(&entryToMatch, &dpEntries[dpIndex]) >= 0) { | |
1001 | dayPeriod = dpEntries[dpIndex].value; | |
1002 | } | |
1003 | ||
1004 | return dayPeriod; | |
1005 | } | |
1006 | ||
1007 | ||
57a6839d | 1008 | |
b75a7d8f | 1009 | #endif /* #if !UCONFIG_NO_FORMATTING */ |