~ubuntu-branches/ubuntu/gutsy/icu/gutsy-updates

« back to all changes in this revision

Viewing changes to source/i18n/gregocal.cpp

  • Committer: Package Import Robot
  • Author(s): Jay Berkenbilt
  • Date: 2005-11-19 11:29:31 UTC
  • mfrom: (1.1.2)
  • Revision ID: package-import@ubuntu.com-20051119112931-vcizkrp10tli4enw
Tags: 3.4-3
Explicitly build with g++ 3.4.  The current ICU fails its test suite
with 4.0 but not with 3.4.  Future versions should work properly with
4.0.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/*
2
 
*******************************************************************************
3
 
* Copyright (C) 1997-1999, International Business Machines Corporation and    *
4
 
* others. All Rights Reserved.                                                *
5
 
*******************************************************************************
6
 
*
7
 
* File GREGOCAL.CPP
8
 
*
9
 
* Modification History:
10
 
*
11
 
*   Date        Name        Description
12
 
*   02/05/97    clhuang     Creation.
13
 
*   03/28/97    aliu        Made highly questionable fix to computeFields to
14
 
*                           handle DST correctly.
15
 
*   04/22/97    aliu        Cleaned up code drastically.  Added monthLength().
16
 
*                           Finished unimplemented parts of computeTime() for
17
 
*                           week-based date determination.  Removed quetionable
18
 
*                           fix and wrote correct fix for computeFields() and
19
 
*                           daylight time handling.  Rewrote inDaylightTime()
20
 
*                           and computeFields() to handle sensitive Daylight to
21
 
*                           Standard time transitions correctly.
22
 
*   05/08/97    aliu        Added code review changes.  Fixed isLeapYear() to
23
 
*                           not cutover.
24
 
*   08/12/97    aliu        Added equivalentTo.  Misc other fixes.  Updated
25
 
*                           add() from Java source.
26
 
*    07/28/98    stephen        Sync up with JDK 1.2
27
 
*    09/14/98    stephen        Changed type of kOneDay, kOneWeek to double.
28
 
*                            Fixed bug in roll() 
29
 
*   10/15/99    aliu        Fixed j31, incorrect WEEK_OF_YEAR computation.
30
 
*   10/15/99    aliu        Fixed j32, cannot set date to Feb 29 2000 AD.
31
 
*                           {JDK bug 4210209 4209272}
32
 
*   11/15/99    weiv        Added YEAR_WOY and DOW_LOCAL computation
33
 
*                           to timeToFields method, updated kMinValues, kMaxValues & kLeastMaxValues
34
 
*   12/09/99    aliu        Fixed j81, calculation errors and roll bugs
35
 
*                           in year of cutover.
36
 
*   01/24/2000  aliu        Revised computeJulianDay for YEAR YEAR_WOY WOY.
37
 
********************************************************************************
38
 
*/
39
 
 
40
 
#include "unicode/gregocal.h"
41
 
 
42
 
// *****************************************************************************
43
 
// class GregorianCalendar
44
 
// *****************************************************************************
45
 
 
46
 
 
47
 
static const int32_t kJan1_1JulianDay = 1721426; // January 1, year 1 (Gregorian)
48
 
 
49
 
/**
50
 
 * Note that the Julian date used here is not a true Julian date, since
51
 
 * it is measured from midnight, not noon.  This value is the Julian
52
 
 * day number of January 1, 1970 (Gregorian calendar) at noon UTC. [LIU]
53
 
 */
54
 
static const int32_t kEpochStartAsJulianDay    = 2440588; // January 1, 1970 (Gregorian)
55
 
 
56
 
static const int32_t kEpochYear             = 1970;
57
 
 
58
 
static const int32_t kNumDays[]
59
 
    = {0,31,59,90,120,151,181,212,243,273,304,334}; // 0-based, for day-in-year
60
 
static const int32_t kLeapNumDays[]
61
 
    = {0,31,60,91,121,152,182,213,244,274,305,335}; // 0-based, for day-in-year
62
 
static const int32_t kMonthLength[]
63
 
    = {31,28,31,30,31,30,31,31,30,31,30,31}; // 0-based
64
 
static const int32_t kLeapMonthLength[]
65
 
    = {31,29,31,30,31,30,31,31,30,31,30,31}; // 0-based
66
 
 
67
 
// Useful millisecond constants
68
 
static const double  kOneDay    = U_MILLIS_PER_DAY;       //  86,400,000
69
 
static const double  kOneWeek   = 7.0 * U_MILLIS_PER_DAY; // 604,800,000
70
 
 
71
 
// These numbers are 2^52 - 1, the largest allowable mantissa in a 64-bit double
72
 
// with a 0 exponent.  These are the absolute largest numbers for millis that
73
 
// this calendar will handle reliably.  It will work for larger values, however.
74
 
// The problem is that, once the exponent is not 0, the calendar will jump.
75
 
// When translated into a year, LATEST_SUPPORTED_MILLIS corresponds to 144,683 AD 
76
 
// and EARLIEST_SUPPORTED_MILLIS corresponds to 140,742 BC
77
 
static const UDate EARLIEST_SUPPORTED_MILLIS = - 4503599627370495.0;
78
 
static const UDate LATEST_SUPPORTED_MILLIS    =   4503599627370495.0;
79
 
 
80
 
/*
81
 
 * <pre>
82
 
 *                            Greatest       Least 
83
 
 * Field name        Minimum   Minimum     Maximum     Maximum
84
 
 * ----------        -------   -------     -------     -------
85
 
 * ERA                     0         0           1           1
86
 
 * YEAR                    1         1      140742      144683
87
 
 * MONTH                   0         0          11          11
88
 
 * WEEK_OF_YEAR            1         1          52          53
89
 
 * WEEK_OF_MONTH           0         0           4           6
90
 
 * DAY_OF_MONTH            1         1          28          31
91
 
 * DAY_OF_YEAR             1         1         365         366
92
 
 * DAY_OF_WEEK             1         1           7           7
93
 
 * DAY_OF_WEEK_IN_MONTH   -1        -1           4           6
94
 
 * AM_PM                   0         0           1           1
95
 
 * HOUR                    0         0          11          11
96
 
 * HOUR_OF_DAY             0         0          23          23
97
 
 * MINUTE                  0         0          59          59
98
 
 * SECOND                  0         0          59          59
99
 
 * MILLISECOND             0         0         999         999
100
 
 * ZONE_OFFSET           -12*      -12*         12*         12*
101
 
 * DST_OFFSET              0         0           1*          1*
102
 
 * YEAR_WOY                1         1      140742      144683
103
 
 * DOW_LOCAL               1         1           7           7
104
 
 * </pre>
105
 
 * (*) In units of one-hour
106
 
 */
107
 
static const int32_t kMinValues[] = {
108
 
    0,1,0,1,0,1,1,1,-1,0,0,0,0,0,0,-12*U_MILLIS_PER_HOUR,0,1,1
109
 
};
110
 
static const int32_t kLeastMaxValues[] = {
111
 
    1,140742,11,52,4,28,365,7,4,1,11,23,59,59,999,12*U_MILLIS_PER_HOUR,1*U_MILLIS_PER_HOUR,140742,7
112
 
};
113
 
static const int32_t kMaxValues[] = {
114
 
    1,144683,11,53,6,31,366,7,6,1,11,23,59,59,999,12*U_MILLIS_PER_HOUR,1*U_MILLIS_PER_HOUR, 144683,7
115
 
};
116
 
 
117
 
 
118
 
U_NAMESPACE_BEGIN
119
 
 
120
 
const char GregorianCalendar::fgClassID = 0; // Value is irrelevant
121
 
 
122
 
// 00:00:00 UTC, October 15, 1582, expressed in ms from the epoch.
123
 
// Note that only Italy and other Catholic countries actually
124
 
// observed this cutover.  Most other countries followed in
125
 
// the next few centuries, some as late as 1928. [LIU]
126
 
// in Java, -12219292800000L
127
 
//const UDate GregorianCalendar::kPapalCutover = -12219292800000L;
128
 
static const UDate kPapalCutover = (2299161.0 - kEpochStartAsJulianDay) * U_MILLIS_PER_DAY;
129
 
 
130
 
// -------------------------------------
131
 
 
132
 
GregorianCalendar::GregorianCalendar(UErrorCode& status)
133
 
    :   Calendar(TimeZone::createDefault(), Locale::getDefault(), status),
134
 
        fGregorianCutover(kPapalCutover),
135
 
        fNormalizedGregorianCutover(fGregorianCutover),
136
 
        fGregorianCutoverYear(1582)
137
 
{
138
 
    setTimeInMillis(getNow(), status);
139
 
}
140
 
 
141
 
// -------------------------------------
142
 
 
143
 
GregorianCalendar::GregorianCalendar(TimeZone* zone, UErrorCode& status)
144
 
    :   Calendar(zone, Locale::getDefault(), status),
145
 
        fGregorianCutover(kPapalCutover),
146
 
        fNormalizedGregorianCutover(fGregorianCutover),
147
 
        fGregorianCutoverYear(1582)
148
 
{
149
 
    setTimeInMillis(getNow(), status);
150
 
}
151
 
 
152
 
// -------------------------------------
153
 
 
154
 
GregorianCalendar::GregorianCalendar(const TimeZone& zone, UErrorCode& status)
155
 
    :   Calendar(zone, Locale::getDefault(), status),
156
 
        fGregorianCutover(kPapalCutover),
157
 
        fNormalizedGregorianCutover(fGregorianCutover),
158
 
        fGregorianCutoverYear(1582)
159
 
{
160
 
    setTimeInMillis(getNow(), status);
161
 
}
162
 
 
163
 
// -------------------------------------
164
 
 
165
 
GregorianCalendar::GregorianCalendar(const Locale& aLocale, UErrorCode& status)
166
 
    :   Calendar(TimeZone::createDefault(), aLocale, status),
167
 
        fGregorianCutover(kPapalCutover),
168
 
        fNormalizedGregorianCutover(fGregorianCutover),
169
 
        fGregorianCutoverYear(1582)
170
 
{
171
 
    setTimeInMillis(getNow(), status);
172
 
}
173
 
 
174
 
// -------------------------------------
175
 
 
176
 
GregorianCalendar::GregorianCalendar(TimeZone* zone, const Locale& aLocale,
177
 
                                     UErrorCode& status)
178
 
    :   Calendar(zone, aLocale, status),
179
 
        fGregorianCutover(kPapalCutover),
180
 
        fNormalizedGregorianCutover(fGregorianCutover),
181
 
        fGregorianCutoverYear(1582)
182
 
{
183
 
    setTimeInMillis(getNow(), status);
184
 
}
185
 
 
186
 
// -------------------------------------
187
 
 
188
 
GregorianCalendar::GregorianCalendar(const TimeZone& zone, const Locale& aLocale,
189
 
                                     UErrorCode& status)
190
 
    :   Calendar(zone, aLocale, status),
191
 
        fGregorianCutover(kPapalCutover),
192
 
        fNormalizedGregorianCutover(fGregorianCutover),
193
 
        fGregorianCutoverYear(1582)
194
 
{
195
 
    setTimeInMillis(getNow(), status);
196
 
}
197
 
 
198
 
// -------------------------------------
199
 
 
200
 
GregorianCalendar::GregorianCalendar(int32_t year, int32_t month, int32_t date,
201
 
                                     UErrorCode& status)
202
 
    :   Calendar(TimeZone::createDefault(), Locale::getDefault(), status),
203
 
        fGregorianCutover(kPapalCutover),
204
 
        fNormalizedGregorianCutover(fGregorianCutover),
205
 
        fGregorianCutoverYear(1582)
206
 
{
207
 
    set(Calendar::ERA, AD);
208
 
    set(Calendar::YEAR, year);
209
 
    set(Calendar::MONTH, month);
210
 
    set(Calendar::DATE, date);
211
 
}
212
 
 
213
 
// -------------------------------------
214
 
 
215
 
GregorianCalendar::GregorianCalendar(int32_t year, int32_t month, int32_t date,
216
 
                                     int32_t hour, int32_t minute, UErrorCode& status)
217
 
    :   Calendar(TimeZone::createDefault(), Locale::getDefault(), status),
218
 
        fGregorianCutover(kPapalCutover),
219
 
        fNormalizedGregorianCutover(fGregorianCutover),
220
 
        fGregorianCutoverYear(1582)
221
 
{
222
 
    set(Calendar::ERA, AD);
223
 
    set(Calendar::YEAR, year);
224
 
    set(Calendar::MONTH, month);
225
 
    set(Calendar::DATE, date);
226
 
    set(Calendar::HOUR_OF_DAY, hour);
227
 
    set(Calendar::MINUTE, minute);
228
 
}
229
 
 
230
 
