ICU-2966 improve performance by storing finalMillis

X-SVN-Rev: 13002
This commit is contained in:
Alan Liu 2003-09-01 22:02:52 +00:00
parent e8d3058495
commit 6afecf4ef8
2 changed files with 45 additions and 30 deletions

View File

@ -17,6 +17,7 @@
#include "unicode/gregocal.h"
#include "cmemory.h"
#include "uassert.h"
#include <float.h> // DBL_MAX
U_NAMESPACE_BEGIN
@ -133,7 +134,8 @@ static void dayToFields(double day, int32_t& year, int32_t& month,
* Default constructor. Creates a time zone with an empty ID and
* a fixed GMT offset of zero.
*/
OlsonTimeZone::OlsonTimeZone() : finalZone(0), finalYear(INT32_MAX) {
OlsonTimeZone::OlsonTimeZone() : finalZone(0), finalYear(INT32_MAX),
finalMillis(DBL_MAX) {
constructEmpty();
}
@ -158,7 +160,7 @@ void OlsonTimeZone::constructEmpty() {
OlsonTimeZone::OlsonTimeZone(const UResourceBundle* top,
const UResourceBundle* res,
UErrorCode& ec) :
finalZone(0), finalYear(INT32_MAX) {
finalZone(0), finalYear(INT32_MAX), finalMillis(DBL_MAX) {
if ((top == NULL || res == NULL) && U_SUCCESS(ec)) {
ec = U_ILLEGAL_ARGUMENT_ERROR;
}
@ -222,6 +224,9 @@ OlsonTimeZone::OlsonTimeZone(const UResourceBundle* top,
// years, including INT32_MAX.
U_ASSERT(data[1] > INT32_MIN);
finalYear = data[1] - 1;
// Also compute the millis for Jan 1, 0:00 GMT of the
// finalYear. This reduces runtime computations.
finalMillis = fieldsToDay(data[1], 0, 1) * U_MILLIS_PER_DAY;
char key[64];
key[0] = '_';
ruleid.extract(0, sizeof(key)-2, key+1, sizeof(key)-1, "");
@ -273,6 +278,7 @@ OlsonTimeZone& OlsonTimeZone::operator=(const OlsonTimeZone& other) {
typeOffsets = other.typeOffsets;
typeData = other.typeData;
finalYear = other.finalYear;
finalMillis = other.finalMillis;
delete finalZone;
finalZone = (other.finalZone != 0) ?
(SimpleTimeZone*) other.finalZone->clone() : 0;
@ -300,6 +306,7 @@ UBool OlsonTimeZone::operator==(const TimeZone& other) const {
// If the pointers are not equal, the zones may still
// be equal if their rules and transitions are equal
(finalYear == z->finalYear &&
// Don't compare finalMillis; if finalYear is ==, so is finalMillis
((finalZone == 0 && z->finalZone == 0) ||
(finalZone != 0 && z->finalZone != 0 &&
*finalZone == *z->finalZone)) &&
@ -382,27 +389,6 @@ int32_t OlsonTimeZone::getOffset(uint8_t era, int32_t year, int32_t month,
return zoneOffset(findTransition(time, TRUE)) * U_MILLIS_PER_SECOND;
}
/**
* TimeZone API.
*/
void OlsonTimeZone::setRawOffset(int32_t /*offsetMillis*/) {
// We don't support this operation, since OlsonTimeZones are
// immutable (except for the ID, which is in the base class).
// Nothing to do!
}
/**
* TimeZone API.
*/
int32_t OlsonTimeZone::getRawOffset() const {
UErrorCode ec = U_ZERO_ERROR;
int32_t raw, dst;
getOffset((double) uprv_getUTCtime() * U_MILLIS_PER_SECOND,
FALSE, raw, dst, ec);
return raw;
}
/**
* TimeZone API.
*/
@ -412,14 +398,15 @@ void OlsonTimeZone::getOffset(UDate date, UBool local, int32_t& rawoff,
return;
}
int32_t year, month, dom, dow;
double secs = uprv_floor(date / U_MILLIS_PER_SECOND);
double days = uprv_floor(date / U_MILLIS_PER_DAY);
// The check against finalMillis will suffice most of the time, except
// for the case in which finalMillis == DBL_MAX, date == DBL_MAX,
// and finalZone == 0. For this case we add "&& finalZone != 0".
if (date >= finalMillis && finalZone != 0) {
int32_t year, month, dom, dow;
double days = uprv_floor(date / U_MILLIS_PER_DAY);
dayToFields(days, year, month, dom, dow);
dayToFields(days, year, month, dom, dow);
if (year > finalYear) { // [sic] >, not >=; see above
U_ASSERT(finalZone != 0);
int32_t millis = (int32_t) (date - days * U_MILLIS_PER_DAY);
rawoff = finalZone->getRawOffset();
@ -439,11 +426,33 @@ void OlsonTimeZone::getOffset(UDate date, UBool local, int32_t& rawoff,
return;
}
double secs = uprv_floor(date / U_MILLIS_PER_SECOND);
int16_t i = findTransition(secs, local);
rawoff = rawOffset(i) * U_MILLIS_PER_SECOND;
dstoff = dstOffset(i) * U_MILLIS_PER_SECOND;
}
/**
* TimeZone API.
*/
void OlsonTimeZone::setRawOffset(int32_t /*offsetMillis*/) {
// We don't support this operation, since OlsonTimeZones are
// immutable (except for the ID, which is in the base class).
// Nothing to do!
}
/**
* TimeZone API.
*/
int32_t OlsonTimeZone::getRawOffset() const {
UErrorCode ec = U_ZERO_ERROR;
int32_t raw, dst;
getOffset((double) uprv_getUTCtime() * U_MILLIS_PER_SECOND,
FALSE, raw, dst, ec);
return raw;
}
/**
* Find the smallest i (in 0..transitionCount-1) such that time >=
* transition(i), where transition(i) is either the GMT or the local

View File

@ -170,6 +170,12 @@ class U_I18N_API OlsonTimeZone: public TimeZone {
*/
int32_t finalYear;
/**
* The millis for the start of the first year for which finalZone
* is to be used, or DBL_MAX if finalZone is 0.
*/
double finalMillis;
/**
* A SimpleTimeZone that governs the behavior for years > finalYear.
* If and only if finalYear == INT32_MAX then finalZone == 0.