home *** CD-ROM | disk | FTP | other *** search
/ AmigActive 6 / AACD06.ISO / AACD / Programming / ICU / src / icu / source / i18n / calendar.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  1999-10-19  |  21.3 KB  |  760 lines

  1. /*
  2. *******************************************************************************
  3. *                                                                             *
  4. * COPYRIGHT:                                                                  *
  5. *   (C) Copyright Taligent, Inc.,  1997                                       *
  6. *   (C) Copyright International Business Machines Corporation,  1997-1998     *
  7. *   Licensed Material - Program-Property of IBM - All Rights Reserved.        *
  8. *   US Government Users Restricted Rights - Use, duplication, or disclosure   *
  9. *   restricted by GSA ADP Schedule Contract with IBM Corp.                    *
  10. *                                                                             *
  11. *******************************************************************************
  12. *
  13. * File CALENDAR.CPP
  14. *
  15. * Modification History:
  16. *
  17. *   Date        Name        Description
  18. *   02/03/97    clhuang     Creation.
  19. *   04/22/97    aliu        Cleaned up, fixed memory leak, made 
  20. *                           setWeekCountData() more robust.  
  21. *                           Moved platform code to TPlatformUtilities.
  22. *   05/01/97    aliu        Made equals(), before(), after() arguments const.
  23. *   05/20/97    aliu        Changed logic of when to compute fields and time
  24. *                           to fix bugs.
  25. *   08/12/97    aliu        Added equivalentTo.  Misc other fixes.
  26. *   07/28/98    stephen     Sync up with JDK 1.2
  27. *   09/02/98    stephen     Sync with JDK 1.2 8/31 build (getActualMin/Max)
  28. *   03/17/99    stephen     Changed adoptTimeZone() - now fAreFieldsSet is
  29. *                           set to FALSE to force update of time.
  30. *******************************************************************************
  31. */
  32.  
  33. #include "cpputils.h"
  34. #include "resbund.h"
  35. #include "gregocal.h"
  36.  
  37. // Resource bundle tags read by this class
  38. const char* Calendar::kDateTimeElements = "DateTimeElements";
  39.  
  40. // Data flow in Calendar
  41. // ---------------------
  42.  
  43. // The current time is represented in two ways by Calendar: as UTC
  44. // milliseconds from the epoch start (1 January 1970 0:00 UTC), and as local
  45. // fields such as MONTH, HOUR, AM_PM, etc.  It is possible to compute the
  46. // millis from the fields, and vice versa.  The data needed to do this
  47. // conversion is encapsulated by a TimeZone object owned by the Calendar.
  48. // The data provided by the TimeZone object may also be overridden if the
  49. // user sets the ZONE_OFFSET and/or DST_OFFSET fields directly. The class
  50. // keeps track of what information was most recently set by the caller, and
  51. // uses that to compute any other information as needed.
  52.  
  53. // If the user sets the fields using set(), the data flow is as follows.
  54. // This is implemented by the Calendar subclass's computeTime() method.
  55. // During this process, certain fields may be ignored.  The disambiguation
  56. // algorithm for resolving which fields to pay attention to is described
  57. // above.
  58.  
  59. //   local fields (YEAR, MONTH, DATE, HOUR, MINUTE, etc.)
  60. //           |
  61. //           | Using Calendar-specific algorithm
  62. //           V
  63. //   local standard millis
  64. //           |
  65. //           | Using TimeZone or user-set ZONE_OFFSET / DST_OFFSET
  66. //           V
  67. //   UTC millis (in time data member)
  68.  
  69. // If the user sets the UTC millis using setTime(), the data flow is as
  70. // follows.  This is implemented by the Calendar subclass's computeFields()
  71. // method.
  72.  
  73. //   UTC millis (in time data member)
  74. //           |
  75. //           | Using TimeZone getOffset()
  76. //           V
  77. //   local standard millis
  78. //           |
  79. //           | Using Calendar-specific algorithm
  80. //           V
  81. //   local fields (YEAR, MONTH, DATE, HOUR, MINUTE, etc.)
  82.  
  83. // In general, a round trip from fields, through local and UTC millis, and
  84. // back out to fields is made when necessary.  This is implemented by the
  85. // complete() method.  Resolving a partial set of fields into a UTC millis
  86. // value allows all remaining fields to be generated from that value.  If
  87. // the Calendar is lenient, the fields are also renormalized to standard
  88. // ranges when they are regenerated.
  89.  
  90. // -------------------------------------
  91.  
  92. Calendar::Calendar(UErrorCode& success)
  93. :   fTime(0),
  94.     fIsTimeSet(FALSE),
  95.     fAreFieldsSet(FALSE),
  96.     fAreAllFieldsSet(FALSE),
  97.     fLenient(TRUE),
  98.     fZone(0),
  99.     fNextStamp(kMinimumUserStamp)
  100. {
  101.     clear();
  102.     fZone = TimeZone::createDefault();
  103.     setWeekCountData(Locale::getDefault(), success);
  104. }
  105.  
  106. // -------------------------------------
  107.  
  108. Calendar::Calendar(TimeZone* zone, const Locale& aLocale, UErrorCode& success)
  109. :   fTime(0),
  110.     fIsTimeSet(FALSE),
  111.     fAreFieldsSet(FALSE),
  112.     fAreAllFieldsSet(FALSE),
  113.     fLenient(TRUE),
  114.     fZone(0),
  115.     fNextStamp(kMinimumUserStamp)
  116. {
  117.     if(zone == 0) {
  118.         success = U_ILLEGAL_ARGUMENT_ERROR;
  119.         return;
  120.     }
  121.  
  122.     clear();    
  123.     fZone = zone;
  124.     
  125.     setWeekCountData(aLocale, success);
  126. }
  127.  
  128. // -------------------------------------
  129.  
  130. Calendar::Calendar(const TimeZone& zone, const Locale& aLocale, UErrorCode& success)
  131. :   fTime(0),
  132.     fIsTimeSet(FALSE),
  133.     fAreFieldsSet(FALSE),
  134.     fAreAllFieldsSet(FALSE),
  135.     fLenient(TRUE),
  136.     fZone(0),
  137.     fNextStamp(kMinimumUserStamp)
  138. {
  139.     clear();
  140.     fZone = zone.clone();
  141.     setWeekCountData(aLocale, success);
  142. }
  143.  
  144. // -------------------------------------
  145.  
  146. Calendar::~Calendar()
  147. {
  148.     delete fZone;
  149. }
  150.  
  151. // -------------------------------------
  152.  
  153. Calendar::Calendar(const Calendar &source)
  154. {
  155.     fZone = 0;
  156.     *this = source;
  157. }
  158.  
  159. // -------------------------------------
  160.  
  161. Calendar &
  162. Calendar::operator=(const Calendar &right)
  163. {
  164.     if (this != &right)
  165.     {
  166.         icu_arrayCopy(right.fFields, fFields, FIELD_COUNT);
  167.         icu_arrayCopy(right.fIsSet, fIsSet, FIELD_COUNT);
  168.         icu_arrayCopy(right.fStamp, fStamp, FIELD_COUNT);
  169.         fTime                     = right.fTime;
  170.         fIsTimeSet                 = right.fIsTimeSet;
  171.         fAreAllFieldsSet         = right.fAreAllFieldsSet;
  172.         fAreFieldsSet             = right.fAreFieldsSet;
  173.         fLenient                 = right.fLenient;
  174.         delete fZone;
  175.         fZone                    = right.fZone->clone();
  176.         fFirstDayOfWeek         = right.fFirstDayOfWeek;
  177.         fMinimalDaysInFirstWeek = right.fMinimalDaysInFirstWeek;
  178.         fNextStamp                 = right.fNextStamp;
  179.     }
  180.     
  181.     return *this;
  182. }
  183.  
  184. // -------------------------------------
  185.  
  186. Calendar*
  187. Calendar::createInstance(UErrorCode& success)
  188. {
  189.     if (U_FAILURE(success)) return 0;
  190.     // right now, createInstance will always return an instance of GregorianCalendar
  191.     Calendar* c = new GregorianCalendar(success);
  192.     if (U_FAILURE(success)) { delete c; c = 0; }
  193.     return c;
  194. }
  195.  
  196. // -------------------------------------
  197.  
  198. Calendar*
  199. Calendar::createInstance(const TimeZone& zone, UErrorCode& success)
  200. {
  201.     if (U_FAILURE(success)) return 0;
  202.     // since the Locale isn't specified, use the default locale
  203.     Calendar* c = new GregorianCalendar(zone, Locale::getDefault(), success);
  204.     if (U_FAILURE(success)) { delete c; c = 0; }
  205.     return c;
  206. }
  207.  
  208. // -------------------------------------
  209.  
  210. Calendar*
  211. Calendar::createInstance(const Locale& aLocale, UErrorCode& success)
  212. {
  213.     if (U_FAILURE(success)) return 0;
  214.     // since the TimeZone isn't specfied, use the default time zone
  215.     Calendar* c = new GregorianCalendar(TimeZone::createDefault(), aLocale, success);
  216.     if (U_FAILURE(success)) { delete c; c = 0; }
  217.     return c;
  218. }
  219.  
  220. // -------------------------------------
  221.  
  222. Calendar*
  223. Calendar::createInstance(TimeZone* zone, const Locale& aLocale, UErrorCode& success)
  224. {
  225.     if (U_FAILURE(success)) {
  226.         delete zone;
  227.         return 0;
  228.     }
  229.     Calendar* c = new GregorianCalendar(zone, aLocale, success);
  230.     if (c == 0) {
  231.         success = U_MEMORY_ALLOCATION_ERROR;
  232.         delete zone;
  233.     } else if (U_FAILURE(success)) {
  234.         delete c;
  235.         c = 0;
  236.     }
  237.     return c;
  238. }
  239.  
  240. // -------------------------------------
  241.  
  242. Calendar*
  243. Calendar::createInstance(const TimeZone& zone, const Locale& aLocale, UErrorCode& success)
  244. {
  245.     if (U_FAILURE(success)) return 0;
  246.     Calendar* c = new GregorianCalendar(zone, aLocale, success);
  247.     if (U_FAILURE(success)) { delete c; c = 0; }
  248.     return c;
  249. }
  250.  
  251. // -------------------------------------
  252.  
  253. bool_t
  254. Calendar::operator==(const Calendar& that) const
  255. {
  256.     UErrorCode status = U_ZERO_ERROR;
  257.     // {sfb} is this correct? (Java equals)
  258.     return (getDynamicClassID() == that.getDynamicClassID() && 
  259.         getTimeInMillis(status) == that.getTimeInMillis(status) &&
  260.         fLenient == that.fLenient &&
  261.         fFirstDayOfWeek == that.fFirstDayOfWeek &&
  262.         fMinimalDaysInFirstWeek == that.fMinimalDaysInFirstWeek &&
  263.         *fZone == *(that.fZone));
  264.  
  265.     // As it stands, this is a very narrowly defined ==, since the
  266.     // Calendars must not only represent the same time; they must
  267.     // also be in exactly the same state.  This would be looser if
  268.     // we forced field or fTime computation, and then did the comparison.
  269. /*
  270.     if (this == &that) return TRUE;
  271.     for (int32_t i=0; i<FIELD_COUNT; ++i)
  272.     {
  273.         if (fFields[i] != that.fFields[i] ||
  274.             fIsSet[i] != that.fIsSet[i]) return FALSE;
  275.     }
  276.     return (getDynamicClassID() == that.getDynamicClassID() &&
  277.             fTime == that.fTime &&
  278.             fIsTimeSet == that.fIsTimeSet &&
  279.             fAreAllFieldsSet == that.fAreAllFieldsSet &&
  280.             fAreFieldsSet == that.fAreFieldsSet &&
  281.             fLenient == that.fLenient &&
  282.             (!fIsSet[ZONE_OFFSET] || (fUserSetZoneOffset == that.fUserSetZoneOffset)) &&
  283.             (!fIsSet[DST_OFFSET] || (fUserSetDSTOffset == that.fUserSetDSTOffset)) &&
  284.             fFirstDayOfWeek == that.fFirstDayOfWeek &&
  285.             fMinimalDaysInFirstWeek == that.fMinimalDaysInFirstWeek &&
  286.             *fZone == *(that.fZone));
  287. */
  288. }
  289.  
  290. // -------------------------------------
  291.  
  292. bool_t
  293. Calendar::equals(const Calendar& when, UErrorCode& status) const
  294. {
  295.     return (this == &when ||
  296.             getTime(status) == when.getTime(status));
  297. }
  298.  
  299. // -------------------------------------
  300.  
  301. bool_t
  302. Calendar::before(const Calendar& when, UErrorCode& status) const
  303. {
  304.     return (this != &when &&
  305.             getTimeInMillis(status) < when.getTimeInMillis(status));
  306. }
  307.  
  308. // -------------------------------------
  309.  
  310. bool_t
  311. Calendar::after(const Calendar& when, UErrorCode& status) const
  312. {
  313.     return (this != &when &&
  314.             getTimeInMillis(status) > when.getTimeInMillis(status));
  315. }
  316.  
  317. // {sfb} not in Java API, but looks similar to operator==
  318. bool_t 
  319. Calendar::equivalentTo(const Calendar& other) const
  320. {
  321.     // Return true if another Calendar object is equivalent to this one.  An equivalent
  322.     // Calendar will behave exactly as this one does (i.e., it will have be the same subclass
  323.     // of Calendar, and have the same time zone, week-count values, and leniency level), 
  324.     // but may be set to a different time.
  325.     return getDynamicClassID() == other.getDynamicClassID() &&
  326.         fLenient                == other.fLenient &&
  327.         fFirstDayOfWeek         == other.fFirstDayOfWeek &&
  328.         fMinimalDaysInFirstWeek == other.fMinimalDaysInFirstWeek &&
  329.         *fZone                  == *other.fZone;
  330. }
  331.  
  332. // -------------------------------------
  333.  
  334.  
  335. const Locale*
  336. Calendar::getAvailableLocales(int32_t& count)
  337. {
  338.     return Locale::getAvailableLocales(count);
  339. }
  340.  
  341. // -------------------------------------
  342.  
  343. UDate
  344. Calendar::getNow()
  345. {
  346.     return (UDate)icu_getUTCtime() * U_MILLIS_PER_SECOND; // return as milliseconds
  347. }
  348.  
  349. // -------------------------------------
  350.  
  351. /**
  352.  * Gets this Calendar's current time as a long.
  353.  * @return the current time as UTC milliseconds from the epoch.
  354.  */
  355. double 
  356. Calendar::getTimeInMillis(UErrorCode& status) const
  357. {
  358.     if(U_FAILURE(status)) 
  359.         return 0.0;
  360.  
  361.     if ( ! fIsTimeSet) 
  362.         ((Calendar*)this)->updateTime(status);
  363.     return fTime;
  364. }
  365.  
  366. // -------------------------------------
  367.  
  368. /**
  369.  * Sets this Calendar's current time from the given long value.
  370.  * @param date the new time in UTC milliseconds from the epoch.
  371.  */
  372. void 
  373. Calendar::setTimeInMillis( double millis, UErrorCode& status ) {
  374.     if(U_FAILURE(status)) 
  375.         return;
  376.  
  377.     fIsTimeSet = TRUE;
  378.     fTime = millis;
  379.  
  380.     fAreFieldsSet = FALSE;
  381.  
  382.     computeFields(status);
  383.     fAreFieldsSet = TRUE;
  384.     fAreAllFieldsSet = TRUE;
  385. }
  386.  
  387. // -------------------------------------
  388.  
  389. int32_t
  390. Calendar::get(EDateFields field, UErrorCode& status) const
  391. {
  392.     // field values are only computed when actually requested; for more on when computation
  393.     // of various things happens, see the "data flow in Calendar" description at the top
  394.     // of this file
  395.     if (U_SUCCESS(status)) ((Calendar*)this)->complete(status); // Cast away const
  396.     return U_SUCCESS(status) ? fFields[field] : 0;
  397. }
  398.  
  399. // -------------------------------------
  400.  
  401. void
  402. Calendar::set(EDateFields field, int32_t value)
  403. {
  404.     fIsTimeSet         = FALSE;
  405.     fFields[field]     = value;
  406.     fStamp[field]     = fNextStamp++;
  407.     fAreFieldsSet     = FALSE;
  408.     fIsSet[field]     = TRUE; // Remove later
  409. }
  410.  
  411. // -------------------------------------
  412.  
  413. void
  414. Calendar::set(int32_t year, int32_t month, int32_t date)
  415. {
  416.     set(YEAR, year);
  417.     set(MONTH, month);
  418.     set(DATE, date);
  419. }
  420.  
  421. // -------------------------------------
  422.  
  423. void
  424. Calendar::set(int32_t year, int32_t month, int32_t date, int32_t hour, int32_t minute)
  425. {
  426.     set(YEAR, year);
  427.     set(MONTH, month);
  428.     set(DATE, date);
  429.     set(HOUR_OF_DAY, hour);
  430.     set(MINUTE, minute);
  431. }
  432.  
  433. // -------------------------------------
  434.  
  435. void
  436. Calendar::set(int32_t year, int32_t month, int32_t date, int32_t hour, int32_t minute, int32_t second)
  437. {
  438.     set(YEAR, year);
  439.     set(MONTH, month);
  440.     set(DATE, date);
  441.     set(HOUR_OF_DAY, hour);
  442.     set(MINUTE, minute);
  443.     set(SECOND, second);
  444. }
  445.  
  446. // -------------------------------------
  447.  
  448. void
  449. Calendar::clear()
  450. {
  451.     for (int32_t i=0; i<FIELD_COUNT; ++i) {
  452.         fFields[i]     = 0; // Must do this; other code depends on it
  453.         fIsSet[i]     = FALSE;
  454.         fStamp[i]     = kUnset;
  455.     }
  456.     
  457.     fAreFieldsSet         = FALSE;
  458.     fAreAllFieldsSet    = FALSE;
  459.     fIsTimeSet             = FALSE;
  460. }
  461.  
  462. // -------------------------------------
  463.  
  464. void
  465. Calendar::clear(EDateFields field)
  466. {
  467.     fFields[field]         = 0;
  468.     fStamp[field]         = kUnset;
  469.     fAreFieldsSet         = FALSE;
  470.     fAreAllFieldsSet     = FALSE;
  471.     fIsSet[field]         = FALSE; // Remove later
  472.     fIsTimeSet             = FALSE;
  473. }
  474.  
  475. // -------------------------------------
  476.  
  477. bool_t
  478. Calendar::isSet(EDateFields field) const
  479. {
  480.     return fStamp[field] != kUnset;
  481. }
  482.  
  483. // -------------------------------------
  484.  
  485. void
  486. Calendar::complete(UErrorCode& status)
  487. {
  488.     if (!fIsTimeSet) 
  489.         updateTime(status);
  490.     if (!fAreFieldsSet) {
  491.         computeFields(status); // fills in unset fields
  492.         fAreFieldsSet         = TRUE;
  493.         fAreAllFieldsSet     = TRUE;
  494.     }
  495. }
  496.  
  497. // -------------------------------------
  498.  
  499. void
  500. Calendar::adoptTimeZone(TimeZone* zone)
  501. {
  502.     // Do nothing if passed-in zone is NULL
  503.     if (zone == NULL) return;
  504.  
  505.     // fZone should always be non-null
  506.     if (fZone != NULL) delete fZone;
  507.     fZone = zone;
  508.  
  509.     // if the zone changes, we need to recompute the time fields
  510.     fAreFieldsSet = FALSE;
  511. }
  512.  
  513. // -------------------------------------
  514. void
  515. Calendar::setTimeZone(const TimeZone& zone)
  516. {
  517.     adoptTimeZone(zone.clone());
  518. }
  519.  
  520. // -------------------------------------
  521.  
  522. const TimeZone&
  523. Calendar::getTimeZone() const
  524. {
  525.     return *fZone;
  526. }
  527.  
  528. // -------------------------------------
  529.  
  530. TimeZone*
  531. Calendar::orphanTimeZone()
  532. {
  533.     TimeZone *z = fZone;
  534.     // we let go of the time zone; the new time zone is the system default time zone
  535.     fZone = TimeZone::createDefault();
  536.     return z;
  537. }
  538.  
  539. // -------------------------------------
  540.  
  541. void
  542. Calendar::setLenient(bool_t lenient)
  543. {
  544.     fLenient = lenient;
  545. }
  546.  
  547. // -------------------------------------
  548.  
  549. bool_t
  550. Calendar::isLenient() const
  551. {
  552.     return fLenient;
  553. }
  554.  
  555. // -------------------------------------
  556.  
  557. void
  558. Calendar::setFirstDayOfWeek(EDaysOfWeek value)
  559. {
  560.     fFirstDayOfWeek = value;
  561. }
  562.  
  563. // -------------------------------------
  564.  
  565. Calendar::EDaysOfWeek
  566. Calendar::getFirstDayOfWeek() const
  567. {
  568.     return fFirstDayOfWeek;
  569. }
  570.  
  571. // -------------------------------------
  572.  
  573. void
  574. Calendar::setMinimalDaysInFirstWeek(uint8_t value)
  575. {
  576.     fMinimalDaysInFirstWeek = value;
  577. }
  578.  
  579. // -------------------------------------
  580.  
  581. uint8_t
  582. Calendar::getMinimalDaysInFirstWeek() const
  583. {
  584.     return fMinimalDaysInFirstWeek;
  585. }
  586.  
  587. // -------------------------------------
  588.  
  589. int32_t
  590. Calendar::getActualMinimum(EDateFields field, UErrorCode& status) const
  591. {
  592.     int32_t fieldValue = getGreatestMinimum(field);
  593.     int32_t endValue = getMinimum(field);
  594.  
  595.     // if we know that the minimum value is always the same, just return it
  596.     if (fieldValue == endValue) {
  597.         return fieldValue;
  598.     }
  599.  
  600.     // clone the calendar so we don't mess with the real one, and set it to
  601.     // accept anything for the field values
  602.     Calendar *work = (Calendar*)this->clone();
  603.     work->setLenient(TRUE);
  604.  
  605.     // now try each value from getLeastMaximum() to getMaximum() one by one until
  606.     // we get a value that normalizes to another value.  The last value that
  607.     // normalizes to itself is the actual minimum for the current date
  608.     int32_t result = fieldValue;
  609.  
  610.     do {
  611.         work->set(field, fieldValue);
  612.         if (work->get(field, status) != fieldValue) {
  613.             break;
  614.         } 
  615.         else {
  616.             result = fieldValue;
  617.             fieldValue--;
  618.         }
  619.     } while (fieldValue >= endValue);
  620.  
  621.     delete work;
  622.     return result;
  623. }
  624.  
  625. // -------------------------------------
  626.  
  627. int32_t
  628. Calendar::getActualMaximum(EDateFields field, UErrorCode& status) const
  629. {
  630.     int32_t fieldValue = getLeastMaximum(field);
  631.     int32_t endValue = getMaximum(field);
  632.  
  633.     // if we know that the maximum value is always the same, just return it
  634.     if (fieldValue == endValue) {
  635.         return fieldValue;
  636.     }
  637.  
  638.     // clone the calendar so we don't mess with the real one, and set it to
  639.     // accept anything for the field values
  640.     Calendar *work = (Calendar*)this->clone();
  641.     work->setLenient(TRUE);
  642.  
  643.     // if we're counting weeks, set the day of the week to Sunday.  We know the
  644.     // last week of a month or year will contain the first day of the week.
  645.     if (field == WEEK_OF_YEAR || field == WEEK_OF_MONTH)
  646.         work->set(DAY_OF_WEEK, fFirstDayOfWeek);
  647.  
  648.     // now try each value from getLeastMaximum() to getMaximum() one by one until
  649.     // we get a value that normalizes to another value.  The last value that
  650.     // normalizes to itself is the actual maximum for the current date
  651.     int32_t result = fieldValue;
  652.  
  653.     do {
  654.         work->set(field, fieldValue);
  655.         if(work->get(field, status) != fieldValue) {
  656.             break;
  657.         } 
  658.         else {
  659.             result = fieldValue;
  660.             fieldValue++;
  661.         }
  662.     } while (fieldValue <= endValue);
  663.  
  664.     delete work;
  665.     return result;
  666. }
  667.  
  668. // -------------------------------------
  669.  
  670. int32_t Calendar::stringToDayNumber(const UnicodeString& string, UErrorCode& status)
  671. {
  672.     // Convert a UnicodeString to a long integer, using the standard C library.
  673.     // Return both the value obtained, and a UErrorCode indicating success or failure.
  674.     // We fail if the string is zero length, of if strtol() does not parse all
  675.     // of the characters in the string, or if the value is not in the range
  676.     // 1..7.  (This is used to read the week-count data from the resource files;
  677.     // ResourceBundle returns all data in string form, so we have to convert it here.)
  678.     if (U_FAILURE(status)) return 0;
  679.  
  680.     int32_t len = string.size();
  681.     char *number = new char[1 + len];
  682.     if (number == 0) { status = U_MEMORY_ALLOCATION_ERROR; return 0; }
  683.     char *end;
  684.  
  685.     string.extract(0, len, number);
  686.     number[len] = 0;
  687.     int32_t value = strtol(number, &end, 10); // Radix 10
  688.  
  689.     delete[] number;
  690.  
  691.     if (end-number != len || len == 0 || value < 1 || value > 7)
  692.         status = U_INVALID_FORMAT_ERROR;
  693.  
  694.     return value;
  695. }
  696.  
  697. // -------------------------------------
  698.  
  699. void
  700. Calendar::setWeekCountData(const Locale& desiredLocale, UErrorCode& status)
  701. {
  702.     // Read the week count data from the resource bundle.  This should
  703.     // have the form:
  704.     //
  705.     //   DateTimeElements {
  706.     //      "1",    // first day of week
  707.     //      "1"     // min days in week
  708.     //   }
  709.  
  710.     const UnicodeString *dateTimeElements;
  711.     int32_t count;
  712.  
  713.     if (U_FAILURE(status)) return;
  714.     ResourceBundle resource(Locale::getDataDirectory(), desiredLocale, status);
  715.  
  716.     // If the resource data doesn't seem to be present at all, then use last-resort
  717.     // hard-coded data.
  718.     if (U_FAILURE(status))
  719.     {
  720.         status = U_USING_FALLBACK_ERROR;
  721.         fFirstDayOfWeek = Calendar::SUNDAY;
  722.         fMinimalDaysInFirstWeek = 1;
  723.         return;
  724.     }
  725.  
  726.     dateTimeElements = resource.getStringArray(kDateTimeElements, count, status);
  727.     if (U_FAILURE(status)) return;
  728.     if (count != 2)
  729.     {
  730.         status = U_INVALID_FORMAT_ERROR;
  731.         return;
  732.     }
  733.  
  734.     fFirstDayOfWeek = (Calendar::EDaysOfWeek)stringToDayNumber(dateTimeElements[0], status);
  735.     fMinimalDaysInFirstWeek = (uint8_t)stringToDayNumber(dateTimeElements[1], status);
  736. }
  737.  
  738. /**
  739.  * Recompute the time and update the status fields isTimeSet
  740.  * and areFieldsSet.  Callers should check isTimeSet and only
  741.  * call this method if isTimeSet is false.
  742.  */
  743. void 
  744. Calendar::updateTime(UErrorCode& status) 
  745. {
  746.     computeTime(status);
  747.     if(U_FAILURE(status))
  748.         return;
  749.         
  750.     // If we are lenient, we need to recompute the fields to normalize
  751.     // the values.  Also, if we haven't set all the fields yet (i.e.,
  752.     // in a newly-created object), we need to fill in the fields. [LIU]
  753.     if (isLenient() || ! fAreAllFieldsSet) 
  754.         fAreFieldsSet = FALSE;
  755.     
  756.     fIsTimeSet = TRUE;
  757. }
  758.  
  759. //eof
  760.