// -------------------------------------
231
 
 
232
 
GregorianCalendar::GregorianCalendar(int32_t year, int32_t month, int32_t date,
233
 
                                     int32_t hour, int32_t minute, int32_t second,
234
 
                                     UErrorCode& status)
235
 
    :   Calendar(TimeZone::createDefault(), Locale::getDefault(), status),
236
 
        fGregorianCutover(kPapalCutover),
237
 
        fNormalizedGregorianCutover(fGregorianCutover),
238
 
        fGregorianCutoverYear(1582)
239
 
{
240
 
    set(Calendar::ERA, AD);
241
 
    set(Calendar::YEAR, year);
242
 
    set(Calendar::MONTH, month);
243
 
    set(Calendar::DATE, date);
244
 
    set(Calendar::HOUR_OF_DAY, hour);
245
 
    set(Calendar::MINUTE, minute);
246
 
    set(Calendar::SECOND, second);
247
 
}
248
 
 
249
 
// -------------------------------------
250
 
 
251
 
GregorianCalendar::~GregorianCalendar()
252
 
{
253
 
}
254
 
 
255
 
// -------------------------------------
256
 
 
257
 
GregorianCalendar::GregorianCalendar(const GregorianCalendar &source)
258
 
    :   Calendar(source),
259
 
        fGregorianCutover(source.fGregorianCutover),
260
 
        fNormalizedGregorianCutover(source.fNormalizedGregorianCutover),
261
 
        fGregorianCutoverYear(source.fGregorianCutoverYear)
262
 
{
263
 
}
264
 
 
265
 
// -------------------------------------
266
 
 
267
 
Calendar* GregorianCalendar::clone() const
268
 
{
269
 
    return new GregorianCalendar(*this);
270
 
}
271
 
 
272
 
// -------------------------------------
273
 
 
274
 
GregorianCalendar &
275
 
GregorianCalendar::operator=(const GregorianCalendar &right)
276
 
{
277
 
    if (this != &right)
278
 
    {
279
 
        Calendar::operator=(right);
280
 
        fGregorianCutover = right.fGregorianCutover;
281
 
        fNormalizedGregorianCutover = right.fNormalizedGregorianCutover;
282
 
        fGregorianCutoverYear = right.fGregorianCutoverYear;
283
 
    }
284
 
    return *this;
285
 
}
286
 
 
287
 
// -------------------------------------
288
 
 
289
 
UBool
290
 
GregorianCalendar::operator==(const Calendar& that) const
291
 
{
292
 
    GregorianCalendar* other = (GregorianCalendar*)&that;
293
 
 
294
 
    return (this == &that) ||
295
 
        (Calendar::operator==(that) &&
296
 
         getDynamicClassID() == that.getDynamicClassID() &&
297
 
         fGregorianCutover == other->fGregorianCutover);
298
 
}
299
 
 
300
 
// {sfb} API change?
301
 
UBool GregorianCalendar::equivalentTo(const Calendar& other) const
302
 
{
303
 
    // Calendar override.
304
 
    // Return true if another Calendar object is equivalent to this one.  An equivalent
305
 
    // Calendar will behave exactly as this one does, but may be set to a different time.
306
 
    return Calendar::equivalentTo(other) &&
307
 
        fGregorianCutover == ((GregorianCalendar*)&other)->fGregorianCutover;
308
 
}
309
 
 
310
 
// -------------------------------------
311
 
 
312
 
void
313
 
GregorianCalendar::setGregorianChange(UDate date, UErrorCode& status)
314
 
{
315
 
    if (U_FAILURE(status)) 
316
 
        return;
317
 
 
318
 
    fGregorianCutover = date;
319
 
 
320
 
    // Precompute two internal variables which we use to do the actual
321
 
    // cutover computations.  These are the normalized cutover, which is the
322
 
    // midnight at or before the cutover, and the cutover year.  The
323
 
    // normalized cutover is in pure date milliseconds; it contains no time
324
 
    // of day or timezone component, and it used to compare against other
325
 
    // pure date values.
326
 
    UDate cutoverDay = floorDivide(fGregorianCutover, kOneDay);
327
 
    fNormalizedGregorianCutover = cutoverDay * kOneDay;
328
 
 
329
 
    // Handle the rare case of numeric overflow.  If the user specifies a
330
 
    // change of UDate(Long.MIN_VALUE), in order to get a pure Gregorian
331
 
    // calendar, then the epoch day is -106751991168, which when multiplied
332
 
    // by ONE_DAY gives 9223372036794351616 -- the negative value is too
333
 
    // large for 64 bits, and overflows into a positive value.  We correct
334
 
    // this by using the next day, which for all intents is semantically
335
 
    // equivalent.
336
 
    if (cutoverDay < 0 && fNormalizedGregorianCutover > 0) {
337
 
        fNormalizedGregorianCutover = (cutoverDay + 1) * kOneDay;
338
 
    }
339
 
 
340
 
    // Normalize the year so BC values are represented as 0 and negative
341
 
    // values.
342
 
    GregorianCalendar *cal = new GregorianCalendar(getTimeZone(), status);
343
 
    if(U_FAILURE(status))
344
 
        return;
345
 
    cal->setTime(date, status);
346
 
    fGregorianCutoverYear = cal->get(YEAR, status);
347
 
    if (cal->get(ERA, status) == BC) 
348
 
        fGregorianCutoverYear = 1 - fGregorianCutoverYear;
349
 
    
350
 
    delete cal;
351
 
}
352
 
 
353
 
// -------------------------------------
354
 
 
355
 
UDate
356
 
GregorianCalendar::getGregorianChange() const
357
 
{
358
 
    return fGregorianCutover;
359
 
}
360
 
 
361
 
// -------------------------------------
362
 
 
363
 
UBool 
364
 
GregorianCalendar::isLeapYear(int32_t year) const
365
 
{
366
 
    return (year >= fGregorianCutoverYear ?
367
 
        ((year%4 == 0) && ((year%100 != 0) || (year%400 == 0))) : // Gregorian
368
 
        (year%4 == 0)); // Julian
369
 
}
370
 
 
371
 
 
372
 
// -------------------------------------
373
 
 
374
 
/**
375
 
 * Compute the date-based fields given the milliseconds since the epoch start.
376
 
 * Do not compute the time-based fields (HOUR, MINUTE, etc.).
377
 
 *
378
 
 * @param theTime the given time as LOCAL milliseconds, not UTC.
379
 
 */
380
 
void
381
 
GregorianCalendar::timeToFields(UDate theTime, UBool quick, UErrorCode& status)
382
 
{
383
 
    if (U_FAILURE(status)) 
384
 
        return;
385
 
 
386
 
    int32_t rawYear;
387
 
    int32_t year, yearOfWeekOfYear, month, date, dayOfWeek, locDayOfWeek, dayOfYear, era;
388
 
    UBool isLeap;
389
 
 
390
 
    // Compute the year, month, and day of month from the given millis
391
 
    if (theTime >= fNormalizedGregorianCutover) {
392
 
        // The Gregorian epoch day is zero for Monday January 1, year 1.
393
 
        double gregorianEpochDay = millisToJulianDay(theTime) - kJan1_1JulianDay;
394
 
        // Here we convert from the day number to the multiple radix
395
 
        // representation.  We use 400-year, 100-year, and 4-year cycles.
396
 
        // For example, the 4-year cycle has 4 years + 1 leap day; giving
397
 
        // 1461 == 365*4 + 1 days.
398
 
        int32_t rem[1];
399
 
        int32_t n400 = floorDivide(gregorianEpochDay, 146097, rem); // 400-year cycle length
400
 
        int32_t n100 = floorDivide(rem[0], 36524, rem); // 100-year cycle length
401
 
        int32_t n4 = floorDivide(rem[0], 1461, rem); // 4-year cycle length
402
 
        int32_t n1 = floorDivide(rem[0], 365, rem);
403
 
        rawYear = 400*n400 + 100*n100 + 4*n4 + n1;
404
 
        dayOfYear = rem[0]; // zero-based day of year
405
 
        if (n100 == 4 || n1 == 4) 
406
 
            dayOfYear = 365; // Dec 31 at end of 4- or 400-yr cycle
407
 
        else 
408
 
            ++rawYear;
409
 
        
410
 
        isLeap = ((rawYear&0x3) == 0) && // equiv. to (rawYear%4 == 0)
411
 
            (rawYear%100 != 0 || rawYear%400 == 0);
412
 
        
413
 
        // Gregorian day zero is a Monday
414
 
        dayOfWeek = (int32_t)uprv_fmod(gregorianEpochDay + 1, 7);
415
 
    }
416
 
    else {
417
 
        // The Julian epoch day (not the same as Julian Day)
418
 
        // is zero on Saturday December 30, 0 (Gregorian).
419
 
        double julianEpochDay = millisToJulianDay(theTime) - (kJan1_1JulianDay - 2);
420
 
        rawYear = (int32_t) floorDivide(4*julianEpochDay + 1464, 1461.0);
421
 
        
422
 
        // Compute the Julian calendar day number for January 1, rawYear
423
 
        double january1 = 365.0 * (rawYear - 1) + floorDivide((double)(rawYear - 1), 4.0);
424
 
        dayOfYear = (int32_t)(julianEpochDay - january1); // 0-based
425
 
        
426
 
        // Julian leap years occurred historically every 4 years starting
427
 
        // with 8 AD.  Before 8 AD the spacing is irregular; every 3 years
428
 
        // from 45 BC to 9 BC, and then none until 8 AD.  However, we don't
429
 
        // implement this historical detail; instead, we implement the
430
 
        // computatinally cleaner proleptic calendar, which assumes
431
 
        // consistent 4-year cycles throughout time.
432
 
        isLeap = ((rawYear & 0x3) == 0); // equiv. to (rawYear%4 == 0)
433
 
        
434
 
        // Julian calendar day zero is a Saturday
435
 
        dayOfWeek = (int32_t)uprv_fmod(julianEpochDay-1, 7);
436
 
    }
437
 
    
438
 
    // Common Julian/Gregorian calculation
439
 
    int32_t correction = 0;
440
 
    int32_t march1 = isLeap ? 60 : 59; // zero-based DOY for March 1
441
 
    if (dayOfYear >= march1) 
442
 
        correction = isLeap ? 1 : 2;
443
 
    month = (12 * (dayOfYear + correction) + 6) / 367; // zero-based month
444
 
    date = dayOfYear -
445
 
        (isLeap ? kLeapNumDays[month] : kNumDays[month]) + 1; // one-based DOM
446
 
    
447
 
    // Normalize day of week
448
 
    dayOfWeek += (dayOfWeek < 0) ? (SUNDAY+7) : SUNDAY;
449
 
    
450
 
 
451
 
    era = AD;
452
 
    year = rawYear;
453
 
    if (year < 1) {
454
 
        era = BC;
455
 
        year = 1 - year;
456
 
    }
457
 
 
458
 
    // Adjust the doy for the cutover year.  Do this AFTER the above
459
 
    // computations using doy!  [j81 - aliu]
460
 
    if (rawYear == fGregorianCutoverYear &&
461
 
        theTime >= fNormalizedGregorianCutover) {
462
 
        dayOfYear -= 10;
463
 
    }
464
 
 
465
 
    // Calculate year of week of year
466
 
 
467
 
 
468
 
    internalSet(ERA, era);
469
 
    internalSet(YEAR, year);
470
 
    internalSet(MONTH, month + JANUARY); // 0-based
471
 
    internalSet(DATE, date);
472
 
    internalSet(DAY_OF_WEEK, dayOfWeek);
473
 
    internalSet(DAY_OF_YEAR, ++dayOfYear); // Convert from 0-based to 1-based
474
 
    if (quick) 
475
 
        return;
476
 
 
477
 
    yearOfWeekOfYear = year;
478
 
 
479
 
    // Compute the week of the year.  Valid week numbers run from 1 to 52
480
 
    // or 53, depending on the year, the first day of the week, and the
481
 
    // minimal days in the first week.  Days at the start of the year may
482
 
    // fall into the last week of the previous year; days at the end of
483
 
    // the year may fall into the first week of the next year.
484
 
    int32_t relDow = (dayOfWeek + 7 - getFirstDayOfWeek()) % 7; // 0..6
485
 
    int32_t relDowJan1 = (dayOfWeek - dayOfYear + 701 - getFirstDayOfWeek()) % 7; // 0..6
486
 
    int32_t woy = (dayOfYear - 1 + relDowJan1) / 7; // 0..53
487
 
    if ((7 - relDowJan1) >= getMinimalDaysInFirstWeek()) {
488
 
        ++woy;
489
 
        // Check to see if we are in the last week; if so, we need
490
 
        // to handle the case in which we are the first week of the
491
 
        // next year.
492
 
        int32_t lastDoy = yearLength();
493
 
        int32_t lastRelDow = (relDow + lastDoy - dayOfYear) % 7;
494
 
        if (lastRelDow < 0) lastRelDow += 7;
495
 
        if (dayOfYear > 359 && // Fast check which eliminates most cases
496
 
            (6 - lastRelDow) >= getMinimalDaysInFirstWeek() &&
497
 
            (dayOfYear + 7 - relDow) > lastDoy) {
498
 
                woy = 1;
499
 
                yearOfWeekOfYear++;
500
 
        }
501
 
    }
502
 
    else if (woy == 0) {
503
 
        // We are the last week of the previous year.
504
 
        int32_t prevDoy = dayOfYear + yearLength(rawYear - 1);
505
 
        woy = weekNumber(prevDoy, dayOfWeek);
506
 
        yearOfWeekOfYear--;
507
 
    }
508
 
 
509
 
 
510
 
    internalSet(WEEK_OF_YEAR, woy);
511
 
    internalSet(YEAR_WOY, yearOfWeekOfYear);
512
 
 
513
 
    internalSet(WEEK_OF_MONTH, weekNumber(date, dayOfWeek));
514
 
    internalSet(DAY_OF_WEEK_IN_MONTH, (date-1) / 7 + 1);
515
 
 
516
 
    // Calculate localized day of week
517
 
    locDayOfWeek = dayOfWeek-getFirstDayOfWeek()+1;
518
 
    locDayOfWeek += (locDayOfWeek<1?7:0);
519
 
    internalSet(DOW_LOCAL, locDayOfWeek);
520
 
}
521
 
 
522
 
