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