ICU-11401 Reduce cache keyspace by caching only the components of DateFormat by locale rather than actual DateFormat objects.

X-SVN-Rev: 36811
This commit is contained in:
Travis Keep 2014-12-05 18:15:35 +00:00
parent 9d54e5711e
commit a6bc072149
15 changed files with 337 additions and 280 deletions

3
.gitattributes vendored
View File

@ -77,7 +77,8 @@ icu4c/source/extra/uconv/uconv.vcxproj.filters -text
icu4c/source/i18n/i18n.vcxproj -text
icu4c/source/i18n/i18n.vcxproj.filters -text
icu4c/source/i18n/scientificnumberformatter.cpp -text
icu4c/source/i18n/shareddatefmt.h -text
icu4c/source/i18n/sharedcalendar.h -text
icu4c/source/i18n/shareddateformatsymbols.h -text
icu4c/source/i18n/shareddatetimepatterngenerator.h -text
icu4c/source/i18n/unicode/scientificnumberformatter.h -text
icu4c/source/io/io.vcxproj -text

View File

@ -57,6 +57,8 @@
#include "ustrenum.h"
#include "uassert.h"
#include "olsontz.h"
#include "sharedcalendar.h"
#include "unifiedcache.h"
#if !UCONFIG_NO_SERVICE
static icu::ICULocaleService* gService = NULL;
@ -199,6 +201,27 @@ typedef enum ECalType {
U_NAMESPACE_BEGIN
SharedCalendar::~SharedCalendar() {
delete ptr;
}
template<> U_I18N_API
const SharedCalendar *LocaleCacheKey<SharedCalendar>::createObject(
const void * /*unusedCreationContext*/, UErrorCode &status) const {
Calendar *calendar = Calendar::makeInstance(fLoc, status);
if (U_FAILURE(status)) {
return NULL;
}
SharedCalendar *shared = new SharedCalendar(calendar);
if (shared == NULL) {
delete calendar;
status = U_MEMORY_ALLOCATION_ERROR;
return NULL;
}
shared->addRef();
return shared;
}
static ECalType getCalendarType(const char *s) {
for (int i = 0; gCalTypes[i] != NULL; i++) {
if (uprv_stricmp(s, gCalTypes[i]) == 0) {
@ -833,9 +856,8 @@ Calendar::createInstance(const Locale& aLocale, UErrorCode& success)
// Note: this is the bottleneck that actually calls the service routines.
Calendar* U_EXPORT2
Calendar::createInstance(TimeZone* zone, const Locale& aLocale, UErrorCode& success)
{
Calendar * U_EXPORT2
Calendar::makeInstance(const Locale& aLocale, UErrorCode& success) {
if (U_FAILURE(success)) {
return NULL;
}
@ -855,7 +877,6 @@ Calendar::createInstance(TimeZone* zone, const Locale& aLocale, UErrorCode& succ
Calendar* c = NULL;
if(U_FAILURE(success) || !u) {
delete zone;
if(U_SUCCESS(success)) { // Propagate some kind of err
success = U_INTERNAL_PROGRAM_ERROR;
}
@ -884,7 +905,6 @@ Calendar::createInstance(TimeZone* zone, const Locale& aLocale, UErrorCode& succ
c = (Calendar*)getCalendarService(success)->get(l, LocaleKey::KIND_ANY, &actualLoc2, success);
if(U_FAILURE(success) || !c) {
delete zone;
if(U_SUCCESS(success)) {
success = U_INTERNAL_PROGRAM_ERROR; // Propagate some err
}
@ -910,7 +930,6 @@ Calendar::createInstance(TimeZone* zone, const Locale& aLocale, UErrorCode& succ
#endif
success = U_MISSING_RESOURCE_ERROR; // requested a calendar type which could NOT be found.
delete c;
delete zone;
return NULL;
}
#ifdef U_DEBUG_CALSVC
@ -933,8 +952,27 @@ Calendar::createInstance(TimeZone* zone, const Locale& aLocale, UErrorCode& succ
c = (Calendar*)u;
}
return c;
}
Calendar* U_EXPORT2
Calendar::createInstance(TimeZone* zone, const Locale& aLocale, UErrorCode& success)
{
LocalPointer<TimeZone> zonePtr(zone);
const SharedCalendar *shared = NULL;
UnifiedCache::getByLocale(aLocale, shared, success);
if (U_FAILURE(success)) {
return NULL;
}
Calendar *c = (*shared)->clone();
shared->removeRef();
if (c == NULL) {
success = U_MEMORY_ALLOCATION_ERROR;
return NULL;
}
// Now, reset calendar to default state:
c->adoptTimeZone(zone); // Set the correct time zone
c->adoptTimeZone(zonePtr.orphan()); // Set the correct time zone
c->setTimeInMillis(getNow(), success); // let the new calendar have the current time.
return c;
@ -954,6 +992,24 @@ Calendar::createInstance(const TimeZone& zone, const Locale& aLocale, UErrorCode
// -------------------------------------
void U_EXPORT2
Calendar::getCalendarTypeFromLocale(
const Locale &aLocale,
char *typeBuffer,
int32_t typeBufferSize,
UErrorCode &success) {
const SharedCalendar *shared = NULL;
UnifiedCache::getByLocale(aLocale, shared, success);
if (U_FAILURE(success)) {
return;
}
uprv_strncpy(typeBuffer, (*shared)->getType(), typeBufferSize);
shared->removeRef();
if (typeBuffer[typeBufferSize - 1]) {
success = U_BUFFER_OVERFLOW_ERROR;
}
}
UBool
Calendar::operator==(const Calendar& that) const
{

View File

@ -27,9 +27,6 @@
#include "unicode/dtptngen.h"
#include "unicode/udisplaycontext.h"
#include "reldtfmt.h"
#include "shareddatefmt.h"
#include "shareddatetimepatterngenerator.h"
#include "unifiedcache.h"
#include "cstring.h"
#include "windtfmt.h"
@ -44,181 +41,6 @@
U_NAMESPACE_BEGIN
SharedDateFormat::~SharedDateFormat() {
delete ptr;
}
// We must fully define LocaleCacheKey<SharedDateFormat>
template<> U_I18N_API
const SharedDateFormat *LocaleCacheKey<SharedDateFormat>::createObject(
const void * /*creationContext*/, UErrorCode &status) const {
status = U_UNSUPPORTED_ERROR;
return NULL;
}
class U_I18N_API DateFmtKeyByStyle : public LocaleCacheKey<SharedDateFormat> {
private:
DateFormat::EStyle fDateStyle;
DateFormat::EStyle fTimeStyle;
public:
DateFmtKeyByStyle(
const Locale &loc,
DateFormat::EStyle dateStyle,
DateFormat::EStyle timeStyle)
: LocaleCacheKey<SharedDateFormat>(loc),
fDateStyle(dateStyle),
fTimeStyle(timeStyle) { }
DateFmtKeyByStyle(const DateFmtKeyByStyle &other) :
LocaleCacheKey<SharedDateFormat>(other),
fDateStyle(other.fDateStyle),
fTimeStyle(other.fTimeStyle) { }
virtual ~DateFmtKeyByStyle();
virtual int32_t hashCode() const {
int32_t hash = 37 * LocaleCacheKey<SharedDateFormat>::hashCode() + fDateStyle;
hash = 37 * hash + fTimeStyle;
return hash;
}
virtual UBool operator==(const CacheKeyBase &other) const {
// reflexive
if (this == &other) {
return TRUE;
}
if (!LocaleCacheKey<SharedDateFormat>::operator==(other)) {
return FALSE;
}
// We know that this an other are of same class if we get this far.
const DateFmtKeyByStyle *realOther =
static_cast<const DateFmtKeyByStyle *>(&other);
return (realOther->fDateStyle == fDateStyle &&
realOther->fTimeStyle == fTimeStyle);
}
virtual CacheKeyBase *clone() const {
return new DateFmtKeyByStyle(*this);
}
virtual const SharedDateFormat *createObject(
const void * /*creationContext*/, UErrorCode &status) const {
DateFormat::EStyle dateStyle = fDateStyle;
if(dateStyle != DateFormat::kNone)
{
dateStyle = (DateFormat::EStyle) (dateStyle + DateFormat::kDateOffset);
}
DateFormat *fmt = DateFormat::create(fTimeStyle, dateStyle, fLoc);
if (fmt == NULL) {
status = U_MEMORY_ALLOCATION_ERROR;
return NULL;
}
SharedDateFormat *result = new SharedDateFormat(fmt);
if (result == NULL) {
delete fmt;
status = U_MEMORY_ALLOCATION_ERROR;
return NULL;
}
result->addRef();
return result;
}
};
DateFmtKeyByStyle::~DateFmtKeyByStyle() {
}
class U_I18N_API DateFmtKeyBySkeleton : public LocaleCacheKey<SharedDateFormat> {
private:
UnicodeString fSkeleton;
public:
DateFmtKeyBySkeleton(const Locale &loc, const UnicodeString &skeleton) :
LocaleCacheKey<SharedDateFormat>(loc),
fSkeleton(skeleton) { }
DateFmtKeyBySkeleton(const DateFmtKeyBySkeleton &other) :
LocaleCacheKey<SharedDateFormat>(other),
fSkeleton(other.fSkeleton) { }
virtual ~DateFmtKeyBySkeleton();
virtual int32_t hashCode() const {
return 37 * LocaleCacheKey<SharedDateFormat>::hashCode() + fSkeleton.hashCode();
}
virtual UBool operator==(const CacheKeyBase &other) const {
// reflexive
if (this == &other) {
return TRUE;
}
if (!LocaleCacheKey<SharedDateFormat>::operator==(other)) {
return FALSE;
}
// We know that this an other are of same class if we get this far.
const DateFmtKeyBySkeleton *realOther =
static_cast<const DateFmtKeyBySkeleton *>(&other);
return (realOther->fSkeleton == fSkeleton);
}
virtual CacheKeyBase *clone() const {
return new DateFmtKeyBySkeleton(*this);
}
virtual const SharedDateFormat *createObject(
const void *creationContext, UErrorCode &status) const {
void *mutableCreationContext = const_cast<void *>(creationContext);
DateTimePatternGenerator *ownedDtpg = NULL;
DateTimePatternGenerator *dtpg =
static_cast<DateTimePatternGenerator *>(mutableCreationContext);
if (dtpg == NULL) {
ownedDtpg = DateTimePatternGenerator::createInstance(fLoc, status);
if (U_FAILURE(status)) {
return NULL;
}
dtpg = ownedDtpg;
}
DateFormat *fmt = new SimpleDateFormat(
dtpg->getBestPattern(fSkeleton, status),
fLoc,
status);
delete ownedDtpg;
if (fmt == NULL) {
status = U_MEMORY_ALLOCATION_ERROR;
return NULL;
}
if (U_FAILURE(status)) {
delete fmt;
return NULL;
}
SharedDateFormat *result = new SharedDateFormat(fmt);
if (result == NULL) {
delete fmt;
status = U_MEMORY_ALLOCATION_ERROR;
return NULL;
}
result->addRef();
return result;
}
};
DateFmtKeyBySkeleton::~DateFmtKeyBySkeleton() {
}
static DateFormat *createFromCache(
const CacheKey<SharedDateFormat> &key,
const void *context,
UErrorCode &status) {
const UnifiedCache *cache = UnifiedCache::getInstance(status);
if (U_FAILURE(status)) {
return NULL;
}
const SharedDateFormat *ptr = NULL;
cache->get(key, context, ptr, status);
if (U_FAILURE(status)) {
return NULL;
}
DateFormat *result = static_cast<DateFormat *>((*ptr)->clone());
ptr->removeRef();
if (result == NULL) {
status = U_MEMORY_ALLOCATION_ERROR;
} else {
// Set the currently active default TimeZone,
// because the cached instance might be created
// with another TimeZone.
// Note: We could do some optimization in SharedDateFormat
// to pick up the current default without cloning old default.
result->adoptTimeZone(TimeZone::createDefault());
}
return result;
}
DateFormat::DateFormat()
: fCalendar(0),
fNumberFormat(0),
@ -487,9 +309,7 @@ DateFormat* U_EXPORT2
DateFormat::createTimeInstance(DateFormat::EStyle style,
const Locale& aLocale)
{
DateFmtKeyByStyle key(aLocale, kNone, style);
UErrorCode status = U_ZERO_ERROR;
return createFromCache(key, NULL, status);
return createDateTimeInstance(kNone, style, aLocale);
}
//----------------------------------------------------------------------
@ -498,9 +318,7 @@ DateFormat* U_EXPORT2
DateFormat::createDateInstance(DateFormat::EStyle style,
const Locale& aLocale)
{
DateFmtKeyByStyle key(aLocale, style, kNone);
UErrorCode status = U_ZERO_ERROR;
return createFromCache(key, NULL, status);
return createDateTimeInstance(style, kNone, aLocale);
}
//----------------------------------------------------------------------
@ -510,9 +328,11 @@ DateFormat::createDateTimeInstance(EStyle dateStyle,
EStyle timeStyle,
const Locale& aLocale)
{
DateFmtKeyByStyle key(aLocale, dateStyle, timeStyle);
UErrorCode status = U_ZERO_ERROR;
return createFromCache(key, NULL, status);
if(dateStyle != kNone)
{
dateStyle = (EStyle) (dateStyle + kDateOffset);
}
return create(timeStyle, dateStyle, aLocale);
}
//----------------------------------------------------------------------
@ -520,9 +340,7 @@ DateFormat::createDateTimeInstance(EStyle dateStyle,
DateFormat* U_EXPORT2
DateFormat::createInstance()
{
DateFmtKeyByStyle key(Locale::getDefault(), kShort, kShort);
UErrorCode status = U_ZERO_ERROR;
return createFromCache(key, NULL, status);
return createDateTimeInstance(kShort, kShort, Locale::getDefault());
}
//----------------------------------------------------------------------
@ -541,8 +359,7 @@ DateFormat::createInstanceForSkeleton(
status = U_ILLEGAL_ARGUMENT_ERROR;
return NULL;
}
DateFmtKeyBySkeleton key(locale, skeleton);
DateFormat *result = createFromCache(key, NULL, status);
DateFormat *result = createInstanceForSkeleton(skeleton, locale, status);
if (U_FAILURE(status)) {
return NULL;
}
@ -555,22 +372,21 @@ DateFormat::createInstanceForSkeleton(
const UnicodeString& skeleton,
const Locale &locale,
UErrorCode &status) {
LocalPointer<DateTimePatternGenerator> gen(
DateTimePatternGenerator::createInstance(locale, status));
if (U_FAILURE(status)) {
return NULL;
}
DateFmtKeyBySkeleton key(locale, skeleton);
return createFromCache(key, NULL, status);
return internalCreateInstanceForSkeleton(
skeleton, locale, *gen, status);
}
DateFormat* U_EXPORT2
DateFormat::createInstanceForSkeleton(
const UnicodeString& skeleton,
UErrorCode &status) {
if (U_FAILURE(status)) {
return NULL;
}
DateFmtKeyBySkeleton key(Locale::getDefault(), skeleton);
return createFromCache(key, NULL, status);
return createInstanceForSkeleton(
skeleton, Locale::getDefault(), status);
}
DateFormat* U_EXPORT2
@ -582,8 +398,19 @@ DateFormat::internalCreateInstanceForSkeleton(
if (U_FAILURE(status)) {
return NULL;
}
DateFmtKeyBySkeleton key(locale, skeleton);
return createFromCache(key, &gen, status);
DateFormat *fmt = new SimpleDateFormat(
gen.getBestPattern(skeleton, status),
locale,
status);
if (fmt == NULL) {
status = U_MEMORY_ALLOCATION_ERROR;
return NULL;
}
if (U_FAILURE(status)) {
delete fmt;
return NULL;
}
return fmt;
}
//----------------------------------------------------------------------

View File

@ -36,6 +36,9 @@
#include "hash.h"
#include "uresimp.h"
#include "ureslocs.h"
#include "shareddateformatsymbols.h"
#include "unicode/calendar.h"
#include "unifiedcache.h"
// *****************************************************************************
// class DateFormatSymbols
@ -146,6 +149,32 @@ typedef enum LastResortSize {
U_NAMESPACE_BEGIN
SharedDateFormatSymbols::~SharedDateFormatSymbols() {
}
template<> U_I18N_API
const SharedDateFormatSymbols *
LocaleCacheKey<SharedDateFormatSymbols>::createObject(
const void */*unusedContext*/, UErrorCode &status) const {
char type[256];
Calendar::getCalendarTypeFromLocale(fLoc, type, UPRV_LENGTHOF(type), status);
if (U_FAILURE(status)) {
return NULL;
}
SharedDateFormatSymbols *shared
= new SharedDateFormatSymbols(fLoc, type, status);
if (shared == NULL) {
status = U_MEMORY_ALLOCATION_ERROR;
return NULL;
}
if (U_FAILURE(status)) {
delete shared;
return NULL;
}
shared->addRef();
return shared;
}
UOBJECT_DEFINE_RTTI_IMPLEMENTATION(DateFormatSymbols)
#define kSUPPLEMENTAL "supplementalData"
@ -191,6 +220,23 @@ static inline UnicodeString* newUnicodeStringArray(size_t count) {
//------------------------------------------------------
DateFormatSymbols * U_EXPORT2
DateFormatSymbols::createForLocale(
const Locale& locale, UErrorCode &status) {
const SharedDateFormatSymbols *shared = NULL;
UnifiedCache::getByLocale(locale, shared, status);
if (U_FAILURE(status)) {
return NULL;
}
DateFormatSymbols *result = new DateFormatSymbols(shared->get());
shared->removeRef();
if (result == NULL) {
status = U_MEMORY_ALLOCATION_ERROR;
return NULL;
}
return result;
}
DateFormatSymbols::DateFormatSymbols(const Locale& locale,
UErrorCode& status)
: UObject()

View File

@ -1152,7 +1152,8 @@
<ClInclude Include="plurrule_impl.h" />
<ClInclude Include="quantityformatter.h" />
<ClInclude Include="sharedbreakiterator.h" />
<ClInclude Include="shareddatefmt.h" />
<ClInclude Include="sharedcalendar.h" />
<ClInclude Include="shareddateformatsymbols.h" />
<ClInclude Include="shareddatetimepatterngenerator.h" />
<ClInclude Include="sharednumberformat.h" />
<ClInclude Include="sharedpluralrules.h" />

View File

@ -698,7 +698,10 @@
<ClInclude Include="sharedbreakiterator.h">
<Filter>formatting</Filter>
</ClInclude>
<ClInclude Include="shareddatefmt.h">
<ClInclude Include="sharedcalendar.h">
<Filter>formatting</Filter>
</ClInclude>
<ClInclude Include="shareddateformatsymbols.h">
<Filter>formatting</Filter>
</ClInclude>
<ClInclude Include="shareddatetimepatterngenerator.h">

View File

@ -0,0 +1,34 @@
/*
******************************************************************************
* Copyright (C) 2014, International Business Machines
* Corporation and others. All Rights Reserved.
******************************************************************************
* sharedcalendar.h
*/
#ifndef __SHARED_CALENDAR_H__
#define __SHARED_CALENDAR_H__
#include "unicode/utypes.h"
#include "sharedobject.h"
U_NAMESPACE_BEGIN
class Calendar;
class U_I18N_API SharedCalendar : public SharedObject {
public:
SharedCalendar(Calendar *calToAdopt) : ptr(calToAdopt) { }
virtual ~SharedCalendar();
const Calendar *get() const { return ptr; }
const Calendar *operator->() const { return ptr; }
const Calendar &operator*() const { return *ptr; }
private:
Calendar *ptr;
SharedCalendar(const SharedCalendar &);
SharedCalendar &operator=(const SharedCalendar &);
};
U_NAMESPACE_END
#endif

View File

@ -1,34 +0,0 @@
/*
******************************************************************************
* Copyright (C) 2014, International Business Machines
* Corporation and others. All Rights Reserved.
******************************************************************************
* shareddateformat.h
*/
#ifndef __SHARED_DATEFORMAT_H__
#define __SHARED_DATEFORMAT_H__
#include "unicode/utypes.h"
#include "sharedobject.h"
U_NAMESPACE_BEGIN
class DateFormat;
class U_I18N_API SharedDateFormat : public SharedObject {
public:
SharedDateFormat(DateFormat *dfToAdopt) : ptr(dfToAdopt) { }
virtual ~SharedDateFormat();
const DateFormat *get() const { return ptr; }
const DateFormat *operator->() const { return ptr; }
const DateFormat &operator*() const { return *ptr; }
private:
DateFormat *ptr;
SharedDateFormat(const SharedDateFormat &);
SharedDateFormat &operator=(const SharedDateFormat &);
};
U_NAMESPACE_END
#endif

View File

@ -0,0 +1,34 @@
/*
******************************************************************************
* Copyright (C) 2014, International Business Machines
* Corporation and others. All Rights Reserved.
******************************************************************************
* shareddateformatsymbols.h
*/
#ifndef __SHARED_DATEFORMATSYMBOLS_H__
#define __SHARED_DATEFORMATSYMBOLS_H__
#include "unicode/utypes.h"
#include "sharedobject.h"
#include "unicode/dtfmtsym.h"
U_NAMESPACE_BEGIN
class U_I18N_API SharedDateFormatSymbols : public SharedObject {
public:
SharedDateFormatSymbols(
const Locale &loc, const char *type, UErrorCode &status)
: dfs(loc, type, status) { }
virtual ~SharedDateFormatSymbols();
const DateFormatSymbols &get() const { return dfs; }
private:
DateFormatSymbols dfs;
SharedDateFormatSymbols(const SharedDateFormatSymbols &);
SharedDateFormatSymbols &operator=(const SharedDateFormatSymbols &);
};
U_NAMESPACE_END
#endif

View File

@ -394,7 +394,8 @@ SimpleDateFormat::SimpleDateFormat(const UnicodeString& pattern,
fDateOverride.setToBogus();
fTimeOverride.setToBogus();
initializeBooleanAttributes();
initializeSymbols(fLocale, initializeCalendar(NULL,fLocale,status), status);
initializeCalendar(NULL,fLocale,status);
fSymbols = DateFormatSymbols::createForLocale(fLocale, status);
initialize(fLocale, status);
initializeDefaultCentury();
@ -414,7 +415,8 @@ SimpleDateFormat::SimpleDateFormat(const UnicodeString& pattern,
fDateOverride.setTo(override);
fTimeOverride.setToBogus();
initializeBooleanAttributes();
initializeSymbols(fLocale, initializeCalendar(NULL,fLocale,status), status);
initializeCalendar(NULL,fLocale,status);
fSymbols = DateFormatSymbols::createForLocale(fLocale, status);
initialize(fLocale, status);
initializeDefaultCentury();
@ -438,7 +440,8 @@ SimpleDateFormat::SimpleDateFormat(const UnicodeString& pattern,
fTimeOverride.setToBogus();
initializeBooleanAttributes();
initializeSymbols(fLocale, initializeCalendar(NULL,fLocale,status), status);
initializeCalendar(NULL,fLocale,status);
fSymbols = DateFormatSymbols::createForLocale(fLocale, status);
initialize(fLocale, status);
initializeDefaultCentury();
}
@ -460,7 +463,8 @@ SimpleDateFormat::SimpleDateFormat(const UnicodeString& pattern,
fTimeOverride.setToBogus();
initializeBooleanAttributes();
initializeSymbols(fLocale, initializeCalendar(NULL,fLocale,status), status);
initializeCalendar(NULL,fLocale,status);
fSymbols = DateFormatSymbols::createForLocale(fLocale, status);
initialize(fLocale, status);
initializeDefaultCentury();
@ -550,7 +554,8 @@ SimpleDateFormat::SimpleDateFormat(const Locale& locale,
{
if (U_FAILURE(status)) return;
initializeBooleanAttributes();
initializeSymbols(fLocale, initializeCalendar(NULL, fLocale, status),status);
initializeCalendar(NULL, fLocale, status);
fSymbols = DateFormatSymbols::createForLocale(fLocale, status);
if (U_FAILURE(status))
{
status = U_ZERO_ERROR;
@ -699,7 +704,7 @@ void SimpleDateFormat::construct(EStyle timeStyle,
ures_getLocaleByType(dateTimePatterns, ULOC_ACTUAL_LOCALE, &status));
// create a symbols object from the locale
initializeSymbols(locale,fCalendar, status);
fSymbols = DateFormatSymbols::createForLocale(locale, status);
if (U_FAILURE(status)) return;
/* test for NULL */
if (fSymbols == 0) {
@ -870,28 +875,9 @@ SimpleDateFormat::initializeCalendar(TimeZone* adoptZone, const Locale& locale,
if(!U_FAILURE(status)) {
fCalendar = Calendar::createInstance(adoptZone?adoptZone:TimeZone::createDefault(), locale, status);
}
if (U_SUCCESS(status) && fCalendar == NULL) {
status = U_MEMORY_ALLOCATION_ERROR;
}
return fCalendar;
}
void
SimpleDateFormat::initializeSymbols(const Locale& locale, Calendar* calendar, UErrorCode& status)
{
if(U_FAILURE(status)) {
fSymbols = NULL;
} else {
// pass in calendar type - use NULL (default) if no calendar set (or err).
fSymbols = new DateFormatSymbols(locale, calendar?calendar->getType() :NULL , status);
// Null pointer check
if (fSymbols == NULL) {
status = U_MEMORY_ALLOCATION_ERROR;
return;
}
}
}
void
SimpleDateFormat::initialize(const Locale& locale,
UErrorCode& status)
@ -3517,10 +3503,16 @@ SimpleDateFormat::setTimeZoneFormat(const TimeZoneFormat& newTimeZoneFormat)
void SimpleDateFormat::adoptCalendar(Calendar* calendarToAdopt)
{
UErrorCode status = U_ZERO_ERROR;
Locale calLocale(fLocale);
calLocale.setKeywordValue("calendar", calendarToAdopt->getType(), status);
DateFormatSymbols *newSymbols =
DateFormatSymbols::createForLocale(calLocale, status);
if (U_FAILURE(status)) {
return;
}
DateFormat::adoptCalendar(calendarToAdopt);
delete fSymbols;
fSymbols=NULL;
initializeSymbols(fLocale, fCalendar, status); // we need new symbols
fSymbols = newSymbols;
initializeDefaultCentury(); // we need a new century (possibly)
}

View File

@ -2461,6 +2461,34 @@ private:
* @return TRUE if a transition is found.
*/
UBool getImmediatePreviousZoneTransition(UDate base, UDate *transitionTime, UErrorCode& status) const;
public:
/**
* Creates a new Calendar from a Locale for the cache.
* This method does not set the time or timezone in returned calendar.
* @param locale the locale.
* @param status any error returned here.
* @return the new Calendar object with no time or timezone set.
* @internal For ICU use only.
*/
static Calendar U_EXPORT2 *makeInstance(
const Locale &locale, UErrorCode &status);
/**
* Get the calendar type for given locale.
* @param locale the locale
* @param typeBuffer calendar type returned here
* @param typeBufferSize The size of typeBuffer in bytes. If the type
* can't fit in the buffer, this method sets status to
* U_BUFFER_OVERFLOW_ERROR
* @param status error, if any, returned here.
* @internal For ICU use only.
*/
static void U_EXPORT2 getCalendarTypeFromLocale(
const Locale &locale,
char *typeBuffer,
int32_t typeBufferSize,
UErrorCode &status);
};
// -------------------------------------

View File

@ -902,6 +902,20 @@ private:
* Returns TRUE if c (repeated count times) is the pattern character for a numeric field.
*/
static UBool U_EXPORT2 isNumericPatternChar(UChar c, int32_t count);
public:
/**
* Gets a DateFormatSymbols by locale.
* Unlike the constructors which always use gregorian calendar, this
* method uses the calendar in the locale. If the locale contains no
* explicit calendar, this method uses the default calendar for that
* locale.
* @param locale the locale.
* @param status error returned here.
* @return the new DateFormatSymbols which the caller owns.
* @internal For ICU use only.
*/
static DateFormatSymbols * U_EXPORT2 createForLocale(
const Locale &locale, UErrorCode &status);
};
U_NAMESPACE_END

View File

@ -1310,14 +1310,6 @@ private:
*/
Calendar *initializeCalendar(TimeZone* adoptZone, const Locale& locale, UErrorCode& status);
/**
* initializes fSymbols from parameters.
* @param locale Locale of the symbols
* @param calendar Alias to Calendar that will be used.
* @param status Error code
*/
void initializeSymbols(const Locale& locale, Calendar* calendar, UErrorCode& status);
/**
* Called by several of the constructors to load pattern data and formatting symbols
* out of a resource bundle and initialize the locale based on it.

View File

@ -108,6 +108,9 @@ void DateFormatTest::runIndexedTest( int32_t index, UBool exec, const char* &nam
TESTCASE_AUTO(TestCreateInstanceForSkeleton);
TESTCASE_AUTO(TestCreateInstanceForSkeletonDefault);
TESTCASE_AUTO(TestCreateInstanceForSkeletonWithCalendar);
TESTCASE_AUTO(TestDFSCreateForLocaleNonGregorianLocale);
TESTCASE_AUTO(TestDFSCreateForLocaleWithCalendarInLocale);
TESTCASE_AUTO(TestChangeCalendar);
TESTCASE_AUTO_END;
}
@ -4686,6 +4689,63 @@ void DateFormatTest::TestCreateInstanceForSkeletonWithCalendar() {
assertSuccess("", status);
}
void DateFormatTest::TestDFSCreateForLocaleNonGregorianLocale() {
UErrorCode status = U_ZERO_ERROR;
Locale fa("fa");
LocalPointer<DateFormatSymbols> sym(
DateFormatSymbols::createForLocale(fa, status));
if (!assertSuccess("", status)) {
return;
}
// Farsi should default to the persian calendar, not gregorian
int32_t count;
const UnicodeString *months = sym->getShortMonths(count);
// First persian month.
UnicodeString expected("\\u0641\\u0631\\u0648\\u0631\\u062f\\u06cc\\u0646");
assertEquals("", expected.unescape(), months[0]);
}
void DateFormatTest::TestDFSCreateForLocaleWithCalendarInLocale() {
UErrorCode status = U_ZERO_ERROR;
Locale en_heb("en@calendar=hebrew");
LocalPointer<DateFormatSymbols> sym(
DateFormatSymbols::createForLocale(en_heb, status));
if (!assertSuccess("", status)) {
return;
}
// We should get the months of the hebrew calendar, not the gregorian
// calendar.
int32_t count;
const UnicodeString *months = sym->getShortMonths(count);
// First hebrew month.
UnicodeString expected("Tishri");
assertEquals("", expected, months[0]);
}
void DateFormatTest::TestChangeCalendar() {
UErrorCode status = U_ZERO_ERROR;
Locale en("en");
Locale en_heb("en@calendar=hebrew");
LocalPointer<DateFormat> fmt(
DateFormat::createInstanceForSkeleton("yMMMd", en, status));
if (!assertSuccess("", status)) {
return;
}
fmt->adoptCalendar(Calendar::createInstance(en_heb, status));
if (!assertSuccess("", status)) {
return;
}
UnicodeString result;
FieldPosition pos(0);
fmt->format(date(98, 5-1, 25), result, pos);
assertEquals("format yMMMd", "Iyar 29, 5758", result);
}
#endif /* #if !UCONFIG_NO_FORMATTING */
//eof

View File

@ -244,6 +244,9 @@ public:
void TestCreateInstanceForSkeleton();
void TestCreateInstanceForSkeletonDefault();
void TestCreateInstanceForSkeletonWithCalendar();
void TestDFSCreateForLocaleNonGregorianLocale();
void TestDFSCreateForLocaleWithCalendarInLocale();
void TestChangeCalendar();
private:
UBool showParse(DateFormat &format, const UnicodeString &formattedString);