// -------------------------------------
523
 
 
524
 
/**
525
 
 * Return the week number of a day, within a period. This may be the week number in
526
 
 * a year, or the week number in a month. Usually this will be a value >= 1, but if
527
 
 * some initial days of the period are excluded from week 1, because
528
 
 * minimalDaysInFirstWeek is > 1, then the week number will be zero for those
529
 
 * initial days. Requires the day of week for the given date in order to determine
530
 
 * the day of week of the first day of the period.
531
 
 *
532
 
 * @param dayOfPeriod  Day-of-year or day-of-month. Should be 1 for first day of period.
533
 
 * @param day   Day-of-week for given dayOfPeriod. 1-based with 1=Sunday.
534
 
 * @return      Week number, one-based, or zero if the day falls in part of the
535
 
 *              month before the first week, when there are days before the first
536
 
 *              week because the minimum days in the first week is more than one.
537
 
 */
538
 
int32_t
539
 
GregorianCalendar::weekNumber(int32_t dayOfPeriod, int32_t dayOfWeek)
540
 
{
541
 
    // Determine the day of the week of the first day of the period
542
 
    // in question (either a year or a month).  Zero represents the
543
 
    // first day of the week on this calendar.
544
 
    int32_t periodStartDayOfWeek = (dayOfWeek - getFirstDayOfWeek() - dayOfPeriod + 1) % 7;
545
 
    if (periodStartDayOfWeek < 0) 
546
 
        periodStartDayOfWeek += 7;
547
 
    
548
 
    // Compute the week number.  Initially, ignore the first week, which
549
 
    // may be fractional (or may not be).  We add periodStartDayOfWeek in
550
 
    // order to fill out the first week, if it is fractional.
551
 
    int32_t weekNo = (dayOfPeriod + periodStartDayOfWeek - 1)/7;
552
 
    
553
 
    // If the first week is long enough, then count it.  If
554
 
    // the minimal days in the first week is one, or if the period start
555
 
    // is zero, we always increment weekNo.
556
 
    if ((7 - periodStartDayOfWeek) >= getMinimalDaysInFirstWeek()) 
557
 
        ++weekNo;
558
 
    
559
 
    return weekNo;
560
 
}
561
 
 
562
 
// -------------------------------------
563
 
 
564
 
int32_t
565
 
GregorianCalendar::monthLength(int32_t month) const
566
 
{
567
 
    int32_t year = internalGet(YEAR);
568
 
    if(internalGetEra() == BC) {
569
 
        year = 1 - year;
570
 
    }
571
 
 
572
 
    return monthLength(month, year);
573
 
}
574
 
 
575
 
// -------------------------------------
576
 
 
577
 
int32_t
578
 
GregorianCalendar::monthLength(int32_t month, int32_t year) const
579
 
{
580
 
    return isLeapYear(year) ? kLeapMonthLength[month] : kMonthLength[month];
581
 
}
582
 
 
583
 
// -------------------------------------
584
 
 
585
 
int32_t
586
 
GregorianCalendar::yearLength(int32_t year) const
587
 
{
588
 
    return isLeapYear(year) ? 366 : 365;
589
 
}
590
 
 
591
 
// -------------------------------------
592
 
 
593
 
int32_t
594
 
GregorianCalendar::yearLength() const
595
 
{
596
 
    return isLeapYear(internalGet(YEAR)) ? 366 : 365;
597
 
}
598
 
 
599
 
// -------------------------------------
600
 
 
601
 
/**
602
 
 * Overrides Calendar
603
 
 * Converts UTC as milliseconds to time field values.
604
 
 * The time is <em>not</em>
605
 
 * recomputed first; to recompute the time, then the fields, call the
606
 
 * <code>complete</code> method.
607
 
 * @see Calendar#complete
608
 
 */
609
 
void
610
 
GregorianCalendar::computeFields(UErrorCode& status)
611
 
{
612
 
    if (U_FAILURE(status)) 
613
 
        return;
614
 
 
615
 
    int32_t rawOffset = getTimeZone().getRawOffset();
616
 
    double localMillis = internalGetTime() + rawOffset;
617
 
 
618
 
    /* Check for very extreme values -- millis near Long.MIN_VALUE or
619
 
     * Long.MAX_VALUE.  For these values, adding the zone offset can push
620
 
     * the millis past MAX_VALUE to MIN_VALUE, or vice versa.  This produces
621
 
     * the undesirable effect that the time can wrap around at the ends,
622
 
     * yielding, for example, a UDate(Long.MAX_VALUE) with a big BC year
623
 
     * (should be AD).  Handle this by pinning such values to Long.MIN_VALUE
624
 
     * or Long.MAX_VALUE. - liu 8/11/98 bug 4149677 */
625
 
    
626
 
    /* {sfb} 9/04/98 
627
 
     * Since in C++ we use doubles instead of longs for dates, there is
628
 
     * an inherent loss of range in the calendar (because in Java you have all 64
629
 
     * bits to store data, while in C++ you have only 52 bits of mantissa.
630
 
     * So, I will pin to these (2^52 - 1) values instead */
631
 
    
632
 
    if(internalGetTime() > 0 && localMillis < 0 && rawOffset > 0) {
633
 
        localMillis = LATEST_SUPPORTED_MILLIS;
634
 
    } 
635
 
    else if(internalGetTime() < 0 && localMillis > 0 && rawOffset < 0) {
636
 
        localMillis = EARLIEST_SUPPORTED_MILLIS;
637
 
    }
638
 
 
639
 
    // Time to fields takes the wall millis (Standard or DST).
640
 
    timeToFields(localMillis, FALSE, status);
641
 
 
642
 
    uint8_t era         = (uint8_t) internalGetEra();
643
 
    int32_t year         = internalGet(YEAR);
644
 
    int32_t month         = internalGet(MONTH);
645
 
    int32_t date         = internalGet(DATE);
646
 
    uint8_t dayOfWeek     = (uint8_t) internalGet(DAY_OF_WEEK);
647
 
 
648
 
    double days = uprv_floor(localMillis / kOneDay);
649
 
    int32_t millisInDay = (int32_t) (localMillis - (days * kOneDay));
650
 
    if (millisInDay < 0) 
651
 
        millisInDay += U_MILLIS_PER_DAY;
652
 
 
653
 
    // Call getOffset() to get the TimeZone offset.  The millisInDay value must
654
 
    // be standard local millis.
655
 
    int32_t dstOffset = getTimeZone().getOffset(era, year, month, date, dayOfWeek, millisInDay,
656
 
                                            monthLength(month), status) - rawOffset;
657
 
    if(U_FAILURE(status))
658
 
        return;
659
 
 
660
 
    // Adjust our millisInDay for DST, if necessary.
661
 
    millisInDay += dstOffset;
662
 
 
663
 
    // If DST has pushed us into the next day, we must call timeToFields() again.
664
 
    // This happens in DST between 12:00 am and 1:00 am every day.  The call to
665
 
    // timeToFields() will give the wrong day, since the Standard time is in the
666
 
    // previous day.
667
 
    if (millisInDay >= U_MILLIS_PER_DAY) {
668
 
        UDate dstMillis = localMillis + dstOffset;
669
 
        millisInDay -= U_MILLIS_PER_DAY;
670
 
        // As above, check for and pin extreme values
671
 
        if(localMillis > 0 && dstMillis < 0 && dstOffset > 0) {
672
 
            dstMillis = LATEST_SUPPORTED_MILLIS;
673
 
        } 
674
 
        else if(localMillis < 0 && dstMillis > 0 && dstOffset < 0) {
675
 
            dstMillis = EARLIEST_SUPPORTED_MILLIS;
676
 
        }
677
 
        timeToFields(dstMillis, FALSE, status);
678
 
    }
679
 
 
680
 
    // Fill in all time-related fields based on millisInDay.  Call internalSet()
681
 
    // so as not to perturb flags.
682
 
    internalSet(MILLISECOND, millisInDay % 1000);
683
 
    millisInDay /= 1000;
684
 
    internalSet(SECOND, millisInDay % 60);
685
 
    millisInDay /= 60;
686
 
    internalSet(MINUTE, millisInDay % 60);
687
 
    millisInDay /= 60;
688
 
    internalSet(HOUR_OF_DAY, millisInDay);
689
 
    internalSet(AM_PM, millisInDay / 12); // Assume AM == 0
690
 
    internalSet(HOUR, millisInDay % 12);
691
 
 
692
 
    internalSet(ZONE_OFFSET, rawOffset);
693
 
    internalSet(DST_OFFSET, dstOffset);
694
 
 
695
 
    // Careful here: We are manually setting the time stamps[] flags to
696
 
    // INTERNALLY_SET, so we must be sure that the above code actually does
697
 
    // set all these fields.
698
 
    for (int i=0; i<FIELD_COUNT; ++i) {
699
 
        fStamp[i] = kInternallySet;
700
 
        fIsSet[i] = TRUE; // Remove later
701
 
    }
702
 
}
703
 
 
704
 
// -------------------------------------
705
 
 
706
 
/**
707
 
 * After adjustments such as add(MONTH), add(YEAR), we don't want the
708
 
 * month to jump around.  E.g., we don't want Jan 31 + 1 month to go to Mar
709
 
 * 3, we want it to go to Feb 28.  Adjustments which might run into this
710
 
 * problem call this method to retain the proper month.
711
 
 */
712
 
void 
713
 
GregorianCalendar::pinDayOfMonth() 
714
 
{
715
 
    int32_t monthLen = monthLength(internalGet(MONTH));
716
 
    int32_t dom = internalGet(DAY_OF_MONTH);
717
 
    if(dom > monthLen) 
718
 
        set(DAY_OF_MONTH, monthLen);
719
 
}
720
 
 
721
 
// -------------------------------------
722
 
 
723
 
UBool
724
 
GregorianCalendar::validateFields() const
725
 
{
726
 
    for (int32_t field = 0; field < FIELD_COUNT; field++) {
727
 
        // Ignore DATE and DAY_OF_YEAR which are handled below
728
 
        if (field != DATE &&
729
 
            field != DAY_OF_YEAR &&
730
 
            isSet((EDateFields)field) &&
731
 
            ! boundsCheck(internalGet((EDateFields)field), (EDateFields)field))
732
 
 
733
 
            return FALSE;
734
 
    }
735
 
 
736
 
    // Values differ in Least-Maximum and Maximum should be handled
737
 
    // specially.
738
 
    if (isSet(DATE)) {
739
 
        int32_t date = internalGet(DATE);
740
 
        if (date < getMinimum(DATE) ||
741
 
            date > monthLength(internalGet(MONTH))) {
742
 
            return FALSE;
743
 
        }
744
 
    }
745
 
 
746
 
    if (isSet(DAY_OF_YEAR)) {
747
 
        int32_t days = internalGet(DAY_OF_YEAR);
748
 
        if (days < 1 || days > yearLength()) 
749
 
            return FALSE;
750
 
    }
751
 
 
752
 
    // Handle DAY_OF_WEEK_IN_MONTH, which must not have the value zero.
753
 
    // We've checked against minimum and maximum above already.
754
 
    if (isSet(DAY_OF_WEEK_IN_MONTH) &&
755
 
        0 == internalGet(DAY_OF_WEEK_IN_MONTH)) 
756
 
            return FALSE;
757
 
 
758
 
    return TRUE;
759
 
}
760
 
 
761
 
