1b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru/*
2b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru*******************************************************************************
359d709d503bab6e2b61931737e662dd293b40578ccornelius* Copyright (C) 1997-2013, International Business Machines Corporation and
459d709d503bab6e2b61931737e662dd293b40578ccornelius* others. All Rights Reserved.
5b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru*******************************************************************************
6b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru*
7b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru* File GREGOCAL.CPP
8b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru*
9b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru* Modification History:
10b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru*
11b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru*   Date        Name        Description
12b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru*   02/05/97    clhuang     Creation.
13b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru*   03/28/97    aliu        Made highly questionable fix to computeFields to
14b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru*                           handle DST correctly.
15b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru*   04/22/97    aliu        Cleaned up code drastically.  Added monthLength().
16b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru*                           Finished unimplemented parts of computeTime() for
17b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru*                           week-based date determination.  Removed quetionable
18b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru*                           fix and wrote correct fix for computeFields() and
19b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru*                           daylight time handling.  Rewrote inDaylightTime()
20b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru*                           and computeFields() to handle sensitive Daylight to
21b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru*                           Standard time transitions correctly.
22b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru*   05/08/97    aliu        Added code review changes.  Fixed isLeapYear() to
23b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru*                           not cutover.
24b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru*   08/12/97    aliu        Added equivalentTo.  Misc other fixes.  Updated
25b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru*                           add() from Java source.
26b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru*    07/28/98    stephen        Sync up with JDK 1.2
27b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru*    09/14/98    stephen        Changed type of kOneDay, kOneWeek to double.
28b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru*                            Fixed bug in roll()
29b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru*   10/15/99    aliu        Fixed j31, incorrect WEEK_OF_YEAR computation.
30b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru*   10/15/99    aliu        Fixed j32, cannot set date to Feb 29 2000 AD.
31b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru*                           {JDK bug 4210209 4209272}
32b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru*   11/15/99    weiv        Added YEAR_WOY and DOW_LOCAL computation
33b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru*                           to timeToFields method, updated kMinValues, kMaxValues & kLeastMaxValues
34b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru*   12/09/99    aliu        Fixed j81, calculation errors and roll bugs
35b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru*                           in year of cutover.
36b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru*   01/24/2000  aliu        Revised computeJulianDay for YEAR YEAR_WOY WOY.
37b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru********************************************************************************
38b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru*/
39b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
40b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#include "unicode/utypes.h"
41b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#include <float.h>
42b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
43b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#if !UCONFIG_NO_FORMATTING
44b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
45b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#include "unicode/gregocal.h"
46b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#include "gregoimp.h"
47b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#include "umutex.h"
48b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#include "uassert.h"
49b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
50b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// *****************************************************************************
51b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// class GregorianCalendar
52b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// *****************************************************************************
53b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
54b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru/**
55b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru* Note that the Julian date used here is not a true Julian date, since
56b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru* it is measured from midnight, not noon.  This value is the Julian
57b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru* day number of January 1, 1970 (Gregorian calendar) at noon UTC. [LIU]
58b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru*/
59b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
60c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Querustatic const int16_t kNumDays[]
61b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru= {0,31,59,90,120,151,181,212,243,273,304,334}; // 0-based, for day-in-year
62c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Querustatic const int16_t kLeapNumDays[]
63b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru= {0,31,60,91,121,152,182,213,244,274,305,335}; // 0-based, for day-in-year
64c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Querustatic const int8_t kMonthLength[]
65b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru= {31,28,31,30,31,30,31,31,30,31,30,31}; // 0-based
66c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Querustatic const int8_t kLeapMonthLength[]
67b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru= {31,29,31,30,31,30,31,31,30,31,30,31}; // 0-based
68b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
69b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// setTimeInMillis() limits the Julian day range to +/-7F000000.
70b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// This would seem to limit the year range to:
71b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru//  ms=+183882168921600000  jd=7f000000  December 20, 5828963 AD
72b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru//  ms=-184303902528000000  jd=81000000  September 20, 5838270 BC
73b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// HOWEVER, CalendarRegressionTest/Test4167060 shows that the actual
74b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// range limit on the year field is smaller (~ +/-140000). [alan 3.0]
75b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
76b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querustatic const int32_t kGregorianCalendarLimits[UCAL_FIELD_COUNT][4] = {
77b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // Minimum  Greatest    Least  Maximum
78b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    //           Minimum  Maximum
79c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    {        0,        0,        1,        1}, // ERA
80c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    {        1,        1,   140742,   144683}, // YEAR
81c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    {        0,        0,       11,       11}, // MONTH
82c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    {        1,        1,       52,       53}, // WEEK_OF_YEAR
83c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    {/*N/A*/-1,/*N/A*/-1,/*N/A*/-1,/*N/A*/-1}, // WEEK_OF_MONTH
84c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    {        1,        1,       28,       31}, // DAY_OF_MONTH
85c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    {        1,        1,      365,      366}, // DAY_OF_YEAR
86c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    {/*N/A*/-1,/*N/A*/-1,/*N/A*/-1,/*N/A*/-1}, // DAY_OF_WEEK
87c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    {       -1,       -1,        4,        5}, // DAY_OF_WEEK_IN_MONTH
88c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    {/*N/A*/-1,/*N/A*/-1,/*N/A*/-1,/*N/A*/-1}, // AM_PM
89c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    {/*N/A*/-1,/*N/A*/-1,/*N/A*/-1,/*N/A*/-1}, // HOUR
90c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    {/*N/A*/-1,/*N/A*/-1,/*N/A*/-1,/*N/A*/-1}, // HOUR_OF_DAY
91c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    {/*N/A*/-1,/*N/A*/-1,/*N/A*/-1,/*N/A*/-1}, // MINUTE
92c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    {/*N/A*/-1,/*N/A*/-1,/*N/A*/-1,/*N/A*/-1}, // SECOND
93c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    {/*N/A*/-1,/*N/A*/-1,/*N/A*/-1,/*N/A*/-1}, // MILLISECOND
94c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    {/*N/A*/-1,/*N/A*/-1,/*N/A*/-1,/*N/A*/-1}, // ZONE_OFFSET
95c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    {/*N/A*/-1,/*N/A*/-1,/*N/A*/-1,/*N/A*/-1}, // DST_OFFSET
96c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    {  -140742,  -140742,   140742,   144683}, // YEAR_WOY
97c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    {/*N/A*/-1,/*N/A*/-1,/*N/A*/-1,/*N/A*/-1}, // DOW_LOCAL
98c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    {  -140742,  -140742,   140742,   144683}, // EXTENDED_YEAR
99c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    {/*N/A*/-1,/*N/A*/-1,/*N/A*/-1,/*N/A*/-1}, // JULIAN_DAY
100c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    {/*N/A*/-1,/*N/A*/-1,/*N/A*/-1,/*N/A*/-1}, // MILLISECONDS_IN_DAY
101c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    {/*N/A*/-1,/*N/A*/-1,/*N/A*/-1,/*N/A*/-1}, // IS_LEAP_MONTH
102b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru};
103b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
104b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru/*
105b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru* <pre>
106b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru*                            Greatest       Least
107b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru* Field name        Minimum   Minimum     Maximum     Maximum
108b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru* ----------        -------   -------     -------     -------
109b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru* ERA                     0         0           1           1
110b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru* YEAR                    1         1      140742      144683
111b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru* MONTH                   0         0          11          11
112b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru* WEEK_OF_YEAR            1         1          52          53
113b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru* WEEK_OF_MONTH           0         0           4           6
114b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru* DAY_OF_MONTH            1         1          28          31
115b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru* DAY_OF_YEAR             1         1         365         366
116b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru* DAY_OF_WEEK             1         1           7           7
117b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru* DAY_OF_WEEK_IN_MONTH   -1        -1           4           5
118b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru* AM_PM                   0         0           1           1
119b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru* HOUR                    0         0          11          11
120b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru* HOUR_OF_DAY             0         0          23          23
121b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru* MINUTE                  0         0          59          59
122b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru* SECOND                  0         0          59          59
123b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru* MILLISECOND             0         0         999         999
124b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru* ZONE_OFFSET           -12*      -12*         12*         12*
125b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru* DST_OFFSET              0         0           1*          1*
126b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru* YEAR_WOY                1         1      140742      144683
127b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru* DOW_LOCAL               1         1           7           7
128b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru* </pre>
129b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru* (*) In units of one-hour
130b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru*/
131b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
132b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#if defined( U_DEBUG_CALSVC ) || defined (U_DEBUG_CAL)
133b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#include <stdio.h>
134b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#endif
135b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
136b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruU_NAMESPACE_BEGIN
137b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
138b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruUOBJECT_DEFINE_RTTI_IMPLEMENTATION(GregorianCalendar)
139b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
140b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// 00:00:00 UTC, October 15, 1582, expressed in ms from the epoch.
141b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// Note that only Italy and other Catholic countries actually
142b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// observed this cutover.  Most other countries followed in
143b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// the next few centuries, some as late as 1928. [LIU]
144b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// in Java, -12219292800000L
145b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru//const UDate GregorianCalendar::kPapalCutover = -12219292800000L;
146b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querustatic const uint32_t kCutoverJulianDay = 2299161;
147b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querustatic const UDate kPapalCutover = (2299161.0 - kEpochStartAsJulianDay) * U_MILLIS_PER_DAY;
148b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru//static const UDate kPapalCutoverJulian = (2299161.0 - kEpochStartAsJulianDay);
149b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
150b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// -------------------------------------
151b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
152b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruGregorianCalendar::GregorianCalendar(UErrorCode& status)
15350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho:   Calendar(status),
154b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QuerufGregorianCutover(kPapalCutover),
155b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QuerufCutoverJulianDay(kCutoverJulianDay), fNormalizedGregorianCutover(fGregorianCutover), fGregorianCutoverYear(1582),
156b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QuerufIsGregorian(TRUE), fInvertGregorian(FALSE)
157b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
158b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    setTimeInMillis(getNow(), status);
159b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
160b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
161b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// -------------------------------------
162b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
163b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruGregorianCalendar::GregorianCalendar(TimeZone* zone, UErrorCode& status)
164b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru:   Calendar(zone, Locale::getDefault(), status),
165b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QuerufGregorianCutover(kPapalCutover),
166b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QuerufCutoverJulianDay(kCutoverJulianDay), fNormalizedGregorianCutover(fGregorianCutover), fGregorianCutoverYear(1582),
167b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QuerufIsGregorian(TRUE), fInvertGregorian(FALSE)
168b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
169b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    setTimeInMillis(getNow(), status);
170b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
171b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
172b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// -------------------------------------
173b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
174b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruGregorianCalendar::GregorianCalendar(const TimeZone& zone, UErrorCode& status)
175b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru:   Calendar(zone, Locale::getDefault(), status),
176b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QuerufGregorianCutover(kPapalCutover),
177b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QuerufCutoverJulianDay(kCutoverJulianDay), fNormalizedGregorianCutover(fGregorianCutover), fGregorianCutoverYear(1582),
178b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QuerufIsGregorian(TRUE), fInvertGregorian(FALSE)
179b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
180b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    setTimeInMillis(getNow(), status);
181b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
182b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
183b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// -------------------------------------
184b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
185b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruGregorianCalendar::GregorianCalendar(const Locale& aLocale, UErrorCode& status)
186b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru:   Calendar(TimeZone::createDefault(), aLocale, status),
187b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QuerufGregorianCutover(kPapalCutover),
188b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QuerufCutoverJulianDay(kCutoverJulianDay), fNormalizedGregorianCutover(fGregorianCutover), fGregorianCutoverYear(1582),
189b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QuerufIsGregorian(TRUE), fInvertGregorian(FALSE)
190b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
191b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    setTimeInMillis(getNow(), status);
192b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
193b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
194b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// -------------------------------------
195b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
196b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruGregorianCalendar::GregorianCalendar(TimeZone* zone, const Locale& aLocale,
197b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                                     UErrorCode& status)
198b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                                     :   Calendar(zone, aLocale, status),
199b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                                     fGregorianCutover(kPapalCutover),
200b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                                     fCutoverJulianDay(kCutoverJulianDay), fNormalizedGregorianCutover(fGregorianCutover), fGregorianCutoverYear(1582),
201b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                                     fIsGregorian(TRUE), fInvertGregorian(FALSE)
202b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
203b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    setTimeInMillis(getNow(), status);
204b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
205b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
206b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// -------------------------------------
207b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
208b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruGregorianCalendar::GregorianCalendar(const TimeZone& zone, const Locale& aLocale,
209b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                                     UErrorCode& status)
210b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                                     :   Calendar(zone, aLocale, status),
211b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                                     fGregorianCutover(kPapalCutover),
212b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                                     fCutoverJulianDay(kCutoverJulianDay), fNormalizedGregorianCutover(fGregorianCutover), fGregorianCutoverYear(1582),
213b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                                     fIsGregorian(TRUE), fInvertGregorian(FALSE)
214b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
215b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    setTimeInMillis(getNow(), status);
216b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
217b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
218b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// -------------------------------------
219b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
220b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruGregorianCalendar::GregorianCalendar(int32_t year, int32_t month, int32_t date,
221b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                                     UErrorCode& status)
222b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                                     :   Calendar(TimeZone::createDefault(), Locale::getDefault(), status),
223b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                                     fGregorianCutover(kPapalCutover),
224b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                                     fCutoverJulianDay(kCutoverJulianDay), fNormalizedGregorianCutover(fGregorianCutover), fGregorianCutoverYear(1582),
225b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                                     fIsGregorian(TRUE), fInvertGregorian(FALSE)
226b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
227b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    set(UCAL_ERA, AD);
228b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    set(UCAL_YEAR, year);
229b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    set(UCAL_MONTH, month);
230b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    set(UCAL_DATE, date);
231b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
232b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
233b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// -------------------------------------
234b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
235b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruGregorianCalendar::GregorianCalendar(int32_t year, int32_t month, int32_t date,
236b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                                     int32_t hour, int32_t minute, UErrorCode& status)
237b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                                     :   Calendar(TimeZone::createDefault(), Locale::getDefault(), status),
238b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                                     fGregorianCutover(kPapalCutover),
239b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                                     fCutoverJulianDay(kCutoverJulianDay), fNormalizedGregorianCutover(fGregorianCutover), fGregorianCutoverYear(1582),
240b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                                     fIsGregorian(TRUE), fInvertGregorian(FALSE)
241b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
242b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    set(UCAL_ERA, AD);
243b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    set(UCAL_YEAR, year);
244b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    set(UCAL_MONTH, month);
245b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    set(UCAL_DATE, date);
246b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    set(UCAL_HOUR_OF_DAY, hour);
247b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    set(UCAL_MINUTE, minute);
248b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
249b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
250b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// -------------------------------------
251b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
252b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruGregorianCalendar::GregorianCalendar(int32_t year, int32_t month, int32_t date,
253b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                                     int32_t hour, int32_t minute, int32_t second,
254b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                                     UErrorCode& status)
255b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                                     :   Calendar(TimeZone::createDefault(), Locale::getDefault(), status),
256b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                                     fGregorianCutover(kPapalCutover),
257b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                                     fCutoverJulianDay(kCutoverJulianDay), fNormalizedGregorianCutover(fGregorianCutover), fGregorianCutoverYear(1582),
258b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                                     fIsGregorian(TRUE), fInvertGregorian(FALSE)
259b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
260b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    set(UCAL_ERA, AD);
261b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    set(UCAL_YEAR, year);
262b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    set(UCAL_MONTH, month);
263b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    set(UCAL_DATE, date);
264b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    set(UCAL_HOUR_OF_DAY, hour);
265b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    set(UCAL_MINUTE, minute);
266b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    set(UCAL_SECOND, second);
267b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
268b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
269b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// -------------------------------------
270b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
271b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruGregorianCalendar::~GregorianCalendar()
272b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
273b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
274b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
275b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// -------------------------------------
276b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
277b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruGregorianCalendar::GregorianCalendar(const GregorianCalendar &source)
278b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru:   Calendar(source),
279b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QuerufGregorianCutover(source.fGregorianCutover),
280b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QuerufCutoverJulianDay(source.fCutoverJulianDay), fNormalizedGregorianCutover(source.fNormalizedGregorianCutover), fGregorianCutoverYear(source.fGregorianCutoverYear),
281b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QuerufIsGregorian(source.fIsGregorian), fInvertGregorian(source.fInvertGregorian)
282b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
283b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
284b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
285b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// -------------------------------------
286b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
287b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruCalendar* GregorianCalendar::clone() const
288b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
289b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return new GregorianCalendar(*this);
290b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
291b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
292b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// -------------------------------------
293b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
294b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruGregorianCalendar &
295b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruGregorianCalendar::operator=(const GregorianCalendar &right)
296b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
297b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if (this != &right)
298b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {
299b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        Calendar::operator=(right);
300b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        fGregorianCutover = right.fGregorianCutover;
301b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        fNormalizedGregorianCutover = right.fNormalizedGregorianCutover;
302b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        fGregorianCutoverYear = right.fGregorianCutoverYear;
303b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        fCutoverJulianDay = right.fCutoverJulianDay;
304b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
305b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return *this;
306b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
307b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
308b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// -------------------------------------
309b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
310b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruUBool GregorianCalendar::isEquivalentTo(const Calendar& other) const
311b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
312b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // Calendar override.
313b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return Calendar::isEquivalentTo(other) &&
314b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        fGregorianCutover == ((GregorianCalendar*)&other)->fGregorianCutover;
315b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
316b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
317b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// -------------------------------------
318b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
319b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruvoid
320b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruGregorianCalendar::setGregorianChange(UDate date, UErrorCode& status)
321b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
322b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if (U_FAILURE(status))
323b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        return;
324b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
325b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    fGregorianCutover = date;
326b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
327b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // Precompute two internal variables which we use to do the actual
328b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // cutover computations.  These are the normalized cutover, which is the
329b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // midnight at or before the cutover, and the cutover year.  The
330b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // normalized cutover is in pure date milliseconds; it contains no time
331b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // of day or timezone component, and it used to compare against other
332b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // pure date values.
333b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    int32_t cutoverDay = (int32_t)ClockMath::floorDivide(fGregorianCutover, (double)kOneDay);
334b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    fNormalizedGregorianCutover = cutoverDay * kOneDay;
335b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
336b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // Handle the rare case of numeric overflow.  If the user specifies a
337b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // change of UDate(Long.MIN_VALUE), in order to get a pure Gregorian
338b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // calendar, then the epoch day is -106751991168, which when multiplied
339b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // by ONE_DAY gives 9223372036794351616 -- the negative value is too
340b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // large for 64 bits, and overflows into a positive value.  We correct
341b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // this by using the next day, which for all intents is semantically
342b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // equivalent.
343b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if (cutoverDay < 0 && fNormalizedGregorianCutover > 0) {
344b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        fNormalizedGregorianCutover = (cutoverDay + 1) * kOneDay;
345b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
346b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
347b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // Normalize the year so BC values are represented as 0 and negative
348b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // values.
349b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    GregorianCalendar *cal = new GregorianCalendar(getTimeZone(), status);
350b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    /* test for NULL */
351b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if (cal == 0) {
352b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        status = U_MEMORY_ALLOCATION_ERROR;
353b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        return;
354b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
355b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if(U_FAILURE(status))
356b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        return;
357b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    cal->setTime(date, status);
358b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    fGregorianCutoverYear = cal->get(UCAL_YEAR, status);
359b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if (cal->get(UCAL_ERA, status) == BC)
360b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        fGregorianCutoverYear = 1 - fGregorianCutoverYear;
361b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    fCutoverJulianDay = cutoverDay;
362b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    delete cal;
363b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
364b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
365b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
366b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruvoid GregorianCalendar::handleComputeFields(int32_t julianDay, UErrorCode& status) {
36754dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius    int32_t eyear, month, dayOfMonth, dayOfYear, unusedRemainder;
368b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
369b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
370b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if(U_FAILURE(status)) {
371b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        return;
372b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
373b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
374b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#if defined (U_DEBUG_CAL)
375b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    fprintf(stderr, "%s:%d: jd%d- (greg's %d)- [cut=%d]\n",
376b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        __FILE__, __LINE__, julianDay, getGregorianDayOfYear(), fCutoverJulianDay);
377b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#endif
378b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
379b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
380b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if (julianDay >= fCutoverJulianDay) {
381b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        month = getGregorianMonth();
382b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        dayOfMonth = getGregorianDayOfMonth();
383b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        dayOfYear = getGregorianDayOfYear();
384b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        eyear = getGregorianYear();
385b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    } else {
386b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        // The Julian epoch day (not the same as Julian Day)
387b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        // is zero on Saturday December 30, 0 (Gregorian).
388b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        int32_t julianEpochDay = julianDay - (kJan1_1JulianDay - 2);
38954dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius		eyear = (int32_t) ClockMath::floorDivide((4.0*julianEpochDay) + 1464.0, (int32_t) 1461, unusedRemainder);
390b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
391b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        // Compute the Julian calendar day number for January 1, eyear
392b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        int32_t january1 = 365*(eyear-1) + ClockMath::floorDivide(eyear-1, (int32_t)4);
393b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        dayOfYear = (julianEpochDay - january1); // 0-based
394b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
395b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        // Julian leap years occurred historically every 4 years starting
396b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        // with 8 AD.  Before 8 AD the spacing is irregular; every 3 years
397b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        // from 45 BC to 9 BC, and then none until 8 AD.  However, we don't
398b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        // implement this historical detail; instead, we implement the
399b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        // computatinally cleaner proleptic calendar, which assumes
400b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        // consistent 4-year cycles throughout time.
401b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        UBool isLeap = ((eyear&0x3) == 0); // equiv. to (eyear%4 == 0)
402b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
403b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        // Common Julian/Gregorian calculation
404b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        int32_t correction = 0;
405b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        int32_t march1 = isLeap ? 60 : 59; // zero-based DOY for March 1
406b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        if (dayOfYear >= march1) {
407b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            correction = isLeap ? 1 : 2;
408b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
409b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        month = (12 * (dayOfYear + correction) + 6) / 367; // zero-based month
410b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        dayOfMonth = dayOfYear - (isLeap?kLeapNumDays[month]:kNumDays[month]) + 1; // one-based DOM
411b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        ++dayOfYear;
412b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#if defined (U_DEBUG_CAL)
413b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        //     fprintf(stderr, "%d - %d[%d] + 1\n", dayOfYear, isLeap?kLeapNumDays[month]:kNumDays[month], month );
414b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        //           fprintf(stderr, "%s:%d:  greg's HCF %d -> %d/%d/%d not %d/%d/%d\n",
415b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        //                   __FILE__, __LINE__,julianDay,
416b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        //          eyear,month,dayOfMonth,
417b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        //          getGregorianYear(), getGregorianMonth(), getGregorianDayOfMonth()  );
418b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        fprintf(stderr, "%s:%d: doy %d (greg's %d)- [cut=%d]\n",
419b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            __FILE__, __LINE__, dayOfYear, getGregorianDayOfYear(), fCutoverJulianDay);
420b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#endif
421b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
422b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
423b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
424b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // [j81] if we are after the cutover in its year, shift the day of the year
425b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if((eyear == fGregorianCutoverYear) && (julianDay >= fCutoverJulianDay)) {
426b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        //from handleComputeMonthStart
427b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        int32_t gregShift = Grego::gregorianShift(eyear);
428b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#if defined (U_DEBUG_CAL)
429b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        fprintf(stderr, "%s:%d:  gregorian shift %d :::  doy%d => %d [cut=%d]\n",
430b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            __FILE__, __LINE__,gregShift, dayOfYear, dayOfYear+gregShift, fCutoverJulianDay);
431b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#endif
432b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        dayOfYear += gregShift;
433b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
434b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
435b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    internalSet(UCAL_MONTH, month);
436b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    internalSet(UCAL_DAY_OF_MONTH, dayOfMonth);
437b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    internalSet(UCAL_DAY_OF_YEAR, dayOfYear);
438b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    internalSet(UCAL_EXTENDED_YEAR, eyear);
439b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    int32_t era = AD;
440b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if (eyear < 1) {
441b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        era = BC;
442b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        eyear = 1 - eyear;
443b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
444b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    internalSet(UCAL_ERA, era);
445b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    internalSet(UCAL_YEAR, eyear);
446b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
447b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
448b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
449b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// -------------------------------------
450b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
451b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruUDate
452b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruGregorianCalendar::getGregorianChange() const
453b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
454b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return fGregorianCutover;
455b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
456b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
457b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// -------------------------------------
458b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
459b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruUBool
460b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruGregorianCalendar::isLeapYear(int32_t year) const
461b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
462b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // MSVC complains bitterly if we try to use Grego::isLeapYear here
463b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // NOTE: year&0x3 == year%4
464b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return (year >= fGregorianCutoverYear ?
465b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        (((year&0x3) == 0) && ((year%100 != 0) || (year%400 == 0))) : // Gregorian
466b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    ((year&0x3) == 0)); // Julian
467b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
468b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
469b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// -------------------------------------
470b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
471b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruint32_t GregorianCalendar::handleComputeJulianDay(UCalendarDateFields bestField)
472b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
473b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    fInvertGregorian = FALSE;
474b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
475b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    int32_t jd = Calendar::handleComputeJulianDay(bestField);
476b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
477b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if((bestField == UCAL_WEEK_OF_YEAR) &&  // if we are doing WOY calculations, we are counting relative to Jan 1 *julian*
478b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        (internalGet(UCAL_EXTENDED_YEAR)==fGregorianCutoverYear) &&
479b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        jd >= fCutoverJulianDay) {
480b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            fInvertGregorian = TRUE;  // So that the Julian Jan 1 will be used in handleComputeMonthStart
481b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            return Calendar::handleComputeJulianDay(bestField);
482b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
483b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
484b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
485b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        // The following check handles portions of the cutover year BEFORE the
486b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        // cutover itself happens.
487b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        //if ((fIsGregorian==TRUE) != (jd >= fCutoverJulianDay)) {  /*  cutoverJulianDay)) { */
488b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        if ((fIsGregorian==TRUE) != (jd >= fCutoverJulianDay)) {  /*  cutoverJulianDay)) { */
489b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#if defined (U_DEBUG_CAL)
490b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            fprintf(stderr, "%s:%d: jd [invert] %d\n",
491b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                __FILE__, __LINE__, jd);
492b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#endif
493b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            fInvertGregorian = TRUE;
494b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            jd = Calendar::handleComputeJulianDay(bestField);
495b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#if defined (U_DEBUG_CAL)
496b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            fprintf(stderr, "%s:%d:  fIsGregorian %s, fInvertGregorian %s - ",
497b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                __FILE__, __LINE__,fIsGregorian?"T":"F", fInvertGregorian?"T":"F");
498b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            fprintf(stderr, " jd NOW %d\n",
499b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                jd);
500b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#endif
501b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        } else {
502b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#if defined (U_DEBUG_CAL)
503b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            fprintf(stderr, "%s:%d: jd [==] %d - %sfIsGregorian %sfInvertGregorian, %d\n",
504b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                __FILE__, __LINE__, jd, fIsGregorian?"T":"F", fInvertGregorian?"T":"F", bestField);
505b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#endif
506b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
507b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
508b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        if(fIsGregorian && (internalGet(UCAL_EXTENDED_YEAR) == fGregorianCutoverYear)) {
509b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            int32_t gregShift = Grego::gregorianShift(internalGet(UCAL_EXTENDED_YEAR));
510b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            if (bestField == UCAL_DAY_OF_YEAR) {
511b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#if defined (U_DEBUG_CAL)
512b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                fprintf(stderr, "%s:%d: [DOY%d] gregorian shift of JD %d += %d\n",
513b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    __FILE__, __LINE__, fFields[bestField],jd, gregShift);
514b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#endif
515b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                jd -= gregShift;
516b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            } else if ( bestField == UCAL_WEEK_OF_MONTH ) {
517b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                int32_t weekShift = 14;
518b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#if defined (U_DEBUG_CAL)
519b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                fprintf(stderr, "%s:%d: [WOY/WOM] gregorian week shift of %d += %d\n",
520b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    __FILE__, __LINE__, jd, weekShift);
521b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#endif
522b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                jd += weekShift; // shift by weeks for week based fields.
523b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            }
524b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
525b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
526b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        return jd;
527b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
528b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
529b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruint32_t GregorianCalendar::handleComputeMonthStart(int32_t eyear, int32_t month,
530b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
531b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                                                   UBool /* useMonth */) const
532b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
533b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    GregorianCalendar *nonConstThis = (GregorianCalendar*)this; // cast away const
534b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
535b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // If the month is out of range, adjust it into range, and
536b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // modify the extended year value accordingly.
537b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if (month < 0 || month > 11) {
538b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        eyear += ClockMath::floorDivide(month, 12, month);
539b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
540b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
541b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    UBool isLeap = eyear%4 == 0;
542b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    int32_t y = eyear-1;
543b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    int32_t julianDay = 365*y + ClockMath::floorDivide(y, 4) + (kJan1_1JulianDay - 3);
544b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
545b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    nonConstThis->fIsGregorian = (eyear >= fGregorianCutoverYear);
546b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#if defined (U_DEBUG_CAL)
547b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    fprintf(stderr, "%s:%d: (hcms%d/%d) fIsGregorian %s, fInvertGregorian %s\n",
548b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        __FILE__, __LINE__, eyear,month, fIsGregorian?"T":"F", fInvertGregorian?"T":"F");
549b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#endif
550b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if (fInvertGregorian) {
551b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        nonConstThis->fIsGregorian = !fIsGregorian;
552b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
553b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if (fIsGregorian) {
554b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        isLeap = isLeap && ((eyear%100 != 0) || (eyear%400 == 0));
555b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        // Add 2 because Gregorian calendar starts 2 days after
556b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        // Julian calendar
557b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        int32_t gregShift = Grego::gregorianShift(eyear);
558b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#if defined (U_DEBUG_CAL)
559b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        fprintf(stderr, "%s:%d: (hcms%d/%d) gregorian shift of %d += %d\n",
560b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            __FILE__, __LINE__, eyear, month, julianDay, gregShift);
561b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#endif
562b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        julianDay += gregShift;
563b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
564b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
565b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // At this point julianDay indicates the day BEFORE the first
566b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // day of January 1, <eyear> of either the Julian or Gregorian
567b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // calendar.
568b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
569b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if (month != 0) {
570b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        julianDay += isLeap?kLeapNumDays[month]:kNumDays[month];
571b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
572b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
573b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return julianDay;
574b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
575b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
576b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruint32_t GregorianCalendar::handleGetMonthLength(int32_t extendedYear, int32_t month)  const
577b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
578b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // If the month is out of range, adjust it into range, and
579b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // modify the extended year value accordingly.
580b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if (month < 0 || month > 11) {
581b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        extendedYear += ClockMath::floorDivide(month, 12, month);
582b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
583b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
584b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return isLeapYear(extendedYear) ? kLeapMonthLength[month] : kMonthLength[month];
585b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
586b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
587b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruint32_t GregorianCalendar::handleGetYearLength(int32_t eyear) const {
588b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return isLeapYear(eyear) ? 366 : 365;
589b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
590b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
591b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
592b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruint32_t
593b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruGregorianCalendar::monthLength(int32_t month) const
594b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
595b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    int32_t year = internalGet(UCAL_EXTENDED_YEAR);
596b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return handleGetMonthLength(year, month);
597b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
598b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
599b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// -------------------------------------
600b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
601b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruint32_t
602b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruGregorianCalendar::monthLength(int32_t month, int32_t year) const
603b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
604b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return isLeapYear(year) ? kLeapMonthLength[month] : kMonthLength[month];
605b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
606b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
607b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// -------------------------------------
608b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
609b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruint32_t
610b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruGregorianCalendar::yearLength(int32_t year) const
611b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
612b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return isLeapYear(year) ? 366 : 365;
613b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
614b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
615b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// -------------------------------------
616b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
617b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruint32_t
618b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruGregorianCalendar::yearLength() const
619b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
620b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return isLeapYear(internalGet(UCAL_YEAR)) ? 366 : 365;
621b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
622b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
623b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// -------------------------------------
624b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
625b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru/**
626b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru* After adjustments such as add(MONTH), add(YEAR), we don't want the
627b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru* month to jump around.  E.g., we don't want Jan 31 + 1 month to go to Mar
628b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru* 3, we want it to go to Feb 28.  Adjustments which might run into this
629b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru* problem call this method to retain the proper month.
630b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru*/
631b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruvoid
632b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruGregorianCalendar::pinDayOfMonth()
633b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
634b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    int32_t monthLen = monthLength(internalGet(UCAL_MONTH));
635b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    int32_t dom = internalGet(UCAL_DATE);
636b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if(dom > monthLen)
637b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        set(UCAL_DATE, monthLen);
638b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
639b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
640b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// -------------------------------------
641b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
642b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
643b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruUBool
644b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruGregorianCalendar::validateFields() const
645b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
646b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    for (int32_t field = 0; field < UCAL_FIELD_COUNT; field++) {
647b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        // Ignore DATE and DAY_OF_YEAR which are handled below
648b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        if (field != UCAL_DATE &&
649b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            field != UCAL_DAY_OF_YEAR &&
650b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            isSet((UCalendarDateFields)field) &&
651b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            ! boundsCheck(internalGet((UCalendarDateFields)field), (UCalendarDateFields)field))
652b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            return FALSE;
653b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
654b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
655b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // Values differ in Least-Maximum and Maximum should be handled
656b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // specially.
657b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if (isSet(UCAL_DATE)) {
658b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        int32_t date = internalGet(UCAL_DATE);
659b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        if (date < getMinimum(UCAL_DATE) ||
660b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            date > monthLength(internalGet(UCAL_MONTH))) {
661b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                return FALSE;
662b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            }
663b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
664b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
665b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if (isSet(UCAL_DAY_OF_YEAR)) {
666b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        int32_t days = internalGet(UCAL_DAY_OF_YEAR);
667b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        if (days < 1 || days > yearLength()) {
668b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            return FALSE;
669b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
670b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
671b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
672b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // Handle DAY_OF_WEEK_IN_MONTH, which must not have the value zero.
673b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // We've checked against minimum and maximum above already.
674b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if (isSet(UCAL_DAY_OF_WEEK_IN_MONTH) &&
675b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        0 == internalGet(UCAL_DAY_OF_WEEK_IN_MONTH)) {
676b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            return FALSE;
677b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
678b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
679b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        return TRUE;
680b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
681b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
682b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// -------------------------------------
683b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
684b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruUBool
685b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruGregorianCalendar::boundsCheck(int32_t value, UCalendarDateFields field) const
686b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
687b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return value >= getMinimum(field) && value <= getMaximum(field);
688b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
689b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
690b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// -------------------------------------
691b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
692b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruUDate
693b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruGregorianCalendar::getEpochDay(UErrorCode& status)
694b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
695b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    complete(status);
696b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // Divide by 1000 (convert to seconds) in order to prevent overflow when
697b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // dealing with UDate(Long.MIN_VALUE) and UDate(Long.MAX_VALUE).
698b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    double wallSec = internalGetTime()/1000 + (internalGet(UCAL_ZONE_OFFSET) + internalGet(UCAL_DST_OFFSET))/1000;
699b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
700b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    return ClockMath::floorDivide(wallSec, kOneDay/1000.0);
701b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
702b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
703b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// -------------------------------------
704b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
705b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
706b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// -------------------------------------
707b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
708b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru/**
709b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru* Compute the julian day number of the day BEFORE the first day of
710b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru* January 1, year 1 of the given calendar.  If julianDay == 0, it
711b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru* specifies (Jan. 1, 1) - 1, in whatever calendar we are using (Julian
712b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru* or Gregorian).
713b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru*/
714b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querudouble GregorianCalendar::computeJulianDayOfYear(UBool isGregorian,
715b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                                                 int32_t year, UBool& isLeap)
716b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
717b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    isLeap = year%4 == 0;
718b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    int32_t y = year - 1;
719b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    double julianDay = 365.0*y + ClockMath::floorDivide(y, 4) + (kJan1_1JulianDay - 3);
720b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
721b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if (isGregorian) {
722b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        isLeap = isLeap && ((year%100 != 0) || (year%400 == 0));
723b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        // Add 2 because Gregorian calendar starts 2 days after Julian calendar
724b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        julianDay += Grego::gregorianShift(year);
725b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
726b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
727b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return julianDay;
728b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
729b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
730b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// /**
731b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru//  * Compute the day of week, relative to the first day of week, from
732b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru//  * 0..6, of the current DOW_LOCAL or DAY_OF_WEEK fields.  This is
733b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru//  * equivalent to get(DOW_LOCAL) - 1.
734b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru//  */
735b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// int32_t GregorianCalendar::computeRelativeDOW() const {
736b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru//     int32_t relDow = 0;
737b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru//     if (fStamp[UCAL_DOW_LOCAL] > fStamp[UCAL_DAY_OF_WEEK]) {
738b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru//         relDow = internalGet(UCAL_DOW_LOCAL) - 1; // 1-based
739b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru//     } else if (fStamp[UCAL_DAY_OF_WEEK] != kUnset) {
740b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru//         relDow = internalGet(UCAL_DAY_OF_WEEK) - getFirstDayOfWeek();
741b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru//         if (relDow < 0) relDow += 7;
742b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru//     }
743b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru//     return relDow;
744b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// }
745b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
746b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// /**
747b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru//  * Compute the day of week, relative to the first day of week,
748b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru//  * from 0..6 of the given julian day.
749b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru//  */
750b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// int32_t GregorianCalendar::computeRelativeDOW(double julianDay) const {
751b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru//   int32_t relDow = julianDayToDayOfWeek(julianDay) - getFirstDayOfWeek();
752b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru//     if (relDow < 0) {
753b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru//         relDow += 7;
754b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru//     }
755b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru//     return relDow;
756b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// }
757b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
758b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// /**
759b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru//  * Compute the DOY using the WEEK_OF_YEAR field and the julian day
760b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru//  * of the day BEFORE January 1 of a year (a return value from
761b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru//  * computeJulianDayOfYear).
762b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru//  */
763b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// int32_t GregorianCalendar::computeDOYfromWOY(double julianDayOfYear) const {
764b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru//     // Compute DOY from day of week plus week of year
765b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
766b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru//     // Find the day of the week for the first of this year.  This
767b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru//     // is zero-based, with 0 being the locale-specific first day of
768b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru//     // the week.  Add 1 to get first day of year.
769b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru//     int32_t fdy = computeRelativeDOW(julianDayOfYear + 1);
770b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
771b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru//     return
772b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru//         // Compute doy of first (relative) DOW of WOY 1
773b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru//         (((7 - fdy) < getMinimalDaysInFirstWeek())
774b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru//          ? (8 - fdy) : (1 - fdy))
775b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
776b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru//         // Adjust for the week number.
777b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru//         + (7 * (internalGet(UCAL_WEEK_OF_YEAR) - 1))
778b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
779b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru//         // Adjust for the DOW
780b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru//         + computeRelativeDOW();
781b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// }
782b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
783b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// -------------------------------------
784b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
785b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querudouble
786b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruGregorianCalendar::millisToJulianDay(UDate millis)
787b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
788b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    return (double)kEpochStartAsJulianDay + ClockMath::floorDivide(millis, (double)kOneDay);
789b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
790b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
791b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// -------------------------------------
792b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
793b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruUDate
794b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruGregorianCalendar::julianDayToMillis(double julian)
795b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
796b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return (UDate) ((julian - kEpochStartAsJulianDay) * (double) kOneDay);
797b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
798b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
799b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// -------------------------------------
800b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
801b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruint32_t
802b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruGregorianCalendar::aggregateStamp(int32_t stamp_a, int32_t stamp_b)
803b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
804b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return (((stamp_a != kUnset && stamp_b != kUnset)
805b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        ? uprv_max(stamp_a, stamp_b)
806b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        : (int32_t)kUnset));
807b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
808b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
809b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// -------------------------------------
810b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
811b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru/**
812b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru* Roll a field by a signed amount.
813b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru* Note: This will be made public later. [LIU]
814b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru*/
815b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
816b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruvoid
817b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruGregorianCalendar::roll(EDateFields field, int32_t amount, UErrorCode& status) {
818b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    roll((UCalendarDateFields) field, amount, status);
819b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
820b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
821b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruvoid
822b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruGregorianCalendar::roll(UCalendarDateFields field, int32_t amount, UErrorCode& status)
823b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
824b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if((amount == 0) || U_FAILURE(status)) {
825b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        return;
826b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
827b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
828b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // J81 processing. (gregorian cutover)
829b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    UBool inCutoverMonth = FALSE;
830b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    int32_t cMonthLen=0; // 'c' for cutover; in days
831b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    int32_t cDayOfMonth=0; // no discontinuity: [0, cMonthLen)
832b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    double cMonthStart=0.0; // in ms
833b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
834b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // Common code - see if we're in the cutover month of the cutover year
835b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if(get(UCAL_EXTENDED_YEAR, status) == fGregorianCutoverYear) {
836b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        switch (field) {
837b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        case UCAL_DAY_OF_MONTH:
838b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        case UCAL_WEEK_OF_MONTH:
839b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            {
840b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                int32_t max = monthLength(internalGet(UCAL_MONTH));
841b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                UDate t = internalGetTime();
842b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                // We subtract 1 from the DAY_OF_MONTH to make it zero-based, and an
843b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                // additional 10 if we are after the cutover. Thus the monthStart
844b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                // value will be correct iff we actually are in the cutover month.
845b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                cDayOfMonth = internalGet(UCAL_DAY_OF_MONTH) - ((t >= fGregorianCutover) ? 10 : 0);
846b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                cMonthStart = t - ((cDayOfMonth - 1) * kOneDay);
847b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                // A month containing the cutover is 10 days shorter.
848b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                if ((cMonthStart < fGregorianCutover) &&
849b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    (cMonthStart + (cMonthLen=(max-10))*kOneDay >= fGregorianCutover)) {
850b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                        inCutoverMonth = TRUE;
851b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    }
852b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            }
853b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        default:
854b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            ;
855b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
856b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
857b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
858b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    switch (field) {
859b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    case UCAL_WEEK_OF_YEAR: {
860b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        // Unlike WEEK_OF_MONTH, WEEK_OF_YEAR never shifts the day of the
861b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        // week.  Also, rolling the week of the year can have seemingly
862b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        // strange effects simply because the year of the week of year
863b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        // may be different from the calendar year.  For example, the
864b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        // date Dec 28, 1997 is the first day of week 1 of 1998 (if
865b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        // weeks start on Sunday and the minimal days in first week is
866b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        // <= 3).
867b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        int32_t woy = get(UCAL_WEEK_OF_YEAR, status);
868b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        // Get the ISO year, which matches the week of year.  This
869b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        // may be one year before or after the calendar year.
870b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        int32_t isoYear = get(UCAL_YEAR_WOY, status);
871b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        int32_t isoDoy = internalGet(UCAL_DAY_OF_YEAR);
872b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        if (internalGet(UCAL_MONTH) == UCAL_JANUARY) {
873b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            if (woy >= 52) {
874b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                isoDoy += handleGetYearLength(isoYear);
875b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            }
876b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        } else {
877b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            if (woy == 1) {
878b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                isoDoy -= handleGetYearLength(isoYear - 1);
879b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            }
880b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
881b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        woy += amount;
882b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        // Do fast checks to avoid unnecessary computation:
883b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        if (woy < 1 || woy > 52) {
884b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            // Determine the last week of the ISO year.
885b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            // We do this using the standard formula we use
886b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            // everywhere in this file.  If we can see that the
887b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            // days at the end of the year are going to fall into
888b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            // week 1 of the next year, we drop the last week by
889b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            // subtracting 7 from the last day of the year.
890b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            int32_t lastDoy = handleGetYearLength(isoYear);
891b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            int32_t lastRelDow = (lastDoy - isoDoy + internalGet(UCAL_DAY_OF_WEEK) -
892b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                getFirstDayOfWeek()) % 7;
893b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            if (lastRelDow < 0) lastRelDow += 7;
894b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            if ((6 - lastRelDow) >= getMinimalDaysInFirstWeek()) lastDoy -= 7;
895b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            int32_t lastWoy = weekNumber(lastDoy, lastRelDow + 1);
896b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            woy = ((woy + lastWoy - 1) % lastWoy) + 1;
897b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
898b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        set(UCAL_WEEK_OF_YEAR, woy);
899b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        set(UCAL_YEAR_WOY,isoYear);
900b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        return;
901b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                            }
902b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
903b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    case UCAL_DAY_OF_MONTH:
904b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        if( !inCutoverMonth ) {
905b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            Calendar::roll(field, amount, status);
906b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            return;
907b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        } else {
908b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            // [j81] 1582 special case for DOM
909b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            // The default computation works except when the current month
910b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            // contains the Gregorian cutover.  We handle this special case
911b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            // here.  [j81 - aliu]
912b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            double monthLen = cMonthLen * kOneDay;
913b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            double msIntoMonth = uprv_fmod(internalGetTime() - cMonthStart +
914b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                amount * kOneDay, monthLen);
915b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            if (msIntoMonth < 0) {
916b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                msIntoMonth += monthLen;
917b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            }
918b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#if defined (U_DEBUG_CAL)
919b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            fprintf(stderr, "%s:%d: roll DOM %d  -> %.0lf ms  \n",
920b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                __FILE__, __LINE__,amount, cMonthLen, cMonthStart+msIntoMonth);
921b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#endif
922b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            setTimeInMillis(cMonthStart + msIntoMonth, status);
923b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            return;
924b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
925b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
926b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    case UCAL_WEEK_OF_MONTH:
927b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        if( !inCutoverMonth ) {
928b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            Calendar::roll(field, amount, status);
929b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            return;
930b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        } else {
931b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#if defined (U_DEBUG_CAL)
932b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            fprintf(stderr, "%s:%d: roll WOM %d ??????????????????? \n",
933b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                __FILE__, __LINE__,amount);
934b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#endif
935b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            // NOTE: following copied from  the old
936b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            //     GregorianCalendar::roll( WEEK_OF_MONTH )  code
937b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
938b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            // This is tricky, because during the roll we may have to shift
939b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            // to a different day of the week.  For example:
940b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
941b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            //    s  m  t  w  r  f  s
942b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            //          1  2  3  4  5
943b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            //    6  7  8  9 10 11 12
944b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
945b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            // When rolling from the 6th or 7th back one week, we go to the
946b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            // 1st (assuming that the first partial week counts).  The same
947b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            // thing happens at the end of the month.
948b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
949b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            // The other tricky thing is that we have to figure out whether
950b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            // the first partial week actually counts or not, based on the
951b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            // minimal first days in the week.  And we have to use the
952b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            // correct first day of the week to delineate the week
953b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            // boundaries.
954b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
955b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            // Here's our algorithm.  First, we find the real boundaries of
956b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            // the month.  Then we discard the first partial week if it
957b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            // doesn't count in this locale.  Then we fill in the ends with
958b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            // phantom days, so that the first partial week and the last
959b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            // partial week are full weeks.  We then have a nice square
960b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            // block of weeks.  We do the usual rolling within this block,
961b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            // as is done elsewhere in this method.  If we wind up on one of
962b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            // the phantom days that we added, we recognize this and pin to
963b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            // the first or the last day of the month.  Easy, eh?
964b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
965b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            // Another wrinkle: To fix jitterbug 81, we have to make all this
966b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            // work in the oddball month containing the Gregorian cutover.
967b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            // This month is 10 days shorter than usual, and also contains
968b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            // a discontinuity in the days; e.g., the default cutover month
969b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            // is Oct 1582, and goes from day of month 4 to day of month 15.
970b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
971b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            // Normalize the DAY_OF_WEEK so that 0 is the first day of the week
972b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            // in this locale.  We have dow in 0..6.
973b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            int32_t dow = internalGet(UCAL_DAY_OF_WEEK) - getFirstDayOfWeek();
974b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            if (dow < 0)
975b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                dow += 7;
976b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
977b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            // Find the day of month, compensating for cutover discontinuity.
978b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            int32_t dom = cDayOfMonth;
979b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
980b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            // Find the day of the week (normalized for locale) for the first
981b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            // of the month.
982b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            int32_t fdm = (dow - dom + 1) % 7;
983b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            if (fdm < 0)
984b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                fdm += 7;
985b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
986b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            // Get the first day of the first full week of the month,
987b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            // including phantom days, if any.  Figure out if the first week
988b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            // counts or not; if it counts, then fill in phantom days.  If
989b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            // not, advance to the first real full week (skip the partial week).
990b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            int32_t start;
991b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            if ((7 - fdm) < getMinimalDaysInFirstWeek())
992b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                start = 8 - fdm; // Skip the first partial week
993b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            else
994b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                start = 1 - fdm; // This may be zero or negative
995b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
996b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            // Get the day of the week (normalized for locale) for the last
997b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            // day of the month.
998b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            int32_t monthLen = cMonthLen;
999b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            int32_t ldm = (monthLen - dom + dow) % 7;
1000b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            // We know monthLen >= DAY_OF_MONTH so we skip the += 7 step here.
1001b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1002b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            // Get the limit day for the blocked-off rectangular month; that
1003b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            // is, the day which is one past the last day of the month,
1004b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            // after the month has already been filled in with phantom days
1005b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            // to fill out the last week.  This day has a normalized DOW of 0.
1006b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            int32_t limit = monthLen + 7 - ldm;
1007b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1008b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            // Now roll between start and (limit - 1).
1009b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            int32_t gap = limit - start;
1010b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            int32_t newDom = (dom + amount*7 - start) % gap;
1011b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            if (newDom < 0)
1012b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                newDom += gap;
1013b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            newDom += start;
1014b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1015b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            // Finally, pin to the real start and end of the month.
1016b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            if (newDom < 1)
1017b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                newDom = 1;
1018b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            if (newDom > monthLen)
1019b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                newDom = monthLen;
1020b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1021b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            // Set the DAY_OF_MONTH.  We rely on the fact that this field
1022b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            // takes precedence over everything else (since all other fields
1023b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            // are also set at this point).  If this fact changes (if the
1024b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            // disambiguation algorithm changes) then we will have to unset
1025b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            // the appropriate fields here so that DAY_OF_MONTH is attended
1026b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            // to.
1027b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1028b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            // If we are in the cutover month, manipulate ms directly.  Don't do
1029b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            // this in general because it doesn't work across DST boundaries
1030b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            // (details, details).  This takes care of the discontinuity.
1031b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            setTimeInMillis(cMonthStart + (newDom-1)*kOneDay, status);
1032b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            return;
1033b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
1034b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1035b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    default:
1036b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        Calendar::roll(field, amount, status);
1037b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        return;
1038b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
1039b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
1040b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1041b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// -------------------------------------
1042b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1043b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1044b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru/**
1045b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru* Return the minimum value that this field could have, given the current date.
1046b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru* For the Gregorian calendar, this is the same as getMinimum() and getGreatestMinimum().
1047b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru* @param field    the time field.
1048b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru* @return         the minimum value that this field could have, given the current date.
1049b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru* @deprecated ICU 2.6. Use getActualMinimum(UCalendarDateFields field) instead.
1050b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru*/
1051b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruint32_t GregorianCalendar::getActualMinimum(EDateFields field) const
1052b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
1053b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return getMinimum((UCalendarDateFields)field);
1054b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
1055b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1056b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruint32_t GregorianCalendar::getActualMinimum(EDateFields field, UErrorCode& /* status */) const
1057b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
1058b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return getMinimum((UCalendarDateFields)field);
1059b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
1060b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1061b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru/**
1062b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru* Return the minimum value that this field could have, given the current date.
1063b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru* For the Gregorian calendar, this is the same as getMinimum() and getGreatestMinimum().
1064b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru* @param field    the time field.
1065b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru* @return         the minimum value that this field could have, given the current date.
1066b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru* @draft ICU 2.6.
1067b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru*/
1068b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruint32_t GregorianCalendar::getActualMinimum(UCalendarDateFields field, UErrorCode& /* status */) const
1069b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
1070b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return getMinimum(field);
1071b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
1072b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1073b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1074b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// ------------------------------------
1075b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1076b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru/**
1077b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru* Old year limits were least max 292269054, max 292278994.
1078b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru*/
1079b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1080b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru/**
1081b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru* @stable ICU 2.0
1082b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru*/
1083b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruint32_t GregorianCalendar::handleGetLimit(UCalendarDateFields field, ELimitType limitType) const {
1084b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return kGregorianCalendarLimits[field][limitType];
1085b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
1086b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1087b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru/**
1088b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru* Return the maximum value that this field could have, given the current date.
1089b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru* For example, with the date "Feb 3, 1997" and the DAY_OF_MONTH field, the actual
1090b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru* maximum would be 28; for "Feb 3, 1996" it s 29.  Similarly for a Hebrew calendar,
1091b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru* for some years the actual maximum for MONTH is 12, and for others 13.
1092b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru* @stable ICU 2.0
1093b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru*/
1094b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruint32_t GregorianCalendar::getActualMaximum(UCalendarDateFields field, UErrorCode& status) const
1095b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
1096b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    /* It is a known limitation that the code here (and in getActualMinimum)
1097b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    * won't behave properly at the extreme limits of GregorianCalendar's
1098b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    * representable range (except for the code that handles the YEAR
1099b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    * field).  That's because the ends of the representable range are at
1100b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    * odd spots in the year.  For calendars with the default Gregorian
1101b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    * cutover, these limits are Sun Dec 02 16:47:04 GMT 292269055 BC to Sun
1102b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    * Aug 17 07:12:55 GMT 292278994 AD, somewhat different for non-GMT
1103b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    * zones.  As a result, if the calendar is set to Aug 1 292278994 AD,
1104b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    * the actual maximum of DAY_OF_MONTH is 17, not 30.  If the date is Mar
1105b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    * 31 in that year, the actual maximum month might be Jul, whereas is
1106b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    * the date is Mar 15, the actual maximum might be Aug -- depending on
1107b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    * the precise semantics that are desired.  Similar considerations
1108b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    * affect all fields.  Nonetheless, this effect is sufficiently arcane
1109b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    * that we permit it, rather than complicating the code to handle such
1110b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    * intricacies. - liu 8/20/98
1111b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1112b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    * UPDATE: No longer true, since we have pulled in the limit values on
1113b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    * the year. - Liu 11/6/00 */
1114b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1115b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    switch (field) {
1116b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1117b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    case UCAL_YEAR:
1118b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        /* The year computation is no different, in principle, from the
1119b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        * others, however, the range of possible maxima is large.  In
1120b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        * addition, the way we know we've exceeded the range is different.
1121b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        * For these reasons, we use the special case code below to handle
1122b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        * this field.
1123b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        *
1124b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        * The actual maxima for YEAR depend on the type of calendar:
1125b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        *
1126b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        *     Gregorian = May 17, 292275056 BC - Aug 17, 292278994 AD
1127b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        *     Julian    = Dec  2, 292269055 BC - Jan  3, 292272993 AD
1128b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        *     Hybrid    = Dec  2, 292269055 BC - Aug 17, 292278994 AD
1129b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        *
1130b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        * We know we've exceeded the maximum when either the month, date,
1131b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        * time, or era changes in response to setting the year.  We don't
1132b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        * check for month, date, and time here because the year and era are
1133b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        * sufficient to detect an invalid year setting.  NOTE: If code is
1134b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        * added to check the month and date in the future for some reason,
1135b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        * Feb 29 must be allowed to shift to Mar 1 when setting the year.
1136b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        */
1137b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        {
1138b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            if(U_FAILURE(status)) return 0;
1139b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            Calendar *cal = clone();
1140b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            if(!cal) {
1141b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                status = U_MEMORY_ALLOCATION_ERROR;
1142b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                return 0;
1143b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            }
1144b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1145b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            cal->setLenient(TRUE);
1146b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1147b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            int32_t era = cal->get(UCAL_ERA, status);
1148b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            UDate d = cal->getTime(status);
1149b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1150b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            /* Perform a binary search, with the invariant that lowGood is a
1151b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            * valid year, and highBad is an out of range year.
1152b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            */
1153b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            int32_t lowGood = kGregorianCalendarLimits[UCAL_YEAR][1];
1154b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            int32_t highBad = kGregorianCalendarLimits[UCAL_YEAR][2]+1;
1155b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            while ((lowGood + 1) < highBad) {
1156b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                int32_t y = (lowGood + highBad) / 2;
1157b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                cal->set(UCAL_YEAR, y);
1158b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                if (cal->get(UCAL_YEAR, status) == y && cal->get(UCAL_ERA, status) == era) {
1159b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    lowGood = y;
1160b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                } else {
1161b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    highBad = y;
1162b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    cal->setTime(d, status); // Restore original fields
1163b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                }
1164b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            }
1165b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1166b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            delete cal;
1167b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            return lowGood;
1168b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
1169b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1170b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    default:
1171b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        return Calendar::getActualMaximum(field,status);
1172b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
1173b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
1174b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1175b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1176b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruint32_t GregorianCalendar::handleGetExtendedYear() {
117750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    // the year to return
1178b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    int32_t year = kEpochYear;
117950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho
118050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    // year field to use
118150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    int32_t yearField = UCAL_EXTENDED_YEAR;
118250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho
118350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    // There are three separate fields which could be used to
118450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    // derive the proper year.  Use the one most recently set.
118550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    if (fStamp[yearField] < fStamp[UCAL_YEAR])
118650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho        yearField = UCAL_YEAR;
118750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    if (fStamp[yearField] < fStamp[UCAL_YEAR_WOY])
118850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho        yearField = UCAL_YEAR_WOY;
118950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho
119050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    // based on the "best" year field, get the year
119150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    switch(yearField) {
1192b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    case UCAL_EXTENDED_YEAR:
1193b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        year = internalGet(UCAL_EXTENDED_YEAR, kEpochYear);
1194b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        break;
1195b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1196b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    case UCAL_YEAR:
1197b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        {
1198b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            // The year defaults to the epoch start, the era to AD
1199b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            int32_t era = internalGet(UCAL_ERA, AD);
1200b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            if (era == BC) {
1201b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                year = 1 - internalGet(UCAL_YEAR, 1); // Convert to extended year
1202b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            } else {
1203b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                year = internalGet(UCAL_YEAR, kEpochYear);
1204b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            }
1205b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
1206b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        break;
1207b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1208b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    case UCAL_YEAR_WOY:
1209b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        year = handleGetExtendedYearFromWeekFields(internalGet(UCAL_YEAR_WOY), internalGet(UCAL_WEEK_OF_YEAR));
1210b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#if defined (U_DEBUG_CAL)
1211b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        //    if(internalGet(UCAL_YEAR_WOY) != year) {
1212b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        fprintf(stderr, "%s:%d: hGEYFWF[%d,%d] ->  %d\n",
1213b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            __FILE__, __LINE__,internalGet(UCAL_YEAR_WOY),internalGet(UCAL_WEEK_OF_YEAR),year);
1214b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        //}
1215b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#endif
1216b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        break;
1217b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1218b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    default:
1219b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        year = kEpochYear;
1220b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
1221b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return year;
1222b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
1223b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1224b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruint32_t GregorianCalendar::handleGetExtendedYearFromWeekFields(int32_t yearWoy, int32_t woy)
1225b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
1226b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // convert year to extended form
1227b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    int32_t era = internalGet(UCAL_ERA, AD);
1228b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if(era == BC) {
1229b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        yearWoy = 1 - yearWoy;
1230b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
1231b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return Calendar::handleGetExtendedYearFromWeekFields(yearWoy, woy);
1232b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
1233b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1234b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1235b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// -------------------------------------
1236b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1237b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruUBool
1238b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruGregorianCalendar::inDaylightTime(UErrorCode& status) const
1239b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
1240b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if (U_FAILURE(status) || !getTimeZone().useDaylightTime())
1241b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        return FALSE;
1242b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1243b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // Force an update of the state of the Calendar.
1244b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    ((GregorianCalendar*)this)->complete(status); // cast away const
1245b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1246b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return (UBool)(U_SUCCESS(status) ? (internalGet(UCAL_DST_OFFSET) != 0) : FALSE);
1247b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
1248b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1249b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// -------------------------------------
1250b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1251b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru/**
1252b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru* Return the ERA.  We need a special method for this because the
1253b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru* default ERA is AD, but a zero (unset) ERA is BC.
1254b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru*/
1255b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruint32_t
1256b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruGregorianCalendar::internalGetEra() const {
1257b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return isSet(UCAL_ERA) ? internalGet(UCAL_ERA) : (int32_t)AD;
1258b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
1259b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1260b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruconst char *
1261b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruGregorianCalendar::getType() const {
1262b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    //static const char kGregorianType = "gregorian";
1263b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1264b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return "gregorian";
1265b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
1266b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
126759d709d503bab6e2b61931737e662dd293b40578ccornelius/**
126859d709d503bab6e2b61931737e662dd293b40578ccornelius * The system maintains a static default century start date and Year.  They are
126959d709d503bab6e2b61931737e662dd293b40578ccornelius * initialized the first time they are used.  Once the system default century date
127059d709d503bab6e2b61931737e662dd293b40578ccornelius * and year are set, they do not change.
127159d709d503bab6e2b61931737e662dd293b40578ccornelius */
127259d709d503bab6e2b61931737e662dd293b40578ccorneliusstatic UDate           gSystemDefaultCenturyStart       = DBL_MIN;
127359d709d503bab6e2b61931737e662dd293b40578ccorneliusstatic int32_t         gSystemDefaultCenturyStartYear   = -1;
127459d709d503bab6e2b61931737e662dd293b40578ccorneliusstatic icu::UInitOnce  gSystemDefaultCenturyInit        = U_INITONCE_INITIALIZER;
1275b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1276b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1277b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruUBool GregorianCalendar::haveDefaultCentury() const
1278b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
1279b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return TRUE;
1280b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
1281b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
128259d709d503bab6e2b61931737e662dd293b40578ccorneliusstatic void U_CALLCONV
128359d709d503bab6e2b61931737e662dd293b40578ccorneliusinitializeSystemDefaultCentury()
1284b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
1285b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // initialize systemDefaultCentury and systemDefaultCenturyYear based
1286b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // on the current time.  They'll be set to 80 years before
1287b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // the current time.
1288b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    UErrorCode status = U_ZERO_ERROR;
128959d709d503bab6e2b61931737e662dd293b40578ccornelius    GregorianCalendar calendar(status);
129059d709d503bab6e2b61931737e662dd293b40578ccornelius    if (U_SUCCESS(status)) {
129159d709d503bab6e2b61931737e662dd293b40578ccornelius        calendar.setTime(Calendar::getNow(), status);
129259d709d503bab6e2b61931737e662dd293b40578ccornelius        calendar.add(UCAL_YEAR, -80, status);
1293b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
129459d709d503bab6e2b61931737e662dd293b40578ccornelius        gSystemDefaultCenturyStart = calendar.getTime(status);
129559d709d503bab6e2b61931737e662dd293b40578ccornelius        gSystemDefaultCenturyStartYear = calendar.get(UCAL_YEAR, status);
1296b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
1297b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    // We have no recourse upon failure unless we want to propagate the failure
1298b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    // out.
1299b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
1300b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
130159d709d503bab6e2b61931737e662dd293b40578ccorneliusUDate GregorianCalendar::defaultCenturyStart() const {
130259d709d503bab6e2b61931737e662dd293b40578ccornelius    // lazy-evaluate systemDefaultCenturyStart
130359d709d503bab6e2b61931737e662dd293b40578ccornelius    umtx_initOnce(gSystemDefaultCenturyInit, &initializeSystemDefaultCentury);
130459d709d503bab6e2b61931737e662dd293b40578ccornelius    return gSystemDefaultCenturyStart;
130559d709d503bab6e2b61931737e662dd293b40578ccornelius}
130659d709d503bab6e2b61931737e662dd293b40578ccornelius
130759d709d503bab6e2b61931737e662dd293b40578ccorneliusint32_t GregorianCalendar::defaultCenturyStartYear() const {
130859d709d503bab6e2b61931737e662dd293b40578ccornelius    // lazy-evaluate systemDefaultCenturyStartYear
130959d709d503bab6e2b61931737e662dd293b40578ccornelius    umtx_initOnce(gSystemDefaultCenturyInit, &initializeSystemDefaultCentury);
131059d709d503bab6e2b61931737e662dd293b40578ccornelius    return gSystemDefaultCenturyStartYear;
131159d709d503bab6e2b61931737e662dd293b40578ccornelius}
1312b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1313b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruU_NAMESPACE_END
1314b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1315b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#endif /* #if !UCONFIG_NO_FORMATTING */
1316b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1317b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru//eof
1318