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