// -------------------------------------
762
 
 
763
 
UBool
764
 
GregorianCalendar::boundsCheck(int32_t value, EDateFields field) const
765
 
{
766
 
    return value >= getMinimum(field) && value <= getMaximum(field);
767
 
}
768
 
 
769
 
// -------------------------------------
770
 
 
771
 
UDate 
772
 
GregorianCalendar::getEpochDay(UErrorCode& status) 
773
 
{
774
 
    complete(status);
775
 
    // Divide by 1000 (convert to seconds) in order to prevent overflow when
776
 
    // dealing with UDate(Long.MIN_VALUE) and UDate(Long.MAX_VALUE).
777
 
    double wallSec = internalGetTime()/1000 + (internalGet(ZONE_OFFSET) + internalGet(DST_OFFSET))/1000;
778
 
    
779
 
    // {sfb} force conversion to double
780
 
    return uprv_trunc(wallSec / (kOneDay/1000.0));
781
 
    //return floorDivide(wallSec, kOneDay/1000.0);
782
 
}
783
 
 
784
 
// -------------------------------------
785
 
 
786
 
void
787
 
GregorianCalendar::computeTime(UErrorCode& status)
788
 
{
789
 
    if (U_FAILURE(status)) 
790
 
        return;
791
 
 
792
 
    if (! isLenient() && ! validateFields()) {
793
 
        status = U_ILLEGAL_ARGUMENT_ERROR;
794
 
        return;
795
 
    }
796
 
 
797
 
    // This function takes advantage of the fact that unset fields in
798
 
    // the time field list have a value of zero.
799
 
 
800
 
    // The year is either the YEAR or the epoch year.  YEAR_WOY is
801
 
    // used only if WOY is the predominant field; see computeJulianDay.
802
 
    int32_t year = (fStamp[YEAR] != kUnset) ? internalGet(YEAR) : kEpochYear;
803
 
    int32_t era = AD;
804
 
    if (fStamp[ERA] != kUnset) {
805
 
        era = internalGet(ERA);
806
 
        if (era == BC)
807
 
            year = 1 - year;
808
 
        // Even in lenient mode we disallow ERA values other than AD & BC
809
 
        else if (era != AD) {
810
 
            status = U_ILLEGAL_ARGUMENT_ERROR;
811
 
            return;
812
 
        }
813
 
    }
814
 
 
815
 
    // First, use the year to determine whether to use the Gregorian or the
816
 
    // Julian calendar. If the year is not the year of the cutover, this
817
 
    // computation will be correct. But if the year is the cutover year,
818
 
    // this may be incorrect. In that case, assume the Gregorian calendar,
819
 
    // make the computation, and then recompute if the resultant millis
820
 
    // indicate the wrong calendar has been assumed.
821
 
 
822
 
    // A date such as Oct. 10, 1582 does not exist in a Gregorian calendar
823
 
    // with the default changeover of Oct. 15, 1582, since in such a
824
 
    // calendar Oct. 4 (Julian) is followed by Oct. 15 (Gregorian).  This
825
 
    // algorithm will interpret such a date using the Julian calendar,
826
 
    // yielding Oct. 20, 1582 (Gregorian).
827
 
    UBool isGregorian = year >= fGregorianCutoverYear;
828
 
    double julianDay = computeJulianDay(isGregorian, year);
829
 
    double millis = julianDayToMillis(julianDay);
830
 
 
831
 
    // The following check handles portions of the cutover year BEFORE the
832
 
    // cutover itself happens. The check for the julianDate number is for a
833
 
    // rare case; it's a hardcoded number, but it's efficient.  The given
834
 
    // Julian day number corresponds to Dec 3, 292269055 BC, which
835
 
    // corresponds to millis near Long.MIN_VALUE.  The need for the check
836
 
    // arises because for extremely negative Julian day numbers, the millis
837
 
    // actually overflow to be positive values. Without the check, the
838
 
    // initial date is interpreted with the Gregorian calendar, even when
839
 
    // the cutover doesn't warrant it.
840
 
    if (isGregorian != (millis >= fNormalizedGregorianCutover) &&
841
 
        julianDay != -106749550580.0) { // See above
842
 
        julianDay = computeJulianDay(!isGregorian, year);
843
 
        millis = julianDayToMillis(julianDay);
844
 
    }
845
 
 
846
 
    // Do the time portion of the conversion.
847
 
 
848
 
    int32_t millisInDay = 0;
849
 
 
850
 
    // Find the best set of fields specifying the time of day.  There
851
 
    // are only two possibilities here; the HOUR_OF_DAY or the
852
 
    // AM_PM and the HOUR.
853
 
    int32_t hourOfDayStamp = fStamp[HOUR_OF_DAY];
854
 
    int32_t hourStamp = fStamp[HOUR];
855
 
    int32_t bestStamp = (hourStamp > hourOfDayStamp) ? hourStamp : hourOfDayStamp;
856
 
 
857
 
    // Hours
858
 
    if (bestStamp != kUnset) {
859
 
        if (bestStamp == hourOfDayStamp)
860
 
            // Don't normalize here; let overflow bump into the next period.
861
 
            // This is consistent with how we handle other fields.
862
 
            millisInDay += internalGet(HOUR_OF_DAY);
863
 
 
864
 
        else {
865
 
            // Don't normalize here; let overflow bump into the next period.
866
 
            // This is consistent with how we handle other fields.
867
 
            millisInDay += internalGet(HOUR);
868
 
 
869
 
            millisInDay += 12 * internalGet(AM_PM); // Default works for unset AM_PM
870
 
        }
871
 
    }
872
 
 
873
 
    // We use the fact that unset == 0; we start with millisInDay
874
 
    // == HOUR_OF_DAY.
875
 
    millisInDay *= 60;
876
 
    millisInDay += internalGet(MINUTE); // now have minutes
877
 
    millisInDay *= 60;
878
 
    millisInDay += internalGet(SECOND); // now have seconds
879
 
    millisInDay *= 1000;
880
 
    millisInDay += internalGet(MILLISECOND); // now have millis
881
 
 
882
 
    // Compute the time zone offset and DST offset.  There are two potential
883
 
    // ambiguities here.  We'll assume a 2:00 am (wall time) switchover time
884
 
    // for discussion purposes here.
885
 
    // 1. The transition into DST.  Here, a designated time of 2:00 am - 2:59 am
886
 
    //    can be in standard or in DST depending.  However, 2:00 am is an invalid
887
 
    //    representation (the representation jumps from 1:59:59 am Std to 3:00:00 am DST).
888
 
    //    We assume standard time.
889
 
    // 2. The transition out of DST.  Here, a designated time of 1:00 am - 1:59 am
890
 
    //    can be in standard or DST.  Both are valid representations (the rep
891
 
    //    jumps from 1:59:59 DST to 1:00:00 Std).
892
 
    //    Again, we assume standard time.
893
 
    // We use the TimeZone object, unless the user has explicitly set the ZONE_OFFSET
894
 
    // or DST_OFFSET fields; then we use those fields.
895
 
    const TimeZone& zone = getTimeZone();
896
 
    int32_t zoneOffset = (fStamp[ZONE_OFFSET] >= kMinimumUserStamp)
897
 
        /*isSet(ZONE_OFFSET) && userSetZoneOffset*/ ?
898
 
        internalGet(ZONE_OFFSET) : zone.getRawOffset();
899
 
 
900
 
    // Now add date and millisInDay together, to make millis contain local wall
901
 
    // millis, with no zone or DST adjustments
902
 
    millis += millisInDay;
903
 
 
904
 
    int32_t dstOffset = 0;
905
 
    if (fStamp[ZONE_OFFSET] >= kMinimumUserStamp
906
 
        /*isSet(DST_OFFSET) && userSetDSTOffset*/)
907
 
        dstOffset = internalGet(DST_OFFSET);
908
 
    else {
909
 
        /* Normalize the millisInDay to 0..ONE_DAY-1.  If the millis is out
910
 
         * of range, then we must call timeToFields() to recompute our
911
 
         * fields. */
912
 
        int32_t normalizedMillisInDay [1];
913
 
        floorDivide(millis, (int32_t)kOneDay, normalizedMillisInDay);
914
 
 
915
 
        // We need to have the month, the day, and the day of the week.
916
 
        // Calling timeToFields will compute the MONTH and DATE fields.
917
 
        // If we're lenient then we need to call timeToFields() to
918
 
        // normalize the year, month, and date numbers.
919
 
        uint8_t dow;
920
 
        if (isLenient() || fStamp[MONTH] == kUnset || fStamp[DATE] == kUnset
921
 
                || millisInDay != normalizedMillisInDay[0]) {
922
 
            timeToFields(millis, TRUE, status); // Use wall time; true == do quick computation
923
 
            dow = (uint8_t) internalGet(DAY_OF_WEEK); // DOW is computed by timeToFields
924
 
        }
925
 
        else {
926
 
            // It's tempting to try to use DAY_OF_WEEK here, if it
927
 
            // is set, but we CAN'T.  Even if it's set, it might have
928
 
            // been set wrong by the user.  We should rely only on
929
 
            // the Julian day number, which has been computed correctly
930
 
            // using the disambiguation algorithm above. [LIU]
931
 
            dow = julianDayToDayOfWeek(julianDay);
932
 
        }
933
 
 
934
 
        // It's tempting to try to use DAY_OF_WEEK here, if it
935
 
        // is set, but we CAN'T.  Even if it's set, it might have
936
 
        // been set wrong by the user.  We should rely only on
937
 
        // the Julian day number, which has been computed correctly
938
 
        // using the disambiguation algorithm above. [LIU]
939
 
        dstOffset = zone.getOffset((uint8_t)era,
940
 
                                   internalGet(YEAR),
941
 
                                   internalGet(MONTH),
942
 
                                   internalGet(DATE),
943
 
                                   dow,
944
 
                                   normalizedMillisInDay[0],
945
 
                                   monthLength(internalGet(MONTH)),
946
 
                                   status) -
947
 
            zoneOffset;
948
 
        // Note: Because we pass in wall millisInDay, rather than
949
 
        // standard millisInDay, we interpret "1:00 am" on the day
950
 
        // of cessation of DST as "1:00 am Std" (assuming the time
951
 
        // of cessation is 2:00 am).
952
 
    }
953
 
 
954
 
    // Store our final computed GMT time, with timezone adjustments.
955
 
    internalSetTime(millis - zoneOffset - dstOffset);
956
 
}
957
 
 
958
 
// -------------------------------------
959
 
 
960
 
/**
961
 
 * Compute the julian day number of the day BEFORE the first day of
962
 
 * January 1, year 1 of the given calendar.  If julianDay == 0, it
963
 
 * specifies (Jan. 1, 1) - 1, in whatever calendar we are using (Julian
964
 
 * or Gregorian).
965
 
 */
966
 
double GregorianCalendar::computeJulianDayOfYear(UBool isGregorian,
967
 
                                                 int32_t year, UBool& isLeap) {
968
 
    isLeap = year%4 == 0;
969
 
    int32_t y = year - 1;
970
 
    double julianDay = 365.0*y + floorDivide(y, 4) + (kJan1_1JulianDay - 3);
971
 
 
972
 
    if (isGregorian) {
973
 
        isLeap = isLeap && ((year%100 != 0) || (year%400 == 0));
974
 
        // Add 2 because Gregorian calendar starts 2 days after Julian calendar
975
 
        julianDay += floorDivide(y, 400) - floorDivide(y, 100) + 2;
976
 
    }
977
 
 
978
 
    return julianDay;
979
 
}
980
 
 
981
 
/**
982
 
 * Compute the day of week, relative to the first day of week, from
983
 
 * 0..6, of the current DOW_LOCAL or DAY_OF_WEEK fields.  This is
984
 
 * equivalent to get(DOW_LOCAL) - 1.
985
 
 */
986
 
int32_t GregorianCalendar::computeRelativeDOW() const {
987
 
    int32_t relDow = 0;
988
 
    if (fStamp[DOW_LOCAL] > fStamp[DAY_OF_WEEK]) {
989
 
        relDow = internalGet(DOW_LOCAL) - 1; // 1-based
990
 
    } else if (fStamp[DAY_OF_WEEK] != kUnset) {
991
 
        relDow = internalGet(DAY_OF_WEEK) - getFirstDayOfWeek();
992
 
        if (relDow < 0) relDow += 7;
993
 
    }
994
 
    return relDow;
995
 
}
996
 
 
997
 
