mirror of
https://github.com/unicode-org/icu.git
synced 2025-04-15 01:42:37 +00:00
ICU-11632 icu4c changes for integer overflow in calendar support
X-SVN-Rev: 40369
This commit is contained in:
parent
3a02afc3bf
commit
29cd7b1fc9
4 changed files with 343 additions and 302 deletions
|
@ -8,12 +8,12 @@
|
|||
*
|
||||
* File CALENDAR.CPP
|
||||
*
|
||||
* Modification History:
|
||||
* Modification History:
|
||||
*
|
||||
* Date Name Description
|
||||
* 02/03/97 clhuang Creation.
|
||||
* 04/22/97 aliu Cleaned up, fixed memory leak, made
|
||||
* setWeekCountData() more robust.
|
||||
* 04/22/97 aliu Cleaned up, fixed memory leak, made
|
||||
* setWeekCountData() more robust.
|
||||
* Moved platform code to TPlatformUtilities.
|
||||
* 05/01/97 aliu Made equals(), before(), after() arguments const.
|
||||
* 05/20/97 aliu Changed logic of when to compute fields and time
|
||||
|
@ -26,7 +26,7 @@
|
|||
*******************************************************************************
|
||||
*/
|
||||
|
||||
#include "utypeinfo.h" // for 'typeid' to work
|
||||
#include "utypeinfo.h" // for 'typeid' to work
|
||||
|
||||
#include "unicode/utypes.h"
|
||||
|
||||
|
@ -93,9 +93,9 @@ U_CDECL_END
|
|||
|
||||
#if defined( U_DEBUG_CALSVC ) || defined (U_DEBUG_CAL)
|
||||
|
||||
/**
|
||||
* fldName was removed as a duplicate implementation.
|
||||
* use udbg_ services instead,
|
||||
/**
|
||||
* fldName was removed as a duplicate implementation.
|
||||
* use udbg_ services instead,
|
||||
* which depend on include files and library from ../tools/toolutil, the following circular link:
|
||||
* CPPFLAGS+=-I$(top_srcdir)/tools/toolutil
|
||||
* LIBS+=$(LIBICUTOOLUTIL)
|
||||
|
@ -123,7 +123,7 @@ void ucal_dump(const Calendar &cal) {
|
|||
void Calendar::dump() const {
|
||||
int i;
|
||||
fprintf(stderr, "@calendar=%s, timeset=%c, fieldset=%c, allfields=%c, virtualset=%c, t=%.2f",
|
||||
getType(), fIsTimeSet?'y':'n', fAreFieldsSet?'y':'n', fAreAllFieldsSet?'y':'n',
|
||||
getType(), fIsTimeSet?'y':'n', fAreFieldsSet?'y':'n', fAreAllFieldsSet?'y':'n',
|
||||
fAreFieldsVirtuallySet?'y':'n',
|
||||
fTime);
|
||||
|
||||
|
@ -135,9 +135,9 @@ void Calendar::dump() const {
|
|||
fprintf(stderr, " %25s: %-11ld", f, fFields[i]);
|
||||
if(fStamp[i] == kUnset) {
|
||||
fprintf(stderr, " (unset) ");
|
||||
} else if(fStamp[i] == kInternallySet) {
|
||||
} else if(fStamp[i] == kInternallySet) {
|
||||
fprintf(stderr, " (internally set) ");
|
||||
//} else if(fStamp[i] == kInternalDefault) {
|
||||
//} else if(fStamp[i] == kInternalDefault) {
|
||||
// fprintf(stderr, " (internal default) ");
|
||||
} else {
|
||||
fprintf(stderr, " %%%d ", fStamp[i]);
|
||||
|
@ -213,7 +213,7 @@ const SharedCalendar *LocaleCacheKey<SharedCalendar>::createObject(
|
|||
const void * /*unusedCreationContext*/, UErrorCode &status) const {
|
||||
Calendar *calendar = Calendar::makeInstance(fLoc, status);
|
||||
if (U_FAILURE(status)) {
|
||||
return NULL;
|
||||
return NULL;
|
||||
}
|
||||
SharedCalendar *shared = new SharedCalendar(calendar);
|
||||
if (shared == NULL) {
|
||||
|
@ -234,7 +234,7 @@ static ECalType getCalendarType(const char *s) {
|
|||
return CALTYPE_UNKNOWN;
|
||||
}
|
||||
|
||||
static UBool isStandardSupportedKeyword(const char *keyword, UErrorCode& status) {
|
||||
static UBool isStandardSupportedKeyword(const char *keyword, UErrorCode& status) {
|
||||
if(U_FAILURE(status)) {
|
||||
return FALSE;
|
||||
}
|
||||
|
@ -291,7 +291,7 @@ static ECalType getCalendarTypeForLocale(const char *locid) {
|
|||
if (U_FAILURE(status)) {
|
||||
return CALTYPE_GREGORIAN;
|
||||
}
|
||||
|
||||
|
||||
// Read preferred calendar values from supplementalData calendarPreference
|
||||
UResourceBundle *rb = ures_openDirect(NULL, "supplementalData", &status);
|
||||
ures_getByKey(rb, "calendarPreferenceData", rb, &status);
|
||||
|
@ -394,7 +394,7 @@ static Calendar *createStandardCalendar(ECalType calType, const Locale &loc, UEr
|
|||
// -------------------------------------
|
||||
|
||||
/**
|
||||
* a Calendar Factory which creates the "basic" calendar types, that is, those
|
||||
* a Calendar Factory which creates the "basic" calendar types, that is, those
|
||||
* shipped with ICU.
|
||||
*/
|
||||
class BasicCalendarFactory : public LocaleKeyFactory {
|
||||
|
@ -408,7 +408,7 @@ public:
|
|||
virtual ~BasicCalendarFactory();
|
||||
|
||||
protected:
|
||||
//virtual UBool isSupportedID( const UnicodeString& id, UErrorCode& status) const {
|
||||
//virtual UBool isSupportedID( const UnicodeString& id, UErrorCode& status) const {
|
||||
// if(U_FAILURE(status)) {
|
||||
// return FALSE;
|
||||
// }
|
||||
|
@ -466,7 +466,7 @@ protected:
|
|||
|
||||
BasicCalendarFactory::~BasicCalendarFactory() {}
|
||||
|
||||
/**
|
||||
/**
|
||||
* A factory which looks up the DefaultCalendar resource to determine which class of calendar to use
|
||||
*/
|
||||
|
||||
|
@ -510,7 +510,7 @@ public:
|
|||
virtual UObject* cloneInstance(UObject* instance) const {
|
||||
UnicodeString *s = dynamic_cast<UnicodeString *>(instance);
|
||||
if(s != NULL) {
|
||||
return s->clone();
|
||||
return s->clone();
|
||||
} else {
|
||||
#ifdef U_DEBUG_CALSVC_F
|
||||
UErrorCode status2 = U_ZERO_ERROR;
|
||||
|
@ -573,7 +573,7 @@ initCalendarService(UErrorCode &status)
|
|||
fprintf(stderr, "Registering classes..\n");
|
||||
#endif
|
||||
|
||||
// Register all basic instances.
|
||||
// Register all basic instances.
|
||||
gService->registerFactory(new BasicCalendarFactory(),status);
|
||||
|
||||
#ifdef U_DEBUG_CALSVC
|
||||
|
@ -589,7 +589,7 @@ initCalendarService(UErrorCode &status)
|
|||
}
|
||||
}
|
||||
|
||||
static ICULocaleService*
|
||||
static ICULocaleService*
|
||||
getCalendarService(UErrorCode &status)
|
||||
{
|
||||
umtx_initOnce(gServiceInitOnce, &initCalendarService, status);
|
||||
|
@ -743,7 +743,7 @@ fSkippedWallTime(UCAL_WALLTIME_LAST)
|
|||
return;
|
||||
}
|
||||
|
||||
clear();
|
||||
clear();
|
||||
fZone = zone;
|
||||
setWeekData(aLocale, NULL, success);
|
||||
}
|
||||
|
@ -850,7 +850,7 @@ Calendar::createInstance(const Locale& aLocale, UErrorCode& success)
|
|||
return createInstance(TimeZone::createDefault(), aLocale, success);
|
||||
}
|
||||
|
||||
// ------------------------------------- Adopting
|
||||
// ------------------------------------- Adopting
|
||||
|
||||
// Note: this is the bottleneck that actually calls the service routines.
|
||||
|
||||
|
@ -903,7 +903,7 @@ Calendar::makeInstance(const Locale& aLocale, UErrorCode& success) {
|
|||
c = (Calendar*)getCalendarService(success)->get(l, LocaleKey::KIND_ANY, &actualLoc2, success);
|
||||
|
||||
if(U_FAILURE(success) || !c) {
|
||||
if(U_SUCCESS(success)) {
|
||||
if(U_SUCCESS(success)) {
|
||||
success = U_INTERNAL_PROGRAM_ERROR; // Propagate some err
|
||||
}
|
||||
return NULL;
|
||||
|
@ -911,7 +911,7 @@ Calendar::makeInstance(const Locale& aLocale, UErrorCode& success) {
|
|||
|
||||
str = dynamic_cast<const UnicodeString*>(c);
|
||||
if(str != NULL) {
|
||||
// recursed! Second lookup returned a UnicodeString.
|
||||
// recursed! Second lookup returned a UnicodeString.
|
||||
// Perhaps DefaultCalendar{} was set to another locale.
|
||||
#ifdef U_DEBUG_CALSVC
|
||||
char tmp[200];
|
||||
|
@ -985,7 +985,7 @@ Calendar::createInstance(const TimeZone& zone, const Locale& aLocale, UErrorCode
|
|||
if(U_SUCCESS(success) && c) {
|
||||
c->setTimeZone(zone);
|
||||
}
|
||||
return c;
|
||||
return c;
|
||||
}
|
||||
|
||||
// -------------------------------------
|
||||
|
@ -1017,7 +1017,7 @@ Calendar::operator==(const Calendar& that) const
|
|||
U_SUCCESS(status);
|
||||
}
|
||||
|
||||
UBool
|
||||
UBool
|
||||
Calendar::isEquivalentTo(const Calendar& other) const
|
||||
{
|
||||
return typeid(*this) == typeid(other) &&
|
||||
|
@ -1099,13 +1099,13 @@ Calendar::getNow()
|
|||
* Gets this Calendar's current time as a long.
|
||||
* @return the current time as UTC milliseconds from the epoch.
|
||||
*/
|
||||
double
|
||||
double
|
||||
Calendar::getTimeInMillis(UErrorCode& status) const
|
||||
{
|
||||
if(U_FAILURE(status))
|
||||
if(U_FAILURE(status))
|
||||
return 0.0;
|
||||
|
||||
if ( ! fIsTimeSet)
|
||||
if ( ! fIsTimeSet)
|
||||
((Calendar*)this)->updateTime(status);
|
||||
|
||||
/* Test for buffer overflows */
|
||||
|
@ -1124,9 +1124,9 @@ Calendar::getTimeInMillis(UErrorCode& status) const
|
|||
* when in lenient mode the out of range values are pinned to their respective min/max.
|
||||
* @param date the new time in UTC milliseconds from the epoch.
|
||||
*/
|
||||
void
|
||||
void
|
||||
Calendar::setTimeInMillis( double millis, UErrorCode& status ) {
|
||||
if(U_FAILURE(status))
|
||||
if(U_FAILURE(status))
|
||||
return;
|
||||
|
||||
if (millis > MAX_MILLIS) {
|
||||
|
@ -1154,7 +1154,7 @@ Calendar::setTimeInMillis( double millis, UErrorCode& status ) {
|
|||
fStamp[i] = kUnset;
|
||||
fIsSet[i] = FALSE;
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
@ -1479,7 +1479,7 @@ void Calendar::computeFields(UErrorCode &ec)
|
|||
double localMillis = internalGetTime();
|
||||
int32_t rawOffset, dstOffset;
|
||||
getTimeZone().getOffset(localMillis, FALSE, rawOffset, dstOffset, ec);
|
||||
localMillis += (rawOffset + dstOffset);
|
||||
localMillis += (rawOffset + dstOffset);
|
||||
|
||||
// Mark fields as set. Do this before calling handleComputeFields().
|
||||
uint32_t mask = //fInternalSetMask;
|
||||
|
@ -1488,7 +1488,7 @@ void Calendar::computeFields(UErrorCode &ec)
|
|||
(1 << UCAL_MONTH) |
|
||||
(1 << UCAL_DAY_OF_MONTH) | // = UCAL_DATE
|
||||
(1 << UCAL_DAY_OF_YEAR) |
|
||||
(1 << UCAL_EXTENDED_YEAR);
|
||||
(1 << UCAL_EXTENDED_YEAR);
|
||||
|
||||
for (int32_t i=0; i<UCAL_FIELD_COUNT; ++i) {
|
||||
if ((mask & 1) == 0) {
|
||||
|
@ -1517,7 +1517,7 @@ void Calendar::computeFields(UErrorCode &ec)
|
|||
#if defined (U_DEBUG_CAL)
|
||||
//fprintf(stderr, "%s:%d- Hmm! Jules @ %d, as per %.0lf millis\n",
|
||||
//__FILE__, __LINE__, fFields[UCAL_JULIAN_DAY], localMillis);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
computeGregorianAndDOWFields(fFields[UCAL_JULIAN_DAY], ec);
|
||||
|
||||
|
@ -1615,7 +1615,7 @@ void Calendar::computeGregorianFields(int32_t julianDay, UErrorCode & /* ec */)
|
|||
* proleptic Gregorian calendar, which has no field larger than a year.
|
||||
*/
|
||||
void Calendar::computeWeekFields(UErrorCode &ec) {
|
||||
if(U_FAILURE(ec)) {
|
||||
if(U_FAILURE(ec)) {
|
||||
return;
|
||||
}
|
||||
int32_t eyear = fFields[UCAL_EXTENDED_YEAR];
|
||||
|
@ -1678,7 +1678,7 @@ void Calendar::computeWeekFields(UErrorCode &ec) {
|
|||
fFields[UCAL_WEEK_OF_MONTH] = weekNumber(dayOfMonth, dayOfWeek);
|
||||
fFields[UCAL_DAY_OF_WEEK_IN_MONTH] = (dayOfMonth-1) / 7 + 1;
|
||||
#if defined (U_DEBUG_CAL)
|
||||
if(fFields[UCAL_DAY_OF_WEEK_IN_MONTH]==0) fprintf(stderr, "%s:%d: DOWIM %d on %g\n",
|
||||
if(fFields[UCAL_DAY_OF_WEEK_IN_MONTH]==0) fprintf(stderr, "%s:%d: DOWIM %d on %g\n",
|
||||
__FILE__, __LINE__,fFields[UCAL_DAY_OF_WEEK_IN_MONTH], fTime);
|
||||
#endif
|
||||
}
|
||||
|
@ -1723,7 +1723,7 @@ void Calendar::handleComputeFields(int32_t /* julianDay */, UErrorCode &/* statu
|
|||
// -------------------------------------
|
||||
|
||||
|
||||
void Calendar::roll(EDateFields field, int32_t amount, UErrorCode& status)
|
||||
void Calendar::roll(EDateFields field, int32_t amount, UErrorCode& status)
|
||||
{
|
||||
roll((UCalendarDateFields)field, amount, status);
|
||||
}
|
||||
|
@ -2061,7 +2061,7 @@ void Calendar::roll(UCalendarDateFields field, int32_t amount, UErrorCode& statu
|
|||
default:
|
||||
// Other fields cannot be rolled by this method
|
||||
#if defined (U_DEBUG_CAL)
|
||||
fprintf(stderr, "%s:%d: ILLEGAL ARG because of roll on non-rollable field %s\n",
|
||||
fprintf(stderr, "%s:%d: ILLEGAL ARG because of roll on non-rollable field %s\n",
|
||||
__FILE__, __LINE__,fldName(field));
|
||||
#endif
|
||||
status = U_ILLEGAL_ARGUMENT_ERROR;
|
||||
|
@ -2252,7 +2252,7 @@ void Calendar::add(UCalendarDateFields field, int32_t amount, UErrorCode& status
|
|||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// -------------------------------------
|
||||
|
@ -2617,7 +2617,7 @@ Calendar::isWeekend(void) const
|
|||
|
||||
// ------------------------------------- limits
|
||||
|
||||
int32_t
|
||||
int32_t
|
||||
Calendar::getMinimum(EDateFields field) const {
|
||||
return getLimit((UCalendarDateFields) field,UCAL_LIMIT_MINIMUM);
|
||||
}
|
||||
|
@ -2668,7 +2668,7 @@ Calendar::getLeastMaximum(UCalendarDateFields field) const
|
|||
}
|
||||
|
||||
// -------------------------------------
|
||||
int32_t
|
||||
int32_t
|
||||
Calendar::getActualMinimum(EDateFields field, UErrorCode& status) const
|
||||
{
|
||||
return getActualMinimum((UCalendarDateFields) field, status);
|
||||
|
@ -2744,7 +2744,7 @@ Calendar::getActualMinimum(UCalendarDateFields field, UErrorCode& status) const
|
|||
work->set(field, fieldValue);
|
||||
if (work->get(field, status) != fieldValue) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
else {
|
||||
result = fieldValue;
|
||||
fieldValue--;
|
||||
|
@ -2800,7 +2800,7 @@ void Calendar::validateField(UCalendarDateFields field, UErrorCode &status) {
|
|||
case UCAL_DAY_OF_WEEK_IN_MONTH:
|
||||
if (internalGet(field) == 0) {
|
||||
#if defined (U_DEBUG_CAL)
|
||||
fprintf(stderr, "%s:%d: ILLEGAL ARG because DOW in month cannot be 0\n",
|
||||
fprintf(stderr, "%s:%d: ILLEGAL ARG because DOW in month cannot be 0\n",
|
||||
__FILE__, __LINE__);
|
||||
#endif
|
||||
status = U_ILLEGAL_ARGUMENT_ERROR; // "DAY_OF_WEEK_IN_MONTH cannot be zero"
|
||||
|
@ -2826,7 +2826,7 @@ void Calendar::validateField(UCalendarDateFields field, int32_t min, int32_t max
|
|||
int32_t value = fFields[field];
|
||||
if (value < min || value > max) {
|
||||
#if defined (U_DEBUG_CAL)
|
||||
fprintf(stderr, "%s:%d: ILLEGAL ARG because of field %s out of range %d..%d at %d\n",
|
||||
fprintf(stderr, "%s:%d: ILLEGAL ARG because of field %s out of range %d..%d at %d\n",
|
||||
__FILE__, __LINE__,fldName(field),min,max,value);
|
||||
#endif
|
||||
status = U_ILLEGAL_ARGUMENT_ERROR;
|
||||
|
@ -2892,7 +2892,7 @@ linesInGroup:
|
|||
}
|
||||
|
||||
const UFieldResolutionTable Calendar::kDatePrecedence[] =
|
||||
{
|
||||
{
|
||||
{
|
||||
{ UCAL_DAY_OF_MONTH, kResolveSTOP },
|
||||
{ UCAL_WEEK_OF_YEAR, UCAL_DAY_OF_WEEK, kResolveSTOP },
|
||||
|
@ -2913,12 +2913,12 @@ const UFieldResolutionTable Calendar::kDatePrecedence[] =
|
|||
{ kResolveRemap | UCAL_DAY_OF_WEEK_IN_MONTH, UCAL_DAY_OF_WEEK, kResolveSTOP },
|
||||
{ kResolveRemap | UCAL_DAY_OF_WEEK_IN_MONTH, UCAL_DOW_LOCAL, kResolveSTOP },
|
||||
{ kResolveSTOP }
|
||||
},
|
||||
},
|
||||
{{kResolveSTOP}}
|
||||
};
|
||||
|
||||
|
||||
const UFieldResolutionTable Calendar::kDOWPrecedence[] =
|
||||
const UFieldResolutionTable Calendar::kDOWPrecedence[] =
|
||||
{
|
||||
{
|
||||
{ UCAL_DAY_OF_WEEK,kResolveSTOP, kResolveSTOP },
|
||||
|
@ -2929,7 +2929,7 @@ const UFieldResolutionTable Calendar::kDOWPrecedence[] =
|
|||
};
|
||||
|
||||
// precedence for calculating a year
|
||||
const UFieldResolutionTable Calendar::kYearPrecedence[] =
|
||||
const UFieldResolutionTable Calendar::kYearPrecedence[] =
|
||||
{
|
||||
{
|
||||
{ UCAL_YEAR, kResolveSTOP },
|
||||
|
@ -2966,7 +2966,7 @@ void Calendar::computeTime(UErrorCode& status) {
|
|||
// }
|
||||
#endif
|
||||
|
||||
int32_t millisInDay;
|
||||
double millisInDay;
|
||||
|
||||
// We only use MILLISECONDS_IN_DAY if it has been set by the user.
|
||||
// This makes it possible for the caller to set the calendar to a
|
||||
|
@ -3086,10 +3086,10 @@ UBool Calendar::getImmediatePreviousZoneTransition(UDate base, UDate *transition
|
|||
* reflects local zone wall time.
|
||||
* @stable ICU 2.0
|
||||
*/
|
||||
int32_t Calendar::computeMillisInDay() {
|
||||
double Calendar::computeMillisInDay() {
|
||||
// Do the time portion of the conversion.
|
||||
|
||||
int32_t millisInDay = 0;
|
||||
double millisInDay = 0;
|
||||
|
||||
// Find the best set of fields specifying the time of day. There
|
||||
// are only two possibilities here; the HOUR_OF_DAY or the
|
||||
|
@ -3131,7 +3131,7 @@ int32_t Calendar::computeMillisInDay() {
|
|||
* or range.
|
||||
* @stable ICU 2.0
|
||||
*/
|
||||
int32_t Calendar::computeZoneOffset(double millis, int32_t millisInDay, UErrorCode &ec) {
|
||||
int32_t Calendar::computeZoneOffset(double millis, double millisInDay, UErrorCode &ec) {
|
||||
int32_t rawOffset, dstOffset;
|
||||
UDate wall = millis + millisInDay;
|
||||
BasicTimeZone* btz = getBasicTimeZone();
|
||||
|
@ -3178,7 +3178,7 @@ int32_t Calendar::computeZoneOffset(double millis, int32_t millisInDay, UErrorCo
|
|||
return rawOffset + dstOffset;
|
||||
}
|
||||
|
||||
int32_t Calendar::computeJulianDay()
|
||||
int32_t Calendar::computeJulianDay()
|
||||
{
|
||||
// We want to see if any of the date fields is newer than the
|
||||
// JULIAN_DAY. If not, then we use JULIAN_DAY. If so, then we do
|
||||
|
@ -3220,9 +3220,9 @@ int32_t Calendar::handleComputeJulianDay(UCalendarDateFields bestField) {
|
|||
internalSet(UCAL_EXTENDED_YEAR, year);
|
||||
}
|
||||
|
||||
#if defined (U_DEBUG_CAL)
|
||||
#if defined (U_DEBUG_CAL)
|
||||
fprintf(stderr, "%s:%d: bestField= %s - y=%d\n", __FILE__, __LINE__, fldName(bestField), year);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
// Get the Julian day of the day BEFORE the start of this year.
|
||||
// If useMonth is true, get the day before the start of the month.
|
||||
|
@ -3304,9 +3304,9 @@ int32_t Calendar::handleComputeJulianDay(UCalendarDateFields bestField) {
|
|||
date += ((monthLength - date) / 7 + dim + 1) * 7;
|
||||
}
|
||||
} else {
|
||||
#if defined (U_DEBUG_CAL)
|
||||
#if defined (U_DEBUG_CAL)
|
||||
fprintf(stderr, "%s:%d - bf= %s\n", __FILE__, __LINE__, fldName(bestField));
|
||||
#endif
|
||||
#endif
|
||||
|
||||
if(bestField == UCAL_WEEK_OF_YEAR) { // ------------------------------------- WOY -------------
|
||||
if(!isSet(UCAL_YEAR_WOY) || // YWOY not set at all or
|
||||
|
@ -3317,30 +3317,30 @@ int32_t Calendar::handleComputeJulianDay(UCalendarDateFields bestField) {
|
|||
int32_t woy = internalGet(bestField);
|
||||
|
||||
int32_t nextJulianDay = handleComputeMonthStart(year+1, 0, FALSE); // jd of day before jan 1
|
||||
int32_t nextFirst = julianDayToDayOfWeek(nextJulianDay + 1) - firstDayOfWeek;
|
||||
int32_t nextFirst = julianDayToDayOfWeek(nextJulianDay + 1) - firstDayOfWeek;
|
||||
|
||||
if (nextFirst < 0) { // 0..6 ldow of Jan 1
|
||||
nextFirst += 7;
|
||||
}
|
||||
|
||||
if(woy==1) { // FIRST WEEK ---------------------------------
|
||||
#if defined (U_DEBUG_CAL)
|
||||
fprintf(stderr, "%s:%d - woy=%d, yp=%d, nj(%d)=%d, nf=%d", __FILE__, __LINE__,
|
||||
internalGet(bestField), resolveFields(kYearPrecedence), year+1,
|
||||
#if defined (U_DEBUG_CAL)
|
||||
fprintf(stderr, "%s:%d - woy=%d, yp=%d, nj(%d)=%d, nf=%d", __FILE__, __LINE__,
|
||||
internalGet(bestField), resolveFields(kYearPrecedence), year+1,
|
||||
nextJulianDay, nextFirst);
|
||||
|
||||
fprintf(stderr, " next: %d DFW, min=%d \n", (7-nextFirst), getMinimalDaysInFirstWeek() );
|
||||
#endif
|
||||
#endif
|
||||
|
||||
// nextFirst is now the localized DOW of Jan 1 of y-woy+1
|
||||
if((nextFirst > 0) && // Jan 1 starts on FDOW
|
||||
(7-nextFirst) >= getMinimalDaysInFirstWeek()) // or enough days in the week
|
||||
{
|
||||
// Jan 1 of (yearWoy+1) is in yearWoy+1 - recalculate JD to next year
|
||||
#if defined (U_DEBUG_CAL)
|
||||
fprintf(stderr, "%s:%d - was going to move JD from %d to %d [d%d]\n", __FILE__, __LINE__,
|
||||
#if defined (U_DEBUG_CAL)
|
||||
fprintf(stderr, "%s:%d - was going to move JD from %d to %d [d%d]\n", __FILE__, __LINE__,
|
||||
julianDay, nextJulianDay, (nextJulianDay-julianDay));
|
||||
#endif
|
||||
#endif
|
||||
julianDay = nextJulianDay;
|
||||
|
||||
// recalculate 'first' [0-based local dow of jan 1]
|
||||
|
@ -3351,7 +3351,7 @@ int32_t Calendar::handleComputeJulianDay(UCalendarDateFields bestField) {
|
|||
// recalculate date.
|
||||
date = 1 - first + dowLocal;
|
||||
}
|
||||
} else if(woy>=getLeastMaximum(bestField)) {
|
||||
} else if(woy>=getLeastMaximum(bestField)) {
|
||||
// could be in the last week- find out if this JD would overstep
|
||||
int32_t testDate = date;
|
||||
if ((7 - first) < getMinimalDaysInFirstWeek()) {
|
||||
|
@ -3361,7 +3361,7 @@ int32_t Calendar::handleComputeJulianDay(UCalendarDateFields bestField) {
|
|||
// Now adjust for the week number.
|
||||
testDate += 7 * (woy - 1);
|
||||
|
||||
#if defined (U_DEBUG_CAL)
|
||||
#if defined (U_DEBUG_CAL)
|
||||
fprintf(stderr, "%s:%d - y=%d, y-1=%d doy%d, njd%d (C.F. %d)\n",
|
||||
__FILE__, __LINE__, year, year-1, testDate, julianDay+testDate, nextJulianDay);
|
||||
#endif
|
||||
|
@ -3375,7 +3375,7 @@ int32_t Calendar::handleComputeJulianDay(UCalendarDateFields bestField) {
|
|||
}
|
||||
date = 1 - first + dowLocal;
|
||||
|
||||
#if defined (U_DEBUG_CAL)
|
||||
#if defined (U_DEBUG_CAL)
|
||||
fprintf(stderr, "%s:%d - date now %d, jd%d, ywoy%d\n",
|
||||
__FILE__, __LINE__, date, julianDay, year-1);
|
||||
#endif
|
||||
|
@ -3400,13 +3400,13 @@ int32_t Calendar::handleComputeJulianDay(UCalendarDateFields bestField) {
|
|||
}
|
||||
|
||||
int32_t
|
||||
Calendar::getDefaultMonthInYear(int32_t /*eyear*/)
|
||||
Calendar::getDefaultMonthInYear(int32_t /*eyear*/)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
int32_t
|
||||
Calendar::getDefaultDayInMonth(int32_t /*eyear*/, int32_t /*month*/)
|
||||
Calendar::getDefaultDayInMonth(int32_t /*eyear*/, int32_t /*month*/)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
@ -3436,13 +3436,13 @@ int32_t Calendar::getLocalDOW()
|
|||
|
||||
int32_t Calendar::handleGetExtendedYearFromWeekFields(int32_t yearWoy, int32_t woy)
|
||||
{
|
||||
// We have UCAL_YEAR_WOY and UCAL_WEEK_OF_YEAR - from those, determine
|
||||
// We have UCAL_YEAR_WOY and UCAL_WEEK_OF_YEAR - from those, determine
|
||||
// what year we fall in, so that other code can set it properly.
|
||||
// (code borrowed from computeWeekFields and handleComputeJulianDay)
|
||||
//return yearWoy;
|
||||
|
||||
// First, we need a reliable DOW.
|
||||
UCalendarDateFields bestField = resolveFields(kDatePrecedence); // !! Note: if subclasses have a different table, they should override handleGetExtendedYearFromWeekFields
|
||||
UCalendarDateFields bestField = resolveFields(kDatePrecedence); // !! Note: if subclasses have a different table, they should override handleGetExtendedYearFromWeekFields
|
||||
|
||||
// Now, a local DOW
|
||||
int32_t dowLocal = getLocalDOW(); // 0..6
|
||||
|
@ -3475,9 +3475,9 @@ int32_t Calendar::handleGetExtendedYearFromWeekFields(int32_t yearWoy, int32_t w
|
|||
|
||||
int32_t minDays = getMinimalDaysInFirstWeek();
|
||||
UBool jan1InPrevYear = FALSE; // January 1st in the year of WOY is the 1st week? (i.e. first week is < minimal )
|
||||
//UBool nextJan1InPrevYear = FALSE; // January 1st of Year of WOY + 1 is in the first week?
|
||||
//UBool nextJan1InPrevYear = FALSE; // January 1st of Year of WOY + 1 is in the first week?
|
||||
|
||||
if((7 - first) < minDays) {
|
||||
if((7 - first) < minDays) {
|
||||
jan1InPrevYear = TRUE;
|
||||
}
|
||||
|
||||
|
@ -3500,8 +3500,8 @@ int32_t Calendar::handleGetExtendedYearFromWeekFields(int32_t yearWoy, int32_t w
|
|||
return yearWoy; // in this year
|
||||
}
|
||||
}
|
||||
} else if(woy >= getLeastMaximum(bestField)) {
|
||||
// we _might_ be in the last week..
|
||||
} else if(woy >= getLeastMaximum(bestField)) {
|
||||
// we _might_ be in the last week..
|
||||
int32_t jd = // Calculate JD of our target day:
|
||||
jan1Start + // JD of Jan 1
|
||||
(7-first) + // days in the first week (Jan 1.. )
|
||||
|
@ -3538,7 +3538,7 @@ int32_t Calendar::handleGetExtendedYearFromWeekFields(int32_t yearWoy, int32_t w
|
|||
}
|
||||
|
||||
//(internalGet(UCAL_DATE) <= (7-first)) /* && in minDow */ ) {
|
||||
//within 1st week and in this month..
|
||||
//within 1st week and in this month..
|
||||
//return yearWoy+1;
|
||||
return yearWoy;
|
||||
|
||||
|
@ -3671,7 +3671,7 @@ void Calendar::prepareGetActual(UCalendarDateFields field, UBool isMinimum, UErr
|
|||
dow += 7;
|
||||
}
|
||||
}
|
||||
#if defined (U_DEBUG_CAL)
|
||||
#if defined (U_DEBUG_CAL)
|
||||
fprintf(stderr, "prepareGetActualHelper(WOM/WOY) - dow=%d\n", dow);
|
||||
#endif
|
||||
set(UCAL_DAY_OF_WEEK, dow);
|
||||
|
@ -3687,7 +3687,7 @@ void Calendar::prepareGetActual(UCalendarDateFields field, UBool isMinimum, UErr
|
|||
|
||||
int32_t Calendar::getActualHelper(UCalendarDateFields field, int32_t startValue, int32_t endValue, UErrorCode &status) const
|
||||
{
|
||||
#if defined (U_DEBUG_CAL)
|
||||
#if defined (U_DEBUG_CAL)
|
||||
fprintf(stderr, "getActualHelper(%d,%d .. %d, %s)\n", field, startValue, endValue, u_errorName(status));
|
||||
#endif
|
||||
if (startValue == endValue) {
|
||||
|
@ -3723,7 +3723,7 @@ int32_t Calendar::getActualHelper(UCalendarDateFields field, int32_t startValue,
|
|||
int32_t result = startValue;
|
||||
if ((work->get(field, status) != startValue
|
||||
&& field != UCAL_WEEK_OF_MONTH && delta > 0 ) || U_FAILURE(status)) {
|
||||
#if defined (U_DEBUG_CAL)
|
||||
#if defined (U_DEBUG_CAL)
|
||||
fprintf(stderr, "getActualHelper(fld %d) - got %d (not %d) - %s\n", field, work->get(field,status), startValue, u_errorName(status));
|
||||
#endif
|
||||
} else {
|
||||
|
@ -3740,7 +3740,7 @@ int32_t Calendar::getActualHelper(UCalendarDateFields field, int32_t startValue,
|
|||
} while (startValue != endValue);
|
||||
}
|
||||
delete work;
|
||||
#if defined (U_DEBUG_CAL)
|
||||
#if defined (U_DEBUG_CAL)
|
||||
fprintf(stderr, "getActualHelper(%d) = %d\n", field, result);
|
||||
#endif
|
||||
return result;
|
||||
|
@ -3767,18 +3767,18 @@ Calendar::setWeekData(const Locale& desiredLocale, const char *type, UErrorCode&
|
|||
// Since week and weekend data is territory based instead of language based,
|
||||
// we may need to tweak the locale that we are using to try to get the appropriate
|
||||
// values, using the following logic:
|
||||
// 1). If the locale has a language but no territory, use the territory as defined by
|
||||
// 1). If the locale has a language but no territory, use the territory as defined by
|
||||
// the likely subtags.
|
||||
// 2). If the locale has a script designation then we ignore it,
|
||||
// then remove it ( i.e. "en_Latn_US" becomes "en_US" )
|
||||
|
||||
|
||||
char minLocaleID[ULOC_FULLNAME_CAPACITY] = { 0 };
|
||||
UErrorCode myStatus = U_ZERO_ERROR;
|
||||
|
||||
uloc_minimizeSubtags(desiredLocale.getName(),minLocaleID,ULOC_FULLNAME_CAPACITY,&myStatus);
|
||||
Locale min = Locale::createFromName(minLocaleID);
|
||||
Locale useLocale;
|
||||
if ( uprv_strlen(desiredLocale.getCountry()) == 0 ||
|
||||
if ( uprv_strlen(desiredLocale.getCountry()) == 0 ||
|
||||
(uprv_strlen(desiredLocale.getScript()) > 0 && uprv_strlen(min.getScript()) == 0) ) {
|
||||
char maxLocaleID[ULOC_FULLNAME_CAPACITY] = { 0 };
|
||||
myStatus = U_ZERO_ERROR;
|
||||
|
@ -3788,8 +3788,8 @@ Calendar::setWeekData(const Locale& desiredLocale, const char *type, UErrorCode&
|
|||
} else {
|
||||
useLocale = Locale(desiredLocale);
|
||||
}
|
||||
|
||||
/* The code here is somewhat of a hack, since week data and weekend data aren't really tied to
|
||||
|
||||
/* The code here is somewhat of a hack, since week data and weekend data aren't really tied to
|
||||
a specific calendar, they aren't truly locale data. But this is the only place where valid and
|
||||
actual locale can be set, so we take a shot at it here by loading a representative resource
|
||||
from the calendar data. The code used to use the dateTimeElements resource to get first day
|
||||
|
@ -3865,8 +3865,8 @@ Calendar::setWeekData(const Locale& desiredLocale, const char *type, UErrorCode&
|
|||
* and areFieldsSet. Callers should check isTimeSet and only
|
||||
* call this method if isTimeSet is false.
|
||||
*/
|
||||
void
|
||||
Calendar::updateTime(UErrorCode& status)
|
||||
void
|
||||
Calendar::updateTime(UErrorCode& status)
|
||||
{
|
||||
computeTime(status);
|
||||
if(U_FAILURE(status))
|
||||
|
@ -3875,14 +3875,14 @@ Calendar::updateTime(UErrorCode& status)
|
|||
// If we are lenient, we need to recompute the fields to normalize
|
||||
// the values. Also, if we haven't set all the fields yet (i.e.,
|
||||
// in a newly-created object), we need to fill in the fields. [LIU]
|
||||
if (isLenient() || ! fAreAllFieldsSet)
|
||||
if (isLenient() || ! fAreAllFieldsSet)
|
||||
fAreFieldsSet = FALSE;
|
||||
|
||||
fIsTimeSet = TRUE;
|
||||
fAreFieldsVirtuallySet = FALSE;
|
||||
}
|
||||
|
||||
Locale
|
||||
Locale
|
||||
Calendar::getLocale(ULocDataLocaleType type, UErrorCode& status) const {
|
||||
U_LOCALE_BASED(locBased, *this);
|
||||
return locBased.getLocale(type, status);
|
||||
|
@ -3945,4 +3945,3 @@ U_NAMESPACE_END
|
|||
|
||||
|
||||
//eof
|
||||
|
||||
|
|
|
@ -30,7 +30,7 @@
|
|||
#include "unicode/utypes.h"
|
||||
|
||||
/**
|
||||
* \file
|
||||
* \file
|
||||
* \brief C++ API: Calendar object
|
||||
*/
|
||||
#if !UCONFIG_NO_FORMATTING
|
||||
|
@ -137,7 +137,7 @@ class BasicTimeZone;
|
|||
* Calendar resolves the time using the UTC offset before the transition by default.
|
||||
* In this example, 1:30 AM is interpreted as 1:30 AM standard time (non-exist),
|
||||
* so the final result will be 2:30 AM daylight time.
|
||||
*
|
||||
*
|
||||
* <p>On the date switching back to standard time, wall clock time is moved back one
|
||||
* hour at 2:00 AM. So wall clock time from 1:00 AM to 1:59 AM occur twice. In this
|
||||
* case, the ICU Calendar resolves the time using the UTC offset after the transition
|
||||
|
@ -235,7 +235,7 @@ public:
|
|||
DST_OFFSET, // Example: 0 or U_MILLIS_PER_HOUR
|
||||
YEAR_WOY, // 'Y' Example: 1..big number - Year of Week of Year
|
||||
DOW_LOCAL, // 'e' Example: 1..7 - Day of Week / Localized
|
||||
|
||||
|
||||
EXTENDED_YEAR,
|
||||
JULIAN_DAY,
|
||||
MILLISECONDS_IN_DAY,
|
||||
|
@ -914,7 +914,7 @@ public:
|
|||
* option for this. When the argument is neither <code>UCAL_WALLTIME_FIRST</code>
|
||||
* nor <code>UCAL_WALLTIME_LAST</code>, this method has no effect and will keep
|
||||
* the current setting.
|
||||
*
|
||||
*
|
||||
* @param option the behavior for handling repeating wall time, either
|
||||
* <code>UCAL_WALLTIME_FIRST</code> or <code>UCAL_WALLTIME_LAST</code>.
|
||||
* @see #getRepeatedWallTimeOption
|
||||
|
@ -925,7 +925,7 @@ public:
|
|||
/**
|
||||
* Gets the behavior for handling wall time repeating multiple times
|
||||
* at negative time zone offset transitions.
|
||||
*
|
||||
*
|
||||
* @return the behavior for handling repeating wall time, either
|
||||
* <code>UCAL_WALLTIME_FIRST</code> or <code>UCAL_WALLTIME_LAST</code>.
|
||||
* @see #setRepeatedWallTimeOption
|
||||
|
@ -946,12 +946,12 @@ public:
|
|||
* <p>
|
||||
* <b>Note:</b>This option is effective only when this calendar is lenient.
|
||||
* When the calendar is strict, such non-existing wall time will cause an error.
|
||||
*
|
||||
*
|
||||
* @param option the behavior for handling skipped wall time at positive time zone
|
||||
* offset transitions, one of <code>UCAL_WALLTIME_FIRST</code>, <code>UCAL_WALLTIME_LAST</code> and
|
||||
* <code>UCAL_WALLTIME_NEXT_VALID</code>.
|
||||
* @see #getSkippedWallTimeOption
|
||||
*
|
||||
*
|
||||
* @stable ICU 49
|
||||
*/
|
||||
void setSkippedWallTimeOption(UCalendarWallTimeOption option);
|
||||
|
@ -959,7 +959,7 @@ public:
|
|||
/**
|
||||
* Gets the behavior for handling skipped wall time at positive time zone offset
|
||||
* transitions.
|
||||
*
|
||||
*
|
||||
* @return the behavior for handling skipped wall time, one of
|
||||
* <code>UCAL_WALLTIME_FIRST</code>, <code>UCAL_WALLTIME_LAST</code>
|
||||
* and <code>UCAL_WALLTIME_NEXT_VALID</code>.
|
||||
|
@ -1741,7 +1741,7 @@ protected:
|
|||
* reflects local zone wall time.
|
||||
* @internal
|
||||
*/
|
||||
int32_t computeMillisInDay();
|
||||
double computeMillisInDay();
|
||||
|
||||
/**
|
||||
* This method can assume EXTENDED_YEAR has been set.
|
||||
|
@ -1752,7 +1752,7 @@ protected:
|
|||
* when this function fails.
|
||||
* @internal
|
||||
*/
|
||||
int32_t computeZoneOffset(double millis, int32_t millisInDay, UErrorCode &ec);
|
||||
int32_t computeZoneOffset(double millis, double millisInDay, UErrorCode &ec);
|
||||
|
||||
|
||||
/**
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -1,14 +1,14 @@
|
|||
// © 2016 and later: Unicode, Inc. and others.
|
||||
// License & terms of use: http://www.unicode.org/copyright.html
|
||||
/********************************************************************
|
||||
* COPYRIGHT:
|
||||
* COPYRIGHT:
|
||||
* Copyright (c) 1997-2012, International Business Machines Corporation and
|
||||
* others. All Rights Reserved.
|
||||
********************************************************************/
|
||||
|
||||
#ifndef _CALENDARREGRESSIONTEST_
|
||||
#define _CALENDARREGRESSIONTEST_
|
||||
|
||||
|
||||
#include "unicode/utypes.h"
|
||||
|
||||
#if !UCONFIG_NO_FORMATTING
|
||||
|
@ -17,11 +17,11 @@
|
|||
#include "unicode/gregocal.h"
|
||||
#include "intltest.h"
|
||||
|
||||
/**
|
||||
/**
|
||||
* Performs regression test for Calendar
|
||||
**/
|
||||
class CalendarRegressionTest: public IntlTest {
|
||||
|
||||
class CalendarRegressionTest: public IntlTest {
|
||||
|
||||
// IntlTest override
|
||||
void runIndexedTest( int32_t index, UBool exec, const char* &name, char* par );
|
||||
public:
|
||||
|
@ -77,6 +77,7 @@ public:
|
|||
void TestT8596(void);
|
||||
void Test9019(void);
|
||||
void TestT9452(void);
|
||||
void TestT11632(void);
|
||||
|
||||
void printdate(GregorianCalendar *cal, const char *string);
|
||||
void dowTest(UBool lenient) ;
|
||||
|
@ -94,6 +95,6 @@ protected:
|
|||
};
|
||||
|
||||
#endif /* #if !UCONFIG_NO_FORMATTING */
|
||||
|
||||
|
||||
#endif // _CALENDARREGRESSIONTEST_
|
||||
//eof
|
||||
|
|
Loading…
Add table
Reference in a new issue