ICU-2943 calendar update (sync with Java, prepare for other calendars)

X-SVN-Rev: 13494
This commit is contained in:
Steven R. Loomis 2003-10-26 10:24:58 +00:00
parent ec7ae0cdde
commit 92fb1fead2
16 changed files with 3119 additions and 1669 deletions

View file

@ -15,6 +15,7 @@ top_builddir = ..
## All the flags and other definitions are included here.
include $(top_builddir)/icudefs.mk
-include Makefile.local
## Build directory information
subdir = i18n

View file

@ -99,7 +99,7 @@ BuddhistCalendar::monthLength(int32_t month) const
int32_t BuddhistCalendar::internalGetEra() const
{
return isSet(UCAL_ERA) ? internalGet(UCAL_ERA) : BE;
return internalGet(UCAL_ERA, BE);
}
int32_t
@ -117,9 +117,47 @@ BuddhistCalendar::getGregorianYear(UErrorCode &status) const
return year + kBuddhistEraStart;
}
int32_t BuddhistCalendar::handleGetExtendedYear()
{
int32_t year;
if (newerField(UCAL_EXTENDED_YEAR, UCAL_YEAR) == UCAL_EXTENDED_YEAR) {
year = internalGet(UCAL_EXTENDED_YEAR, 1);
} else {
// Ignore the era, as there is only one
year = internalGet(UCAL_YEAR, 1);
}
return year;
}
int32_t BuddhistCalendar::handleComputeMonthStart(int32_t eyear, int32_t month,
UBool useMonth) const
{
return GregorianCalendar::handleComputeMonthStart(eyear+kBuddhistEraStart, month, useMonth);
}
void BuddhistCalendar::handleComputeFields(int32_t julianDay, UErrorCode& status)
{
GregorianCalendar::handleComputeFields(julianDay, status);
int32_t y = internalGet(UCAL_EXTENDED_YEAR) - kBuddhistEraStart;
internalSet(UCAL_EXTENDED_YEAR, y);
internalSet(UCAL_ERA, 0);
internalSet(UCAL_YEAR, y);
}
int32_t BuddhistCalendar::handleGetLimit(UCalendarDateFields field, ELimitType limitType) const
{
if(field == UCAL_ERA) {
return BE;
} else {
return GregorianCalendar::handleGetLimit(field,limitType);
}
}
#if 0
void BuddhistCalendar::timeToFields(UDate theTime, UBool quick, UErrorCode& status)
{
GregorianCalendar::timeToFields(theTime, quick, status);
//Calendar::timeToFields(theTime, quick, status);
int32_t era = internalGet(UCAL_ERA);
int32_t year = internalGet(UCAL_YEAR);
@ -138,6 +176,7 @@ void BuddhistCalendar::timeToFields(UDate theTime, UBool quick, UErrorCode& stat
internalSet(UCAL_ERA, era);
internalSet(UCAL_YEAR, year);
}
#endif
void BuddhistCalendar::add(UCalendarDateFields field, int32_t amount, UErrorCode& status)
{

View file

@ -153,19 +153,25 @@ public:
inline virtual int32_t getLeastMaximum(EDateFields field) const { return getLeastMaximum((UCalendarDateFields)field); }
inline virtual void add(EDateFields field, int32_t amount, UErrorCode& status) { add((UCalendarDateFields)field, amount, status); }
private:
BuddhistCalendar(); // default constructor not implemented
static const char fgClassID;
protected:
virtual int32_t handleGetExtendedYear();
virtual void handleComputeFields(int32_t julianDay, UErrorCode& status);
virtual int32_t handleGetLimit(UCalendarDateFields field, ELimitType limitType) const;
virtual int32_t handleComputeMonthStart(int32_t eyear, int32_t month,
UBool useMonth) const;
// older internals below
virtual int32_t monthLength(int32_t month) const;
virtual int32_t monthLength(int32_t month, int32_t year) const;
int32_t getGregorianYear(UErrorCode& status) const;
virtual int32_t internalGetEra() const;
virtual void timeToFields(UDate theTime, UBool quick, UErrorCode& status);
virtual UBool haveDefaultCentury() const;
virtual UDate defaultCenturyStart() const;
virtual int32_t defaultCenturyStartYear() const;

File diff suppressed because it is too large Load diff

View file

@ -25,6 +25,10 @@
#include "unicode/datefmt.h"
#include "unicode/smpdtfmt.h"
#if defined( U_DEBUG_CALSVC ) || defined (U_DEBUG_CAL)
#include <stdio.h>
#endif
// *****************************************************************************
// class DateFormat
// *****************************************************************************
@ -193,7 +197,13 @@ DateFormat::parse(const UnicodeString& text,
ParsePosition pos(0);
UDate result = parse(text, pos);
if (pos.getIndex() == 0) status = U_ILLEGAL_ARGUMENT_ERROR;
if (pos.getIndex() == 0) {
#if defined (U_DEBUG_CAL)
fprintf(stderr, "%s:%d - - failed to parse - err index %d\n"
, __FILE__, __LINE__, pos.getErrorIndex() );
#endif
status = U_ILLEGAL_ARGUMENT_ERROR;
}
return result;
}

File diff suppressed because it is too large Load diff

View file

@ -47,8 +47,7 @@ double Grego::fieldsToDay(int32_t year, int32_t month, int32_t dom) {
}
void Grego::dayToFields(double day, int32_t& year, int32_t& month,
int32_t& dom, int32_t& dow) {
int32_t doy;
int32_t& dom, int32_t& dow, int32_t& doy) {
// Convert from 1970 CE epoch to 1 CE epoch (Gregorian calendar)
day += JULIAN_1970_CE - JULIAN_1_CE;
@ -82,6 +81,7 @@ void Grego::dayToFields(double day, int32_t& year, int32_t& month,
}
month = (12 * (doy + correction) + 6) / 367; // zero-based month
dom = doy - DAYS_BEFORE[month + (isLeap ? 12 : 0)] + 1; // one-based DOM
doy++; // one-based doy
}
//eof

View file

@ -87,6 +87,14 @@ class U_I18N_API Grego {
*/
static inline int8_t monthLength(int32_t year, int32_t month);
/**
* Return the length of a previous month of the Gregorian calendar.
* @param y the extended year
* @param m the 0-based month number
* @return the number of days in the month previous to the given month
*/
static inline int8_t previousMonthLength(int y, int m);
/**
* Convert a year, month, and day-of-month, given in the proleptic
* Gregorian calendar, to 1970 epoch days.
@ -105,9 +113,38 @@ class U_I18N_API Grego {
* @param month output parameter to receive month (0-based, 0==Jan)
* @param dom output parameter to receive day-of-month (1-based)
* @param dow output parameter to receive day-of-week (1-based, 1==Sun)
* @param doy output parameter to receive day-of-year (1-based)
*/
static void dayToFields(double day, int32_t& year, int32_t& month,
int32_t& dom, int32_t& dow);
int32_t& dom, int32_t& dow, int32_t& doy);
/**
* Convert a 1970-epoch day number to proleptic Gregorian year,
* month, day-of-month, and day-of-week.
* @param day 1970-epoch day (integral value)
* @param year output parameter to receive year
* @param month output parameter to receive month (0-based, 0==Jan)
* @param dom output parameter to receive day-of-month (1-based)
* @param dow output parameter to receive day-of-week (1-based, 1==Sun)
*/
static inline void dayToFields(double day, int32_t& year, int32_t& month,
int32_t& dom, int32_t& dow);
/**
* Converts Julian day to time as milliseconds.
* @param julian the given Julian day number.
* @return time as milliseconds.
* @internal
*/
static inline double julianDayToMillis(int32_t julian);
/**
* Converts time as milliseconds to Julian day.
* @param millis the given milliseconds.
* @return the Julian day number.
* @internal
*/
static inline int32_t millisToJulianDay(double millis);
private:
static const int16_t DAYS_BEFORE[24];
@ -128,6 +165,45 @@ Grego::monthLength(int32_t year, int32_t month) {
return MONTH_LENGTH[month + isLeapYear(year)?12:0];
}
inline int8_t
Grego::previousMonthLength(int y, int m) {
return (m > 0) ? monthLength(y, m-1) : 31;
}
inline void Grego::dayToFields(double day, int32_t& year, int32_t& month,
int32_t& dom, int32_t& dow) {
int32_t doy_unused;
return dayToFields(day,year,month,dom,dow,doy_unused);
}
// Useful millisecond constants
static const double kOneDay = U_MILLIS_PER_DAY; // 86,400,000
static const int32_t kOneHour = 60*60*1000;
#define kOneMinute 60000
#define kOneSecond 1000
#define kOneMillisecond 1
static const double kOneWeek = 7.0 * U_MILLIS_PER_DAY; // 604,800,000
static const int32_t kJan1_1JulianDay = 1721426; // January 1, year 1 (Gregorian)
static const int32_t kEpochStartAsJulianDay = 2440588; // January 1, 1970 (Gregorian)
static const int32_t kEpochYear = 1970;
inline double Grego::julianDayToMillis(int32_t julian)
{
return (julian - kEpochStartAsJulianDay) * kOneDay;
}
inline int32_t Grego::millisToJulianDay(double millis) {
return (int32_t) (kEpochStartAsJulianDay + Math::floorDivide(millis, kOneDay));
}
static const double kEarliestViableMillis = -185331720384000000.0; // minimum representable by julian day -1e17
static const double kLatestViableMillis = 185753453990400000.0; // max representable by julian day +1e17
U_NAMESPACE_END
#endif // !UCONFIG_NO_FORMATTING

View file

@ -17,6 +17,7 @@
#include "japancal.h"
#include "unicode/gregocal.h"
#include "mutex.h"
//#define U_DEBUG_JCAL
@ -309,48 +310,12 @@ const char *JapaneseCalendar::getType() const
return "japanese";
}
int32_t
JapaneseCalendar::getMaximum(UCalendarDateFields field) const
{
if(field == UCAL_ERA) {
return kCurrentEra;
} else {
return GregorianCalendar::getMaximum(field);
}
}
int32_t
JapaneseCalendar::getLeastMaximum(UCalendarDateFields field) const
{
if(field == UCAL_ERA) {
return kCurrentEra;
} else {
return GregorianCalendar::getLeastMaximum(field);
}
}
int32_t
JapaneseCalendar::monthLength(int32_t month, int32_t year) const
{
return GregorianCalendar::monthLength(month,year);
}
int32_t
JapaneseCalendar::monthLength(int32_t month) const
{
UErrorCode status = U_ZERO_ERROR;
int32_t year = internalGet(UCAL_YEAR);
// ignore era
return GregorianCalendar::monthLength(month, getGregorianYear(status));
}
int32_t JapaneseCalendar::getDefaultMonthInYear() const
int32_t JapaneseCalendar::getDefaultMonthInYear()
{
UErrorCode status = U_ZERO_ERROR;
int32_t era = internalGetEra();
int32_t year = getGregorianYear(status);
computeFields(status); // slow
int32_t year = getGregorianYear();
// TODO do we assume we can trust 'era'? What if it is denormalized?
int32_t month = GregorianCalendar::getDefaultMonthInYear();
@ -370,11 +335,12 @@ int32_t JapaneseCalendar::getDefaultMonthInYear() const
return month;
}
int32_t JapaneseCalendar::getDefaultDayInMonth(int32_t month) const
int32_t JapaneseCalendar::getDefaultDayInMonth(int32_t month)
{
UErrorCode status = U_ZERO_ERROR;
int32_t era = internalGetEra();
int32_t year = getGregorianYear(status);
computeFields(status); // slow
int32_t year = getGregorianYear();
int32_t day = GregorianCalendar::getDefaultDayInMonth(month);
if(year == kEraInfo[era].year) {
@ -389,37 +355,32 @@ int32_t JapaneseCalendar::getDefaultDayInMonth(int32_t month) const
int32_t JapaneseCalendar::internalGetEra() const
{
return isSet(UCAL_ERA) ? internalGet(UCAL_ERA) : kCurrentEra;
// OLD
internalGet(UCAL_ERA, kCurrentEra);
}
int32_t
JapaneseCalendar::getGregorianYear(UErrorCode &status) const
int32_t JapaneseCalendar::handleGetExtendedYear()
{
int32_t year = (fStamp[UCAL_YEAR] != kUnset) ? internalGet(UCAL_YEAR) : 1; // default year = 1
int32_t era = kCurrentEra;
if (fStamp[UCAL_ERA] != kUnset) {
era = internalGet(UCAL_ERA);
int32_t year;
if (newerField(UCAL_EXTENDED_YEAR, UCAL_YEAR) == UCAL_EXTENDED_YEAR &&
newerField(UCAL_EXTENDED_YEAR, UCAL_ERA) == UCAL_EXTENDED_YEAR) {
year = internalGet(UCAL_EXTENDED_YEAR, 1);
} else {
// Subtract one because year starts at 1
year = internalGet(UCAL_YEAR) + kEraInfo[internalGet(UCAL_ERA)].year - 1;
}
return year;
if ((era<0)||(era>kCurrentEra)) {
status = U_ILLEGAL_ARGUMENT_ERROR;
return 0 ;
}
return year + kEraInfo[era].year - 1;
}
void JapaneseCalendar::timeToFields(UDate theTime, UBool quick, UErrorCode& status)
{
GregorianCalendar::timeToFields(theTime, quick, status);
// these are the gregorian era and year
int32_t era = internalGet(UCAL_ERA);
int32_t year = internalGet(UCAL_YEAR);
if(era == GregorianCalendar::BC) {
year = 1 - year;
}
// grego [e+y] -> e+y
void JapaneseCalendar::handleComputeFields(int32_t julianDay, UErrorCode& status)
{
//Calendar::timeToFields(theTime, quick, status);
GregorianCalendar::handleComputeFields(julianDay, status);
int32_t year = internalGet(UCAL_EXTENDED_YEAR); // Gregorian year
int32_t low = 0;
// Short circuit for recent years. Most modern computations will
@ -512,6 +473,54 @@ int32_t JapaneseCalendar::defaultCenturyStartYear() const
return 0;
}
static int32_t gJapanCalendarLimits[2][4] = {
// Minimum Greatest min Least max Greatest max
{ 0, 0, JapaneseCalendar::kCurrentEra, JapaneseCalendar::kCurrentEra }, // ERA
{ 1, 1, 0, 0 }, // YEAR
};
static UBool gJapanYearLimitsKnown = FALSE;
int32_t JapaneseCalendar::handleGetLimit(UCalendarDateFields field, ELimitType limitType) const
{
switch(field) {
case UCAL_YEAR:
{
UBool needCalc = FALSE;
{
Mutex m;
needCalc = (gJapanYearLimitsKnown == FALSE);
}
if(needCalc) {
int32_t min = kEraInfo[1].year - kEraInfo[0].year;
int32_t max = min;
for (int32_t i=2; i<kEraCount; i++) { // counting by year, not field (3's)
int32_t d = kEraInfo[i].year - kEraInfo[i-1].year;
if (d < min) {
min = d;
} else if (d > max) {
max = d;
}
}
{
Mutex m;
if(gJapanYearLimitsKnown==FALSE) {
gJapanCalendarLimits[field][UCAL_LEAST_MAXIMUM] = min;
gJapanCalendarLimits[field][UCAL_MAXIMUM] = max;
gJapanYearLimitsKnown = TRUE;
}
}
}
return gJapanCalendarLimits[field][limitType];
}
case UCAL_ERA:
return gJapanCalendarLimits[field][limitType];
default:
return GregorianCalendar::handleGetLimit(field,limitType);
}
}
U_NAMESPACE_END

View file

@ -99,7 +99,7 @@ public:
*/
virtual Calendar* clone(void) const;
virtual int32_t handleGetExtendedYear();
public:
@ -144,26 +144,18 @@ public:
virtual UDate defaultCenturyStart() const;
virtual int32_t defaultCenturyStartYear() const;
/**
* @internal
* API overrides
*/
int32_t getMaximum(UCalendarDateFields field) const;
int32_t getLeastMaximum(UCalendarDateFields field) const;
inline virtual int32_t getMaximum(EDateFields field) const { return getMaximum((UCalendarDateFields)field); }
inline virtual int32_t getLeastMaximum(EDateFields field) const { return getLeastMaximum((UCalendarDateFields)field); }
private:
JapaneseCalendar(); // default constructor not implemented
static const char fgClassID;
protected:
virtual int32_t monthLength(int32_t month) const;
virtual int32_t monthLength(int32_t month, int32_t year) const;
int32_t getGregorianYear(UErrorCode& status) const;
//virtual int32_t monthLength(int32_t month) const;
//virtual int32_t monthLength(int32_t month, int32_t year) const;
// int32_t getGregorianYear(UErrorCode& status) const;
virtual int32_t internalGetEra() const;
virtual void timeToFields(UDate theTime, UBool quick, UErrorCode& status);
virtual void handleComputeFields(int32_t julianDay, UErrorCode& status);
virtual int32_t handleGetLimit(UCalendarDateFields field, ELimitType limitType) const;
/**
* (Overrides Calendar) Converts Calendar's time field values to GMT as
@ -182,14 +174,14 @@ protected:
* Called by computeJulianDay. Returns the default month (0-based) for the year,
* taking year and era into account. Defaults to 0 for Gregorian, which doesn't care.
*/
virtual int32_t getDefaultMonthInYear() const;
virtual int32_t getDefaultMonthInYear() ;
/***
* Called by computeJulianDay. Returns the default day (1-based) for the month,
* taking currently-set year and era into account. Defaults to 1 for Gregorian, which doesn't care.
*/
virtual int32_t getDefaultDayInMonth(int32_t month) const;
virtual int32_t getDefaultDayInMonth(int32_t month) ;
};
inline UClassID

View file

@ -42,6 +42,10 @@
#include "uprops.h"
#include <float.h>
#if defined( U_DEBUG_CALSVC ) || defined (U_DEBUG_CAL)
#include <stdio.h>
#endif
// *****************************************************************************
// class SimpleDateFormat
// *****************************************************************************
@ -78,12 +82,6 @@ static const char gDateTimePatternsTag[]="DateTimePatterns";
UOBJECT_DEFINE_RTTI_IMPLEMENTATION(SimpleDateFormat)
/**
* This value of defaultCenturyStart indicates that the system default is to be
* used. To be removed in 2.8
*/
const UDate SimpleDateFormat::fgSystemDefaultCentury = DBL_MIN;
static const UChar QUOTE = 0x27; // Single quote
//----------------------------------------------------------------------
@ -534,7 +532,8 @@ SimpleDateFormat::fgPatternIndexToCalendarField[] =
UCAL_DAY_OF_YEAR, UCAL_DAY_OF_WEEK_IN_MONTH,
UCAL_WEEK_OF_YEAR, UCAL_WEEK_OF_MONTH,
UCAL_AM_PM, UCAL_HOUR, UCAL_HOUR, UCAL_ZONE_OFFSET,
UCAL_YEAR_WOY, UCAL_DOW_LOCAL
UCAL_YEAR_WOY, UCAL_DOW_LOCAL,UCAL_EXTENDED_YEAR,
UCAL_JULIAN_DAY,UCAL_MILLISECONDS_IN_DAY
};
// Map index into pattern character string to DateFormat field number
@ -549,7 +548,8 @@ SimpleDateFormat::fgPatternIndexToDateFormatField[] = {
DateFormat::kWeekOfMonthField, DateFormat::kAmPmField,
DateFormat::kHour1Field, DateFormat::kHour0Field,
DateFormat::kTimezoneField, DateFormat::kYearWOYField,
DateFormat::kDOWLocalField
DateFormat::kDOWLocalField, DateFormat::kExtendedYearField,
DateFormat::kJulianDayField, DateFormat::kMillisecondsInDayField
};
@ -1079,6 +1079,10 @@ int32_t SimpleDateFormat::subParse(const UnicodeString& text, int32_t& start, UC
UnicodeString temp;
UChar *patternCharPtr = u_strchr(DateFormatSymbols::getPatternUChars(), ch);
#if defined (U_DEBUG_CAL)
//fprintf(stderr, "%s:%d - [%c] st=%d \n", __FILE__, __LINE__, (char) ch, start);
#endif
if (patternCharPtr == NULL) {
return -start;
}

View file

@ -186,6 +186,11 @@ public:
// here will go names for 'Y' and 'e'
YEAR_WOY, // 'Y' Example: 1..big number
DOW_LOCAL, // 'e' Example: 1..7
EXTENDED_YEAR, // Year of this calendar system, encompassing all supra-year fields. For example, in Gregorian/Julian calendars, positive Extended Year values indicate years AD, 1 BC = -1 extended, 2 BC = -2 extended, and so on.
JULIAN_DAY, // Modified Julian day number, encompassing all date-related fields. Demarcates at local midnight.
MILLISECONDS_IN_DAY, // Ranges from 0 to 23:59:59.999 (regardless of DST). This field behaves <em>exactly</em> like a composite of all time-related fields, not including the zone fields. As such, it also reflects discontinuities of those fields on DST transition days. On a day of DST onset, it will jump forward. On a day of DST cessation, it will jump backward. This reflects the fact that is must be combined with the DST_OFFSET field to obtain a unique local time value.
FIELD_COUNT,
DAY_OF_MONTH = DATE // Synonyms
@ -476,7 +481,7 @@ public:
* leniency, this will be set to an error status.
* @deprecated ICU 2.6. use add(UCalendarDateFields field, int32_t amount, UErrorCode& status) instead.
*/
virtual void add(EDateFields field, int32_t amount, UErrorCode& status) = 0;
virtual void add(EDateFields field, int32_t amount, UErrorCode& status);
/**
* UDate Arithmetic function. Adds the specified (signed) amount of time to the given
@ -495,7 +500,7 @@ public:
* leniency, this will be set to an error status.
* @draft ICU 2.6.
*/
virtual void add(UCalendarDateFields field, int32_t amount, UErrorCode& status) = 0;
virtual void add(UCalendarDateFields field, int32_t amount, UErrorCode& status);
/**
* Time Field Rolling function. Rolls (up/down) a single unit of time on the given
@ -593,7 +598,7 @@ public:
* an error status.
* @draft ICU 2.6.
*/
virtual void roll(UCalendarDateFields field, int32_t amount, UErrorCode& status) = 0;
virtual void roll(UCalendarDateFields field, int32_t amount, UErrorCode& status);
/**
* Return the difference between the given time and the time this
@ -843,7 +848,7 @@ public:
* @return The minimum value for the given time field.
* @deprecated ICU 2.6. Use getMinimum(UCalendarDateFields field) instead.
*/
virtual int32_t getMinimum(EDateFields field) const = 0;
virtual int32_t getMinimum(EDateFields field) const;
/**
* Gets the minimum value for the given time field. e.g., for Gregorian
@ -853,7 +858,7 @@ public:
* @return The minimum value for the given time field.
* @draft ICU 2.6.
*/
virtual int32_t getMinimum(UCalendarDateFields field) const = 0;
virtual int32_t getMinimum(UCalendarDateFields field) const;
/**
* Gets the maximum value for the given time field. e.g. for Gregorian DAY_OF_MONTH,
@ -863,7 +868,7 @@ public:
* @return The maximum value for the given time field.
* @deprecated ICU 2.6. Use getMaximum(UCalendarDateFields field) instead.
*/
virtual int32_t getMaximum(EDateFields field) const = 0;
virtual int32_t getMaximum(EDateFields field) const;
/**
* Gets the maximum value for the given time field. e.g. for Gregorian DAY_OF_MONTH,
@ -873,7 +878,7 @@ public:
* @return The maximum value for the given time field.
* @draft ICU 2.6.
*/
virtual int32_t getMaximum(UCalendarDateFields field) const = 0;
virtual int32_t getMaximum(UCalendarDateFields field) const;
/**
* Gets the highest minimum value for the given field if varies. Otherwise same as
@ -883,7 +888,7 @@ public:
* @return The highest minimum value for the given time field.
* @deprecated ICU 2.6. Use getGreatestMinimum(UCalendarDateFields field) instead.
*/
virtual int32_t getGreatestMinimum(EDateFields field) const = 0;
virtual int32_t getGreatestMinimum(EDateFields field) const;
/**
* Gets the highest minimum value for the given field if varies. Otherwise same as
@ -893,7 +898,7 @@ public:
* @return The highest minimum value for the given time field.
* @draft ICU 2.6.
*/
virtual int32_t getGreatestMinimum(UCalendarDateFields field) const = 0;
virtual int32_t getGreatestMinimum(UCalendarDateFields field) const;
/**
* Gets the lowest maximum value for the given field if varies. Otherwise same as
@ -903,7 +908,7 @@ public:
* @return The lowest maximum value for the given time field.
* @deprecated ICU 2.6. Use getLeastMaximum(UCalendarDateFields field) instead.
*/
virtual int32_t getLeastMaximum(EDateFields field) const = 0;
virtual int32_t getLeastMaximum(EDateFields field) const;
/**
* Gets the lowest maximum value for the given field if varies. Otherwise same as
@ -913,7 +918,7 @@ public:
* @return The lowest maximum value for the given time field.
* @draft ICU 2.6.
*/
virtual int32_t getLeastMaximum(UCalendarDateFields field) const = 0;
virtual int32_t getLeastMaximum(UCalendarDateFields field) const;
/**
* Return the minimum value that this field could have, given the current date.
@ -1206,7 +1211,7 @@ protected:
* leniency, this will be set to an error status.
* @stable ICU 2.0
*/
virtual void computeTime(UErrorCode& status) = 0;
virtual void computeTime(UErrorCode& status);
/**
* Converts GMT as milliseconds to time field values. This allows you to sync up the
@ -1219,7 +1224,7 @@ protected:
* leniency, this will be set to an error status.
* @stable ICU 2.0
*/
virtual void computeFields(UErrorCode& status) = 0;
virtual void computeFields(UErrorCode& status);
/**
* Gets this Calendar's current time as a long.
@ -1263,13 +1268,25 @@ protected:
*/
inline int32_t internalGet(EDateFields field) const {return fFields[field];}
/**
* Gets the value for a given time field. Subclasses can use this function to get
* field values without forcing recomputation of time. If the field's stamp is UNSET,
* the defaultValue is used.
*
* @param field The given time field.
* @param defaultValue a default value used if the field is unset.
* @return The value for the given time field.
* @internal
*/
inline int32_t internalGet(UCalendarDateFields field, int32_t defaultValue) const {return fStamp[field]>kUnset ? fFields[field] : defaultValue;}
/**
* Gets the value for a given time field. Subclasses can use this function to get
* field values without forcing recomputation of time.
*
* @param field The given time field.
* @return The value for the given time field.
* @draft ICU 2.6.
* @internal
*/
inline int32_t internalGet(UCalendarDateFields field) const {return fFields[field];}
@ -1295,6 +1312,200 @@ protected:
*/
inline void internalSet(UCalendarDateFields field, int32_t value);
/**
* Prepare this calendar for computing the actual minimum or maximum.
* This method modifies this calendar's fields; it is called on a
* temporary calendar.
* @internal
*/
virtual void prepareGetActual(UCalendarDateFields field, UBool isMinimum, UErrorCode &status);
enum ELimitType { U_CAL_LIMIT_MINIMUM = 0, U_CAL_LIMIT_GREATEST_MINIMUM, U_CAL_LIMIT_LEAST_MAXIMUM, U_CAL_LIMIT_MAXIMUM, U_CAL_LIMIT_COUNT };
/**
* Subclass API for defining limits of different types.
* Subclasses must implement this method to return limits for the
* following fields:
*
* <pre>UCAL_ERA
* UCAL_YEAR
* UCAL_MONTH
* UCAL_WEEK_OF_YEAR
* UCAL_WEEK_OF_MONTH
* UCAL_DATE (DAY_OF_MONTH on Java)
* UCAL_DAY_OF_YEAR
* UCAL_DAY_OF_WEEK_IN_MONTH
* UCAL_YEAR_WOY
* UCAL_EXTENDED_YEAR</pre>
*
* @param field one of the above field numbers
* @param limitType one of <code>MINIMUM</code>, <code>GREATEST_MINIMUM</code>,
* <code>LEAST_MAXIMUM</code>, or <code>MAXIMUM</code>
* @internal
*/
virtual int32_t handleGetLimit(UCalendarDateFields field, ELimitType limitType) const = 0;
/**
* Return a limit for a field.
* @param field the field, from 0..UCAL_MAX_FIELD</code>
* @param limitType the type specifier for the limit
* @see #ELimitType
* @internal
*/
int32_t getLimit(UCalendarDateFields field, ELimitType limitType) const;
/**
* Return the Julian day number of day before the first day of the
* given month in the given extended year. Subclasses should override
* this method to implement their calendar system.
* @param eyear the extended year
* @param month the zero-based month, or 0 if useMonth is false
* @param useMonth if false, compute the day before the first day of
* the given year, otherwise, compute the day before the first day of
* the given month
* @param return the Julian day number of the day before the first
* day of the given month and year
* @internal
*/
virtual int32_t handleComputeMonthStart(int32_t eyear, int32_t month,
UBool useMonth) const = 0;
/**
* Return the number of days in the given month of the given extended
* year of this calendar system. Subclasses should override this
* method if they can provide a more correct or more efficient
* implementation than the default implementation in Calendar.
* @internal
*/
virtual int32_t handleGetMonthLength(int32_t extendedYear, int32_t month) const ;
/**
* Return the number of days in the given extended year of this
* calendar system. Subclasses should override this method if they can
* provide a more correct or more efficient implementation than the
* default implementation in Calendar.
* @stable ICU 2.0
*/
virtual int32_t handleGetYearLength(int eyear) const;
/**
* Return the extended year defined by the current fields. This will
* use the UCAL_EXTENDED_YEAR field or the UCAL_YEAR and supra-year fields (such
* as UCAL_ERA) specific to the calendar system, depending on which set of
* fields is newer.
* @return the extended year
* @internal
*/
virtual int32_t handleGetExtendedYear() = 0;
/**
* Subclasses may override this. This method calls
* handleGetMonthLength() to obtain the calendar-specific month
* length.
* @internal
*/
virtual int32_t handleComputeJulianDay(UCalendarDateFields bestField);
/**
* Subclasses must override this to convert from week fields
* (YEAR_WOY and WEEK_OF_YEAR) to an extended year in the case
* where YEAR, EXTENDED_YEAR are not set.
* The Calendar implementation assumes yearWoy is in extended gregorian form
* @internal
* @return the extended year, UCAL_EXTENDED_YEAR
*/
virtual int32_t handleGetExtendedYearFromWeekFields(int32_t yearWoy, int32_t woy);
int32_t computeJulianDay();
/**
* Compute the milliseconds in the day from the fields. This is a
* value from 0 to 23:59:59.999 inclusive, unless fields are out of
* range, in which case it can be an arbitrary value. This value
* reflects local zone wall time.
* @internal
*/
int32_t computeMillisInDay();
/**
* This method can assume EXTENDED_YEAR has been set.
* @param millis milliseconds of the date fields
* @param millisInDay milliseconds of the time fields; may be out
* or range.
* @internal
*/
int32_t computeZoneOffset(double millis, int32_t millisInDay, UErrorCode &ec);
/**
* Return the best stamp in a range.
* @param start first enum to look at
* @param end last enum to look at
* @param best stamp prior to function call
*/
int32_t newestStamp(UCalendarDateFields start, UCalendarDateFields end, int32_t bestSoFar) const;
/**
* Value to OR against resolve table field values for remapping.
* @see #resolveFields
* @internal
*/
static const int32_t kResolveRemap;
/**
* Type for resolution tables
*/
typedef int32_t UFieldResolutionTable[12][8];
static const UFieldResolutionTable kDatePrecedence[];
static const UFieldResolutionTable kYearPrecedence[];
static const UFieldResolutionTable kDOWPrecedence[];
/**
* Given a precedence table, return the newest field combination in
* the table, or -1 if none is found.
*
* <p>The precedence table is a 3-dimensional array of integers. It
* may be thought of as an array of groups. Each group is an array of
* lines. Each line is an array of field numbers. Within a line, if
* all fields are set, then the time stamp of the line is taken to be
* the stamp of the most recently set field. If any field of a line is
* unset, then the line fails to match. Within a group, the line with
* the newest time stamp is selected. The first field of the line is
* returned to indicate which line matched.
*
* <p>In some cases, it may be desirable to map a line to field that
* whose stamp is NOT examined. For example, if the best field is
* DAY_OF_WEEK then the DAY_OF_WEEK_IN_MONTH algorithm may be used. In
* order to do this, insert the value <code>REMAP_RESOLVE | F</code> at
* the start of the line, where <code>F</code> is the desired return
* field value. This field will NOT be examined; it only determines
* the return value if the other fields in the line are the newest.
*
* <p>If all lines of a group contain at least one unset field, then no
* line will match, and the group as a whole will fail to match. In
* that case, the next group will be processed. If all groups fail to
* match, then -1 is returned.
* @internal
*/
UCalendarDateFields resolveFields(const UFieldResolutionTable *precedenceTable);
virtual const UFieldResolutionTable* getFieldResolutionTable() const;
/**
* Return the field that is newer, either defaultField, or
* alternateField. If neither is newer or neither is set, return defaultField.
* @internal
*/
UCalendarDateFields newerField(UCalendarDateFields defaultField, UCalendarDateFields alternateField) const;
private:
int32_t getActualHelper(UCalendarDateFields field, int32_t startValue, int32_t endValue, UErrorCode &status) const;
protected:
/**
* The flag which indicates if the current time is set in the calendar.
@ -1346,7 +1557,7 @@ protected:
/**
* The flags which tell if a specified time field for the calendar is set.
* @stable ICU 2.0
* @deprecated ICU 2.8 use (fStamp[n]!=kUnset)
*/
UBool fIsSet[UCAL_FIELD_COUNT];
@ -1367,6 +1578,197 @@ protected:
*/
int32_t fStamp[UCAL_FIELD_COUNT];
/**
* Subclasses may override this method to compute several fields
* specific to each calendar system. These are:
*
* <ul><li>ERA
* <li>YEAR
* <li>MONTH
* <li>DAY_OF_MONTH
* <li>DAY_OF_YEAR
* <li>EXTENDED_YEAR</ul>
*
* Subclasses can refer to the DAY_OF_WEEK and DOW_LOCAL fields, which
* will be set when this method is called. Subclasses can also call
* the getGregorianXxx() methods to obtain Gregorian calendar
* equivalents for the given Julian day.
*
* <p>In addition, subclasses should compute any subclass-specific
* fields, that is, fields from BASE_FIELD_COUNT to
* getFieldCount() - 1.
*
* <p>The default implementation in <code>Calendar</code> implements
* a pure proleptic Gregorian calendar.
* @internal
*/
virtual void handleComputeFields(int32_t julianDay, UErrorCode &status);
/**
* Return the extended year on the Gregorian calendar as computed by
* <code>computeGregorianFields()</code>.
* @see #computeGregorianFields
*/
int32_t getGregorianYear() const {
return fGregorianYear;
}
/**
* Return the month (0-based) on the Gregorian calendar as computed by
* <code>computeGregorianFields()</code>.
* @see #computeGregorianFields
*/
int32_t getGregorianMonth() const {
return fGregorianMonth;
}
/**
* Return the day of year (1-based) on the Gregorian calendar as
* computed by <code>computeGregorianFields()</code>.
* @see #computeGregorianFields
*/
int32_t getGregorianDayOfYear() const {
return fGregorianDayOfYear;
}
/**
* Return the day of month (1-based) on the Gregorian calendar as
* computed by <code>computeGregorianFields()</code>.
* @see #computeGregorianFields
*/
int32_t getGregorianDayOfMonth() const {
return fGregorianDayOfMonth;
}
/**
* Called by computeJulianDay. Returns the default month (0-based) for the year,
* taking year and era into account. Defaults to 0 for Gregorian, which doesn't care.
* @internal
*/
virtual int32_t getDefaultMonthInYear() ;
/**
* Called by computeJulianDay. Returns the default day (1-based) for the month,
* taking currently-set year and era into account. Defaults to 1 for Gregorian, which doesn't care.
* @internal
*/
virtual int32_t getDefaultDayInMonth(int32_t /*month*/);
//-------------------------------------------------------------------------
// Protected utility methods for use by subclasses. These are very handy
// for implementing add, roll, and computeFields.
//-------------------------------------------------------------------------
/**
* Adjust the specified field so that it is within
* the allowable range for the date to which this calendar is set.
* For example, in a Gregorian calendar pinning the {@link #DAY_OF_MONTH DAY_OF_MONTH}
* field for a calendar set to April 31 would cause it to be set
* to April 30.
* <p>
* <b>Subclassing:</b>
* <br>
* This utility method is intended for use by subclasses that need to implement
* their own overrides of {@link #roll roll} and {@link #add add}.
* <p>
* <b>Note:</b>
* <code>pinField</code> is implemented in terms of
* {@link #getActualMinimum getActualMinimum}
* and {@link #getActualMaximum getActualMaximum}. If either of those methods uses
* a slow, iterative algorithm for a particular field, it would be
* unwise to attempt to call <code>pinField</code> for that field. If you
* really do need to do so, you should override this method to do
* something more efficient for that field.
* <p>
* @param field The calendar field whose value should be pinned.
*
* @see #getActualMinimum
* @see #getActualMaximum
* @stable ICU 2.0
*/
virtual void pinField(UCalendarDateFields field, UErrorCode& status);
/**
* Return the week number of a day, within a period. This may be the week number in
* a year or the week number in a month. Usually this will be a value >= 1, but if
* some initial days of the period are excluded from week 1, because
* {@link #getMinimalDaysInFirstWeek getMinimalDaysInFirstWeek} is > 1, then
* the week number will be zero for those
* initial days. This method requires the day number and day of week for some
* known date in the period in order to determine the day of week
* on the desired day.
* <p>
* <b>Subclassing:</b>
* <br>
* This method is intended for use by subclasses in implementing their
* {@link #computeTime computeTime} and/or {@link #computeFields computeFields} methods.
* It is often useful in {@link #getActualMinimum getActualMinimum} and
* {@link #getActualMaximum getActualMaximum} as well.
* <p>
* This variant is handy for computing the week number of some other
* day of a period (often the first or last day of the period) when its day
* of the week is not known but the day number and day of week for some other
* day in the period (e.g. the current date) <em>is</em> known.
* <p>
* @param desiredDay The {@link #DAY_OF_YEAR DAY_OF_YEAR} or
* {@link #DAY_OF_MONTH DAY_OF_MONTH} whose week number is desired.
* Should be 1 for the first day of the period.
*
* @param knownDayOfPeriod The {@link #DAY_OF_YEAR DAY_OF_YEAR}
* or {@link #DAY_OF_MONTH DAY_OF_MONTH} for a day in the period whose
* {@link #DAY_OF_WEEK DAY_OF_WEEK} is specified by the
* <code>knownDayOfWeek</code> parameter.
* Should be 1 for first day of period.
*
* @param knownDayOfWeek The {@link #DAY_OF_WEEK DAY_OF_WEEK} for the day
* corresponding to the <code>knownDayOfPeriod</code> parameter.
* 1-based with 1=Sunday.
*
* @return The week number (one-based), or zero if the day falls before
* the first week because
* {@link #getMinimalDaysInFirstWeek getMinimalDaysInFirstWeek}
* is more than one.
*/
int32_t weekNumber(int32_t desiredDay, int32_t dayOfPeriod, int32_t dayOfWeek);
/**
* Return the week number of a day, within a period. This may be the week number in
* a year, or the week number in a month. Usually this will be a value >= 1, but if
* some initial days of the period are excluded from week 1, because
* {@link #getMinimalDaysInFirstWeek getMinimalDaysInFirstWeek} is > 1,
* then the week number will be zero for those
* initial days. This method requires the day of week for the given date in order to
* determine the result.
* <p>
* <b>Subclassing:</b>
* <br>
* This method is intended for use by subclasses in implementing their
* {@link #computeTime computeTime} and/or {@link #computeFields computeFields} methods.
* It is often useful in {@link #getActualMinimum getActualMinimum} and
* {@link #getActualMaximum getActualMaximum} as well.
* <p>
* @param dayOfPeriod The {@link #DAY_OF_YEAR DAY_OF_YEAR} or
* {@link #DAY_OF_MONTH DAY_OF_MONTH} whose week number is desired.
* Should be 1 for the first day of the period.
*
* @param dayofWeek The {@link #DAY_OF_WEEK DAY_OF_WEEK} for the day
* corresponding to the <code>dayOfPeriod</code> parameter.
* 1-based with 1=Sunday.
*
* @return The week number (one-based), or zero if the day falls before
* the first week because
* {@link #getMinimalDaysInFirstWeek getMinimalDaysInFirstWeek}
* is more than one.
*/
inline int32_t weekNumber(int32_t dayOfPeriod, int32_t dayOfWeek);
/**
* returns the local DOW, valid range 0..6
*/
int32_t getLocalDOW();
private:
// The next available value for stampp[]
@ -1430,6 +1832,118 @@ private:
* The resource tag where the default calendar is stored.
*/
static const char kDefaultCalendar[];
/**
* The Gregorian year, as computed by computeGregorianFields() and
* returned by getGregorianYear().
*/
int32_t fGregorianYear;
/**
* The Gregorian month, as computed by computeGregorianFields() and
* returned by getGregorianMonth().
*/
int32_t fGregorianMonth;
/**
* The Gregorian day of the year, as computed by
* computeGregorianFields() and returned by getGregorianDayOfYear().
*/
int32_t fGregorianDayOfYear;
/**
* The Gregorian day of the month, as computed by
* computeGregorianFields() and returned by getGregorianDayOfMonth().
*/
int32_t fGregorianDayOfMonth;
/* calculations */
/**
* Compute the Gregorian calendar year, month, and day of month from
* the given Julian day. These values are not stored in fields, but in
* member variables gregorianXxx. Also compute the DAY_OF_WEEK and
* DOW_LOCAL fields.
*/
void computeGregorianAndDOWFields(int32_t julianDay, UErrorCode &ec);
/**
* Compute the Gregorian calendar year, month, and day of month from the
* Julian day. These values are not stored in fields, but in member
* variables gregorianXxx. They are used for time zone computations and by
* subclasses that are Gregorian derivatives. Subclasses may call this
* method to perform a Gregorian calendar millis->fields computation.
* To perform a Gregorian calendar fields->millis computation, call
* computeGregorianMonthStart().
* @see #computeGregorianMonthStart
*/
void computeGregorianFields(int32_t julianDay, UErrorCode &ec);
/**
* Compute the fields WEEK_OF_YEAR, YEAR_WOY, WEEK_OF_MONTH,
* DAY_OF_WEEK_IN_MONTH, and DOW_LOCAL from EXTENDED_YEAR, YEAR,
* DAY_OF_WEEK, and DAY_OF_YEAR. The latter fields are computed by the
* subclass based on the calendar system.
*
* <p>The YEAR_WOY field is computed simplistically. It is equal to YEAR
* most of the time, but at the year boundary it may be adjusted to YEAR-1
* or YEAR+1 to reflect the overlap of a week into an adjacent year. In
* this case, a simple increment or decrement is performed on YEAR, even
* though this may yield an invalid YEAR value. For instance, if the YEAR
* is part of a calendar system with an N-year cycle field CYCLE, then
* incrementing the YEAR may involve incrementing CYCLE and setting YEAR
* back to 0 or 1. This is not handled by this code, and in fact cannot be
* simply handled without having subclasses define an entire parallel set of
* fields for fields larger than or equal to a year. This additional
* complexity is not warranted, since the intention of the YEAR_WOY field is
* to support ISO 8601 notation, so it will typically be used with a
* proleptic Gregorian calendar, which has no field larger than a year.
*/
void computeWeekFields(UErrorCode &ec);
/**
* Ensure that each field is within its valid range by calling {@link
* #validateField(int)} on each field that has been set. This method
* should only be called if this calendar is not lenient.
* @see #isLenient
* @see #validateField(int)
* @internal
*/
void validateFields(UErrorCode &status);
/**
* Validate a single field of this calendar. Subclasses should
* override this method to validate any calendar-specific fields.
* Generic fields can be handled by
* <code>Calendar.validateField()</code>.
* @see #validateField(int, int, int)
* @internal
*/
virtual void validateField(UCalendarDateFields field, UErrorCode &status);
/**
* Validate a single field of this calendar given its minimum and
* maximum allowed value. If the field is out of range,
* <code>U_ILLEGAL_ARGUMENT_ERROR</code> will be set. Subclasses may
* use this method in their implementation of {@link
* #validateField(int)}.
* @internal
*/
void validateField(UCalendarDateFields field, int32_t min, int32_t max, UErrorCode& status);
protected:
/**
* Convert a quasi Julian date to the day of the week. The Julian date used here is
* not a true Julian date, since it is measured from midnight, not noon. Return
* value is one-based.
*
* @param julian The given Julian date number.
* @return Day number from 1..7 (SUN..SAT).
*/
static uint8_t julianDayToDayOfWeek(double julian);
public:
/**
@ -1537,6 +2051,8 @@ inline void
Calendar::internalSet(UCalendarDateFields field, int32_t value)
{
fFields[field] = value;
fStamp[field] = kInternallySet;
fIsSet[field] = TRUE; // Remove later
}
inline void
@ -1545,6 +2061,22 @@ Calendar::internalSet(EDateFields field, int32_t value)
internalSet((UCalendarDateFields) field, value);
}
inline uint8_t Calendar::julianDayToDayOfWeek(double julian)
{
// If julian is negative, then julian%7 will be negative, so we adjust
// accordingly. We add 1 because Julian day 0 is Monday.
int8_t dayOfWeek = (int8_t) uprv_fmod(julian + 1, 7);
uint8_t result = (uint8_t)(dayOfWeek + ((dayOfWeek < 0) ? (7+UCAL_SUNDAY ) : UCAL_SUNDAY));
return result;
}
inline int32_t Calendar::weekNumber(int32_t dayOfPeriod, int32_t dayOfWeek)
{
return weekNumber(dayOfPeriod, dayOfPeriod, dayOfWeek);
}
U_NAMESPACE_END
#endif /* #if !UCONFIG_NO_FORMATTING */

View file

@ -167,7 +167,9 @@ public:
kTimezoneField, // TIMEZONE field alignment.
kYearWOYField, // Corrected year for week representation
kDOWLocalField, // localized day of week
kExtendedYearField,
kJulianDayField,
kMillisecondsInDayField,
/**

View file

@ -353,7 +353,7 @@ public:
* an error status.
* @deprecated ICU 2.6. Use add(UCalendarDateFields field, int32_t amount, UErrorCode& status) instead.
*/
virtual void add(EDateFields field, int32_t amount, UErrorCode& status);
// virtual void add(EDateFields field, int32_t amount, UErrorCode& status);
/**
* (Overrides Calendar) UDate Arithmetic function. Adds the specified (signed) amount
@ -367,7 +367,7 @@ public:
* an error status.
* @draft ICU 2.6.
*/
virtual void add(UCalendarDateFields field, int32_t amount, UErrorCode& status);
// virtual void add(UCalendarDateFields field, int32_t amount, UErrorCode& status);
/**
* (Overrides Calendar) Rolls up or down by the given amount in the specified field.
@ -395,81 +395,6 @@ public:
*/
virtual void roll(UCalendarDateFields field, int32_t amount, UErrorCode& status);
/**
* (Overrides Calendar) Returns minimum value for the given field. e.g. for
* Gregorian DAY_OF_MONTH, 1.
* @param field the time field.
* @return minimum value for the given field
* @deprecated ICU 2.6. Use getMinimum(UCalendarDateFields field) instead.
*/
virtual int32_t getMinimum(EDateFields field) const;
/**
* (Overrides Calendar) Returns minimum value for the given field. e.g. for
* Gregorian DAY_OF_MONTH, 1.
* @param field the time field.
* @return minimum value for the given field
* @draft ICU 2.6.
*/
virtual int32_t getMinimum(UCalendarDateFields field) const;
/**
* (Overrides Calendar) Returns maximum value for the given field. e.g. for
* Gregorian DAY_OF_MONTH, 31.
* @param field the time field.
* @return maximum value for the given field
* @deprecated ICU 2.6. Use getMaximum(UCalendarDateFields field) instead.
*/
virtual int32_t getMaximum(EDateFields field) const;
/**
* (Overrides Calendar) Returns maximum value for the given field. e.g. for
* Gregorian DAY_OF_MONTH, 31.
* @param field the time field.
* @return maximum value for the given field
* @draft ICU 2.6.
*/
virtual int32_t getMaximum(UCalendarDateFields field) const;
/**
* (Overrides Calendar) Returns highest minimum value for the given field if varies.
* Otherwise same as getMinimum(). For Gregorian, no difference.
* @param field the time field.
* @return highest minimum value for the given field if varies.
* Otherwise same as getMinimum().
* @deprecated ICU 2.6. Use getGreatestMinimum(UCalendarDateFields field) instead.
*/
virtual int32_t getGreatestMinimum(EDateFields field) const;
/**
* (Overrides Calendar) Returns highest minimum value for the given field if varies.
* Otherwise same as getMinimum(). For Gregorian, no difference.
* @param field the time field.
* @return highest minimum value for the given field if varies.
* Otherwise same as getMinimum().
* @draft ICU 2.6.
*/
virtual int32_t getGreatestMinimum(UCalendarDateFields field) const;
/**
* (Overrides Calendar) Returns lowest maximum value for the given field if varies.
* Otherwise same as getMaximum(). For Gregorian DAY_OF_MONTH, 28.
* @param field the time field.
* @return lowest maximum value for the given field if varies.
* Otherwise same as getMaximum().
* @deprecated ICU 2.6. Use getLeastMaximum(UCalendarDateFields field) instead.
*/
virtual int32_t getLeastMaximum(EDateFields field) const;
/**
* (Overrides Calendar) Returns lowest maximum value for the given field if varies.
* Otherwise same as getMaximum(). For Gregorian DAY_OF_MONTH, 28.
* @param field the time field.
* @return lowest maximum value for the given field if varies.
* Otherwise same as getMaximum().
* @draft ICU 2.6.
*/
virtual int32_t getLeastMaximum(UCalendarDateFields field) const;
/**
* Return the minimum value that this field could have, given the current date.
@ -507,9 +432,14 @@ public:
* for some years the actual maximum for MONTH is 12, and for others 13.
* @param field the time field.
* @return the maximum value that this field could have, given the current date.
* @draft ICU 2.6.
* @internal.
*/
int32_t getActualMaximum(UCalendarDateFields field) const;
virtual int32_t getActualMaximum(UCalendarDateFields field, UErrorCode& status) const;
/*
* @draft ICU 2.6
*/
inline int32_t getActualMaximum(UCalendarDateFields field) const;
/**
* (Overrides Calendar) Return true if the current date for this Calendar is in
@ -559,45 +489,11 @@ public:
protected:
/**
* Called by computeFields. Converts calendar's year into Gregorian Extended Year (where negative = BC)
* @return Current year in Gregorian years, where -3 means 4 BC (1-bcyear)
* @internal
*/
virtual int32_t getGregorianYear(UErrorCode &status) const;
/**
* Called by computeJulianDay. Returns the default month (0-based) for the year,
* taking year and era into account. Defaults to 0 for Gregorian, which doesn't care.
* @internal
*/
virtual int32_t getDefaultMonthInYear() const;
/**
* Called by computeJulianDay. Returns the default day (1-based) for the month,
* taking currently-set year and era into account. Defaults to 1 for Gregorian, which doesn't care.
* @internal
*/
virtual int32_t getDefaultDayInMonth(int32_t /*month*/) const;
/**
* (Overrides Calendar) Converts GMT as milliseconds to time field values.
* @param status Fill-in parameter which receives the status of this operation.
* @stable ICU 2.0
*/
virtual void computeFields(UErrorCode& status);
/**
* (Overrides Calendar) Converts Calendar's time field values to GMT as
* milliseconds.
*
* @param status Output param set to success/failure code on exit. If any value
* previously set in the time field is invalid, this will be set to
* an error status.
* @stable ICU 2.0
*/
virtual void computeTime(UErrorCode& status);
private:
GregorianCalendar(); // default constructor not implemented
@ -611,6 +507,36 @@ protected:
*/
virtual int32_t internalGetEra() const;
/**
* Return the Julian day number of day before the first day of the
* given month in the given extended year. Subclasses should override
* this method to implement their calendar system.
* @param eyear the extended year
* @param month the zero-based month, or 0 if useMonth is false
* @param useMonth if false, compute the day before the first day of
* the given year, otherwise, compute the day before the first day of
* the given month
* @param return the Julian day number of the day before the first
* day of the given month and year
* @internal
*/
virtual int32_t handleComputeMonthStart(int32_t eyear, int32_t month,
UBool useMonth) const;
virtual int32_t GregorianCalendar::handleComputeJulianDay(UCalendarDateFields bestField) ;
/**
* Return the number of days in the given month of the given extended
* year of this calendar system. Subclasses should override this
* method if they can provide a more correct or more efficient
* implementation than the default implementation in Calendar.
* @internal
*/
virtual int32_t handleGetMonthLength(int32_t extendedYear, int32_t month) const;
virtual int32_t handleGetYearLength(int32_t eyear) const;
/**
* return the length of the given month.
* @param month the given month.
@ -672,7 +598,44 @@ protected:
* @param status Fill-in parameter which receives the status of this operation.
* @internal
*/
virtual void timeToFields(UDate theTime, UBool quick, UErrorCode& status);
// virtual void timeToFields(UDate theTime, UBool quick, UErrorCode& status);
/**
* Subclass API for defining limits of different types.
* Subclasses must implement this method to return limits for the
* following fields:
*
* <pre>UCAL_ERA
* UCAL_YEAR
* UCAL_MONTH
* UCAL_WEEK_OF_YEAR
* UCAL_WEEK_OF_MONTH
* UCAL_DATE (DAY_OF_MONTH on Java)
* UCAL_DAY_OF_YEAR
* UCAL_DAY_OF_WEEK_IN_MONTH
* UCAL_YEAR_WOY
* UCAL_EXTENDED_YEAR</pre>
*
* @param field one of the above field numbers
* @param limitType one of <code>MINIMUM</code>, <code>GREATEST_MINIMUM</code>,
* <code>LEAST_MAXIMUM</code>, or <code>MAXIMUM</code>
* @internal
*/
virtual int32_t handleGetLimit(UCalendarDateFields field, ELimitType limitType) const;
virtual int32_t GregorianCalendar::handleGetExtendedYear();
/**
* Subclasses may override this to convert from week fields
* (YEAR_WOY and WEEK_OF_YEAR) to an extended year in the case
* where YEAR, EXTENDED_YEAR are not set.
* The Gregorian implementation assumes a yearWoy in gregorian format, according to the current era.
* @return the extended year, UCAL_EXTENDED_YEAR
*/
virtual int32_t handleGetExtendedYearFromWeekFields(int32_t yearWoy, int32_t woy);
virtual void handleComputeFields(int32_t julianDay, UErrorCode &status);
private:
/**
@ -685,59 +648,6 @@ protected:
static double computeJulianDayOfYear(UBool isGregorian, int32_t year,
UBool& isLeap);
/**
* Compute the day of week, relative to the first day of week, from
* 0..6, of the current DOW_LOCAL or DAY_OF_WEEK fields. This is
* equivalent to get(DOW_LOCAL) - 1.
* @return the day of week, relative to the first day of week.
*/
int32_t computeRelativeDOW() const;
/**
* Compute the day of week, relative to the first day of week,
* from 0..6 of the given julian day.
* @param julianDay the given julian day.
* @return the day of week, relative to the first day of week.
*/
int32_t computeRelativeDOW(double julianDay) const;
/**
* Compute the DOY using the WEEK_OF_YEAR field and the julian day
* of the day BEFORE January 1 of a year (a return value from
* computeJulianDayOfYear).
* @param julianDayOfYear the given julian day of the day BEFORE
* January 1 of a year.
* @return the DOY using the WEEK_OF_YEAR field.
*/
int32_t computeDOYfromWOY(double julianDayOfYear) const;
/**
* Compute the Julian day number under either the Gregorian or the
* Julian calendar, using the given year and the remaining fields.
* @param isGregorian if true, use the Gregorian calendar
* @param year the adjusted year number, with 0 indicating the
* year 1 BC, -1 indicating 2 BC, etc.
* @return the Julian day number
*/
double computeJulianDay(UBool isGregorian, int32_t year);
/**
* Return the week number of a day, within a period. This may be the week number in
* a year, or the week number in a month. Usually this will be a value >= 1, but if
* some initial days of the period are excluded from week 1, because
* minimalDaysInFirstWeek is > 1, then the week number will be zero for those
* initial days. Requires the day of week for the given date in order to determine
* the day of week of the first day of the period.
*
* @param date Day-of-year or day-of-month. Should be 1 for first day of period.
* @param day Day-of-week for given dayOfPeriod. 1-based with 1=Sunday.
* @return Week number, one-based, or zero if the day falls in part of the
* month before the first week, when there are days before the first
* week because the minimum days in the first week is more than one.
*/
int32_t weekNumber(int32_t date, int32_t day);
/**
* Validates the values of the set time fields. True if they're all valid.
* @return True if the set time fields are all valid.
@ -770,6 +680,11 @@ protected:
// This is measured from the standard epoch, not in Julian Days.
UDate fGregorianCutover;
/**
* Julian day number of the Gregorian cutover
*/
uint32_t fCutoverJulianDay;
/**
* Midnight, local time (using this Calendar's TimeZone) at or before the
* gregorianCutover. This is a pure date value with no time of day or
@ -783,6 +698,12 @@ protected:
*/
int32_t fGregorianCutoverYear;// = 1582;
/**
* The year of the gregorianCutover, with 0 representing
* 1 BC, -1 representing 2 BC, etc.
*/
int32_t fGregorianCutoverJulianDay;// = 2299161;
/**
* Converts time as milliseconds to Julian date. The Julian date used here is not a
* true Julian date, since it is measured from midnight, not noon.
@ -802,14 +723,16 @@ protected:
static UDate julianDayToMillis(double julian);
/**
* Convert a quasi Julian date to the day of the week. The Julian date used here is
* not a true Julian date, since it is measured from midnight, not noon. Return
* value is one-based.
*
* @param julian The given Julian date number.
* @return Day number from 1..7 (SUN..SAT).
* Used by handleComputeJulianDay() and handleComputeMonthStart().
*/
static uint8_t julianDayToDayOfWeek(double julian);
UBool fIsGregorian;
/**
* Used by handleComputeJulianDay() and handleComputeMonthStart().
*/
UBool fInvertGregorian;
public: // internal implementation
@ -851,9 +774,9 @@ protected:
static const int32_t fgSystemDefaultCenturyYear;
/**
* TODO: (ICU 2.8) use this value instead of SimpleDateFormat::fgSystemDefaultCentury
* Default value that indicates the UDate of the beginning of the system default century
*/
//static const UDate fgSystemDefaultCentury;
static const UDate fgSystemDefaultCentury;
/**
* Returns the beginning date of the 100-year window that dates with 2-digit years
@ -879,16 +802,14 @@ protected:
};
inline uint8_t GregorianCalendar::julianDayToDayOfWeek(double julian)
{
// If julian is negative, then julian%7 will be negative, so we adjust
// accordingly. We add 1 because Julian day 0 is Monday.
int8_t dayOfWeek = (int8_t) uprv_fmod(julian + 1, 7);
uint8_t result = (uint8_t)(dayOfWeek + ((dayOfWeek < 0) ? (7 + UCAL_SUNDAY) : UCAL_SUNDAY));
return result;
inline int32_t GregorianCalendar::getActualMaximum(UCalendarDateFields field) const
{
UErrorCode status = U_ZERO_ERROR;
return getActualMaximum(field, status);
}
U_NAMESPACE_END
#endif /* #if !UCONFIG_NO_FORMATTING */

View file

@ -798,16 +798,6 @@ private:
/*transient*/ int32_t fDefaultCenturyStartYear;
UBool fHaveDefaultCentury;
public:
/**
* If a start date is set to this value, that indicates that the system default
* start is in effect for this instance.
* @internal
* @obsolete ICU 2.8 Use parseAmbiguousDatesAsAfter instead, since this member will be removed in that release.
*/
static const UDate fgSystemDefaultCentury;
// TODO Not supposed to be public: make it private in 2.8!
};
inline UDate

View file

@ -197,8 +197,17 @@ enum UCalendarDateFields {
UCAL_YEAR_WOY,
/** Day of week, localized (1..7) */
UCAL_DOW_LOCAL,
/** Year of this calendar system, encompassing all supra-year fields. For example, in Gregorian/Julian calendars, positive Extended Year values indicate years AD, 1 BC = -1 extended, 2 BC = -2 extended, and so on. */
UCAL_EXTENDED_YEAR,
/** Modified Julian day number, encompassing all date-related fields. Demarcates at local midnight.*/
UCAL_JULIAN_DAY,
/** Ranges from 0 to 23:59:59.999 (regardless of DST). This field behaves <em>exactly</em> like a composite of all time-related fields, not including the zone fields. As such, it also reflects discontinuities of those fields on DST transition days. On a day of DST onset, it will jump forward. On a day of DST cessation, it will jump backward. This reflects the fact that is must be combined with the DST_OFFSET field to obtain a unique local time value. */
UCAL_MILLISECONDS_IN_DAY,
/** Field count */
UCAL_FIELD_COUNT
UCAL_FIELD_COUNT,
/** Synonym for UCAL_DATE - @internal **/
UCAL_DAY_OF_MONTH=UCAL_DATE
};
/** @stable ICU 2.0 */