/**
998
 
 * Compute the day of week, relative to the first day of week,
999
 
 * from 0..6 of the given julian day.
1000
 
 */
1001
 
int32_t GregorianCalendar::computeRelativeDOW(double julianDay) const {
1002
 
    int32_t relDow = julianDayToDayOfWeek(julianDay) - getFirstDayOfWeek();
1003
 
    if (relDow < 0) {
1004
 
        relDow += 7;
1005
 
    }
1006
 
    return relDow;
1007
 
}
1008
 
 
1009
 
/**
1010
 
 * Compute the DOY using the WEEK_OF_YEAR field and the julian day
1011
 
 * of the day BEFORE January 1 of a year (a return value from
1012
 
 * computeJulianDayOfYear).
1013
 
 */
1014
 
int32_t GregorianCalendar::computeDOYfromWOY(double julianDayOfYear) const {
1015
 
    // Compute DOY from day of week plus week of year
1016
 
 
1017
 
    // Find the day of the week for the first of this year.  This
1018
 
    // is zero-based, with 0 being the locale-specific first day of
1019
 
    // the week.  Add 1 to get first day of year.
1020
 
    int32_t fdy = computeRelativeDOW(julianDayOfYear + 1);
1021
 
 
1022
 
    return
1023
 
        // Compute doy of first (relative) DOW of WOY 1
1024
 
        (((7 - fdy) < getMinimalDaysInFirstWeek())
1025
 
         ? (8 - fdy) : (1 - fdy))
1026
 
                
1027
 
        // Adjust for the week number.
1028
 
        + (7 * (internalGet(WEEK_OF_YEAR) - 1))
1029
 
 
1030
 
        // Adjust for the DOW
1031
 
        + computeRelativeDOW();
1032
 
}
1033
 
 
1034
 
double 
1035
 
GregorianCalendar::computeJulianDay(UBool isGregorian, int32_t year) 
1036
 
{
1037
 
    // Find the most recent set of fields specifying the day within
1038
 
    // the year.  These may be any of the following combinations:
1039
 
    //   MONTH* + DAY_OF_MONTH*
1040
 
    //   MONTH* + WEEK_OF_MONTH* + DAY_OF_WEEK
1041
 
    //   MONTH* + DAY_OF_WEEK_IN_MONTH* + DAY_OF_WEEK
1042
 
    //   DAY_OF_YEAR*
1043
 
    //   WEEK_OF_YEAR* + DAY_OF_WEEK*
1044
 
    //   WEEK_OF_YEAR* + DOW_LOCAL
1045
 
    // We look for the most recent of the fields marked thus*.  If other
1046
 
    // fields are missing, we use their default values, which are those of
1047
 
    // the epoch start, or in the case of DAY_OF_WEEK, the first day in
1048
 
    // the week.
1049
 
    int32_t monthStamp   = fStamp[MONTH];
1050
 
    int32_t domStamp     = fStamp[DAY_OF_MONTH];
1051
 
    int32_t womStamp     = fStamp[WEEK_OF_MONTH];
1052
 
    int32_t dowimStamp   = fStamp[DAY_OF_WEEK_IN_MONTH];
1053
 
    int32_t doyStamp     = fStamp[DAY_OF_YEAR];
1054
 
    int32_t woyStamp     = fStamp[WEEK_OF_YEAR];
1055
 
 
1056
 
    UBool isLeap;
1057
 
    double julianDay;
1058
 
 
1059
 
    int32_t bestStamp = (monthStamp > domStamp) ? monthStamp : domStamp;
1060
 
    if (womStamp > bestStamp) bestStamp = womStamp;
1061
 
    if (dowimStamp > bestStamp) bestStamp = dowimStamp;
1062
 
    if (doyStamp > bestStamp) bestStamp = doyStamp;
1063
 
    if (woyStamp >= bestStamp) {
1064
 
        // Note use of >= here, rather than >.  We will see woy ==
1065
 
        // best if (a) all stamps are unset, in which case the
1066
 
        // specific handling of unset will be used below, or (b) all
1067
 
        // stamps are kInternallySet.  In the latter case we want to
1068
 
        // use the YEAR_WOY if it is newer.
1069
 
        if (fStamp[YEAR_WOY] > fStamp[YEAR]) {
1070
 
            year = internalGet(YEAR_WOY);
1071
 
            if (fStamp[ERA] != kUnset && internalGet(ERA) == BC) {
1072
 
                year = 1 - year;
1073
 
            }
1074
 
            // Only the WOY algorithm correctly handles YEAR_WOY, so
1075
 
            // force its use by making its stamp the most recent.
1076
 
            // This only affects the situation in which all stamps are
1077
 
            // equal (see above).
1078
 
            bestStamp = ++woyStamp;
1079
 
        } else if (woyStamp > bestStamp) {
1080
 
            // The WOY stamp is not only equal to, but newer than any
1081
 
            // other stamp.  This means the WOY has been explicitly
1082
 
            // set, and will be used for computation.
1083
 
            bestStamp = woyStamp;
1084
 
            if (fStamp[YEAR_WOY] != kUnset && fStamp[YEAR_WOY] >= fStamp[YEAR]) {
1085
 
 
1086
 
                // The YEAR_WOY is set, and is not superceded by the
1087
 
                // YEAR; use it.
1088
 
                year = internalGet(YEAR_WOY);
1089
 
            }
1090
 
 
1091
 
            /* At this point we cannot avoid using the WEEK_OF_YEAR together
1092
 
             * with the YEAR field, since the YEAR_WOY is unavailable.  Our goal
1093
 
             * is round-trip field integrity.  We cannot guarantee round-trip
1094
 
             * time integrity because the YEAR + WOY combination may be
1095
 
             * ambiguous; consider a calendar with MDFW 3 and FDW Sunday.  YEAR
1096
 
             * 1997 + WOY 1 + DOW Wednesday specifies two days: Jan 1 1997, and
1097
 
             * Dec 31 1997.  However, we can guarantee that the YEAR fields, as
1098
 
             * set, will remain unchanged.
1099
 
             * 
1100
 
             * In general, YEAR and YEAR_WOY are equal, but at the ends of the
1101
 
             * years, the YEAR and YEAR_WOY can differ by one.  To detect this
1102
 
             * in WOY 1, we look at the position of WOY 1.  If it extends into
1103
 
             * the previous year, then we check the DOW and see if it falls in
1104
 
             * the previous year.  If so, we increment the year.  This allows us
1105
 
             * to have round-trip integrity on the YEAR field.
1106
 
             *
1107
 
             * If the WOY is >= 52, then we do an intial computation of the DOY
1108
 
             * for the current year.  If this exceeds the length of this year,
1109
 
             * we decrement the year.  Again, this provides round-trip integrity
1110
 
             * on the YEAR field. - aliu
1111
 
             */
1112
 
 
1113
 
            else if (internalGet(WEEK_OF_YEAR) == 1) {
1114
 
                // YEAR_WOY has not been set, so we must use the YEAR.
1115
 
                // Since WOY computations rely on the YEAR_WOY, not the
1116
 
                // YEAR, we must guess at its value.  It is usually equal
1117
 
                // to the YEAR, but may be one greater in WOY 1, and may
1118
 
                // be one less in WOY >= 52.  Note that YEAR + WOY is
1119
 
                // ambiguous (YEAR_WOY + WOY is not).
1120
 
 
1121
 
                // FDW = Mon, MDFW = 2, Mon Dec 27 1999, WOY 1, YEAR_WOY 2000
1122
 
 
1123
 
                // Find out where WOY 1 falls; some of it may extend
1124
 
                // into the previous year.  If so, and if the DOW is
1125
 
                // one of those days, then increment the YEAR_WOY.
1126
 
                julianDay = computeJulianDayOfYear(isGregorian, year, isLeap);
1127
 
                int32_t fdy = computeRelativeDOW(1 + julianDay);
1128
 
 
1129
 
                int32_t doy =
1130
 
                    (((7 - fdy) < getMinimalDaysInFirstWeek())
1131
 
                     ? (8 - fdy) : (1 - fdy));
1132
 
 
1133
 
                if (doy < 1) {
1134
 
                    // Some of WOY 1 for YEAR year extends into YEAR
1135
 
                    // year-1 if doy < 1.  doy == 0 -- 1 day of WOY 1
1136
 
                    // in previous year; doy == -1 -- 2 days, etc.
1137
 
 
1138
 
                    // Compute the day of week, relative to the first day of week,
1139
 
                    // from 0..6.
1140
 
                    int32_t relDow = computeRelativeDOW();
1141
 
 
1142
 
                    // Range of days that are in YEAR year (as opposed
1143
 
                    // to YEAR year-1) are DOY == 1..6+doy.  Range of
1144
 
                    // days of the week in YEAR year are fdy..fdy + 5
1145
 
                    // + doy.  These are relative DOWs.
1146
 
                    if ((relDow < fdy) || (relDow > (fdy + 5 + doy))) {
1147
 
                        ++year;
1148
 
                    }
1149
 
                }
1150
 
 
1151
 
            } else if (internalGet(WEEK_OF_YEAR) >= 52) {
1152
 
                // FDW = Mon, MDFW = 4, Sat Jan 01 2000, WOY 52, YEAR_WOY 1999
1153
 
                julianDay = computeJulianDayOfYear(isGregorian, year, isLeap);
1154
 
                if (computeDOYfromWOY(julianDay) > yearLength(year)) {
1155
 
                    --year;
1156
 
                }
1157
 
                // It's tempting to take our julianDay and DOY here, in an else
1158
 
                // clause, and return them, since they are correct.  However,
1159
 
                // this neglects the cutover adjustment, and it's easier to
1160
 
                // maintain the code if everything goes through the same control
1161
 
                // path below. - aliu
1162
 
            }
1163
 
        }
1164
 
    }
1165
 
 
1166
 
    // The following if() clause checks if the month field
1167
 
    // predominates.  This set of computations must be done BEFORE
1168
 
    // using the year, since the year value may be adjusted here.
1169
 
    UBool useMonth = FALSE;
1170
 
    int32_t month = 0;
1171
 
    if (bestStamp != kUnset &&
1172
 
        (bestStamp == monthStamp ||
1173
 
         bestStamp == domStamp ||
1174
 
         bestStamp == womStamp ||
1175
 
         bestStamp == dowimStamp)) {
1176
 
        useMonth = TRUE;
1177
 
 
1178
 
        // We have the month specified. Make it 0-based for the algorithm.
1179
 
        month = (monthStamp != kUnset) ? internalGet(MONTH) - JANUARY : 0;
1180
 
 
1181
 
        // If the month is out of range, adjust it into range
1182
 
        if (month < 0 || month > 11) {
1183
 
            int32_t rem[1];
1184
 
            year += floorDivide(month, 12, rem);
1185
 
            month = rem[0];
1186
 
        }
1187
 
    }
1188
 
 
1189
 
    // Compute the julian day number of the day BEFORE the first day of
1190
 
    // January 1, year 1 of the given calendar.  If julianDay == 0, it
1191
 
    // specifies (Jan. 1, 1) - 1, in whatever calendar we are using (Julian
1192
 
    // or Gregorian).
1193
 
    julianDay = computeJulianDayOfYear(isGregorian, year, isLeap);
1194
 
 
1195
 
    if (useMonth) {
1196
 
 
1197
 
        // Move julianDay to the day BEFORE the first of the month.
1198
 
        julianDay += isLeap ? kLeapNumDays[month] : kNumDays[month];
1199
 
        int32_t date = 0;
1200
 
 
1201
 
        if (bestStamp == domStamp ||
1202
 
            bestStamp == monthStamp) {
1203
 
 
1204
 
            date = (domStamp != kUnset) ? internalGet(DAY_OF_MONTH) : 1;
1205
 
        }
1206
 
        else { // assert(bestStamp == womStamp || bestStamp == dowimStamp)
1207
 
            // Compute from day of week plus week number or from the day of
1208
 
            // week plus the day of week in month.  The computations are
1209
 
            // almost identical.
1210
 
 
1211
 
            // Find the day of the week for the first of this month.  This
1212
 
            // is zero-based, with 0 being the locale-specific first day of
1213
 
            // the week.  Add 1 to get first day of month.
1214
 
            int32_t fdm = computeRelativeDOW(julianDay + 1);
1215
 
 
1216
 
            // Find the start of the first week.  This will be a date from
1217
 
            // 1..-6.  It represents the locale-specific first day of the
1218
 
            // week of the first day of the month, ignoring minimal days in
1219
 
            // first week.
1220
 
            date = 1 - fdm + ((fStamp[DAY_OF_WEEK] != kUnset) ?
1221
 
                              (internalGet(DAY_OF_WEEK) - getFirstDayOfWeek()) : 0);
1222
 
 
1223
 
            if (bestStamp == womStamp) {
1224
 
                // Adjust for minimal days in first week.
1225
 
                if ((7 - fdm) < getMinimalDaysInFirstWeek()) 
1226
 
                    date += 7;
1227
 
 
1228
 
                // Now adjust for the week number.
1229
 
                date += 7 * (internalGet(WEEK_OF_MONTH) - 1);
1230
 
            }
1231
 
            else { // assert(bestStamp == dowimStamp)
1232
 
                // Adjust into the month, if needed.
1233
 
                if (date < 1) date += 7;
1234
 
 
1235
 
                // We are basing this on the day-of-week-in-month.  The only
1236
 
                // trickiness occurs if the day-of-week-in-month is
1237
 
                // negative.
1238
 
                int32_t dim = internalGet(DAY_OF_WEEK_IN_MONTH);
1239
 
                if (dim >= 0) {
1240
 
                    date += 7*(dim - 1);
1241
 
                } else {
1242
 
                    // Move date to the last of this day-of-week in this
1243
 
                    // month, then back up as needed.  If dim==-1, we don't
1244
 
                    // back up at all.  If dim==-2, we back up once, etc.
1245
 
                    // Don't back up past the first of the given day-of-week
1246
 
                    // in this month.  Note that we handle -2, -3,
1247
 
                    // etc. correctly, even though values < -1 are
1248
 
                    // technically disallowed.
1249
 
                    date += ((monthLength(internalGet(MONTH), year) - date) / 7 + dim + 1) * 7;
1250
 
                }
1251
 
            }
1252
 
        }
1253
 
 
1254
 
        julianDay += date;
1255
 
    }
1256
 
    else {
1257
 
        // assert(bestStamp == doyStamp || bestStamp == woyStamp ||
1258
 
        // bestStamp == UNSET).  In the last case we should use January 1.
1259
 
 
1260
 
        // No month, start with January 0 (day before Jan 1), then adjust.
1261
 
 
1262
 
        int32_t doy = 0;
1263
 
        UBool doCutoverAdjustment = TRUE;
1264
 
 
1265
 
        if (bestStamp == kUnset) {
1266
 
            doy = 1; // Advance to January 1
1267
 
            doCutoverAdjustment = FALSE;
1268
 
        }
1269
 
        else if (bestStamp == doyStamp) {
1270
 
            doy = internalGet(DAY_OF_YEAR);
1271
 
        }
1272
 
        else if (bestStamp == woyStamp) {
1273
 
            doy = computeDOYfromWOY(julianDay);
1274
 
        }
1275
 
        
1276
 
        // Adjust for cutover year [j81 - aliu]
1277
 
        if (doCutoverAdjustment && year == fGregorianCutoverYear && isGregorian) {
1278
 
            doy -= 10;
1279
 
        }
1280
 
 
1281
 
        julianDay += doy;
1282
 
    }
1283
 
    return julianDay;
1284
 
}
1285
 
 
1286
 
