16f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org/*
26f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org*******************************************************************************
36f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org* Copyright (C) 1997-2013, International Business Machines Corporation and
46f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org* others. All Rights Reserved.
56f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org*******************************************************************************
66f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org*
76f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org* File GREGOCAL.CPP
86f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org*
96f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org* Modification History:
106f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org*
116f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org*   Date        Name        Description
126f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org*   02/05/97    clhuang     Creation.
136f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org*   03/28/97    aliu        Made highly questionable fix to computeFields to
146f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org*                           handle DST correctly.
156f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org*   04/22/97    aliu        Cleaned up code drastically.  Added monthLength().
166f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org*                           Finished unimplemented parts of computeTime() for
176f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org*                           week-based date determination.  Removed quetionable
186f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org*                           fix and wrote correct fix for computeFields() and
196f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org*                           daylight time handling.  Rewrote inDaylightTime()
206f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org*                           and computeFields() to handle sensitive Daylight to
216f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org*                           Standard time transitions correctly.
226f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org*   05/08/97    aliu        Added code review changes.  Fixed isLeapYear() to
236f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org*                           not cutover.
246f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org*   08/12/97    aliu        Added equivalentTo.  Misc other fixes.  Updated
256f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org*                           add() from Java source.
266f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org*    07/28/98    stephen        Sync up with JDK 1.2
276f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org*    09/14/98    stephen        Changed type of kOneDay, kOneWeek to double.
286f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org*                            Fixed bug in roll()
296f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org*   10/15/99    aliu        Fixed j31, incorrect WEEK_OF_YEAR computation.
306f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org*   10/15/99    aliu        Fixed j32, cannot set date to Feb 29 2000 AD.
316f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org*                           {JDK bug 4210209 4209272}
326f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org*   11/15/99    weiv        Added YEAR_WOY and DOW_LOCAL computation
336f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org*                           to timeToFields method, updated kMinValues, kMaxValues & kLeastMaxValues
346f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org*   12/09/99    aliu        Fixed j81, calculation errors and roll bugs
356f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org*                           in year of cutover.
366f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org*   01/24/2000  aliu        Revised computeJulianDay for YEAR YEAR_WOY WOY.
376f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org********************************************************************************
386f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org*/
396f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
406f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org#include "unicode/utypes.h"
416f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org#include <float.h>
426f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
436f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org#if !UCONFIG_NO_FORMATTING
446f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
456f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org#include "unicode/gregocal.h"
466f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org#include "gregoimp.h"
476f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org#include "umutex.h"
486f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org#include "uassert.h"
496f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
506f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org// *****************************************************************************
516f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org// class GregorianCalendar
526f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org// *****************************************************************************
536f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
546f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org/**
556f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org* Note that the Julian date used here is not a true Julian date, since
566f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org* it is measured from midnight, not noon.  This value is the Julian
576f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org* day number of January 1, 1970 (Gregorian calendar) at noon UTC. [LIU]
586f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org*/
596f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
606f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgstatic const int16_t kNumDays[]
616f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org= {0,31,59,90,120,151,181,212,243,273,304,334}; // 0-based, for day-in-year
626f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgstatic const int16_t kLeapNumDays[]
636f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org= {0,31,60,91,121,152,182,213,244,274,305,335}; // 0-based, for day-in-year
646f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgstatic const int8_t kMonthLength[]
656f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org= {31,28,31,30,31,30,31,31,30,31,30,31}; // 0-based
666f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgstatic const int8_t kLeapMonthLength[]
676f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org= {31,29,31,30,31,30,31,31,30,31,30,31}; // 0-based
686f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
696f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org// setTimeInMillis() limits the Julian day range to +/-7F000000.
706f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org// This would seem to limit the year range to:
716f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org//  ms=+183882168921600000  jd=7f000000  December 20, 5828963 AD
726f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org//  ms=-184303902528000000  jd=81000000  September 20, 5838270 BC
736f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org// HOWEVER, CalendarRegressionTest/Test4167060 shows that the actual
746f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org// range limit on the year field is smaller (~ +/-140000). [alan 3.0]
756f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
766f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgstatic const int32_t kGregorianCalendarLimits[UCAL_FIELD_COUNT][4] = {
776f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    // Minimum  Greatest    Least  Maximum
786f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    //           Minimum  Maximum
796f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    {        0,        0,        1,        1}, // ERA
806f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    {        1,        1,   140742,   144683}, // YEAR
816f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    {        0,        0,       11,       11}, // MONTH
826f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    {        1,        1,       52,       53}, // WEEK_OF_YEAR
836f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    {/*N/A*/-1,/*N/A*/-1,/*N/A*/-1,/*N/A*/-1}, // WEEK_OF_MONTH
846f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    {        1,        1,       28,       31}, // DAY_OF_MONTH
856f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    {        1,        1,      365,      366}, // DAY_OF_YEAR
866f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    {/*N/A*/-1,/*N/A*/-1,/*N/A*/-1,/*N/A*/-1}, // DAY_OF_WEEK
876f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    {       -1,       -1,        4,        5}, // DAY_OF_WEEK_IN_MONTH
886f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    {/*N/A*/-1,/*N/A*/-1,/*N/A*/-1,/*N/A*/-1}, // AM_PM
896f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    {/*N/A*/-1,/*N/A*/-1,/*N/A*/-1,/*N/A*/-1}, // HOUR
906f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    {/*N/A*/-1,/*N/A*/-1,/*N/A*/-1,/*N/A*/-1}, // HOUR_OF_DAY
916f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    {/*N/A*/-1,/*N/A*/-1,/*N/A*/-1,/*N/A*/-1}, // MINUTE
926f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    {/*N/A*/-1,/*N/A*/-1,/*N/A*/-1,/*N/A*/-1}, // SECOND
936f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    {/*N/A*/-1,/*N/A*/-1,/*N/A*/-1,/*N/A*/-1}, // MILLISECOND
946f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    {/*N/A*/-1,/*N/A*/-1,/*N/A*/-1,/*N/A*/-1}, // ZONE_OFFSET
956f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    {/*N/A*/-1,/*N/A*/-1,/*N/A*/-1,/*N/A*/-1}, // DST_OFFSET
966f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    {  -140742,  -140742,   140742,   144683}, // YEAR_WOY
976f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    {/*N/A*/-1,/*N/A*/-1,/*N/A*/-1,/*N/A*/-1}, // DOW_LOCAL
986f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    {  -140742,  -140742,   140742,   144683}, // EXTENDED_YEAR
996f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    {/*N/A*/-1,/*N/A*/-1,/*N/A*/-1,/*N/A*/-1}, // JULIAN_DAY
1006f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    {/*N/A*/-1,/*N/A*/-1,/*N/A*/-1,/*N/A*/-1}, // MILLISECONDS_IN_DAY
1016f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    {/*N/A*/-1,/*N/A*/-1,/*N/A*/-1,/*N/A*/-1}, // IS_LEAP_MONTH
1026f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org};
1036f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
1046f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org/*
1056f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org* <pre>
1066f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org*                            Greatest       Least
1076f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org* Field name        Minimum   Minimum     Maximum     Maximum
1086f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org* ----------        -------   -------     -------     -------
1096f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org* ERA                     0         0           1           1
1106f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org* YEAR                    1         1      140742      144683
1116f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org* MONTH                   0         0          11          11
1126f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org* WEEK_OF_YEAR            1         1          52          53
1136f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org* WEEK_OF_MONTH           0         0           4           6
1146f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org* DAY_OF_MONTH            1         1          28          31
1156f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org* DAY_OF_YEAR             1         1         365         366
1166f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org* DAY_OF_WEEK             1         1           7           7
1176f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org* DAY_OF_WEEK_IN_MONTH   -1        -1           4           5
1186f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org* AM_PM                   0         0           1           1
1196f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org* HOUR                    0         0          11          11
1206f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org* HOUR_OF_DAY             0         0          23          23
1216f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org* MINUTE                  0         0          59          59
1226f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org* SECOND                  0         0          59          59
1236f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org* MILLISECOND             0         0         999         999
1246f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org* ZONE_OFFSET           -12*      -12*         12*         12*
1256f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org* DST_OFFSET              0         0           1*          1*
1266f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org* YEAR_WOY                1         1      140742      144683
1276f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org* DOW_LOCAL               1         1           7           7
1286f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org* </pre>
1296f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org* (*) In units of one-hour
1306f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org*/
1316f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
1326f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org#if defined( U_DEBUG_CALSVC ) || defined (U_DEBUG_CAL)
1336f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org#include <stdio.h>
1346f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org#endif
1356f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
1366f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgU_NAMESPACE_BEGIN
1376f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
1386f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgUOBJECT_DEFINE_RTTI_IMPLEMENTATION(GregorianCalendar)
1396f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
1406f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org// 00:00:00 UTC, October 15, 1582, expressed in ms from the epoch.
1416f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org// Note that only Italy and other Catholic countries actually
1426f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org// observed this cutover.  Most other countries followed in
1436f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org// the next few centuries, some as late as 1928. [LIU]
1446f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org// in Java, -12219292800000L
1456f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org//const UDate GregorianCalendar::kPapalCutover = -12219292800000L;
1466f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgstatic const uint32_t kCutoverJulianDay = 2299161;
1476f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgstatic const UDate kPapalCutover = (2299161.0 - kEpochStartAsJulianDay) * U_MILLIS_PER_DAY;
1486f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org//static const UDate kPapalCutoverJulian = (2299161.0 - kEpochStartAsJulianDay);
1496f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
1506f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org// -------------------------------------
1516f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
1526f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgGregorianCalendar::GregorianCalendar(UErrorCode& status)
1536f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org:   Calendar(status),
1546f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgfGregorianCutover(kPapalCutover),
1556f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgfCutoverJulianDay(kCutoverJulianDay), fNormalizedGregorianCutover(fGregorianCutover), fGregorianCutoverYear(1582),
1566f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgfIsGregorian(TRUE), fInvertGregorian(FALSE)
1576f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org{
1586f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    setTimeInMillis(getNow(), status);
1596f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org}
1606f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
1616f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org// -------------------------------------
1626f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
1636f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgGregorianCalendar::GregorianCalendar(TimeZone* zone, UErrorCode& status)
1646f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org:   Calendar(zone, Locale::getDefault(), status),
1656f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgfGregorianCutover(kPapalCutover),
1666f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgfCutoverJulianDay(kCutoverJulianDay), fNormalizedGregorianCutover(fGregorianCutover), fGregorianCutoverYear(1582),
1676f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgfIsGregorian(TRUE), fInvertGregorian(FALSE)
1686f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org{
1696f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    setTimeInMillis(getNow(), status);
1706f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org}
1716f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
1726f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org// -------------------------------------
1736f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
1746f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgGregorianCalendar::GregorianCalendar(const TimeZone& zone, UErrorCode& status)
1756f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org:   Calendar(zone, Locale::getDefault(), status),
1766f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgfGregorianCutover(kPapalCutover),
1776f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgfCutoverJulianDay(kCutoverJulianDay), fNormalizedGregorianCutover(fGregorianCutover), fGregorianCutoverYear(1582),
1786f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgfIsGregorian(TRUE), fInvertGregorian(FALSE)
1796f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org{
1806f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    setTimeInMillis(getNow(), status);
1816f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org}
1826f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
1836f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org// -------------------------------------
1846f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
1856f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgGregorianCalendar::GregorianCalendar(const Locale& aLocale, UErrorCode& status)
1866f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org:   Calendar(TimeZone::createDefault(), aLocale, status),
1876f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgfGregorianCutover(kPapalCutover),
1886f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgfCutoverJulianDay(kCutoverJulianDay), fNormalizedGregorianCutover(fGregorianCutover), fGregorianCutoverYear(1582),
1896f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgfIsGregorian(TRUE), fInvertGregorian(FALSE)
1906f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org{
1916f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    setTimeInMillis(getNow(), status);
1926f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org}
1936f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
1946f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org// -------------------------------------
1956f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
1966f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgGregorianCalendar::GregorianCalendar(TimeZone* zone, const Locale& aLocale,
1976f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                                     UErrorCode& status)
1986f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                                     :   Calendar(zone, aLocale, status),
1996f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                                     fGregorianCutover(kPapalCutover),
2006f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                                     fCutoverJulianDay(kCutoverJulianDay), fNormalizedGregorianCutover(fGregorianCutover), fGregorianCutoverYear(1582),
2016f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                                     fIsGregorian(TRUE), fInvertGregorian(FALSE)
2026f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org{
2036f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    setTimeInMillis(getNow(), status);
2046f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org}
2056f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
2066f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org// -------------------------------------
2076f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
2086f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgGregorianCalendar::GregorianCalendar(const TimeZone& zone, const Locale& aLocale,
2096f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                                     UErrorCode& status)
2106f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                                     :   Calendar(zone, aLocale, status),
2116f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                                     fGregorianCutover(kPapalCutover),
2126f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                                     fCutoverJulianDay(kCutoverJulianDay), fNormalizedGregorianCutover(fGregorianCutover), fGregorianCutoverYear(1582),
2136f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                                     fIsGregorian(TRUE), fInvertGregorian(FALSE)
2146f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org{
2156f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    setTimeInMillis(getNow(), status);
2166f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org}
2176f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
2186f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org// -------------------------------------
2196f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
2206f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgGregorianCalendar::GregorianCalendar(int32_t year, int32_t month, int32_t date,
2216f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                                     UErrorCode& status)
2226f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                                     :   Calendar(TimeZone::createDefault(), Locale::getDefault(), status),
2236f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                                     fGregorianCutover(kPapalCutover),
2246f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                                     fCutoverJulianDay(kCutoverJulianDay), fNormalizedGregorianCutover(fGregorianCutover), fGregorianCutoverYear(1582),
2256f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                                     fIsGregorian(TRUE), fInvertGregorian(FALSE)
2266f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org{
2276f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    set(UCAL_ERA, AD);
2286f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    set(UCAL_YEAR, year);
2296f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    set(UCAL_MONTH, month);
2306f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    set(UCAL_DATE, date);
2316f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org}
2326f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
2336f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org// -------------------------------------
2346f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
2356f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgGregorianCalendar::GregorianCalendar(int32_t year, int32_t month, int32_t date,
2366f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                                     int32_t hour, int32_t minute, UErrorCode& status)
2376f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                                     :   Calendar(TimeZone::createDefault(), Locale::getDefault(), status),
2386f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                                     fGregorianCutover(kPapalCutover),
2396f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                                     fCutoverJulianDay(kCutoverJulianDay), fNormalizedGregorianCutover(fGregorianCutover), fGregorianCutoverYear(1582),
2406f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                                     fIsGregorian(TRUE), fInvertGregorian(FALSE)
2416f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org{
2426f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    set(UCAL_ERA, AD);
2436f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    set(UCAL_YEAR, year);
2446f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    set(UCAL_MONTH, month);
2456f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    set(UCAL_DATE, date);
2466f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    set(UCAL_HOUR_OF_DAY, hour);
2476f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    set(UCAL_MINUTE, minute);
2486f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org}
2496f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
2506f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org// -------------------------------------
2516f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
2526f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgGregorianCalendar::GregorianCalendar(int32_t year, int32_t month, int32_t date,
2536f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                                     int32_t hour, int32_t minute, int32_t second,
2546f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                                     UErrorCode& status)
2556f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                                     :   Calendar(TimeZone::createDefault(), Locale::getDefault(), status),
2566f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                                     fGregorianCutover(kPapalCutover),
2576f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                                     fCutoverJulianDay(kCutoverJulianDay), fNormalizedGregorianCutover(fGregorianCutover), fGregorianCutoverYear(1582),
2586f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                                     fIsGregorian(TRUE), fInvertGregorian(FALSE)
2596f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org{
2606f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    set(UCAL_ERA, AD);
2616f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    set(UCAL_YEAR, year);
2626f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    set(UCAL_MONTH, month);
2636f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    set(UCAL_DATE, date);
2646f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    set(UCAL_HOUR_OF_DAY, hour);
2656f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    set(UCAL_MINUTE, minute);
2666f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    set(UCAL_SECOND, second);
2676f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org}
2686f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
2696f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org// -------------------------------------
2706f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
2716f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgGregorianCalendar::~GregorianCalendar()
2726f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org{
2736f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org}
2746f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
2756f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org// -------------------------------------
2766f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
2776f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgGregorianCalendar::GregorianCalendar(const GregorianCalendar &source)
2786f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org:   Calendar(source),
2796f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgfGregorianCutover(source.fGregorianCutover),
2806f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgfCutoverJulianDay(source.fCutoverJulianDay), fNormalizedGregorianCutover(source.fNormalizedGregorianCutover), fGregorianCutoverYear(source.fGregorianCutoverYear),
2816f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgfIsGregorian(source.fIsGregorian), fInvertGregorian(source.fInvertGregorian)
2826f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org{
2836f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org}
2846f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
2856f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org// -------------------------------------
2866f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
2876f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgCalendar* GregorianCalendar::clone() const
2886f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org{
2896f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    return new GregorianCalendar(*this);
2906f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org}
2916f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
2926f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org// -------------------------------------
2936f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
2946f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgGregorianCalendar &
2956f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgGregorianCalendar::operator=(const GregorianCalendar &right)
2966f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org{
2976f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    if (this != &right)
2986f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    {
2996f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        Calendar::operator=(right);
3006f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        fGregorianCutover = right.fGregorianCutover;
3016f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        fNormalizedGregorianCutover = right.fNormalizedGregorianCutover;
3026f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        fGregorianCutoverYear = right.fGregorianCutoverYear;
3036f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        fCutoverJulianDay = right.fCutoverJulianDay;
3046f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    }
3056f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    return *this;
3066f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org}
3076f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
3086f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org// -------------------------------------
3096f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
3106f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgUBool GregorianCalendar::isEquivalentTo(const Calendar& other) const
3116f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org{
3126f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    // Calendar override.
3136f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    return Calendar::isEquivalentTo(other) &&
3146f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        fGregorianCutover == ((GregorianCalendar*)&other)->fGregorianCutover;
3156f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org}
3166f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
3176f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org// -------------------------------------
3186f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
3196f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgvoid
3206f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgGregorianCalendar::setGregorianChange(UDate date, UErrorCode& status)
3216f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org{
3226f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    if (U_FAILURE(status))
3236f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        return;
3246f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
3256f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    fGregorianCutover = date;
3266f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
3276f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    // Precompute two internal variables which we use to do the actual
3286f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    // cutover computations.  These are the normalized cutover, which is the
3296f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    // midnight at or before the cutover, and the cutover year.  The
3306f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    // normalized cutover is in pure date milliseconds; it contains no time
3316f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    // of day or timezone component, and it used to compare against other
3326f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    // pure date values.
3336f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    int32_t cutoverDay = (int32_t)ClockMath::floorDivide(fGregorianCutover, (double)kOneDay);
3346f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    fNormalizedGregorianCutover = cutoverDay * kOneDay;
3356f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
3366f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    // Handle the rare case of numeric overflow.  If the user specifies a
3376f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    // change of UDate(Long.MIN_VALUE), in order to get a pure Gregorian
3386f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    // calendar, then the epoch day is -106751991168, which when multiplied
3396f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    // by ONE_DAY gives 9223372036794351616 -- the negative value is too
3406f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    // large for 64 bits, and overflows into a positive value.  We correct
3416f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    // this by using the next day, which for all intents is semantically
3426f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    // equivalent.
3436f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    if (cutoverDay < 0 && fNormalizedGregorianCutover > 0) {
3446f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        fNormalizedGregorianCutover = (cutoverDay + 1) * kOneDay;
3456f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    }
3466f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
3476f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    // Normalize the year so BC values are represented as 0 and negative
3486f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    // values.
3496f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    GregorianCalendar *cal = new GregorianCalendar(getTimeZone(), status);
3506f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    /* test for NULL */
3516f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    if (cal == 0) {
3526f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        status = U_MEMORY_ALLOCATION_ERROR;
3536f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        return;
3546f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    }
3556f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    if(U_FAILURE(status))
3566f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        return;
3576f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    cal->setTime(date, status);
3586f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    fGregorianCutoverYear = cal->get(UCAL_YEAR, status);
3596f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    if (cal->get(UCAL_ERA, status) == BC)
3606f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        fGregorianCutoverYear = 1 - fGregorianCutoverYear;
3616f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    fCutoverJulianDay = cutoverDay;
3626f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    delete cal;
3636f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org}
3646f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
3656f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
3666f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgvoid GregorianCalendar::handleComputeFields(int32_t julianDay, UErrorCode& status) {
3676f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    int32_t eyear, month, dayOfMonth, dayOfYear, unusedRemainder;
3686f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
3696f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
3706f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    if(U_FAILURE(status)) {
3716f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        return;
3726f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    }
3736f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
3746f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org#if defined (U_DEBUG_CAL)
3756f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    fprintf(stderr, "%s:%d: jd%d- (greg's %d)- [cut=%d]\n",
3766f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        __FILE__, __LINE__, julianDay, getGregorianDayOfYear(), fCutoverJulianDay);
3776f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org#endif
3786f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
3796f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
3806f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    if (julianDay >= fCutoverJulianDay) {
3816f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        month = getGregorianMonth();
3826f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        dayOfMonth = getGregorianDayOfMonth();
3836f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        dayOfYear = getGregorianDayOfYear();
3846f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        eyear = getGregorianYear();
3856f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    } else {
3866f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        // The Julian epoch day (not the same as Julian Day)
3876f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        // is zero on Saturday December 30, 0 (Gregorian).
3886f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        int32_t julianEpochDay = julianDay - (kJan1_1JulianDay - 2);
3896f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org		eyear = (int32_t) ClockMath::floorDivide((4.0*julianEpochDay) + 1464.0, (int32_t) 1461, unusedRemainder);
3906f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
3916f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        // Compute the Julian calendar day number for January 1, eyear
3926f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        int32_t january1 = 365*(eyear-1) + ClockMath::floorDivide(eyear-1, (int32_t)4);
3936f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        dayOfYear = (julianEpochDay - january1); // 0-based
3946f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
3956f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        // Julian leap years occurred historically every 4 years starting
3966f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        // with 8 AD.  Before 8 AD the spacing is irregular; every 3 years
3976f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        // from 45 BC to 9 BC, and then none until 8 AD.  However, we don't
3986f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        // implement this historical detail; instead, we implement the
3996f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        // computatinally cleaner proleptic calendar, which assumes
4006f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        // consistent 4-year cycles throughout time.
4016f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        UBool isLeap = ((eyear&0x3) == 0); // equiv. to (eyear%4 == 0)
4026f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
4036f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        // Common Julian/Gregorian calculation
4046f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        int32_t correction = 0;
4056f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        int32_t march1 = isLeap ? 60 : 59; // zero-based DOY for March 1
4066f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        if (dayOfYear >= march1) {
4076f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            correction = isLeap ? 1 : 2;
4086f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        }
4096f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        month = (12 * (dayOfYear + correction) + 6) / 367; // zero-based month
4106f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        dayOfMonth = dayOfYear - (isLeap?kLeapNumDays[month]:kNumDays[month]) + 1; // one-based DOM
4116f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        ++dayOfYear;
4126f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org#if defined (U_DEBUG_CAL)
4136f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        //     fprintf(stderr, "%d - %d[%d] + 1\n", dayOfYear, isLeap?kLeapNumDays[month]:kNumDays[month], month );
4146f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        //           fprintf(stderr, "%s:%d:  greg's HCF %d -> %d/%d/%d not %d/%d/%d\n",
4156f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        //                   __FILE__, __LINE__,julianDay,
4166f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        //          eyear,month,dayOfMonth,
4176f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        //          getGregorianYear(), getGregorianMonth(), getGregorianDayOfMonth()  );
4186f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        fprintf(stderr, "%s:%d: doy %d (greg's %d)- [cut=%d]\n",
4196f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            __FILE__, __LINE__, dayOfYear, getGregorianDayOfYear(), fCutoverJulianDay);
4206f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org#endif
4216f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
4226f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    }
4236f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
4246f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    // [j81] if we are after the cutover in its year, shift the day of the year
4256f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    if((eyear == fGregorianCutoverYear) && (julianDay >= fCutoverJulianDay)) {
4266f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        //from handleComputeMonthStart
4276f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        int32_t gregShift = Grego::gregorianShift(eyear);
4286f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org#if defined (U_DEBUG_CAL)
4296f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        fprintf(stderr, "%s:%d:  gregorian shift %d :::  doy%d => %d [cut=%d]\n",
4306f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            __FILE__, __LINE__,gregShift, dayOfYear, dayOfYear+gregShift, fCutoverJulianDay);
4316f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org#endif
4326f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        dayOfYear += gregShift;
4336f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    }
4346f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
4356f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    internalSet(UCAL_MONTH, month);
4366f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    internalSet(UCAL_DAY_OF_MONTH, dayOfMonth);
4376f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    internalSet(UCAL_DAY_OF_YEAR, dayOfYear);
4386f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    internalSet(UCAL_EXTENDED_YEAR, eyear);
4396f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    int32_t era = AD;
4406f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    if (eyear < 1) {
4416f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        era = BC;
4426f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        eyear = 1 - eyear;
4436f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    }
4446f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    internalSet(UCAL_ERA, era);
4456f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    internalSet(UCAL_YEAR, eyear);
4466f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org}
4476f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
4486f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
4496f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org// -------------------------------------
4506f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
4516f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgUDate
4526f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgGregorianCalendar::getGregorianChange() const
4536f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org{
4546f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    return fGregorianCutover;
4556f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org}
4566f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
4576f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org// -------------------------------------
4586f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
4596f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgUBool
4606f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgGregorianCalendar::isLeapYear(int32_t year) const
4616f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org{
4626f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    // MSVC complains bitterly if we try to use Grego::isLeapYear here
4636f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    // NOTE: year&0x3 == year%4
4646f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    return (year >= fGregorianCutoverYear ?
4656f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        (((year&0x3) == 0) && ((year%100 != 0) || (year%400 == 0))) : // Gregorian
4666f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    ((year&0x3) == 0)); // Julian
4676f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org}
4686f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
4696f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org// -------------------------------------
4706f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
4716f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgint32_t GregorianCalendar::handleComputeJulianDay(UCalendarDateFields bestField)
4726f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org{
4736f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    fInvertGregorian = FALSE;
4746f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
4756f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    int32_t jd = Calendar::handleComputeJulianDay(bestField);
4766f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
4776f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    if((bestField == UCAL_WEEK_OF_YEAR) &&  // if we are doing WOY calculations, we are counting relative to Jan 1 *julian*
4786f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        (internalGet(UCAL_EXTENDED_YEAR)==fGregorianCutoverYear) &&
4796f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        jd >= fCutoverJulianDay) {
4806f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            fInvertGregorian = TRUE;  // So that the Julian Jan 1 will be used in handleComputeMonthStart
4816f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            return Calendar::handleComputeJulianDay(bestField);
4826f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        }
4836f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
4846f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
4856f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        // The following check handles portions of the cutover year BEFORE the
4866f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        // cutover itself happens.
4876f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        //if ((fIsGregorian==TRUE) != (jd >= fCutoverJulianDay)) {  /*  cutoverJulianDay)) { */
4886f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        if ((fIsGregorian==TRUE) != (jd >= fCutoverJulianDay)) {  /*  cutoverJulianDay)) { */
4896f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org#if defined (U_DEBUG_CAL)
4906f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            fprintf(stderr, "%s:%d: jd [invert] %d\n",
4916f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                __FILE__, __LINE__, jd);
4926f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org#endif
4936f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            fInvertGregorian = TRUE;
4946f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            jd = Calendar::handleComputeJulianDay(bestField);
4956f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org#if defined (U_DEBUG_CAL)
4966f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            fprintf(stderr, "%s:%d:  fIsGregorian %s, fInvertGregorian %s - ",
4976f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                __FILE__, __LINE__,fIsGregorian?"T":"F", fInvertGregorian?"T":"F");
4986f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            fprintf(stderr, " jd NOW %d\n",
4996f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                jd);
5006f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org#endif
5016f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        } else {
5026f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org#if defined (U_DEBUG_CAL)
5036f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            fprintf(stderr, "%s:%d: jd [==] %d - %sfIsGregorian %sfInvertGregorian, %d\n",
5046f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                __FILE__, __LINE__, jd, fIsGregorian?"T":"F", fInvertGregorian?"T":"F", bestField);
5056f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org#endif
5066f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        }
5076f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
5086f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        if(fIsGregorian && (internalGet(UCAL_EXTENDED_YEAR) == fGregorianCutoverYear)) {
5096f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            int32_t gregShift = Grego::gregorianShift(internalGet(UCAL_EXTENDED_YEAR));
5106f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            if (bestField == UCAL_DAY_OF_YEAR) {
5116f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org#if defined (U_DEBUG_CAL)
5126f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                fprintf(stderr, "%s:%d: [DOY%d] gregorian shift of JD %d += %d\n",
5136f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                    __FILE__, __LINE__, fFields[bestField],jd, gregShift);
5146f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org#endif
5156f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                jd -= gregShift;
5166f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            } else if ( bestField == UCAL_WEEK_OF_MONTH ) {
5176f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                int32_t weekShift = 14;
5186f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org#if defined (U_DEBUG_CAL)
5196f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                fprintf(stderr, "%s:%d: [WOY/WOM] gregorian week shift of %d += %d\n",
5206f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                    __FILE__, __LINE__, jd, weekShift);
5216f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org#endif
5226f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                jd += weekShift; // shift by weeks for week based fields.
5236f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            }
5246f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        }
5256f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
5266f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        return jd;
5276f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org}
5286f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
5296f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgint32_t GregorianCalendar::handleComputeMonthStart(int32_t eyear, int32_t month,
5306f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
5316f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                                                   UBool /* useMonth */) const
5326f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org{
5336f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    GregorianCalendar *nonConstThis = (GregorianCalendar*)this; // cast away const
5346f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
5356f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    // If the month is out of range, adjust it into range, and
5366f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    // modify the extended year value accordingly.
5376f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    if (month < 0 || month > 11) {
5386f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        eyear += ClockMath::floorDivide(month, 12, month);
5396f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    }
5406f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
5416f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    UBool isLeap = eyear%4 == 0;
5426f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    int32_t y = eyear-1;
5436f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    int32_t julianDay = 365*y + ClockMath::floorDivide(y, 4) + (kJan1_1JulianDay - 3);
5446f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
5456f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    nonConstThis->fIsGregorian = (eyear >= fGregorianCutoverYear);
5466f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org#if defined (U_DEBUG_CAL)
5476f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    fprintf(stderr, "%s:%d: (hcms%d/%d) fIsGregorian %s, fInvertGregorian %s\n",
5486f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        __FILE__, __LINE__, eyear,month, fIsGregorian?"T":"F", fInvertGregorian?"T":"F");
5496f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org#endif
5506f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    if (fInvertGregorian) {
5516f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        nonConstThis->fIsGregorian = !fIsGregorian;
5526f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    }
5536f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    if (fIsGregorian) {
5546f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        isLeap = isLeap && ((eyear%100 != 0) || (eyear%400 == 0));
5556f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        // Add 2 because Gregorian calendar starts 2 days after
5566f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        // Julian calendar
5576f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        int32_t gregShift = Grego::gregorianShift(eyear);
5586f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org#if defined (U_DEBUG_CAL)
5596f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        fprintf(stderr, "%s:%d: (hcms%d/%d) gregorian shift of %d += %d\n",
5606f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            __FILE__, __LINE__, eyear, month, julianDay, gregShift);
5616f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org#endif
5626f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        julianDay += gregShift;
5636f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    }
5646f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
5656f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    // At this point julianDay indicates the day BEFORE the first
5666f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    // day of January 1, <eyear> of either the Julian or Gregorian
5676f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    // calendar.
5686f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
5696f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    if (month != 0) {
5706f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        julianDay += isLeap?kLeapNumDays[month]:kNumDays[month];
5716f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    }
5726f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
5736f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    return julianDay;
5746f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org}
5756f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
5766f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgint32_t GregorianCalendar::handleGetMonthLength(int32_t extendedYear, int32_t month)  const
5776f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org{
5786f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    // If the month is out of range, adjust it into range, and
5796f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    // modify the extended year value accordingly.
5806f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    if (month < 0 || month > 11) {
5816f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        extendedYear += ClockMath::floorDivide(month, 12, month);
5826f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    }
5836f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
5846f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    return isLeapYear(extendedYear) ? kLeapMonthLength[month] : kMonthLength[month];
5856f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org}
5866f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
5876f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgint32_t GregorianCalendar::handleGetYearLength(int32_t eyear) const {
5886f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    return isLeapYear(eyear) ? 366 : 365;
5896f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org}
5906f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
5916f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
5926f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgint32_t
5936f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgGregorianCalendar::monthLength(int32_t month) const
5946f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org{
5956f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    int32_t year = internalGet(UCAL_EXTENDED_YEAR);
5966f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    return handleGetMonthLength(year, month);
5976f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org}
5986f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
5996f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org// -------------------------------------
6006f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
6016f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgint32_t
6026f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgGregorianCalendar::monthLength(int32_t month, int32_t year) const
6036f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org{
6046f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    return isLeapYear(year) ? kLeapMonthLength[month] : kMonthLength[month];
6056f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org}
6066f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
6076f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org// -------------------------------------
6086f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
6096f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgint32_t
6106f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgGregorianCalendar::yearLength(int32_t year) const
6116f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org{
6126f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    return isLeapYear(year) ? 366 : 365;
6136f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org}
6146f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
6156f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org// -------------------------------------
6166f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
6176f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgint32_t
6186f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgGregorianCalendar::yearLength() const
6196f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org{
6206f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    return isLeapYear(internalGet(UCAL_YEAR)) ? 366 : 365;
6216f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org}
6226f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
6236f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org// -------------------------------------
6246f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
6256f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org/**
6266f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org* After adjustments such as add(MONTH), add(YEAR), we don't want the
6276f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org* month to jump around.  E.g., we don't want Jan 31 + 1 month to go to Mar
6286f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org* 3, we want it to go to Feb 28.  Adjustments which might run into this
6296f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org* problem call this method to retain the proper month.
6306f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org*/
6316f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgvoid
6326f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgGregorianCalendar::pinDayOfMonth()
6336f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org{
6346f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    int32_t monthLen = monthLength(internalGet(UCAL_MONTH));
6356f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    int32_t dom = internalGet(UCAL_DATE);
6366f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    if(dom > monthLen)
6376f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        set(UCAL_DATE, monthLen);
6386f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org}
6396f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
6406f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org// -------------------------------------
6416f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
6426f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
6436f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgUBool
6446f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgGregorianCalendar::validateFields() const
6456f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org{
6466f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    for (int32_t field = 0; field < UCAL_FIELD_COUNT; field++) {
6476f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        // Ignore DATE and DAY_OF_YEAR which are handled below
6486f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        if (field != UCAL_DATE &&
6496f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            field != UCAL_DAY_OF_YEAR &&
6506f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            isSet((UCalendarDateFields)field) &&
6516f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            ! boundsCheck(internalGet((UCalendarDateFields)field), (UCalendarDateFields)field))
6526f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            return FALSE;
6536f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    }
6546f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
6556f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    // Values differ in Least-Maximum and Maximum should be handled
6566f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    // specially.
6576f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    if (isSet(UCAL_DATE)) {
6586f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        int32_t date = internalGet(UCAL_DATE);
6596f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        if (date < getMinimum(UCAL_DATE) ||
6606f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            date > monthLength(internalGet(UCAL_MONTH))) {
6616f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                return FALSE;
6626f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            }
6636f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    }
6646f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
6656f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    if (isSet(UCAL_DAY_OF_YEAR)) {
6666f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        int32_t days = internalGet(UCAL_DAY_OF_YEAR);
6676f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        if (days < 1 || days > yearLength()) {
6686f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            return FALSE;
6696f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        }
6706f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    }
6716f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
6726f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    // Handle DAY_OF_WEEK_IN_MONTH, which must not have the value zero.
6736f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    // We've checked against minimum and maximum above already.
6746f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    if (isSet(UCAL_DAY_OF_WEEK_IN_MONTH) &&
6756f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        0 == internalGet(UCAL_DAY_OF_WEEK_IN_MONTH)) {
6766f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            return FALSE;
6776f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        }
6786f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
6796f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        return TRUE;
6806f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org}
6816f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
6826f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org// -------------------------------------
6836f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
6846f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgUBool
6856f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgGregorianCalendar::boundsCheck(int32_t value, UCalendarDateFields field) const
6866f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org{
6876f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    return value >= getMinimum(field) && value <= getMaximum(field);
6886f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org}
6896f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
6906f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org// -------------------------------------
6916f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
6926f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgUDate
6936f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgGregorianCalendar::getEpochDay(UErrorCode& status)
6946f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org{
6956f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    complete(status);
6966f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    // Divide by 1000 (convert to seconds) in order to prevent overflow when
6976f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    // dealing with UDate(Long.MIN_VALUE) and UDate(Long.MAX_VALUE).
6986f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    double wallSec = internalGetTime()/1000 + (internalGet(UCAL_ZONE_OFFSET) + internalGet(UCAL_DST_OFFSET))/1000;
6996f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
7006f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    return ClockMath::floorDivide(wallSec, kOneDay/1000.0);
7016f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org}
7026f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
7036f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org// -------------------------------------
7046f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
7056f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
7066f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org// -------------------------------------
7076f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
7086f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org/**
7096f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org* Compute the julian day number of the day BEFORE the first day of
7106f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org* January 1, year 1 of the given calendar.  If julianDay == 0, it
7116f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org* specifies (Jan. 1, 1) - 1, in whatever calendar we are using (Julian
7126f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org* or Gregorian).
7136f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org*/
7146f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgdouble GregorianCalendar::computeJulianDayOfYear(UBool isGregorian,
7156f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                                                 int32_t year, UBool& isLeap)
7166f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org{
7176f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    isLeap = year%4 == 0;
7186f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    int32_t y = year - 1;
7196f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    double julianDay = 365.0*y + ClockMath::floorDivide(y, 4) + (kJan1_1JulianDay - 3);
7206f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
7216f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    if (isGregorian) {
7226f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        isLeap = isLeap && ((year%100 != 0) || (year%400 == 0));
7236f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        // Add 2 because Gregorian calendar starts 2 days after Julian calendar
7246f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        julianDay += Grego::gregorianShift(year);
7256f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    }
7266f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
7276f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    return julianDay;
7286f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org}
7296f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
7306f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org// /**
7316f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org//  * Compute the day of week, relative to the first day of week, from
7326f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org//  * 0..6, of the current DOW_LOCAL or DAY_OF_WEEK fields.  This is
7336f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org//  * equivalent to get(DOW_LOCAL) - 1.
7346f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org//  */
7356f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org// int32_t GregorianCalendar::computeRelativeDOW() const {
7366f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org//     int32_t relDow = 0;
7376f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org//     if (fStamp[UCAL_DOW_LOCAL] > fStamp[UCAL_DAY_OF_WEEK]) {
7386f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org//         relDow = internalGet(UCAL_DOW_LOCAL) - 1; // 1-based
7396f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org//     } else if (fStamp[UCAL_DAY_OF_WEEK] != kUnset) {
7406f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org//         relDow = internalGet(UCAL_DAY_OF_WEEK) - getFirstDayOfWeek();
7416f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org//         if (relDow < 0) relDow += 7;
7426f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org//     }
7436f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org//     return relDow;
7446f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org// }
7456f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
7466f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org// /**
7476f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org//  * Compute the day of week, relative to the first day of week,
7486f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org//  * from 0..6 of the given julian day.
7496f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org//  */
7506f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org// int32_t GregorianCalendar::computeRelativeDOW(double julianDay) const {
7516f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org//   int32_t relDow = julianDayToDayOfWeek(julianDay) - getFirstDayOfWeek();
7526f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org//     if (relDow < 0) {
7536f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org//         relDow += 7;
7546f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org//     }
7556f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org//     return relDow;
7566f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org// }
7576f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
7586f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org// /**
7596f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org//  * Compute the DOY using the WEEK_OF_YEAR field and the julian day
7606f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org//  * of the day BEFORE January 1 of a year (a return value from
7616f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org//  * computeJulianDayOfYear).
7626f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org//  */
7636f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org// int32_t GregorianCalendar::computeDOYfromWOY(double julianDayOfYear) const {
7646f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org//     // Compute DOY from day of week plus week of year
7656f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
7666f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org//     // Find the day of the week for the first of this year.  This
7676f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org//     // is zero-based, with 0 being the locale-specific first day of
7686f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org//     // the week.  Add 1 to get first day of year.
7696f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org//     int32_t fdy = computeRelativeDOW(julianDayOfYear + 1);
7706f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
7716f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org//     return
7726f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org//         // Compute doy of first (relative) DOW of WOY 1
7736f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org//         (((7 - fdy) < getMinimalDaysInFirstWeek())
7746f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org//          ? (8 - fdy) : (1 - fdy))
7756f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
7766f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org//         // Adjust for the week number.
7776f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org//         + (7 * (internalGet(UCAL_WEEK_OF_YEAR) - 1))
7786f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
7796f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org//         // Adjust for the DOW
7806f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org//         + computeRelativeDOW();
7816f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org// }
7826f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
7836f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org// -------------------------------------
7846f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
7856f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgdouble
7866f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgGregorianCalendar::millisToJulianDay(UDate millis)
7876f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org{
7886f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    return (double)kEpochStartAsJulianDay + ClockMath::floorDivide(millis, (double)kOneDay);
7896f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org}
7906f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
7916f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org// -------------------------------------
7926f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
7936f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgUDate
7946f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgGregorianCalendar::julianDayToMillis(double julian)
7956f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org{
7966f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    return (UDate) ((julian - kEpochStartAsJulianDay) * (double) kOneDay);
7976f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org}
7986f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
7996f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org// -------------------------------------
8006f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
8016f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgint32_t
8026f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgGregorianCalendar::aggregateStamp(int32_t stamp_a, int32_t stamp_b)
8036f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org{
8046f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    return (((stamp_a != kUnset && stamp_b != kUnset)
8056f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        ? uprv_max(stamp_a, stamp_b)
8066f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        : (int32_t)kUnset));
8076f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org}
8086f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
8096f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org// -------------------------------------
8106f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
8116f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org/**
8126f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org* Roll a field by a signed amount.
8136f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org* Note: This will be made public later. [LIU]
8146f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org*/
8156f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
8166f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgvoid
8176f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgGregorianCalendar::roll(EDateFields field, int32_t amount, UErrorCode& status) {
8186f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    roll((UCalendarDateFields) field, amount, status);
8196f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org}
8206f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
8216f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgvoid
8226f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgGregorianCalendar::roll(UCalendarDateFields field, int32_t amount, UErrorCode& status)
8236f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org{
8246f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    if((amount == 0) || U_FAILURE(status)) {
8256f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        return;
8266f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    }
8276f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
8286f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    // J81 processing. (gregorian cutover)
8296f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    UBool inCutoverMonth = FALSE;
8306f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    int32_t cMonthLen=0; // 'c' for cutover; in days
8316f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    int32_t cDayOfMonth=0; // no discontinuity: [0, cMonthLen)
8326f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    double cMonthStart=0.0; // in ms
8336f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
8346f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    // Common code - see if we're in the cutover month of the cutover year
8356f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    if(get(UCAL_EXTENDED_YEAR, status) == fGregorianCutoverYear) {
8366f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        switch (field) {
8376f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        case UCAL_DAY_OF_MONTH:
8386f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        case UCAL_WEEK_OF_MONTH:
8396f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            {
8406f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                int32_t max = monthLength(internalGet(UCAL_MONTH));
8416f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                UDate t = internalGetTime();
8426f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                // We subtract 1 from the DAY_OF_MONTH to make it zero-based, and an
8436f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                // additional 10 if we are after the cutover. Thus the monthStart
8446f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                // value will be correct iff we actually are in the cutover month.
8456f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                cDayOfMonth = internalGet(UCAL_DAY_OF_MONTH) - ((t >= fGregorianCutover) ? 10 : 0);
8466f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                cMonthStart = t - ((cDayOfMonth - 1) * kOneDay);
8476f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                // A month containing the cutover is 10 days shorter.
8486f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                if ((cMonthStart < fGregorianCutover) &&
8496f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                    (cMonthStart + (cMonthLen=(max-10))*kOneDay >= fGregorianCutover)) {
8506f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                        inCutoverMonth = TRUE;
8516f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                    }
8526f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            }
8536f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        default:
8546f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            ;
8556f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        }
8566f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    }
8576f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
8586f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    switch (field) {
8596f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    case UCAL_WEEK_OF_YEAR: {
8606f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        // Unlike WEEK_OF_MONTH, WEEK_OF_YEAR never shifts the day of the
8616f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        // week.  Also, rolling the week of the year can have seemingly
8626f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        // strange effects simply because the year of the week of year
8636f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        // may be different from the calendar year.  For example, the
8646f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        // date Dec 28, 1997 is the first day of week 1 of 1998 (if
8656f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        // weeks start on Sunday and the minimal days in first week is
8666f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        // <= 3).
8676f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        int32_t woy = get(UCAL_WEEK_OF_YEAR, status);
8686f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        // Get the ISO year, which matches the week of year.  This
8696f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        // may be one year before or after the calendar year.
8706f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        int32_t isoYear = get(UCAL_YEAR_WOY, status);
8716f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        int32_t isoDoy = internalGet(UCAL_DAY_OF_YEAR);
8726f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        if (internalGet(UCAL_MONTH) == UCAL_JANUARY) {
8736f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            if (woy >= 52) {
8746f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                isoDoy += handleGetYearLength(isoYear);
8756f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            }
8766f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        } else {
8776f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            if (woy == 1) {
8786f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                isoDoy -= handleGetYearLength(isoYear - 1);
8796f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            }
8806f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        }
8816f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        woy += amount;
8826f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        // Do fast checks to avoid unnecessary computation:
8836f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        if (woy < 1 || woy > 52) {
8846f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            // Determine the last week of the ISO year.
8856f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            // We do this using the standard formula we use
8866f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            // everywhere in this file.  If we can see that the
8876f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            // days at the end of the year are going to fall into
8886f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            // week 1 of the next year, we drop the last week by
8896f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            // subtracting 7 from the last day of the year.
8906f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            int32_t lastDoy = handleGetYearLength(isoYear);
8916f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            int32_t lastRelDow = (lastDoy - isoDoy + internalGet(UCAL_DAY_OF_WEEK) -
8926f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                getFirstDayOfWeek()) % 7;
8936f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            if (lastRelDow < 0) lastRelDow += 7;
8946f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            if ((6 - lastRelDow) >= getMinimalDaysInFirstWeek()) lastDoy -= 7;
8956f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            int32_t lastWoy = weekNumber(lastDoy, lastRelDow + 1);
8966f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            woy = ((woy + lastWoy - 1) % lastWoy) + 1;
8976f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        }
8986f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        set(UCAL_WEEK_OF_YEAR, woy);
8996f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        set(UCAL_YEAR_WOY,isoYear);
9006f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        return;
9016f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                            }
9026f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
9036f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    case UCAL_DAY_OF_MONTH:
9046f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        if( !inCutoverMonth ) {
9056f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            Calendar::roll(field, amount, status);
9066f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            return;
9076f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        } else {
9086f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            // [j81] 1582 special case for DOM
9096f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            // The default computation works except when the current month
9106f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            // contains the Gregorian cutover.  We handle this special case
9116f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            // here.  [j81 - aliu]
9126f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            double monthLen = cMonthLen * kOneDay;
9136f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            double msIntoMonth = uprv_fmod(internalGetTime() - cMonthStart +
9146f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                amount * kOneDay, monthLen);
9156f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            if (msIntoMonth < 0) {
9166f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                msIntoMonth += monthLen;
9176f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            }
9186f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org#if defined (U_DEBUG_CAL)
9196f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            fprintf(stderr, "%s:%d: roll DOM %d  -> %.0lf ms  \n",
9206f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                __FILE__, __LINE__,amount, cMonthLen, cMonthStart+msIntoMonth);
9216f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org#endif
9226f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            setTimeInMillis(cMonthStart + msIntoMonth, status);
9236f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            return;
9246f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        }
9256f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
9266f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    case UCAL_WEEK_OF_MONTH:
9276f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        if( !inCutoverMonth ) {
9286f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            Calendar::roll(field, amount, status);
9296f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            return;
9306f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        } else {
9316f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org#if defined (U_DEBUG_CAL)
9326f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            fprintf(stderr, "%s:%d: roll WOM %d ??????????????????? \n",
9336f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                __FILE__, __LINE__,amount);
9346f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org#endif
9356f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            // NOTE: following copied from  the old
9366f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            //     GregorianCalendar::roll( WEEK_OF_MONTH )  code
9376f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
9386f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            // This is tricky, because during the roll we may have to shift
9396f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            // to a different day of the week.  For example:
9406f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
9416f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            //    s  m  t  w  r  f  s
9426f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            //          1  2  3  4  5
9436f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            //    6  7  8  9 10 11 12
9446f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
9456f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            // When rolling from the 6th or 7th back one week, we go to the
9466f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            // 1st (assuming that the first partial week counts).  The same
9476f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            // thing happens at the end of the month.
9486f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
9496f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            // The other tricky thing is that we have to figure out whether
9506f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            // the first partial week actually counts or not, based on the
9516f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            // minimal first days in the week.  And we have to use the
9526f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            // correct first day of the week to delineate the week
9536f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            // boundaries.
9546f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
9556f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            // Here's our algorithm.  First, we find the real boundaries of
9566f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            // the month.  Then we discard the first partial week if it
9576f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            // doesn't count in this locale.  Then we fill in the ends with
9586f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            // phantom days, so that the first partial week and the last
9596f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            // partial week are full weeks.  We then have a nice square
9606f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            // block of weeks.  We do the usual rolling within this block,
9616f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            // as is done elsewhere in this method.  If we wind up on one of
9626f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            // the phantom days that we added, we recognize this and pin to
9636f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            // the first or the last day of the month.  Easy, eh?
9646f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
9656f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            // Another wrinkle: To fix jitterbug 81, we have to make all this
9666f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            // work in the oddball month containing the Gregorian cutover.
9676f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            // This month is 10 days shorter than usual, and also contains
9686f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            // a discontinuity in the days; e.g., the default cutover month
9696f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            // is Oct 1582, and goes from day of month 4 to day of month 15.
9706f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
9716f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            // Normalize the DAY_OF_WEEK so that 0 is the first day of the week
9726f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            // in this locale.  We have dow in 0..6.
9736f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            int32_t dow = internalGet(UCAL_DAY_OF_WEEK) - getFirstDayOfWeek();
9746f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            if (dow < 0)
9756f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                dow += 7;
9766f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
9776f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            // Find the day of month, compensating for cutover discontinuity.
9786f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            int32_t dom = cDayOfMonth;
9796f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
9806f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            // Find the day of the week (normalized for locale) for the first
9816f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            // of the month.
9826f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            int32_t fdm = (dow - dom + 1) % 7;
9836f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            if (fdm < 0)
9846f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                fdm += 7;
9856f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
9866f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            // Get the first day of the first full week of the month,
9876f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            // including phantom days, if any.  Figure out if the first week
9886f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            // counts or not; if it counts, then fill in phantom days.  If
9896f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            // not, advance to the first real full week (skip the partial week).
9906f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            int32_t start;
9916f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            if ((7 - fdm) < getMinimalDaysInFirstWeek())
9926f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                start = 8 - fdm; // Skip the first partial week
9936f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            else
9946f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                start = 1 - fdm; // This may be zero or negative
9956f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
9966f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            // Get the day of the week (normalized for locale) for the last
9976f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            // day of the month.
9986f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            int32_t monthLen = cMonthLen;
9996f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            int32_t ldm = (monthLen - dom + dow) % 7;
10006f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            // We know monthLen >= DAY_OF_MONTH so we skip the += 7 step here.
10016f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
10026f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            // Get the limit day for the blocked-off rectangular month; that
10036f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            // is, the day which is one past the last day of the month,
10046f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            // after the month has already been filled in with phantom days
10056f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            // to fill out the last week.  This day has a normalized DOW of 0.
10066f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            int32_t limit = monthLen + 7 - ldm;
10076f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
10086f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            // Now roll between start and (limit - 1).
10096f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            int32_t gap = limit - start;
10106f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            int32_t newDom = (dom + amount*7 - start) % gap;
10116f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            if (newDom < 0)
10126f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                newDom += gap;
10136f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            newDom += start;
10146f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
10156f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            // Finally, pin to the real start and end of the month.
10166f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            if (newDom < 1)
10176f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                newDom = 1;
10186f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            if (newDom > monthLen)
10196f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                newDom = monthLen;
10206f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
10216f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            // Set the DAY_OF_MONTH.  We rely on the fact that this field
10226f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            // takes precedence over everything else (since all other fields
10236f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            // are also set at this point).  If this fact changes (if the
10246f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            // disambiguation algorithm changes) then we will have to unset
10256f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            // the appropriate fields here so that DAY_OF_MONTH is attended
10266f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            // to.
10276f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
10286f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            // If we are in the cutover month, manipulate ms directly.  Don't do
10296f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            // this in general because it doesn't work across DST boundaries
10306f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            // (details, details).  This takes care of the discontinuity.
10316f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            setTimeInMillis(cMonthStart + (newDom-1)*kOneDay, status);
10326f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            return;
10336f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        }
10346f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
10356f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    default:
10366f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        Calendar::roll(field, amount, status);
10376f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        return;
10386f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    }
10396f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org}
10406f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
10416f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org// -------------------------------------
10426f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
10436f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
10446f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org/**
10456f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org* Return the minimum value that this field could have, given the current date.
10466f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org* For the Gregorian calendar, this is the same as getMinimum() and getGreatestMinimum().
10476f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org* @param field    the time field.
10486f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org* @return         the minimum value that this field could have, given the current date.
10496f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org* @deprecated ICU 2.6. Use getActualMinimum(UCalendarDateFields field) instead.
10506f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org*/
10516f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgint32_t GregorianCalendar::getActualMinimum(EDateFields field) const
10526f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org{
10536f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    return getMinimum((UCalendarDateFields)field);
10546f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org}
10556f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
10566f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgint32_t GregorianCalendar::getActualMinimum(EDateFields field, UErrorCode& /* status */) const
10576f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org{
10586f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    return getMinimum((UCalendarDateFields)field);
10596f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org}
10606f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
10616f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org/**
10626f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org* Return the minimum value that this field could have, given the current date.
10636f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org* For the Gregorian calendar, this is the same as getMinimum() and getGreatestMinimum().
10646f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org* @param field    the time field.
10656f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org* @return         the minimum value that this field could have, given the current date.
10666f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org* @draft ICU 2.6.
10676f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org*/
10686f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgint32_t GregorianCalendar::getActualMinimum(UCalendarDateFields field, UErrorCode& /* status */) const
10696f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org{
10706f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    return getMinimum(field);
10716f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org}
10726f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
10736f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
10746f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org// ------------------------------------
10756f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
10766f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org/**
10776f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org* Old year limits were least max 292269054, max 292278994.
10786f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org*/
10796f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
10806f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org/**
10816f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org* @stable ICU 2.0
10826f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org*/
10836f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgint32_t GregorianCalendar::handleGetLimit(UCalendarDateFields field, ELimitType limitType) const {
10846f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    return kGregorianCalendarLimits[field][limitType];
10856f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org}
10866f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
10876f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org/**
10886f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org* Return the maximum value that this field could have, given the current date.
10896f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org* For example, with the date "Feb 3, 1997" and the DAY_OF_MONTH field, the actual
10906f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org* maximum would be 28; for "Feb 3, 1996" it s 29.  Similarly for a Hebrew calendar,
10916f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org* for some years the actual maximum for MONTH is 12, and for others 13.
10926f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org* @stable ICU 2.0
10936f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org*/
10946f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgint32_t GregorianCalendar::getActualMaximum(UCalendarDateFields field, UErrorCode& status) const
10956f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org{
10966f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    /* It is a known limitation that the code here (and in getActualMinimum)
10976f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    * won't behave properly at the extreme limits of GregorianCalendar's
10986f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    * representable range (except for the code that handles the YEAR
10996f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    * field).  That's because the ends of the representable range are at
11006f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    * odd spots in the year.  For calendars with the default Gregorian
11016f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    * cutover, these limits are Sun Dec 02 16:47:04 GMT 292269055 BC to Sun
11026f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    * Aug 17 07:12:55 GMT 292278994 AD, somewhat different for non-GMT
11036f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    * zones.  As a result, if the calendar is set to Aug 1 292278994 AD,
11046f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    * the actual maximum of DAY_OF_MONTH is 17, not 30.  If the date is Mar
11056f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    * 31 in that year, the actual maximum month might be Jul, whereas is
11066f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    * the date is Mar 15, the actual maximum might be Aug -- depending on
11076f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    * the precise semantics that are desired.  Similar considerations
11086f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    * affect all fields.  Nonetheless, this effect is sufficiently arcane
11096f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    * that we permit it, rather than complicating the code to handle such
11106f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    * intricacies. - liu 8/20/98
11116f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
11126f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    * UPDATE: No longer true, since we have pulled in the limit values on
11136f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    * the year. - Liu 11/6/00 */
11146f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
11156f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    switch (field) {
11166f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
11176f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    case UCAL_YEAR:
11186f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        /* The year computation is no different, in principle, from the
11196f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        * others, however, the range of possible maxima is large.  In
11206f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        * addition, the way we know we've exceeded the range is different.
11216f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        * For these reasons, we use the special case code below to handle
11226f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        * this field.
11236f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        *
11246f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        * The actual maxima for YEAR depend on the type of calendar:
11256f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        *
11266f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        *     Gregorian = May 17, 292275056 BC - Aug 17, 292278994 AD
11276f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        *     Julian    = Dec  2, 292269055 BC - Jan  3, 292272993 AD
11286f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        *     Hybrid    = Dec  2, 292269055 BC - Aug 17, 292278994 AD
11296f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        *
11306f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        * We know we've exceeded the maximum when either the month, date,
11316f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        * time, or era changes in response to setting the year.  We don't
11326f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        * check for month, date, and time here because the year and era are
11336f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        * sufficient to detect an invalid year setting.  NOTE: If code is
11346f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        * added to check the month and date in the future for some reason,
11356f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        * Feb 29 must be allowed to shift to Mar 1 when setting the year.
11366f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        */
11376f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        {
11386f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            if(U_FAILURE(status)) return 0;
11396f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            Calendar *cal = clone();
11406f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            if(!cal) {
11416f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                status = U_MEMORY_ALLOCATION_ERROR;
11426f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                return 0;
11436f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            }
11446f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
11456f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            cal->setLenient(TRUE);
11466f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
11476f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            int32_t era = cal->get(UCAL_ERA, status);
11486f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            UDate d = cal->getTime(status);
11496f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
11506f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            /* Perform a binary search, with the invariant that lowGood is a
11516f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            * valid year, and highBad is an out of range year.
11526f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            */
11536f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            int32_t lowGood = kGregorianCalendarLimits[UCAL_YEAR][1];
11546f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            int32_t highBad = kGregorianCalendarLimits[UCAL_YEAR][2]+1;
11556f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            while ((lowGood + 1) < highBad) {
11566f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                int32_t y = (lowGood + highBad) / 2;
11576f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                cal->set(UCAL_YEAR, y);
11586f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                if (cal->get(UCAL_YEAR, status) == y && cal->get(UCAL_ERA, status) == era) {
11596f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                    lowGood = y;
11606f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                } else {
11616f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                    highBad = y;
11626f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                    cal->setTime(d, status); // Restore original fields
11636f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                }
11646f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            }
11656f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
11666f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            delete cal;
11676f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            return lowGood;
11686f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        }
11696f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
11706f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    default:
11716f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        return Calendar::getActualMaximum(field,status);
11726f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    }
11736f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org}
11746f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
11756f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
11766f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgint32_t GregorianCalendar::handleGetExtendedYear() {
11776f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    // the year to return
11786f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    int32_t year = kEpochYear;
11796f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
11806f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    // year field to use
11816f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    int32_t yearField = UCAL_EXTENDED_YEAR;
11826f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
11836f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    // There are three separate fields which could be used to
11846f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    // derive the proper year.  Use the one most recently set.
11856f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    if (fStamp[yearField] < fStamp[UCAL_YEAR])
11866f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        yearField = UCAL_YEAR;
11876f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    if (fStamp[yearField] < fStamp[UCAL_YEAR_WOY])
11886f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        yearField = UCAL_YEAR_WOY;
11896f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
11906f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    // based on the "best" year field, get the year
11916f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    switch(yearField) {
11926f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    case UCAL_EXTENDED_YEAR:
11936f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        year = internalGet(UCAL_EXTENDED_YEAR, kEpochYear);
11946f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        break;
11956f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
11966f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    case UCAL_YEAR:
11976f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        {
11986f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            // The year defaults to the epoch start, the era to AD
11996f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            int32_t era = internalGet(UCAL_ERA, AD);
12006f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            if (era == BC) {
12016f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                year = 1 - internalGet(UCAL_YEAR, 1); // Convert to extended year
12026f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            } else {
12036f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                year = internalGet(UCAL_YEAR, kEpochYear);
12046f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            }
12056f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        }
12066f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        break;
12076f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
12086f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    case UCAL_YEAR_WOY:
12096f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        year = handleGetExtendedYearFromWeekFields(internalGet(UCAL_YEAR_WOY), internalGet(UCAL_WEEK_OF_YEAR));
12106f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org#if defined (U_DEBUG_CAL)
12116f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        //    if(internalGet(UCAL_YEAR_WOY) != year) {
12126f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        fprintf(stderr, "%s:%d: hGEYFWF[%d,%d] ->  %d\n",
12136f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            __FILE__, __LINE__,internalGet(UCAL_YEAR_WOY),internalGet(UCAL_WEEK_OF_YEAR),year);
12146f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        //}
12156f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org#endif
12166f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        break;
12176f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
12186f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    default:
12196f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        year = kEpochYear;
12206f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    }
12216f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    return year;
12226f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org}
12236f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
12246f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgint32_t GregorianCalendar::handleGetExtendedYearFromWeekFields(int32_t yearWoy, int32_t woy)
12256f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org{
12266f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    // convert year to extended form
12276f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    int32_t era = internalGet(UCAL_ERA, AD);
12286f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    if(era == BC) {
12296f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        yearWoy = 1 - yearWoy;
12306f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    }
12316f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    return Calendar::handleGetExtendedYearFromWeekFields(yearWoy, woy);
12326f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org}
12336f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
12346f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
12356f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org// -------------------------------------
12366f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
12376f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgUBool
12386f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgGregorianCalendar::inDaylightTime(UErrorCode& status) const
12396f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org{
12406f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    if (U_FAILURE(status) || !getTimeZone().useDaylightTime())
12416f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        return FALSE;
12426f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
12436f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    // Force an update of the state of the Calendar.
12446f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    ((GregorianCalendar*)this)->complete(status); // cast away const
12456f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
12466f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    return (UBool)(U_SUCCESS(status) ? (internalGet(UCAL_DST_OFFSET) != 0) : FALSE);
12476f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org}
12486f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
12496f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org// -------------------------------------
12506f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
12516f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org/**
12526f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org* Return the ERA.  We need a special method for this because the
12536f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org* default ERA is AD, but a zero (unset) ERA is BC.
12546f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org*/
12556f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgint32_t
12566f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgGregorianCalendar::internalGetEra() const {
12576f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    return isSet(UCAL_ERA) ? internalGet(UCAL_ERA) : (int32_t)AD;
12586f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org}
12596f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
12606f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgconst char *
12616f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgGregorianCalendar::getType() const {
12626f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    //static const char kGregorianType = "gregorian";
12636f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
12646f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    return "gregorian";
12656f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org}
12666f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
12676f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org/**
12686f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org * The system maintains a static default century start date and Year.  They are
12696f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org * initialized the first time they are used.  Once the system default century date
12706f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org * and year are set, they do not change.
12716f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org */
12726f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgstatic UDate           gSystemDefaultCenturyStart       = DBL_MIN;
12736f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgstatic int32_t         gSystemDefaultCenturyStartYear   = -1;
12746f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgstatic icu::UInitOnce  gSystemDefaultCenturyInit        = U_INITONCE_INITIALIZER;
12756f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
12766f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
12776f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgUBool GregorianCalendar::haveDefaultCentury() const
12786f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org{
12796f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    return TRUE;
12806f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org}
12816f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
12826f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgstatic void U_CALLCONV
12836f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orginitializeSystemDefaultCentury()
12846f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org{
12856f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    // initialize systemDefaultCentury and systemDefaultCenturyYear based
12866f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    // on the current time.  They'll be set to 80 years before
12876f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    // the current time.
12886f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    UErrorCode status = U_ZERO_ERROR;
12896f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    GregorianCalendar calendar(status);
12906f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    if (U_SUCCESS(status)) {
12916f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        calendar.setTime(Calendar::getNow(), status);
12926f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        calendar.add(UCAL_YEAR, -80, status);
12936f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
12946f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        gSystemDefaultCenturyStart = calendar.getTime(status);
12956f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        gSystemDefaultCenturyStartYear = calendar.get(UCAL_YEAR, status);
12966f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    }
12976f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    // We have no recourse upon failure unless we want to propagate the failure
12986f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    // out.
12996f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org}
13006f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
13016f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgUDate GregorianCalendar::defaultCenturyStart() const {
13026f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    // lazy-evaluate systemDefaultCenturyStart
13036f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    umtx_initOnce(gSystemDefaultCenturyInit, &initializeSystemDefaultCentury);
13046f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    return gSystemDefaultCenturyStart;
13056f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org}
13066f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
13076f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgint32_t GregorianCalendar::defaultCenturyStartYear() const {
13086f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    // lazy-evaluate systemDefaultCenturyStartYear
13096f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    umtx_initOnce(gSystemDefaultCenturyInit, &initializeSystemDefaultCentury);
13106f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    return gSystemDefaultCenturyStartYear;
13116f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org}
13126f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
13136f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgU_NAMESPACE_END
13146f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
13156f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org#endif /* #if !UCONFIG_NO_FORMATTING */
13166f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
13176f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org//eof
1318