// -------------------------------------
1287
 
 
1288
 
double 
1289
 
GregorianCalendar::millisToJulianDay(UDate millis)
1290
 
{
1291
 
    return (double)kEpochStartAsJulianDay + floorDivide(millis, kOneDay);
1292
 
    //return kEpochStartAsJulianDay + uprv_trunc(millis / kOneDay);
1293
 
}
1294
 
 
1295
 
// -------------------------------------
1296
 
 
1297
 
UDate
1298
 
GregorianCalendar::julianDayToMillis(double julian)
1299
 
{
1300
 
    return (UDate) ((julian - kEpochStartAsJulianDay) * (double) kOneDay);
1301
 
}
1302
 
 
1303
 
// -------------------------------------
1304
 
 
1305
 
double
1306
 
GregorianCalendar::floorDivide(double numerator, double denominator) 
1307
 
{
1308
 
    return uprv_floor(numerator / denominator);
1309
 
}
1310
 
 
1311
 
// -------------------------------------
1312
 
 
1313
 
int32_t 
1314
 
GregorianCalendar::floorDivide(int32_t numerator, int32_t denominator) 
1315
 
{
1316
 
    // We do this computation in order to handle
1317
 
    // a numerator of Long.MIN_VALUE correctly
1318
 
    return (numerator >= 0) ?
1319
 
        numerator / denominator :
1320
 
        ((numerator + 1) / denominator) - 1;
1321
 
}
1322
 
 
1323
 
// -------------------------------------
1324
 
 
1325
 
int32_t 
1326
 
GregorianCalendar::floorDivide(int32_t numerator, int32_t denominator, int32_t remainder[])
1327
 
{
1328
 
    if (numerator >= 0) {
1329
 
        remainder[0] = numerator % denominator;
1330
 
        return numerator / denominator;
1331
 
    }
1332
 
    int32_t quotient = ((numerator + 1) / denominator) - 1;
1333
 
    remainder[0] = numerator - (quotient * denominator);
1334
 
    return quotient;
1335
 
}
1336
 
 
1337
 
// -------------------------------------
1338
 
 
1339
 
int32_t
1340
 
GregorianCalendar::floorDivide(double numerator, int32_t denominator, int32_t remainder[]) 
1341
 
{
1342
 
    double quotient;
1343
 
    if (numerator >= 0) {
1344
 
        quotient = uprv_trunc(numerator / denominator);
1345
 
        remainder[0] = (int32_t)uprv_fmod(numerator, denominator);
1346
 
    } else {
1347
 
        quotient = uprv_trunc((numerator + 1) / denominator) - 1;
1348
 
        remainder[0] = (int32_t)(numerator - (quotient * denominator));
1349
 
    }
1350
 
    if (quotient < INT32_MIN || quotient > INT32_MAX) {
1351
 
        // Normalize out of range values.  It doesn't matter what
1352
 
        // we return for these cases; the data is wrong anyway.  This
1353
 
        // only occurs for years near 2,000,000,000 CE/BCE.
1354
 
        quotient = 0.0; // Or whatever
1355
 
    }
1356
 
    return (int32_t)quotient;
1357
 
}
1358
 
 
1359
 
 
1360
 
// -------------------------------------
1361
 
 
1362
 
int32_t
1363
 
GregorianCalendar::aggregateStamp(int32_t stamp_a, int32_t stamp_b) 
1364
 
{
1365
 
    return (((stamp_a != kUnset && stamp_b != kUnset) 
1366
 
        ? uprv_max(stamp_a, stamp_b)
1367
 
        : kUnset));
1368
 
}
1369
 
 
1370
 
// -------------------------------------
1371
 
 
1372
 
void
1373
 
GregorianCalendar::add(EDateFields field, int32_t amount, UErrorCode& status)
1374
 
{
1375
 
    if (U_FAILURE(status)) 
1376
 
        return;
1377
 
 
1378
 
    if (amount == 0) 
1379
 
        return;   // Do nothing!
1380
 
    complete(status);
1381
 
 
1382
 
    if (field == YEAR || field == YEAR_WOY) {
1383
 
        int32_t year = internalGet(field);
1384
 
        int32_t era = internalGetEra();
1385
 
        year += (era == AD) ? amount : -amount;
1386
 
        if (year > 0)
1387
 
            set(field, year);
1388
 
        else { // year <= 0
1389
 
            set(field, 1 - year);
1390
 
            // if year == 0, you get 1 BC
1391
 
            set(ERA, (AD + BC) - era);
1392
 
        }
1393
 
        pinDayOfMonth();
1394
 
    }
1395
 
    else if (field == MONTH) {
1396
 
        int32_t month = internalGet(MONTH) + amount;
1397
 
        if (month >= 0) {
1398
 
            add(YEAR, (int32_t) (month / 12), status);
1399
 
            set(MONTH, (int32_t) (month % 12));
1400
 
        }
1401
 
        else { // month < 0
1402
 
 
1403
 
            add(YEAR, (int32_t) ((month + 1) / 12) - 1, status);
1404
 
            month %= 12;
1405
 
            if (month < 0) 
1406
 
                month += 12;
1407
 
            set(MONTH, JANUARY + month);
1408
 
        }
1409
 
        pinDayOfMonth();
1410
 
    }
1411
 
    else if (field == ERA) {
1412
 
        int32_t era = internalGet(ERA) + amount;
1413
 
        if (era < 0) 
1414
 
            era = 0;
1415
 
        if (era > 1) 
1416
 
            era = 1;
1417
 
        set(ERA, era);
1418
 
    }
1419
 
    else {
1420
 
        // We handle most fields here.  The algorithm is to add a computed amount
1421
 
        // of millis to the current millis.  The only wrinkle is with DST -- if
1422
 
        // the result of the add operation is to move from DST to Standard, or vice
1423
 
        // versa, we need to adjust by an hour forward or back, respectively.
1424
 
        // Otherwise you get weird effects in which the hour seems to shift when
1425
 
        // you add to the DAY_OF_MONTH field, for instance.
1426
 
 
1427
 
        // We only adjust the DST for fields larger than an hour.  For fields
1428
 
        // smaller than an hour, we cannot adjust for DST without causing problems.
1429
 
        // for instance, if you add one hour to April 5, 1998, 1:00 AM, in PST,
1430
 
        // the time becomes "2:00 AM PDT" (an illegal value), but then the adjustment
1431
 
        // sees the change and compensates by subtracting an hour.  As a result the
1432
 
        // time doesn't advance at all.
1433
 
 
1434
 
        // {sfb} do we want to use a double here, or a int32_t?
1435
 
        // probably a double, since if we used a int32_t in the
1436
 
        // WEEK_OF_YEAR clause below, if delta was greater than approx.
1437
 
        // 7.1 we would reach the limit of a int32_t
1438
 
        double delta = amount;
1439
 
        UBool adjustDST = TRUE;
1440
 
 
1441
 
        switch (field) {
1442
 
        case WEEK_OF_YEAR:
1443
 
        case WEEK_OF_MONTH:
1444
 
        case DAY_OF_WEEK_IN_MONTH:
1445
 
            delta *= 7 * 24 * 60 * 60 * 1000; // 7 days
1446
 
            break;
1447
 
 
1448
 
        case AM_PM:
1449
 
            delta *= 12 * 60 * 60 * 1000; // 12 hrs
1450
 
            break;
1451
 
 
1452
 
        case DATE: // synonym of DAY_OF_MONTH
1453
 
        case DAY_OF_YEAR:
1454
 
        case DAY_OF_WEEK:
1455
 
        case DOW_LOCAL:
1456
 
            delta *= 24 * 60 * 60 * 1000; // 1 day
1457
 
            break;
1458
 
 
1459
 
        case HOUR_OF_DAY:
1460
 
        case HOUR:
1461
 
            delta *= 60 * 60 * 1000; // 1 hour
1462
 
            adjustDST = FALSE;
1463
 
            break;
1464
 
 
1465
 
        case MINUTE:
1466
 
            delta *= 60 * 1000; // 1 minute
1467
 
            adjustDST = FALSE;
1468
 
            break;
1469
 
 
1470
 
        case SECOND:
1471
 
            delta *= 1000; // 1 second
1472
 
            adjustDST = FALSE;
1473
 
            break;
1474
 
 
1475
 
        case MILLISECOND:
1476
 
            adjustDST = FALSE;
1477
 
            break;
1478
 
 
1479
 
        case ZONE_OFFSET:
1480
 
        case DST_OFFSET:
1481
 
        default:
1482
 
            status = U_ILLEGAL_ARGUMENT_ERROR;
1483
 
            return;
1484
 
        }
1485
 
 
1486
 
        // Save the current DST state.
1487
 
        int32_t dst = 0;
1488
 
        if (adjustDST) 
1489
 
            dst = internalGet(DST_OFFSET);
1490
 
 
1491
 
        setTimeInMillis(internalGetTime() + delta, status); // Automatically computes fields if necessary
1492
 
 
1493
 
        if (adjustDST) {
1494
 
            // Now do the DST adjustment alluded to above.
1495
 
            // Only call setTimeInMillis if necessary, because it's an expensive call.
1496
 
            dst -= internalGet(DST_OFFSET);
1497
 
            if(dst!= 0) 
1498
 
                setTimeInMillis(internalGetTime() + dst, status);
1499
 
        }
1500
 
    }
1501
 
}
1502
 
 
1503
 
// -------------------------------------
1504
 
 
1505
 
/**
1506
 
 * Roll a field by a signed amount.
1507
 
 * Note: This will be made public later. [LIU]
1508
 
 */
1509
 
void
1510
 
GregorianCalendar::roll(EDateFields field, int32_t amount, UErrorCode& status)
1511
 
{
1512
 
    if(U_FAILURE(status))
1513
 
        return;
1514
 
 
1515
 
    if (amount == 0) 
1516
 
        return; // Nothing to do
1517
 
 
1518
 
 
1519
 
    int32_t min = 0, max = 0, gap;
1520
 
    if (field >= 0 && field < FIELD_COUNT) {
1521
 
        complete(status);
1522
 
        min = getMinimum(field);
1523
 
        max = getMaximum(field);
1524
 
    }
1525
 
 
1526
 
    /* Some of the fields require special handling to work in the month
1527
 
     * containing the Gregorian cutover point.  Do shared computations
1528
 
     * for these fields here.  [j81 - aliu] */
1529
 
    UBool inCutoverMonth = FALSE;
1530
 
    int32_t cMonthLen=0; // 'c' for cutover; in days
1531
 
    int32_t cDayOfMonth=0; // no discontinuity: [0, cMonthLen)
1532
 
    double cMonthStart=0.0; // in ms
1533
 
    if (field == DAY_OF_MONTH || field == WEEK_OF_MONTH) {
1534
 
        max = monthLength(internalGet(MONTH));
1535
 
        double t = internalGetTime();
1536
 
        // We subtract 1 from the DAY_OF_MONTH to make it zero-based, and an
1537
 
        // additional 10 if we are after the cutover.  Thus the monthStart
1538
 
        // value will be correct iff we actually are in the cutover month.
1539
 
        cDayOfMonth = internalGet(DAY_OF_MONTH) - ((t >= fGregorianCutover) ? 10 : 0);
1540
 
        cMonthStart = t - ((cDayOfMonth - 1) * kOneDay);
1541
 
 
1542
 
        // A month containing the cutover is 10 days shorter.
1543
 
        if ((cMonthStart < fGregorianCutover) &&
1544
 
            (cMonthStart + (cMonthLen=(max-10))*kOneDay >= fGregorianCutover)) {
1545
 
            inCutoverMonth = TRUE;
1546
 
        }
1547
 
    }
1548
 
 
1549
 
    switch (field) {
1550
 
    case ERA:
1551
 
    case YEAR:
1552
 
    case YEAR_WOY:
1553
 
    case AM_PM:
1554
 
    case MINUTE:
1555
 
    case SECOND:
1556
 
    case MILLISECOND:
1557
 
        // These fields are handled simply, since they have fixed minima
1558
 
        // and maxima.  The field DAY_OF_MONTH is almost as simple.  Other
1559
 
        // fields are complicated, since the range within they must roll
1560
 
        // varies depending on the date.
1561
 
        break;
1562
 
 
1563
 
    case HOUR:
1564
 
    case HOUR_OF_DAY:
1565
 
        // Rolling the hour is difficult on the ONSET and CEASE days of
1566
 
        // daylight savings.  For example, if the change occurs at
1567
 
        // 2 AM, we have the following progression:
1568
 
        // ONSET: 12 Std -> 1 Std -> 3 Dst -> 4 Dst
1569
 
        // CEASE: 12 Dst -> 1 Dst -> 1 Std -> 2 Std
1570
 
        // To get around this problem we don't use fields; we manipulate
1571
 
        // the time in millis directly.
1572
 
        {
1573
 
            // Assume min == 0 in calculations below
1574
 
            UDate start = getTime(status);
1575
 
            int32_t oldHour = internalGet(field);
1576
 
            int32_t newHour = (oldHour + amount) % (max + 1);
1577
 
            if(newHour < 0)
1578
 
                newHour += max + 1;
1579
 
            setTime(start + ((double)U_MILLIS_PER_HOUR * (newHour - oldHour)), status);
1580
 
            return;
1581
 
        }
1582
 
    case MONTH:
1583
 
        // Rolling the month involves both pinning the final value to [0, 11]
1584
 
        // and adjusting the DAY_OF_MONTH if necessary.  We only adjust the
1585
 
        // DAY_OF_MONTH if, after updating the MONTH field, it is illegal.
1586
 
        // E.g., <jan31>.roll(MONTH, 1) -> <feb28> or <feb29>.
1587
 
        {
1588
 
            int32_t mon = (internalGet(MONTH) + amount) % 12;
1589
 
            if (mon < 0) 
1590
 
                mon += 12;
1591
 
            set(MONTH, mon);
1592
 
            
1593
 
            // Keep the day of month in range.  We don't want to spill over
1594
 
            // into the next month; e.g., we don't want jan31 + 1 mo -> feb31 ->
1595
 
            // mar3.
1596
 
            // NOTE: We could optimize this later by checking for dom <= 28
1597
 
            // first.  Do this if there appears to be a need. [LIU]
1598
 
            int32_t monthLen = monthLength(mon);
1599
 
            int32_t dom = internalGet(DAY_OF_MONTH);
1600
 
            if (dom > monthLen) 
1601
 
                set(DAY_OF_MONTH, monthLen);
1602
 
            return;
1603
 
        }
1604
 
 
1605
 
    case WEEK_OF_YEAR:
1606
 
        {
1607
 
            // Unlike WEEK_OF_MONTH, WEEK_OF_YEAR never shifts the day of the
1608
 
            // week.  However, rolling the week of the year can have seemingly
1609
 
            // strange effects simply because the year of the week of year
1610
 
            // may be different from the calendar year.  For example, the
1611
 
            // date Dec 28, 1997 is the first day of week 1 of 1998 (if
1612
 
            // weeks start on Sunday and the minimal days in first week is
1613
 
            // <= 3).
1614
 
            int32_t woy = internalGet(WEEK_OF_YEAR);
1615
 
            // Get the ISO year, which matches the week of year.  This
1616
 
            // may be one year before or after the calendar year.
1617
 
            int32_t isoYear = internalGet(YEAR_WOY);
1618
 
            int32_t isoDoy = internalGet(DAY_OF_YEAR);
1619
 
            if (internalGet(MONTH) == Calendar::JANUARY) {
1620
 
                if (woy >= 52) {
1621
 
                    isoDoy += yearLength(isoYear);
1622
 
                }
1623
 
            }
1624
 
            else {
1625
 
                if (woy == 1) {
1626
 
                    isoDoy -= yearLength(isoYear-1);
1627
 
                }
1628
 
            }
1629
 
            woy += amount;
1630
 
            // Do fast checks to avoid unnecessary computation:
1631
 
            if (woy < 1 || woy > 52) {
1632
 
                // Determine the last week of the ISO year.
1633
 
                // We do this using the standard formula we use
1634
 
                // everywhere in this file.  If we can see that the
1635
 
                // days at the end of the year are going to fall into
1636
 
                // week 1 of the next year, we drop the last week by
1637
 
                // subtracting 7 from the last day of the year.
1638
 
                int32_t lastDoy = yearLength(isoYear);
1639
 
                int32_t lastRelDow = (lastDoy - isoDoy + internalGet(DAY_OF_WEEK) -
1640
 
                                  getFirstDayOfWeek()) % 7;
1641
 
                if (lastRelDow < 0) 
1642
 
                    lastRelDow += 7;
1643
 
                if ((6 - lastRelDow) >= getMinimalDaysInFirstWeek()) 
1644
 
                    lastDoy -= 7;
1645
 
                int32_t lastWoy = weekNumber(lastDoy, lastRelDow + 1);
1646
 
                woy = ((woy + lastWoy - 1) % lastWoy) + 1;
1647
 
            }
1648
 
            set(WEEK_OF_YEAR, woy);
1649
 
            set(YEAR_WOY, isoYear); // make YEAR_WOY timestamp > YEAR timestamp
1650
 
            return;
1651
 
        }
1652
 
    case WEEK_OF_MONTH:
1653
 
        {
1654
 
            // This is tricky, because during the roll we may have to shift
1655
 
            // to a different day of the week.  For example:
1656
 
 
1657
 
            //    s  m  t  w  r  f  s
1658
 
            //          1  2  3  4  5
1659
 
            //    6  7  8  9 10 11 12
1660
 
 
1661
 
            // When rolling from the 6th or 7th back one week, we go to the
1662
 
            // 1st (assuming that the first partial week counts).  The same
1663
 
            // thing happens at the end of the month.
1664
 
 
1665
 
            // The other tricky thing is that we have to figure out whether
1666
 
            // the first partial week actually counts or not, based on the
1667
 
            // minimal first days in the week.  And we have to use the
1668
 
            // correct first day of the week to delineate the week
1669
 
            // boundaries.
1670
 
 
1671
 
            // Here's our algorithm.  First, we find the real boundaries of
1672
 
            // the month.  Then we discard the first partial week if it
1673
 
            // doesn't count in this locale.  Then we fill in the ends with
1674
 
            // phantom days, so that the first partial week and the last
1675
 
            // partial week are full weeks.  We then have a nice square
1676
 
            // block of weeks.  We do the usual rolling within this block,
1677
 
            // as is done elsewhere in this method.  If we wind up on one of
1678
 
            // the phantom days that we added, we recognize this and pin to
1679
 
            // the first or the last day of the month.  Easy, eh?
1680
 
 
1681
 
            // Another wrinkle: To fix jitterbug 81, we have to make all this
1682
 
            // work in the oddball month containing the Gregorian cutover.
1683
 
            // This month is 10 days shorter than usual, and also contains
1684
 
            // a discontinuity in the days; e.g., the default cutover month
1685
 
            // is Oct 1582, and goes from day of month 4 to day of month 15.
1686
 
 
1687
 
            // Normalize the DAY_OF_WEEK so that 0 is the first day of the week
1688
 
            // in this locale.  We have dow in 0..6.
1689
 
            int32_t dow = internalGet(DAY_OF_WEEK) - getFirstDayOfWeek();
1690
 
            if (dow < 0) 
1691
 
                dow += 7;
1692
 
 
1693
 
            // Find the day of month, compensating for cutover discontinuity.
1694
 
            int32_t dom = inCutoverMonth ? cDayOfMonth : internalGet(DAY_OF_MONTH);
1695
 
 
1696
 
            // Find the day of the week (normalized for locale) for the first
1697
 
            // of the month.
1698
 
            int32_t fdm = (dow - dom + 1) % 7;
1699
 
            if (fdm < 0) 
1700
 
                fdm += 7;
1701
 
 
1702
 
            // Get the first day of the first full week of the month,
1703
 
            // including phantom days, if any.  Figure out if the first week
1704
 
            // counts or not; if it counts, then fill in phantom days.  If
1705
 
            // not, advance to the first real full week (skip the partial week).
1706
 
            int32_t start;
1707
 
            if ((7 - fdm) < getMinimalDaysInFirstWeek())
1708
 
                start = 8 - fdm; // Skip the first partial week
1709
 
            else
1710
 
                start = 1 - fdm; // This may be zero or negative
1711
 
 
1712
 
            // Get the day of the week (normalized for locale) for the last
1713
 
            // day of the month.
1714
 
            int32_t monthLen = inCutoverMonth ? cMonthLen : monthLength(internalGet(MONTH));
1715
 
            int32_t ldm = (monthLen - dom + dow) % 7;
1716
 
            // We know monthLen >= DAY_OF_MONTH so we skip the += 7 step here.
1717
 
 
1718
 
            // Get the limit day for the blocked-off rectangular month; that
1719
 
            // is, the day which is one past the last day of the month,
1720
 
            // after the month has already been filled in with phantom days
1721
 
            // to fill out the last week.  This day has a normalized DOW of 0.
1722
 
            int32_t limit = monthLen + 7 - ldm;
1723
 
 
1724
 
            // Now roll between start and (limit - 1).
1725
 
            gap = limit - start;
1726
 
            int32_t newDom = (dom + amount*7 - start) % gap;
1727
 
            if (newDom < 0) 
1728
 
                newDom += gap;
1729
 
            newDom += start;
1730
 
 
1731
 
            // Finally, pin to the real start and end of the month.
1732
 
            if (newDom < 1) 
1733
 
                newDom = 1;
1734
 
            if (newDom > monthLen) 
1735
 
                newDom = monthLen;
1736
 
 
1737
 
            // Set the DAY_OF_MONTH.  We rely on the fact that this field
1738
 
            // takes precedence over everything else (since all other fields
1739
 
            // are also set at this point).  If this fact changes (if the
1740
 
            // disambiguation algorithm changes) then we will have to unset
1741
 
            // the appropriate fields here so that DAY_OF_MONTH is attended
1742
 
            // to.
1743
 
 
1744
 
            // If we are in the cutover month, manipulate ms directly.  Don't do
1745
 
            // this in general because it doesn't work across DST boundaries
1746
 
            // (details, details).  This takes care of the discontinuity.
1747
 
            if (inCutoverMonth) {
1748
 
                setTimeInMillis(cMonthStart + (newDom-1)*kOneDay, status);                
1749
 
            } else {
1750
 
                set(DAY_OF_MONTH, newDom);
1751
 
            }
1752
 
            return;
1753
 
        }
1754
 
    case DAY_OF_MONTH:
1755
 
        if (inCutoverMonth) {            
1756
 
            // The default computation works except when the current month
1757
 
            // contains the Gregorian cutover.  We handle this special case
1758
 
            // here.  [j81 - aliu]
1759
 
            double monthLen = cMonthLen * kOneDay;
1760
 
            double msIntoMonth = uprv_fmod(internalGetTime() - cMonthStart +
1761
 
                                          amount * kOneDay, monthLen);
1762
 
            if (msIntoMonth < 0) {
1763
 
                msIntoMonth += monthLen;
1764
 
            }
1765
 
            setTimeInMillis(cMonthStart + msIntoMonth, status);
1766
 
            return;
1767
 
        } else {
1768
 
            max = monthLength(internalGet(MONTH));
1769
 
            // ...else fall through to default computation
1770
 
        }
1771
 
        break;
1772
 
    case DAY_OF_YEAR:
1773
 
        {
1774
 
            // Roll the day of year using millis.  Compute the millis for
1775
 
            // the start of the year, and get the length of the year.
1776
 
            double delta = amount * kOneDay; // Scale up from days to millis
1777
 
            double min2 = internalGetTime() - (internalGet(DAY_OF_YEAR) - 1) * kOneDay;
1778
 
            int32_t yearLen = yearLength();
1779
 
            internalSetTime( uprv_fmod((internalGetTime() + delta - min2), (yearLen * kOneDay)));
1780
 
            if (internalGetTime() < 0) 
1781
 
                internalSetTime( internalGetTime() + yearLen * kOneDay);
1782
 
 
1783
 
            setTimeInMillis(internalGetTime() + min2, status);
1784
 
            return;
1785
 
        }
1786
 
 
1787
 
    case DAY_OF_WEEK:
1788
 
    case DOW_LOCAL:
1789
 
        {
1790
 
            // Roll the day of week using millis.  Compute the millis for
1791
 
            // the start of the week, using the first day of week setting.
1792
 
            // Restrict the millis to [start, start+7days).
1793
 
            double delta = amount * kOneDay; // Scale up from days to millis
1794
 
            // Compute the number of days before the current day in this
1795
 
            // week.  This will be a value 0..6.
1796
 
            int32_t leadDays = internalGet(field) -
1797
 
                ((field == DAY_OF_WEEK) ? getFirstDayOfWeek() : 1);
1798
 
            if (leadDays < 0) 
1799
 
                leadDays += 7;
1800
 
            double min2 = internalGetTime() - leadDays * kOneDay;
1801
 
            internalSetTime(uprv_fmod((internalGetTime() + delta - min2), kOneWeek));
1802
 
            if (internalGetTime() < 0) 
1803
 
                internalSetTime(internalGetTime() + kOneWeek);
1804
 
            setTimeInMillis(internalGetTime() + min2, status);
1805
 
            return;
1806
 
        }
1807
 
    case DAY_OF_WEEK_IN_MONTH:
1808
 
        {
1809
 
            // Roll the day of week in the month using millis.  Determine
1810
 
            // the first day of the week in the month, and then the last,
1811
 
            // and then roll within that range.
1812
 
            double delta = amount * kOneWeek; // Scale up from weeks to millis
1813
 
            // Find the number of same days of the week before this one
1814
 
            // in this month.
1815
 
            int32_t preWeeks = (internalGet(DAY_OF_MONTH) - 1) / 7;
1816
 
            // Find the number of same days of the week after this one
1817
 
            // in this month.
1818
 
            int32_t postWeeks = (monthLength(internalGet(MONTH)) - internalGet(DAY_OF_MONTH)) / 7;
1819
 
            // From these compute the min and gap millis for rolling.
1820
 
            double min2 = internalGetTime() - preWeeks * kOneWeek;
1821
 
            double gap2 = kOneWeek * (preWeeks + postWeeks + 1); // Must add 1!
1822
 
            // Roll within this range
1823
 
            internalSetTime(uprv_fmod((internalGetTime() + delta - min2), gap2));
1824
 
            if (internalGetTime() < 0) 
1825
 
                internalSetTime(internalGetTime() + gap2);
1826
 
            setTimeInMillis(internalGetTime() + min2, status);
1827
 
            return;
1828
 
        }
1829
 
    case ZONE_OFFSET:
1830
 
    case DST_OFFSET:
1831
 
    default:
1832
 
        status = U_ILLEGAL_ARGUMENT_ERROR;
1833
 
        return;
1834
 
        // These fields cannot be rolled
1835
 
    }
1836
 
 
1837
 
    // These are the standard roll instructions.  These work for all
1838
 
    // simple cases, that is, cases in which the limits are fixed, such
1839
 
    // as the hour, the month, and the era.
1840
 
    gap = max - min + 1;
1841
 
    int32_t value = internalGet(field) + amount;
1842
 
    value = (value - min) % gap;
1843
 
    if (value < 0) 
1844
 
        value += gap;
1845
 
    value += min;
1846
 
 
1847
 
    set(field, value);
1848
 
 
1849
 
}
1850
 
 
1851
 
// -------------------------------------
1852
 
 
1853
 
int32_t
1854
 
GregorianCalendar::getMinimum(EDateFields field) const
1855
 
{
1856
 
    return kMinValues[field];
1857
 
}
1858
 
 
1859
 
// -------------------------------------
1860
 
 
1861
 
int32_t
1862
 
GregorianCalendar::getMaximum(EDateFields field) const
1863
 
{
1864
 
    return kMaxValues[field];
1865
 
}
1866
 
 
1867
 
// -------------------------------------
1868
 
 
1869
 
int32_t
1870
 
GregorianCalendar::getGreatestMinimum(EDateFields field) const
1871
 
{
1872
 
    return kMinValues[field];
1873
 
}
1874
 
 
1875
 
// -------------------------------------
1876
 
 
1877
 
int32_t
1878
 
GregorianCalendar::getLeastMaximum(EDateFields field) const
1879
 
{
1880
 
    return kLeastMaxValues[field];
1881
 
}
1882
 
 
1883
 
// -------------------------------------
1884
 
 
1885
 
int32_t 
1886
 
GregorianCalendar::getActualMinimum(EDateFields field) const
1887
 
{
1888
 
    return getMinimum(field);
1889
 
}
1890
 
 
1891
 
// -------------------------------------
1892
 
 
1893
 
int32_t 
1894
 
GregorianCalendar::getActualMaximum(EDateFields field) const
1895
 
{
1896
 
    /* It is a known limitation that the code here (and in getActualMinimum)
1897
 
     * won't behave properly at the extreme limits of GregorianCalendar's
1898
 
     * representable range (except for the code that handles the YEAR
1899
 
     * field).  That's because the ends of the representable range are at
1900
 
     * odd spots in the year.  For calendars with the default Gregorian
1901
 
     * cutover, these limits are Sun Dec 02 16:47:04 GMT 292269055 BC to Sun
1902
 
     * Aug 17 07:12:55 GMT 292278994 AD, somewhat different for non-GMT
1903
 
     * zones.  As a result, if the calendar is set to Aug 1 292278994 AD,
1904
 
     * the actual maximum of DAY_OF_MONTH is 17, not 30.  If the date is Mar
1905
 
     * 31 in that year, the actual maximum month might be Jul, whereas is
1906
 
     * the date is Mar 15, the actual maximum might be Aug -- depending on
1907
 
     * the precise semantics that are desired.  Similar considerations
1908
 
     * affect all fields.  Nonetheless, this effect is sufficiently arcane
1909
 
     * that we permit it, rather than complicating the code to handle such
1910
 
     * intricacies. - liu 8/20/98 */
1911
 
 
1912
 
    UErrorCode status = U_ZERO_ERROR;
1913
 
 
1914
 
    switch (field) {
1915
 
        // we have functions that enable us to fast-path number of days in month
1916
 
        // of year
1917
 
    case DAY_OF_MONTH:
1918
 
        return monthLength(get(MONTH, status));
1919
 
 
1920
 
    case DAY_OF_YEAR:
1921
 
        return yearLength();
1922
 
 
1923
 
        // for week of year, week of month, or day of week in month, we
1924
 
        // just fall back on the default implementation in Calendar (I'm not sure
1925
 
        // we could do better by having special calculations here)
1926
 
    case WEEK_OF_YEAR:
1927
 
    case WEEK_OF_MONTH:
1928
 
    case DAY_OF_WEEK_IN_MONTH:
1929
 
        return Calendar::getActualMaximum(field, status);
1930
 
 
1931
 
    case YEAR:
1932
 
    case YEAR_WOY:
1933
 
        /* The year computation is no different, in principle, from the
1934
 
         * others, however, the range of possible maxima is large.  In
1935
 
         * addition, the way we know we've exceeded the range is different.
1936
 
         * For these reasons, we use the special case code below to handle
1937
 
         * this field.
1938
 
         *
1939
 
         * The actual maxima for YEAR depend on the type of calendar:
1940
 
         *
1941
 
         *     Gregorian = May 17, 292275056 BC - Aug 17, 292278994 AD
1942
 
         *     Julian    = Dec  2, 292269055 BC - Jan  3, 292272993 AD
1943
 
         *     Hybrid    = Dec  2, 292269055 BC - Aug 17, 292278994 AD
1944
 
         *
1945
 
         * We know we've exceeded the maximum when either the month, date,
1946
 
         * time, or era changes in response to setting the year.  We don't
1947
 
         * check for month, date, and time here because the year and era are
1948
 
         * sufficient to detect an invalid year setting.  NOTE: If code is
1949
 
         * added to check the month and date in the future for some reason,
1950
 
         * Feb 29 must be allowed to shift to Mar 1 when setting the year.
1951
 
         */
1952
 
        {
1953
 
            Calendar *cal = (Calendar*)this->clone();
1954
 
            cal->setLenient(TRUE);
1955
 
            
1956
 
            int32_t era = cal->get(ERA, status);
1957
 
            if(U_FAILURE(status))
1958
 
                return 0;
1959
 
 
1960
 
            UDate d = cal->getTime(status);
1961
 
            if(U_FAILURE(status))
1962
 
                return 0;
1963
 
 
1964
 
            /* Perform a binary search, with the invariant that lowGood is a
1965
 
             * valid year, and highBad is an out of range year.
1966
 
             */
1967
 
            int32_t lowGood = kLeastMaxValues[field];
1968
 
            int32_t highBad = kMaxValues[field] + 1;
1969
 
            while((lowGood + 1) < highBad) {
1970
 
                int32_t y = (lowGood + highBad) / 2;
1971
 
                cal->set(field, y);
1972
 
                if(cal->get(field, status) == y && cal->get(ERA, status) == era) {
1973
 
                    lowGood = y;
1974
 
                } 
1975
 
                else {
1976
 
                    highBad = y;
1977
 
                    cal->setTime(d, status); // Restore original fields
1978
 
                }
1979
 
            }
1980
 
            
1981
 
            delete cal;
1982
 
            return lowGood;
1983
 
        }
1984
 
 
1985
 
        // and we know none of the other fields have variable maxima in
1986
 
        // GregorianCalendar, so we can just return the fixed maximum
1987
 
    default:
1988
 
        return getMaximum(field);
1989
 
    }
1990
 
}
1991
 
 
1992
 
// -------------------------------------
1993
 
 
1994
 
UBool
1995
 
GregorianCalendar::inDaylightTime(UErrorCode& status) const
1996
 
{
1997
 
    if (U_FAILURE(status) || !getTimeZone().useDaylightTime()) 
1998
 
        return FALSE;
1999
 
 
2000
 
    // Force an update of the state of the Calendar.
2001
 
    ((GregorianCalendar*)this)->complete(status); // cast away const
2002
 
 
2003
 
    return (UBool)(U_SUCCESS(status) ? (internalGet(DST_OFFSET) != 0) : FALSE);
2004
 
}
2005
 
 
2006
 
// -------------------------------------
2007
 
 
2008
 
/**
2009
 
 * Return the ERA.  We need a special method for this because the
2010
 
 * default ERA is AD, but a zero (unset) ERA is BC.
2011
 
 */
2012
 
int32_t
2013
 
GregorianCalendar::internalGetEra() const {
2014
 
    return isSet(ERA) ? internalGet(ERA) : AD;
2015
 
}
2016
 
 
2017
 
U_NAMESPACE_END
2018
 
 
2019
 
//eof