]> granicus.if.org Git - icu/commitdiff
ICU-11139 Add JAVA DateFormat factory methods to C++
authorTravis Keep <keep94@gmail.com>
Tue, 18 Nov 2014 00:43:49 +0000 (00:43 +0000)
committerTravis Keep <keep94@gmail.com>
Tue, 18 Nov 2014 00:43:49 +0000 (00:43 +0000)
X-SVN-Rev: 36745

18 files changed:
.gitattributes
icu4c/source/i18n/datefmt.cpp
icu4c/source/i18n/dtfmtsym.cpp
icu4c/source/i18n/dtitvfmt.cpp
icu4c/source/i18n/dtptngen.cpp
icu4c/source/i18n/i18n.vcxproj
icu4c/source/i18n/i18n.vcxproj.filters
icu4c/source/i18n/shareddatefmt.h [new file with mode: 0644]
icu4c/source/i18n/shareddatetimepatterngenerator.h [new file with mode: 0644]
icu4c/source/i18n/smpdtfmt.cpp
icu4c/source/i18n/unicode/datefmt.h
icu4c/source/i18n/unicode/dtptngen.h
icu4c/source/i18n/unicode/smpdtfmt.h
icu4c/source/test/cintltst/cdattst.c
icu4c/source/test/intltest/dtfmttst.cpp
icu4c/source/test/intltest/dtfmttst.h
icu4c/source/test/perf/DateFmtPerf/DateFmtPerf.cpp
icu4c/source/test/perf/DateFmtPerf/DateFmtPerf.h

index 7ce3f9e7f195482a12751d82fb9521a7ff3943e6..d82af5085b653a8e92e2537ef45c2e97e728d203 100644 (file)
@@ -76,6 +76,8 @@ icu4c/source/extra/uconv/uconv.vcxproj -text
 icu4c/source/extra/uconv/uconv.vcxproj.filters -text
 icu4c/source/i18n/i18n.vcxproj -text
 icu4c/source/i18n/i18n.vcxproj.filters -text
+icu4c/source/i18n/shareddatefmt.h -text
+icu4c/source/i18n/shareddatetimepatterngenerator.h -text
 icu4c/source/io/io.vcxproj -text
 icu4c/source/io/io.vcxproj.filters -text
 icu4c/source/layout/layout.vcxproj -text
index e205bf755f3ea31cea95fd22496c1b9fd868e4be..a22c3650973fc281a63ce787a8261623c804e6d6 100644 (file)
@@ -27,6 +27,9 @@
 #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"
 
 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;
+    }
+    return result;
+}
+
 DateFormat::DateFormat()
 :   fCalendar(0),
     fNumberFormat(0),
@@ -309,7 +480,9 @@ DateFormat* U_EXPORT2
 DateFormat::createTimeInstance(DateFormat::EStyle style,
                                const Locale& aLocale)
 {
-    return create(style, kNone, aLocale);
+    DateFmtKeyByStyle key(aLocale, kNone, style);
+    UErrorCode status = U_ZERO_ERROR;
+    return createFromCache(key, NULL, status);
 }
 
 //----------------------------------------------------------------------
@@ -318,13 +491,9 @@ DateFormat* U_EXPORT2
 DateFormat::createDateInstance(DateFormat::EStyle style,
                                const Locale& aLocale)
 {
-    // +4 to set the correct index for getting data out of
-    // LocaleElements.
-    if(style != kNone)
-    {
-        style = (EStyle) (style + kDateOffset);
-    }
-    return create(kNone, (EStyle) (style), aLocale);
+    DateFmtKeyByStyle key(aLocale, style, kNone);
+    UErrorCode status = U_ZERO_ERROR;
+    return createFromCache(key, NULL, status);
 }
 
 //----------------------------------------------------------------------
@@ -334,11 +503,9 @@ DateFormat::createDateTimeInstance(EStyle dateStyle,
                                    EStyle timeStyle,
                                    const Locale& aLocale)
 {
-    if(dateStyle != kNone)
-    {
-        dateStyle = (EStyle) (dateStyle + kDateOffset);
-    }
-    return create(timeStyle, dateStyle, aLocale);
+    DateFmtKeyByStyle key(aLocale, dateStyle, timeStyle);
+    UErrorCode status = U_ZERO_ERROR;
+    return createFromCache(key, NULL, status);
 }
 
 //----------------------------------------------------------------------
@@ -346,7 +513,70 @@ DateFormat::createDateTimeInstance(EStyle dateStyle,
 DateFormat* U_EXPORT2
 DateFormat::createInstance()
 {
-    return create(kShort, (EStyle) (kShort + kDateOffset), Locale::getDefault());
+    DateFmtKeyByStyle key(Locale::getDefault(), kShort, kShort);
+    UErrorCode status = U_ZERO_ERROR;
+    return createFromCache(key, NULL, status);
+}
+
+//----------------------------------------------------------------------
+
+DateFormat* U_EXPORT2
+DateFormat::createInstanceForSkeleton(
+        Calendar *calendarToAdopt,
+        const UnicodeString& skeleton,
+        const Locale &locale,
+        UErrorCode &status) {
+    LocalPointer<Calendar> calendar(calendarToAdopt);
+    if (U_FAILURE(status)) {
+        return NULL;
+    }
+    if (calendar.isNull()) {
+        status = U_ILLEGAL_ARGUMENT_ERROR;
+        return NULL;
+    }
+    DateFmtKeyBySkeleton key(locale, skeleton);
+    DateFormat *result = createFromCache(key, NULL, status);
+    if (U_FAILURE(status)) {
+        return NULL;
+    }
+    result->adoptCalendar(calendar.orphan());
+    return result;
+}
+
+DateFormat* U_EXPORT2
+DateFormat::createInstanceForSkeleton(
+        const UnicodeString& skeleton,
+        const Locale &locale,
+        UErrorCode &status) {
+    if (U_FAILURE(status)) {
+        return NULL;
+    }
+    DateFmtKeyBySkeleton key(locale, skeleton);
+    return createFromCache(key, NULL, 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);
+}
+
+DateFormat* U_EXPORT2
+DateFormat::internalCreateInstanceForSkeleton(
+        const UnicodeString& skeleton,
+        const Locale &locale,
+        DateTimePatternGenerator &gen,
+        UErrorCode &status) {
+    if (U_FAILURE(status)) {
+        return NULL;
+    }
+    DateFmtKeyBySkeleton key(locale, skeleton);
+    return createFromCache(key, &gen, status);
 }
 
 //----------------------------------------------------------------------
index 6dc1d4bcfa64ebd45f6531a15334155bac8d4dd8..a08811b75a35ada73c134442e694a60c17f4a5bb 100644 (file)
@@ -294,6 +294,11 @@ DateFormatSymbols::createZoneStrings(const UnicodeString *const * otherStrings)
  */
 void
 DateFormatSymbols::copyData(const DateFormatSymbols& other) {
+    UErrorCode status = U_ZERO_ERROR;
+    U_LOCALE_BASED(locBased, *this);
+    locBased.setLocaleIDs(
+        other.getLocale(ULOC_VALID_LOCALE, status),
+        other.getLocale(ULOC_ACTUAL_LOCALE, status));
     assignArray(fEras, fErasCount, other.fEras, other.fErasCount);
     assignArray(fEraNames, fEraNamesCount, other.fEraNames, other.fEraNamesCount);
     assignArray(fNarrowEras, fNarrowErasCount, other.fNarrowEras, other.fNarrowErasCount);
index e3a2c4ea6bb6870ac9ab979a64dfea8a3534376f..6741506c4210d84d8d6955a2b421a080c1b78031 100644 (file)
@@ -513,20 +513,9 @@ DateIntervalFormat::createSDFPatternInstance(const UnicodeString& skeleton,
                                              DateTimePatternGenerator* dtpng,
                                              UErrorCode& status)
 {
-    if ( U_FAILURE(status) ) {
-        return NULL;
-    }
-
-    const UnicodeString pattern = dtpng->getBestPattern(skeleton, status);
-    if ( U_FAILURE(status) ) {
-        return NULL;
-    }
-    SimpleDateFormat* dtfmt = new SimpleDateFormat(pattern, locale, status);
-    if ( U_FAILURE(status) ) {
-        delete dtfmt;
-        return NULL;
-    }
-    return dtfmt;
+    DateFormat *df = DateFormat::internalCreateInstanceForSkeleton(
+            skeleton, locale, *dtpng, status);
+    return static_cast<SimpleDateFormat *>(df);
 }
 
 
index fe1f5a150f6359eb5399b0b408309e38389a3448..a40263bc713731ff00fcffb6bd929d9e17f0923b 100644 (file)
@@ -34,6 +34,8 @@
 #include "hash.h"
 #include "uresimp.h"
 #include "dtptngen_impl.h"
+#include "shareddatetimepatterngenerator.h"
+#include "unifiedcache.h"
 
 #if U_CHARSET_FAMILY==U_EBCDIC_FAMILY
 /**
@@ -124,6 +126,27 @@ static const UChar *ures_a_getNextString(UResourceBundleAIterator *aiter, int32_
 
 U_NAMESPACE_BEGIN
 
+SharedDateTimePatternGenerator::~SharedDateTimePatternGenerator() {
+    delete ptr;
+}
+
+template<> U_I18N_API
+const SharedDateTimePatternGenerator *LocaleCacheKey<SharedDateTimePatternGenerator>::createObject(
+        const void * /*creationContext*/, UErrorCode &status) const {
+    DateTimePatternGenerator *fmt = DateTimePatternGenerator::internalMakeInstance(fLoc, status);
+    if (U_FAILURE(status)) {
+        return NULL;
+    }
+    SharedDateTimePatternGenerator *result = new SharedDateTimePatternGenerator(fmt);
+    if (result == NULL) {
+        delete fmt;
+        status = U_MEMORY_ALLOCATION_ERROR;
+        return NULL;
+    }
+    result->addRef();
+    return result;
+}
+
 
 // *****************************************************************************
 // class DateTimePatternGenerator
@@ -245,13 +268,30 @@ DateTimePatternGenerator::createInstance(UErrorCode& status) {
 
 DateTimePatternGenerator* U_EXPORT2
 DateTimePatternGenerator::createInstance(const Locale& locale, UErrorCode& status) {
+    const SharedDateTimePatternGenerator *shared = NULL;
+    UnifiedCache::getByLocale(locale, shared, status);
+    if (U_FAILURE(status)) {
+        return NULL;
+    }
+    DateTimePatternGenerator *result = new DateTimePatternGenerator(**shared);
+    shared->removeRef();
+    if (result == NULL) {
+        status = U_MEMORY_ALLOCATION_ERROR;
+    }
+    return result;
+}
+
+
+DateTimePatternGenerator* U_EXPORT2
+DateTimePatternGenerator::internalMakeInstance(const Locale& locale, UErrorCode& status) {
     DateTimePatternGenerator *result = new DateTimePatternGenerator(locale, status);
     if (result == NULL) {
         status = U_MEMORY_ALLOCATION_ERROR;
+        return NULL;
     }
     if (U_FAILURE(status)) {
         delete result;
-        result = NULL;
+        return NULL;
     }
     return result;
 }
@@ -312,6 +352,10 @@ DateTimePatternGenerator::DateTimePatternGenerator(const DateTimePatternGenerato
 
 DateTimePatternGenerator&
 DateTimePatternGenerator::operator=(const DateTimePatternGenerator& other) {
+    // reflexive case
+    if (&other == this) {
+        return *this;
+    }
     pLocale = other.pLocale;
     fDefaultHourFormatChar = other.fDefaultHourFormatChar;
     *fp = *(other.fp);
@@ -1333,7 +1377,7 @@ PatternMap::copyFrom(const PatternMap& other, UErrorCode& status) {
                 status = U_MEMORY_ALLOCATION_ERROR;
                 return;
             }
-
+            curElem->skeletonWasSpecified = otherElem->skeletonWasSpecified;
             if (prevElem!=NULL) {
                 prevElem->next=curElem;
             }
index 0e47603ddc8ad6e62bae2e32ba57c0433f41ebf1..843e4f8ca2a1f7e6177e4344a05f0bb72156658b 100644 (file)
     <ClInclude Include="plurrule_impl.h" />\r
     <ClInclude Include="quantityformatter.h" />\r
     <ClInclude Include="sharedbreakiterator.h" />\r
+    <ClInclude Include="shareddatefmt.h" />\r
+    <ClInclude Include="shareddatetimepatterngenerator.h" />\r
     <ClInclude Include="sharednumberformat.h" />\r
     <ClInclude Include="sharedpluralrules.h" />\r
     <CustomBuild Include="unicode\rbnf.h">\r
index 73cacd2d822209d72e1e11387aec69ba5e32828f..015a668c1d4ff49bbbc594ad6abeb36f027f7ddd 100644 (file)
     <ClInclude Include="sharedbreakiterator.h">\r
       <Filter>formatting</Filter>\r
     </ClInclude>\r
+    <ClInclude Include="shareddatefmt.h">\r
+      <Filter>formatting</Filter>\r
+    </ClInclude>\r
+    <ClInclude Include="shareddatetimepatterngenerator.h">\r
+      <Filter>formatting</Filter>\r
+    </ClInclude>\r
     <ClInclude Include="sharednumberformat.h">\r
       <Filter>formatting</Filter>\r
     </ClInclude>\r
diff --git a/icu4c/source/i18n/shareddatefmt.h b/icu4c/source/i18n/shareddatefmt.h
new file mode 100644 (file)
index 0000000..010b6e2
--- /dev/null
@@ -0,0 +1,34 @@
+/*
+******************************************************************************
+* 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
diff --git a/icu4c/source/i18n/shareddatetimepatterngenerator.h b/icu4c/source/i18n/shareddatetimepatterngenerator.h
new file mode 100644 (file)
index 0000000..e87e3a9
--- /dev/null
@@ -0,0 +1,34 @@
+/*
+******************************************************************************
+* Copyright (C) 2014, International Business Machines
+* Corporation and others.  All Rights Reserved.
+******************************************************************************
+* shareddateformat.h
+*/
+
+#ifndef __SHARED_DATETIMEPATTERNGENERATOR_H__
+#define __SHARED_DATETIMEPATTERNGENERATOR_H__
+
+#include "unicode/utypes.h"
+#include "sharedobject.h"
+
+U_NAMESPACE_BEGIN
+
+class DateTimePatternGenerator;
+
+class U_I18N_API SharedDateTimePatternGenerator : public SharedObject {
+public:
+    SharedDateTimePatternGenerator(DateTimePatternGenerator *dtpgToAdopt) : ptr(dtpgToAdopt) { }
+    virtual ~SharedDateTimePatternGenerator();
+    const DateTimePatternGenerator *get() const { return ptr; }
+    const DateTimePatternGenerator *operator->() const { return ptr; }
+    const DateTimePatternGenerator &operator*() const { return *ptr; }
+private:
+    DateTimePatternGenerator *ptr;
+    SharedDateTimePatternGenerator(const SharedDateTimePatternGenerator &);
+    SharedDateTimePatternGenerator &operator=(const SharedDateTimePatternGenerator &);
+};
+
+U_NAMESPACE_END
+
+#endif
index 901664115cc773d2b57651e90f2de01a8c12871c..749484e71be0a3b293a5258af3f1f90b9e887efb 100644 (file)
@@ -60,6 +60,7 @@
 #include "umutex.h"
 #include <float.h>
 #include "smpdtfst.h"
+#include "sharednumberformat.h"
 
 #if defined( U_DEBUG_CALSVC ) || defined (U_DEBUG_CAL)
 #include <stdio.h>
@@ -220,25 +221,146 @@ static UMutex LOCK = U_MUTEX_INITIALIZER;
 
 UOBJECT_DEFINE_RTTI_IMPLEMENTATION(SimpleDateFormat)
 
+SimpleDateFormat::NSOverride::~NSOverride() {
+    if (snf != NULL) {
+        snf->removeRef();
+    }
+}
+
+
+void SimpleDateFormat::NSOverride::free() {
+    NSOverride *cur = this;
+    while (cur) {
+        NSOverride *next = cur->next;
+        delete cur;
+        cur = next;
+    }
+}
+
+// no matter what the locale's default number format looked like, we want
+// to modify it so that it doesn't use thousands separators, doesn't always
+// show the decimal point, and recognizes integers only when parsing
+static void fixNumberFormatForDates(NumberFormat &nf) {
+    nf.setGroupingUsed(FALSE);
+    DecimalFormat* decfmt = dynamic_cast<DecimalFormat*>(&nf);
+    if (decfmt != NULL) {
+        decfmt->setDecimalSeparatorAlwaysShown(FALSE);
+    }
+    nf.setParseIntegerOnly(TRUE);
+    nf.setMinimumFractionDigits(0); // To prevent "Jan 1.00, 1997.00"
+}
+
+static const SharedNumberFormat *createSharedNumberFormat(
+        NumberFormat *nfToAdopt) {
+    fixNumberFormatForDates(*nfToAdopt);
+    const SharedNumberFormat *result = new SharedNumberFormat(nfToAdopt);
+    if (result == NULL) {
+        delete nfToAdopt;
+    }
+    return result;
+}
+
+static const SharedNumberFormat *createSharedNumberFormat(
+        const Locale &loc, UErrorCode &status) {
+    NumberFormat *nf = NumberFormat::createInstance(loc, status);
+    if (U_FAILURE(status)) {
+        return NULL;
+    }
+    const SharedNumberFormat *result = createSharedNumberFormat(nf);
+    if (result == NULL) {
+        status = U_MEMORY_ALLOCATION_ERROR;
+    }
+    return result;
+}
+
+static const SharedNumberFormat **allocSharedNumberFormatters() {
+    const SharedNumberFormat **result = (const SharedNumberFormat**)
+            uprv_malloc(UDAT_FIELD_COUNT * sizeof(const SharedNumberFormat*));
+    if (result == NULL) {
+        return NULL;
+    }
+    for (int32_t i = 0; i < UDAT_FIELD_COUNT; ++i) {
+        result[i] = NULL;
+    }
+    return result;
+}
+
+static void freeSharedNumberFormatters(const SharedNumberFormat ** list) {
+    for (int32_t i = 0; i < UDAT_FIELD_COUNT; ++i) {
+        SharedObject::clearPtr(list[i]);
+    }
+    uprv_free(list);
+}
+
+const NumberFormat &SimpleDateFormat::getNumberFormatByIndex(
+        UDateFormatField index) const {
+    if (fSharedNumberFormatters == NULL ||
+        fSharedNumberFormatters[index] == NULL) {
+        return *fNumberFormat;
+    }
+    return **fSharedNumberFormatters[index];
+}
+
+class SimpleDateFormatMutableNFNode {
+ public:
+    const NumberFormat *key;
+    NumberFormat *value;
+    SimpleDateFormatMutableNFNode()
+            : key(NULL), value(NULL) { }
+    ~SimpleDateFormatMutableNFNode() {
+        delete value;
+    }
+ private:
+    SimpleDateFormatMutableNFNode(const SimpleDateFormatMutableNFNode &);
+    SimpleDateFormatMutableNFNode &operator=(const SimpleDateFormatMutableNFNode &);
+};
+
+// Single threaded cache of non const NumberFormats. Designed to be stack
+// allocated and used for a single format call.
+class SimpleDateFormatMutableNFs : public UMemory {
+ public:
+    SimpleDateFormatMutableNFs() {
+    }
+
+    // Returns a non-const clone of nf which can be safely modified.
+    // Subsequent calls with same nf will return the same non-const clone.
+    // This object maintains ownership of all returned non-const
+    // NumberFormat objects. On memory allocation error returns NULL.
+    // Caller must check for NULL return value.
+    NumberFormat *get(const NumberFormat &nf) {
+        int32_t idx = 0;
+        while (nodes[idx].value) {
+            if (&nf == nodes[idx].key) {
+                return nodes[idx].value;
+            }
+            ++idx;
+        }
+        U_ASSERT(idx < UDAT_FIELD_COUNT);
+        nodes[idx].key = &nf;
+        nodes[idx].value = (NumberFormat *) nf.clone();
+        return nodes[idx].value;
+    }
+ private:
+    // +1 extra for sentinel. If each field had its own NumberFormat, this
+    // cache would have to allocate UDAT_FIELD_COUNT mutable versions worst
+    // case.
+    SimpleDateFormatMutableNFNode nodes[UDAT_FIELD_COUNT + 1];
+    SimpleDateFormatMutableNFs(const SimpleDateFormatMutableNFs &);
+    SimpleDateFormatMutableNFs &operator=(const SimpleDateFormatMutableNFs &);
+};
+
 //----------------------------------------------------------------------
 
 SimpleDateFormat::~SimpleDateFormat()
 {
     delete fSymbols;
-    if (fNumberFormatters) {
-        uprv_free(fNumberFormatters);
+    if (fSharedNumberFormatters) {
+        freeSharedNumberFormatters(fSharedNumberFormatters);
     }
     if (fTimeZoneFormat) {
         delete fTimeZoneFormat;
     }
 
-    while (fOverrideList) {
-        NSOverride *cur = fOverrideList;
-        fOverrideList = cur->next;
-        delete cur->nf;
-        uprv_free(cur);
-    }
-
 #if !UCONFIG_NO_BREAK_ITERATION
     delete fCapitalizationBrkIter;
 #endif
@@ -250,8 +372,7 @@ SimpleDateFormat::SimpleDateFormat(UErrorCode& status)
   :   fLocale(Locale::getDefault()),
       fSymbols(NULL),
       fTimeZoneFormat(NULL),
-      fNumberFormatters(NULL),
-      fOverrideList(NULL),
+      fSharedNumberFormatters(NULL),
       fCapitalizationBrkIter(NULL)
 {
     initializeBooleanAttributes();
@@ -267,8 +388,7 @@ SimpleDateFormat::SimpleDateFormat(const UnicodeString& pattern,
     fLocale(Locale::getDefault()),
     fSymbols(NULL),
     fTimeZoneFormat(NULL),
-    fNumberFormatters(NULL),
-    fOverrideList(NULL),
+    fSharedNumberFormatters(NULL),
     fCapitalizationBrkIter(NULL)
 {
     fDateOverride.setToBogus();
@@ -288,8 +408,7 @@ SimpleDateFormat::SimpleDateFormat(const UnicodeString& pattern,
     fLocale(Locale::getDefault()),
     fSymbols(NULL),
     fTimeZoneFormat(NULL),
-    fNumberFormatters(NULL),
-    fOverrideList(NULL),
+    fSharedNumberFormatters(NULL),
     fCapitalizationBrkIter(NULL)
 {
     fDateOverride.setTo(override);
@@ -311,8 +430,7 @@ SimpleDateFormat::SimpleDateFormat(const UnicodeString& pattern,
 :   fPattern(pattern),
     fLocale(locale),
     fTimeZoneFormat(NULL),
-    fNumberFormatters(NULL),
-    fOverrideList(NULL),
+    fSharedNumberFormatters(NULL),
     fCapitalizationBrkIter(NULL)
 {
 
@@ -334,8 +452,7 @@ SimpleDateFormat::SimpleDateFormat(const UnicodeString& pattern,
 :   fPattern(pattern),
     fLocale(locale),
     fTimeZoneFormat(NULL),
-    fNumberFormatters(NULL),
-    fOverrideList(NULL),
+    fSharedNumberFormatters(NULL),
     fCapitalizationBrkIter(NULL)
 {
 
@@ -360,8 +477,7 @@ SimpleDateFormat::SimpleDateFormat(const UnicodeString& pattern,
     fLocale(Locale::getDefault()),
     fSymbols(symbolsToAdopt),
     fTimeZoneFormat(NULL),
-    fNumberFormatters(NULL),
-    fOverrideList(NULL),
+    fSharedNumberFormatters(NULL),
     fCapitalizationBrkIter(NULL)
 {
 
@@ -383,8 +499,7 @@ SimpleDateFormat::SimpleDateFormat(const UnicodeString& pattern,
     fLocale(Locale::getDefault()),
     fSymbols(new DateFormatSymbols(symbols)),
     fTimeZoneFormat(NULL),
-    fNumberFormatters(NULL),
-    fOverrideList(NULL),
+    fSharedNumberFormatters(NULL),
     fCapitalizationBrkIter(NULL)
 {
 
@@ -407,8 +522,7 @@ SimpleDateFormat::SimpleDateFormat(EStyle timeStyle,
 :   fLocale(locale),
     fSymbols(NULL),
     fTimeZoneFormat(NULL),
-    fNumberFormatters(NULL),
-    fOverrideList(NULL),
+    fSharedNumberFormatters(NULL),
     fCapitalizationBrkIter(NULL)
 {
     initializeBooleanAttributes();
@@ -431,8 +545,7 @@ SimpleDateFormat::SimpleDateFormat(const Locale& locale,
     fLocale(locale),
     fSymbols(NULL),
     fTimeZoneFormat(NULL),
-    fNumberFormatters(NULL),
-    fOverrideList(NULL),
+    fSharedNumberFormatters(NULL),
     fCapitalizationBrkIter(NULL)
 {
     if (U_FAILURE(status)) return;
@@ -467,8 +580,7 @@ SimpleDateFormat::SimpleDateFormat(const SimpleDateFormat& other)
     fLocale(other.fLocale),
     fSymbols(NULL),
     fTimeZoneFormat(NULL),
-    fNumberFormatters(NULL),
-    fOverrideList(NULL),
+    fSharedNumberFormatters(NULL),
     fCapitalizationBrkIter(NULL)
 {
     initializeBooleanAttributes();
@@ -483,6 +595,8 @@ SimpleDateFormat& SimpleDateFormat::operator=(const SimpleDateFormat& other)
         return *this;
     }
     DateFormat::operator=(other);
+    fDateOverride = other.fDateOverride;
+    fTimeOverride = other.fTimeOverride;
 
     delete fSymbols;
     fSymbols = NULL;
@@ -509,6 +623,21 @@ SimpleDateFormat& SimpleDateFormat::operator=(const SimpleDateFormat& other)
     }
 #endif
 
+    if (fSharedNumberFormatters != NULL) {
+        freeSharedNumberFormatters(fSharedNumberFormatters);
+        fSharedNumberFormatters = NULL;
+    }
+    if (other.fSharedNumberFormatters != NULL) {
+        fSharedNumberFormatters = allocSharedNumberFormatters();
+        if (fSharedNumberFormatters) {
+            for (int32_t i = 0; i < UDAT_FIELD_COUNT; ++i) {
+                SharedObject::copyPtr(
+                        other.fSharedNumberFormatters[i],
+                        fSharedNumberFormatters[i]);
+            }
+        }
+    }
+
     return *this;
 }
 
@@ -774,18 +903,7 @@ SimpleDateFormat::initialize(const Locale& locale,
     fNumberFormat = NumberFormat::createInstance(locale, status);
     if (fNumberFormat != NULL && U_SUCCESS(status))
     {
-        // no matter what the locale's default number format looked like, we want
-        // to modify it so that it doesn't use thousands separators, doesn't always
-        // show the decimal point, and recognizes integers only when parsing
-
-        fNumberFormat->setGroupingUsed(FALSE);
-        DecimalFormat* decfmt = dynamic_cast<DecimalFormat*>(fNumberFormat);
-        if (decfmt != NULL) {
-            decfmt->setDecimalSeparatorAlwaysShown(FALSE);
-        }
-        fNumberFormat->setParseIntegerOnly(TRUE);
-        fNumberFormat->setMinimumFractionDigits(0); // To prevent "Jan 1.00, 1997.00"
-
+        fixNumberFormatForDates(*fNumberFormat);
         //fNumberFormat->setLenient(TRUE); // Java uses a custom DateNumberFormat to format/parse
 
         initNumberFormatters(locale,status);
@@ -901,6 +1019,11 @@ SimpleDateFormat::_format(Calendar& cal, UnicodeString& appendTo,
     int32_t fieldNum = 0;
     UDisplayContext capitalizationContext = getContext(UDISPCTX_TYPE_CAPITALIZATION, status);
 
+    // Create temporary cache of mutable number format objects. This way
+    // subFormat won't have to clone the const NumberFormat for each field.
+    // if several fields share the same NumberFormat, which will almost
+    // always be the case, this is a big save.
+    SimpleDateFormatMutableNFs mutableNFs;
     // loop through the pattern string character by character
     for (int32_t i = 0; i < fPattern.length() && U_SUCCESS(status); ++i) {
         UChar ch = fPattern[i];
@@ -908,7 +1031,7 @@ SimpleDateFormat::_format(Calendar& cal, UnicodeString& appendTo,
         // Use subFormat() to format a repeated pattern character
         // when a different pattern or non-pattern character is seen
         if (ch != prevCh && count > 0) {
-            subFormat(appendTo, prevCh, count, capitalizationContext, fieldNum++, handler, *workCal, status);
+            subFormat(appendTo, prevCh, count, capitalizationContext, fieldNum++, handler, *workCal, mutableNFs, status);
             count = 0;
         }
         if (ch == QUOTE) {
@@ -936,7 +1059,7 @@ SimpleDateFormat::_format(Calendar& cal, UnicodeString& appendTo,
 
     // Format the last item in the pattern, if any
     if (count > 0) {
-        subFormat(appendTo, prevCh, count, capitalizationContext, fieldNum++, handler, *workCal, status);
+        subFormat(appendTo, prevCh, count, capitalizationContext, fieldNum++, handler, *workCal, mutableNFs, status);
     }
 
     if (calClone != NULL) {
@@ -1073,13 +1196,9 @@ SimpleDateFormat::initNumberFormatters(const Locale &locale,UErrorCode &status)
         return;
     }
     umtx_lock(&LOCK);
-    if (fNumberFormatters == NULL) {
-        fNumberFormatters = (NumberFormat**)uprv_malloc(UDAT_FIELD_COUNT * sizeof(NumberFormat*));
-        if (fNumberFormatters) {
-            for (int32_t i = 0; i < UDAT_FIELD_COUNT; i++) {
-                fNumberFormatters[i] = fNumberFormat;
-            }
-        } else {
+    if (fSharedNumberFormatters == NULL) {
+        fSharedNumberFormatters = allocSharedNumberFormatters();
+        if (fSharedNumberFormatters == NULL) {
             status = U_MEMORY_ALLOCATION_ERROR;
         }
     }
@@ -1099,13 +1218,12 @@ SimpleDateFormat::processOverrideString(const Locale &locale, const UnicodeStrin
         return;
     }
 
-    U_ASSERT(fNumberFormatters != NULL);
-
     int32_t start = 0;
     int32_t len;
     UnicodeString nsName;
     UnicodeString ovrField;
     UBool moreToProcess = TRUE;
+    NSOverride *overrideList = NULL;
 
     while (moreToProcess) {
         int32_t delimiterPosition = str.indexOf((UChar)ULOC_KEYWORD_ITEM_SEPARATOR_UNICODE,start);
@@ -1127,55 +1245,42 @@ SimpleDateFormat::processOverrideString(const Locale &locale, const UnicodeStrin
 
         int32_t nsNameHash = nsName.hashCode();
         // See if the numbering system is in the override list, if not, then add it.
-        NSOverride *cur = fOverrideList;
-        NumberFormat *nf = NULL;
+        NSOverride *cur = overrideList;
+        const SharedNumberFormat *snf = NULL;
         UBool found = FALSE;
         while ( cur && !found ) {
             if ( cur->hash == nsNameHash ) {
-                nf = cur->nf;
+                snf = cur->snf;
                 found = TRUE;
             }
             cur = cur->next;
         }
 
         if (!found) {
-           cur = (NSOverride *)uprv_malloc(sizeof(NSOverride));
-           if (cur) {
+           LocalPointer<NSOverride> cur(new NSOverride);
+           if (!cur.isNull()) {
                char kw[ULOC_KEYWORD_AND_VALUES_CAPACITY];
                uprv_strcpy(kw,"numbers=");
                nsName.extract(0,len,kw+8,ULOC_KEYWORD_AND_VALUES_CAPACITY-8,US_INV);
 
                Locale ovrLoc(locale.getLanguage(),locale.getCountry(),locale.getVariant(),kw);
-               nf = NumberFormat::createInstance(ovrLoc,status);
-
-               // no matter what the locale's default number format looked like, we want
-               // to modify it so that it doesn't use thousands separators, doesn't always
-               // show the decimal point, and recognizes integers only when parsing
-
-               if (U_SUCCESS(status)) {
-                   nf->setGroupingUsed(FALSE);
-                   DecimalFormat* decfmt = dynamic_cast<DecimalFormat*>(nf);
-                   if (decfmt != NULL) {
-                       decfmt->setDecimalSeparatorAlwaysShown(FALSE);
-                   }
-                   nf->setParseIntegerOnly(TRUE);
-                   nf->setMinimumFractionDigits(0); // To prevent "Jan 1.00, 1997.00"
-
-                   cur->nf = nf;
-                   cur->hash = nsNameHash;
-                   cur->next = fOverrideList;
-                   fOverrideList = cur;
-               }
-               else {
-                   // clean up before returning
-                   if (cur != NULL) {
-                       uprv_free(cur);
+               cur->hash = nsNameHash;
+               cur->next = overrideList;
+               SharedObject::copyPtr(
+                       createSharedNumberFormat(ovrLoc, status), cur->snf);
+               if (U_FAILURE(status)) {
+                   if (overrideList) {
+                       overrideList->free();
                    }
-                  return;
+                   return;
                }
-
+               snf = cur->snf;
+               overrideList = cur.orphan();
            } else {
                status = U_MEMORY_ALLOCATION_ERROR;
+               if (overrideList) {
+                   overrideList->free();
+               }
                return;
            }
         }
@@ -1187,7 +1292,7 @@ SimpleDateFormat::processOverrideString(const Locale &locale, const UnicodeStrin
                 case kOvrStrDate:
                 case kOvrStrBoth: {
                     for ( int8_t i=0 ; i<kDateFieldsCount; i++ ) {
-                        fNumberFormatters[kDateFields[i]] = nf;
+                        SharedObject::copyPtr(snf, fSharedNumberFormatters[kDateFields[i]]);
                     }
                     if (type==kOvrStrDate) {
                         break;
@@ -1195,7 +1300,7 @@ SimpleDateFormat::processOverrideString(const Locale &locale, const UnicodeStrin
                 }
                 case kOvrStrTime : {
                     for ( int8_t i=0 ; i<kTimeFieldsCount; i++ ) {
-                        fNumberFormatters[kTimeFields[i]] = nf;
+                        SharedObject::copyPtr(snf, fSharedNumberFormatters[kTimeFields[i]]);
                     }
                     break;
                 }
@@ -1206,15 +1311,19 @@ SimpleDateFormat::processOverrideString(const Locale &locale, const UnicodeStrin
               DateFormatSymbols::getPatternCharIndex(ovrField.charAt(0));
            if (patternCharIndex == UDAT_FIELD_COUNT) {
                status = U_INVALID_FORMAT_ERROR;
+               if (overrideList) {
+                   overrideList->free();
+               }
                return;
            }
-
-           // Set the number formatter in the table
-           fNumberFormatters[patternCharIndex] = nf;
+           SharedObject::copyPtr(snf, fSharedNumberFormatters[patternCharIndex]);
         }
 
         start = delimiterPosition + 1;
     }
+    if (overrideList) {
+        overrideList->free();
+    }
 }
 
 //---------------------------------------------------------------------
@@ -1226,6 +1335,7 @@ SimpleDateFormat::subFormat(UnicodeString &appendTo,
                             int32_t fieldNum,
                             FieldPositionHandler& handler,
                             Calendar& cal,
+                            SimpleDateFormatMutableNFs &mutableNFs,
                             UErrorCode& status) const
 {
     if (U_FAILURE(status)) {
@@ -1259,7 +1369,12 @@ SimpleDateFormat::subFormat(UnicodeString &appendTo,
         return;
     }
 
-    currentNumberFormat = getNumberFormatByIndex(patternCharIndex);
+    currentNumberFormat = mutableNFs.get(
+            getNumberFormatByIndex(patternCharIndex));
+    if (currentNumberFormat == NULL) {
+        status = U_MEMORY_ALLOCATION_ERROR;
+        return;
+    }
     UnicodeString hebr("hebr", 4, US_INV);
     
     switch (patternCharIndex) {
@@ -1654,116 +1769,67 @@ SimpleDateFormat::subFormat(UnicodeString &appendTo,
 //----------------------------------------------------------------------
 
 void SimpleDateFormat::adoptNumberFormat(NumberFormat *formatToAdopt) {
-    formatToAdopt->setParseIntegerOnly(TRUE);
-    if (fNumberFormat && fNumberFormat != formatToAdopt){
-        delete fNumberFormat;
-    }
+    fixNumberFormatForDates(*formatToAdopt);
+    delete fNumberFormat;
     fNumberFormat = formatToAdopt;
-
-    if (fNumberFormatters) {
-        for (int32_t i = 0; i < UDAT_FIELD_COUNT; i++) {
-            if (fNumberFormatters[i] == formatToAdopt) {
-                fNumberFormatters[i] = NULL;
-            }
-        }
-        uprv_free(fNumberFormatters);
-        fNumberFormatters = NULL;
-    }
     
-    while (fOverrideList) {
-        NSOverride *cur = fOverrideList;
-        fOverrideList = cur->next;
-        if (cur->nf != formatToAdopt) { // only delete those not duplicate
-            delete cur->nf;
-            uprv_free(cur);
-        } else {
-            cur->nf = NULL;
-            uprv_free(cur);
-        }
+    // We successfully set the default number format. Now delete the overrides
+    // (can't fail).
+    if (fSharedNumberFormatters) {
+        freeSharedNumberFormatters(fSharedNumberFormatters);
+        fSharedNumberFormatters = NULL;
     }
 }
 
 void SimpleDateFormat::adoptNumberFormat(const UnicodeString& fields, NumberFormat *formatToAdopt, UErrorCode &status){
-    // if it has not been initialized yet, initialize
-    if (fNumberFormatters == NULL) {
-        fNumberFormatters = (NumberFormat**)uprv_malloc(UDAT_FIELD_COUNT * sizeof(NumberFormat*));
-        if (fNumberFormatters) {
-            for (int32_t i = 0; i < UDAT_FIELD_COUNT; i++) {
-                fNumberFormatters[i] = fNumberFormat;
-            }
-        } else {
-            status = U_MEMORY_ALLOCATION_ERROR;
-            return;
-        }
+    fixNumberFormatForDates(*formatToAdopt);
+    LocalPointer<NumberFormat> fmt(formatToAdopt);
+    if (U_FAILURE(status)) {
+        return;
     }
-    
-    // See if the numbering format is in the override list, if not, then add it.
-    NSOverride *cur = fOverrideList;
-    UBool found = FALSE;
-    while (cur && !found) {
-        if ( cur->nf == formatToAdopt ) {
-            found = TRUE;
-        }
-        cur = cur->next;
-    }
-
-    if (!found) {
-        cur = (NSOverride *)uprv_malloc(sizeof(NSOverride));
-        if (cur) {
-            // no matter what the locale's default number format looked like, we want
-            // to modify it so that it doesn't use thousands separators, doesn't always
-            // show the decimal point, and recognizes integers only when parsing
-            formatToAdopt->setGroupingUsed(FALSE);
-            DecimalFormat* decfmt = dynamic_cast<DecimalFormat*>(formatToAdopt);
-            if (decfmt != NULL) {
-                decfmt->setDecimalSeparatorAlwaysShown(FALSE);
-            }
-            formatToAdopt->setParseIntegerOnly(TRUE);
-            formatToAdopt->setMinimumFractionDigits(0); // To prevent "Jan 1.00, 1997.00"
-
-            cur->nf = formatToAdopt;
-            cur->hash = -1; // set duplicate here (before we set it with NumberSystem Hash, here we cannot get nor use it)
-            cur->next = fOverrideList;
-            fOverrideList = cur;
-        } else {
+
+    // We must ensure fSharedNumberFormatters is allocated.
+    if (fSharedNumberFormatters == NULL) {
+        fSharedNumberFormatters = allocSharedNumberFormatters();
+        if (fSharedNumberFormatters == NULL) {
             status = U_MEMORY_ALLOCATION_ERROR;
             return;
         }
     }
-    
+    const SharedNumberFormat *newFormat = createSharedNumberFormat(fmt.orphan());
+    if (newFormat == NULL) {
+        status = U_MEMORY_ALLOCATION_ERROR;
+        return;
+    }
     for (int i=0; i<fields.length(); i++) {
         UChar field = fields.charAt(i);
         // if the pattern character is unrecognized, signal an error and bail out
         UDateFormatField patternCharIndex = DateFormatSymbols::getPatternCharIndex(field);
         if (patternCharIndex == UDAT_FIELD_COUNT) {
             status = U_INVALID_FORMAT_ERROR;
+            newFormat->deleteIfZeroRefCount();
             return;
         }
 
         // Set the number formatter in the table
-        fNumberFormatters[patternCharIndex] = formatToAdopt;
+        SharedObject::copyPtr(
+                newFormat, fSharedNumberFormatters[patternCharIndex]);
     }
+    newFormat->deleteIfZeroRefCount();
 }
 
 const NumberFormat *
 SimpleDateFormat::getNumberFormatForField(UChar field) const {
     UDateFormatField index = DateFormatSymbols::getPatternCharIndex(field);
-    return getNumberFormatByIndex(index);
-}
-
-NumberFormat *
-SimpleDateFormat::getNumberFormatByIndex(UDateFormatField index) const {
-    if (fNumberFormatters != NULL) {
-        return fNumberFormatters[index];
-    } else {
-        return fNumberFormat;
-    }
+    return &getNumberFormatByIndex(index);
 }
 
 //----------------------------------------------------------------------
 void
-SimpleDateFormat::zeroPaddingNumber(NumberFormat *currentNumberFormat,UnicodeString &appendTo,
-                                    int32_t value, int32_t minDigits, int32_t maxDigits) const
+SimpleDateFormat::zeroPaddingNumber(
+        NumberFormat *currentNumberFormat,
+        UnicodeString &appendTo,
+        int32_t value, int32_t minDigits, int32_t maxDigits) const
 {
     if (currentNumberFormat!=NULL) {
         FieldPosition pos(0);
@@ -1834,6 +1900,7 @@ SimpleDateFormat::parse(const UnicodeString& text, Calendar& cal, ParsePosition&
     int32_t saveHebrewMonth = -1;
     int32_t count = 0;
     UTimeZoneFormatTimeType tzTimeType = UTZFMT_TIME_TYPE_UNKNOWN;
+    SimpleDateFormatMutableNFs mutableNFs;
 
     // For parsing abutting numeric fields. 'abutPat' is the
     // offset into 'pattern' of the first of 2 or more abutting
@@ -1927,7 +1994,7 @@ SimpleDateFormat::parse(const UnicodeString& text, Calendar& cal, ParsePosition&
                 }
 
                 pos = subParse(text, pos, ch, count,
-                               TRUE, FALSE, ambiguousYear, saveHebrewMonth, *workCal, i, numericLeapMonthFormatter, &tzTimeType);
+                               TRUE, FALSE, ambiguousYear, saveHebrewMonth, *workCal, i, numericLeapMonthFormatter, &tzTimeType, mutableNFs);
 
                 // If the parse fails anywhere in the run, back up to the
                 // start of the run and retry.
@@ -1942,7 +2009,7 @@ SimpleDateFormat::parse(const UnicodeString& text, Calendar& cal, ParsePosition&
             // fields.
             else if (ch != 0x6C) { // pattern char 'l' (SMALL LETTER L) just gets ignored
                 int32_t s = subParse(text, pos, ch, count,
-                               FALSE, TRUE, ambiguousYear, saveHebrewMonth, *workCal, i, numericLeapMonthFormatter, &tzTimeType);
+                               FALSE, TRUE, ambiguousYear, saveHebrewMonth, *workCal, i, numericLeapMonthFormatter, &tzTimeType, mutableNFs);
 
                 if (s == -pos-1) {
                     // era not present, in special cases allow this to continue
@@ -2548,7 +2615,7 @@ SimpleDateFormat::set2DigitYearStart(UDate d, UErrorCode& status)
  */
 int32_t SimpleDateFormat::subParse(const UnicodeString& text, int32_t& start, UChar ch, int32_t count,
                            UBool obeyCount, UBool allowNegative, UBool ambiguousYear[], int32_t& saveHebrewMonth, Calendar& cal,
-                           int32_t patLoc, MessageFormat * numericLeapMonthFormatter, UTimeZoneFormatTimeType *tzTimeType) const
+                           int32_t patLoc, MessageFormat * numericLeapMonthFormatter, UTimeZoneFormatTimeType *tzTimeType, SimpleDateFormatMutableNFs &mutableNFs) const
 {
     Formattable number;
     int32_t value = 0;
@@ -2569,7 +2636,10 @@ int32_t SimpleDateFormat::subParse(const UnicodeString& text, int32_t& start, UC
         return -start;
     }
 
-    currentNumberFormat = getNumberFormatByIndex(patternCharIndex);
+    currentNumberFormat = mutableNFs.get(getNumberFormatByIndex(patternCharIndex));
+    if (currentNumberFormat == NULL) {
+        return -start;
+    }
     UCalendarDateFields field = fgPatternIndexToCalendarField[patternCharIndex];
     UnicodeString hebr("hebr", 4, US_INV);
 
index ce967a5db6f669612b167b0c2c1f4d195aef1e3a..eb1454ae7232791a0a6c81406813e64e7935ce4b 100644 (file)
@@ -571,6 +571,100 @@ public:
                                               EStyle timeStyle = kDefault,
                                               const Locale& aLocale = Locale::getDefault());
 
+#ifndef U_HIDE_DRAFT_API
+
+    /**
+     * Creates a date/time formatter for the given skeleton and 
+     * default locale.
+     *
+     * @param skeleton The skeleton e.g "yMMMMd." Fields in the skeleton can
+     *                 be in any order, and this method uses the locale to
+     *                 map the skeleton to a pattern that includes locale
+     *                 specific separators with the fields in the appropriate
+     *                 order for that locale.
+     * @param status   Any error returned here.
+     * @return         A date/time formatter which the caller owns.
+     * @draft ICU 55
+     */
+    static DateFormat* U_EXPORT2 createInstanceForSkeleton(
+            const UnicodeString& skeleton,
+            UErrorCode &status);
+
+    /**
+     * Creates a date/time formatter for the given skeleton and locale.
+     *
+     * @param skeleton The skeleton e.g "yMMMMd." Fields in the skeleton can
+     *                 be in any order, and this method uses the locale to
+     *                 map the skeleton to a pattern that includes locale
+     *                 specific separators with the fields in the appropriate
+     *                 order for that locale.
+     * @param locale  The given locale.
+     * @param status   Any error returned here.
+     * @return         A date/time formatter which the caller owns.
+     * @draft ICU 55
+     */
+    static DateFormat* U_EXPORT2 createInstanceForSkeleton(
+            const UnicodeString& skeleton,
+            const Locale &locale,
+            UErrorCode &status);
+
+    /**
+     * Creates a date/time formatter for the given skeleton and locale.
+     *
+     * @param calendarToAdopt the calendar returned DateFormat is to use.
+     * @param skeleton The skeleton e.g "yMMMMd." Fields in the skeleton can
+     *                 be in any order, and this method uses the locale to
+     *                 map the skeleton to a pattern that includes locale
+     *                 specific separators with the fields in the appropriate
+     *                 order for that locale.
+     * @param locale  The given locale.
+     * @param status   Any error returned here.
+     * @return         A date/time formatter which the caller owns.
+     * @draft ICU 55
+     */
+    static DateFormat* U_EXPORT2 createInstanceForSkeleton(
+            Calendar *calendarToAdopt,
+            const UnicodeString& skeleton,
+            const Locale &locale,
+            UErrorCode &status);
+
+#endif /* U_HIDE_DRAFT_API */
+
+#ifndef U_HIDE_INTERNAL_API 
+
+    /**
+     * Creates a date/time formatter for the given skeleton and locale and
+     * uses the given DateTimePatternGenerator to convert the skeleton to
+     * a format pattern. As creating a DateTimePatternGenerator is
+     * expensive, callers can supply it here (if they already have it) to save
+     * this method from creating its own.
+     *
+     * @param skeleton The skeleton e.g "yMMMMd." Fields in the skeleton can
+     *                 be in any order, and this method uses the provided
+     *                 DateTimePatternGenerator to map the skeleton to a
+     *                 pattern that includes appropriate separators with
+     *                 the fields in the appropriate order.
+     * @param locale  The given locale.
+     * @param dpng     The user supplied DateTimePatternGenerator. dpng
+     *                 must be created for the same locale as locale.
+     *                 Moreover, the caller must not modify dpng between
+     *                 creating it by locale and calling this method.
+     *                 Although dpng is a non-const reference, the caller
+     *                 must not regard it as an out or in-out parameter.
+     *                 The only reason dpng is a non-const reference is
+     *                 because its method, getBestPattern, which converts
+     *                 a skeleton to a date format pattern is non-const.
+     * @return         A date/time formatter which the caller owns.
+     * @internal For ICU use only
+     */
+    static DateFormat* U_EXPORT2 internalCreateInstanceForSkeleton(
+            const UnicodeString& skeleton,
+            const Locale &locale,
+            DateTimePatternGenerator &dpng,
+            UErrorCode &status);
+
+#endif /* U_HIDE_INTERNAL_API */
+
     /**
      * Gets the set of locales for which DateFormats are installed.
      * @param count Filled in with the number of locales in the list that is returned.
@@ -817,6 +911,7 @@ private:
 
 
     UDisplayContext fCapitalizationContext;
+    friend class DateFmtKeyByStyle;
 
 public:
 #ifndef U_HIDE_OBSOLETE_API
index 69decd46317286e5bb046aad183a216962047244..2d45b2807b38915239e29a95e40349030d7c3549 100644 (file)
@@ -1,6 +1,6 @@
 /*
 *******************************************************************************
-* Copyright (C) 2007-2013, International Business Machines Corporation and
+* Copyright (C) 2007-2014, International Business Machines Corporation and
 * others. All Rights Reserved.
 *******************************************************************************
 *
@@ -31,6 +31,7 @@ class DateTimeMatcher;
 class DistanceInfo;
 class PatternMap;
 class PtnSkeleton;
+class SharedDateTimePatternGenerator;
 
 /**
  * This class provides flexible generation of date format patterns, like "yy-MM-dd". 
@@ -65,6 +66,17 @@ public:
      */
     static DateTimePatternGenerator* U_EXPORT2 createInstance(const Locale& uLocale, UErrorCode& status);
 
+#ifndef U_HIDE_INTERNAL_API
+
+    /**
+     * For ICU use only
+     *
+     * @internal
+     */
+    static DateTimePatternGenerator* U_EXPORT2 internalMakeInstance(const Locale& uLocale, UErrorCode& status);
+
+#endif /* U_HIDE_INTERNAL_API */
+
     /**
      * Create an empty generator, to be constructed with addPattern(...) etc.
      * @param status  Output param set to success/failure code on exit,
index d41fb59f713ff9323885fb8c0e2468af1690b53e..585ea10a1716ee445e311827de963ea6222abdd2 100644 (file)
@@ -45,6 +45,8 @@ class DateFormat;
 class MessageFormat;
 class FieldPositionHandler;
 class TimeZoneFormat;
+class SharedNumberFormat;
+class SimpleDateFormatMutableNFs;
 
 /**
  *
@@ -1261,6 +1263,7 @@ private:
                    int32_t fieldNum,
                    FieldPositionHandler& handler,
                    Calendar& cal,
+                   SimpleDateFormatMutableNFs &mutableNFs,
                    UErrorCode& status) const; // in case of illegal argument
 
     /**
@@ -1407,7 +1410,7 @@ private:
      */
     int32_t subParse(const UnicodeString& text, int32_t& start, UChar ch, int32_t count,
                      UBool obeyCount, UBool allowNegative, UBool ambiguousYear[], int32_t& saveHebrewMonth, Calendar& cal,
-                     int32_t patLoc, MessageFormat * numericLeapMonthFormatter, UTimeZoneFormatTimeType *tzTimeType) const;
+                     int32_t patLoc, MessageFormat * numericLeapMonthFormatter, UTimeZoneFormatTimeType *tzTimeType, SimpleDateFormatMutableNFs &mutableNFs) const;
 
     void parseInt(const UnicodeString& text,
                   Formattable& number,
@@ -1482,11 +1485,6 @@ private:
      */
     void initNumberFormatters(const Locale &locale,UErrorCode &status);
 
-    /**
-     * Get the numbering system to be used for a particular field.
-     */
-     NumberFormat * getNumberFormatByIndex(UDateFormatField index) const;
-
     /**
      * Parse the given override string and set up structures for number formats
      */
@@ -1507,6 +1505,8 @@ private:
      */
     TimeZoneFormat *tzFormat() const;
 
+    const NumberFormat &getNumberFormatByIndex(UDateFormatField index) const;
+
     /**
      * Used to map Calendar field to field level.
      * The larger the level, the smaller the field unit.
@@ -1563,15 +1563,21 @@ private:
      */
     /*transient*/ int32_t   fDefaultCenturyStartYear;
 
-    typedef struct NSOverride {
-        NumberFormat *nf;
+    struct NSOverride : public UMemory {
+        const SharedNumberFormat *snf;
         int32_t hash;
         NSOverride *next;
-    } NSOverride;
-
-    NumberFormat    **fNumberFormatters;
+        void free();
+        NSOverride() : snf(NULL), hash(0), next(NULL) {
+        }
+        ~NSOverride();
+    };
 
-    NSOverride      *fOverrideList;
+    /**
+     * The number format in use for each date field. NULL means fall back
+     * to fNumberFormat in DateFormat.
+     */
+    const SharedNumberFormat    **fSharedNumberFormatters;
 
     UBool fHaveDefaultCentury;
 
index ac3a1b27577686a86d2cb36959bc87d46868a7ee..f273de726e5d4349c1e1e74dad48a9f6758a9e3e 100644 (file)
@@ -1591,18 +1591,17 @@ static void TestOverrideNumberFormat(void) {
     u_uastrcpy(fields, "d");
     u_uastrcpy(pattern,"MM d");
 
+
     fmt=udat_open(UDAT_PATTERN, UDAT_PATTERN,"en_US",NULL,0,pattern, u_strlen(pattern), &status);
     if (!assertSuccess("udat_open()", &status)) {
         return;
     }
 
-
-    // loop 50 times to check getter/setter
+    // loop 5 times to check getter/setter
     for (i = 0; i < 5; i++){
         UNumberFormat* overrideFmt;
         overrideFmt = unum_open(UNUM_DEFAULT, NULL, 0, localeString, NULL, &status);
         assertSuccess("unum_open()", &status);
-
         udat_adoptNumberFormatForFields(fmt, fields, overrideFmt, &status);
         overrideFmt = NULL; // no longer valid
         assertSuccess("udat_setNumberFormatForField()", &status);
@@ -1612,7 +1611,6 @@ static void TestOverrideNumberFormat(void) {
             log_err("FAIL: udat_getNumberFormatForField did not return a valid pointer\n");
         }
     }
-
     {
       UNumberFormat* overrideFmt;
       overrideFmt = unum_open(UNUM_DEFAULT, NULL, 0, localeString, NULL, &status);
index b289e133c594617ec34f304383ce68baa99102d9..dae599635ede45687c3e14ff1ca43d7941876b34 100644 (file)
@@ -79,6 +79,8 @@ void DateFormatTest::runIndexedTest( int32_t index, UBool exec, const char* &nam
     TESTCASE_AUTO(TestRelative);
     TESTCASE_AUTO(TestRelativeClone);
     TESTCASE_AUTO(TestHostClone);
+    TESTCASE_AUTO(TestHebrewClone);
+    TESTCASE_AUTO(TestDateFormatSymbolsClone);
     TESTCASE_AUTO(TestTimeZoneDisplayName);
     TESTCASE_AUTO(TestRoundtripWithCalendar);
     TESTCASE_AUTO(Test6338);
@@ -103,6 +105,9 @@ void DateFormatTest::runIndexedTest( int32_t index, UBool exec, const char* &nam
 
     TESTCASE_AUTO(TestParseLeniencyAPIs);
     TESTCASE_AUTO(TestNumberFormatOverride);
+    TESTCASE_AUTO(TestCreateInstanceForSkeleton);
+    TESTCASE_AUTO(TestCreateInstanceForSkeletonDefault);
+    TESTCASE_AUTO(TestCreateInstanceForSkeletonWithCalendar);
 
     TESTCASE_AUTO_END;
 }
@@ -2422,7 +2427,7 @@ void DateFormatTest::TestHostClone(void)
     UDate now = Calendar::getNow();
     DateFormat *full = DateFormat::createDateInstance(DateFormat::kFull, loc);
     if (full == NULL) {
-        dataerrln("FAIL: Can't create Relative date instance");
+        dataerrln("FAIL: Can't create host date instance");
         return;
     }
     UnicodeString result1;
@@ -2440,6 +2445,82 @@ void DateFormatTest::TestHostClone(void)
     delete fullClone;
 }
 
+void DateFormatTest::TestHebrewClone(void)
+{
+    /*
+    Verify that a cloned formatter gives the same results
+    and is useable after the original has been deleted.
+    */
+    UErrorCode status = U_ZERO_ERROR;
+    Locale loc("he@calendar=hebrew");
+    UDate now = Calendar::getNow();
+    LocalPointer<DateFormat> fmt(
+            DateFormat::createDateInstance(DateFormat::kLong, loc));
+    if (fmt.isNull()) {
+        dataerrln("FAIL: Can't create Hebrew date instance");
+        return;
+    }
+    UnicodeString result1;
+    fmt->format(now, result1, status);
+    LocalPointer<Format> fmtClone(fmt->clone());
+
+    // free fmt to be sure that fmtClone is independent of fmt.
+    fmt.adoptInstead(NULL);
+
+    UnicodeString result2;
+    fmtClone->format(now, result2, status);
+    ASSERT_OK(status);
+    if (result1 != result2) {
+        errln("FAIL: Clone returned different result from non-clone.");
+    }
+}
+
+static UBool getActualAndValidLocales(
+        const Format &fmt, Locale &valid, Locale &actual) {
+    const SimpleDateFormat* dat = dynamic_cast<const SimpleDateFormat*>(&fmt);
+    if (dat == NULL) {
+        return FALSE;
+    }
+    const DateFormatSymbols *sym = dat->getDateFormatSymbols();
+    if (sym == NULL) {
+        return FALSE;
+    }
+    UErrorCode status = U_ZERO_ERROR;
+    valid = sym->getLocale(ULOC_VALID_LOCALE, status);
+    actual = sym->getLocale(ULOC_ACTUAL_LOCALE, status);
+    return U_SUCCESS(status);
+}
+
+void DateFormatTest::TestDateFormatSymbolsClone(void)
+{
+    /*
+    Verify that a cloned formatter gives the same results
+    and is useable after the original has been deleted.
+    */
+    Locale loc("de_CH_LUCERNE");
+    LocalPointer<DateFormat> fmt(
+            DateFormat::createDateInstance(DateFormat::kDefault, loc));
+    Locale valid1;
+    Locale actual1;
+    if (!getActualAndValidLocales(*fmt, valid1, actual1)) {
+        errln("FAIL: Could not fetch valid + actual locales");
+        return;
+    }
+    LocalPointer<Format> fmtClone(fmt->clone());
+
+    // Free fmt to be sure that fmtClone is really independent of fmt.
+    fmt.adoptInstead(NULL);
+    Locale valid2;
+    Locale actual2;
+    if (!getActualAndValidLocales(*fmtClone, valid2, actual2)) {
+        errln("FAIL: Could not fetch valid + actual locales");
+        return;
+    }
+    if (valid1 != valid2 || actual1 != actual2) {
+        errln("Date format symbol locales of clone don't match original");
+    }
+}
+
 void DateFormatTest::TestTimeZoneDisplayName()
 {
     // This test data was ported from ICU4J.  Don't know why the 6th column in there because it's not being
@@ -4472,17 +4553,18 @@ void DateFormatTest::TestNumberFormatOverride() {
         return;
     }
 
-    NumberFormat* check_nf = NumberFormat::createInstance(Locale("en_US"), status);
-    assertSuccess("NumberFormat en_US", status);
 
-    // loop 100 times to test setter/getter
-    for(int i=0; i<100; i++){
+    for(int i=0; i<3; i++){
+        NumberFormat* check_nf = NumberFormat::createInstance(Locale("en_US"), status);
+        assertSuccess("NumberFormat en_US", status);
         fmt->adoptNumberFormat(fields, check_nf, status);
         assertSuccess("adoptNumberFormat check_nf", status);
 
         const NumberFormat* get_nf = fmt->getNumberFormatForField('M');
         if (get_nf != check_nf) errln("FAIL: getter and setter do not work");
     }
+    NumberFormat* check_nf = NumberFormat::createInstance(Locale("en_US"), status);
+    assertSuccess("NumberFormat en_US", status);
     fmt->adoptNumberFormat(check_nf); // make sure using the same NF will not crash
 
     const char * DATA [][2] = {
@@ -4537,6 +4619,73 @@ void DateFormatTest::TestNumberFormatOverride() {
             errln("FAIL: Expected " + expected + " get: " + result);
     }
 }
+
+void DateFormatTest::TestCreateInstanceForSkeleton() {
+    UErrorCode status = U_ZERO_ERROR;
+    LocalPointer<DateFormat> fmt(DateFormat::createInstanceForSkeleton(
+            "yMMMMd", "en", status));
+    if (!assertSuccess("Create with pattern yMMMMd", status)) {
+        return;
+    }
+    UnicodeString result;
+    FieldPosition pos(0);
+    fmt->format(date(98, 5-1, 25), result, pos);
+    assertEquals("format yMMMMd", "May 25, 1998", result);
+    fmt.adoptInstead(DateFormat::createInstanceForSkeleton(
+            "yMd", "en", status));
+    if (!assertSuccess("Create with pattern yMd", status)) {
+        return;
+    }
+    result.remove();
+    fmt->format(date(98, 5-1, 25), result, pos);
+    assertEquals("format yMd", "5/25/1998", result);
+}
+
+void DateFormatTest::TestCreateInstanceForSkeletonDefault() {
+    UErrorCode status = U_ZERO_ERROR;
+    Locale savedLocale;
+    Locale::setDefault(Locale::getUS(), status);
+    LocalPointer<DateFormat> fmt(DateFormat::createInstanceForSkeleton(
+            "yMMMd", status));
+    Locale::setDefault(savedLocale, status);
+    if (!assertSuccess("Create with pattern yMMMd", status)) {
+        return;
+    }
+    UnicodeString result;
+    FieldPosition pos(0);
+    fmt->format(date(98, 5-1, 25), result, pos);
+    assertEquals("format yMMMd", "May 25, 1998", result);
+}
+
+void DateFormatTest::TestCreateInstanceForSkeletonWithCalendar() {
+    UErrorCode status = U_ZERO_ERROR;
+    LocalPointer<DateFormat> fmt(
+            DateFormat::createInstanceForSkeleton(
+                    Calendar::createInstance(
+                            TimeZone::createTimeZone("GMT-3:00"),
+                            status),
+                    "yMdHm", "en", status));
+    if (!assertSuccess("Create with pattern yMMMMd", status)) {
+        return;
+    }
+    UnicodeString result;
+    FieldPosition pos(0);
+
+    LocalPointer<Calendar> cal(Calendar::createInstance(
+        TimeZone::createTimeZone("GMT-7:00"),
+        status));
+    if (!assertSuccess("Creating GMT-7 time zone failed", status)) {
+        return;
+    }
+    cal->clear();
+    cal->set(1998, 5-1, 25, 0, 0, 0);
+
+    // date format time zone should be 4 hours ahead.
+    fmt->format(cal->getTime(status), result, pos);
+    assertEquals("format yMdHm", "5/25/1998, 04:00", result);
+    assertSuccess("", status);
+}
+
 #endif /* #if !UCONFIG_NO_FORMATTING */
 
 //eof
index a9dd1a66dac7d91fd9ceba3eafe6b5abfabbabec..ae165d5fee8c954e36ece052e48e09837f3553b3 100644 (file)
@@ -214,6 +214,10 @@ public:
     
     void TestHostClone(void);
 
+    void TestHebrewClone(void);
+
+    void TestDateFormatSymbolsClone(void);
+
     void TestTimeZoneDisplayName(void);
 
     void TestRoundtripWithCalendar(void);
@@ -237,6 +241,9 @@ public:
 
     // test override NumberFormat
     void TestNumberFormatOverride();
+    void TestCreateInstanceForSkeleton();
+    void TestCreateInstanceForSkeletonDefault();
+    void TestCreateInstanceForSkeletonWithCalendar();
 
 private:
     UBool showParse(DateFormat &format, const UnicodeString &formattedString);
index 909ec6de3a0e0fa920e4b89065914f539072fe55..66bd2e39976e9d18f9a5bd23be23cb1b0b5ddec6 100644 (file)
@@ -1,6 +1,6 @@
 /*
 **********************************************************************
-* Copyright (c) 2002-2011,International Business Machines
+* Copyright (c) 2002-2014,International Business Machines
 * Corporation and others.  All Rights Reserved.
 **********************************************************************
 **********************************************************************
@@ -42,6 +42,21 @@ UPerfFunction* DateFormatPerfTest::runIndexedTest(int32_t index, UBool exec,cons
         TESTCASE(8,NumFmt100000);
         TESTCASE(9,Collation10000);
         TESTCASE(10,Collation100000);
+        TESTCASE(11, DIFCreate250);
+        TESTCASE(12, DIFCreate10000);
+        TESTCASE(13, TimeZoneCreate250);
+        TESTCASE(14, TimeZoneCreate10000);
+        TESTCASE(15, DTPatternGeneratorCreate250);
+        TESTCASE(16, DTPatternGeneratorCreate10000);
+        TESTCASE(17, DTPatternGeneratorCopy250);
+        TESTCASE(18, DTPatternGeneratorCopy10000);
+        TESTCASE(19, DTPatternGeneratorBestValue250);
+        TESTCASE(20, DTPatternGeneratorBestValue10000);
+        TESTCASE(21,DateFmtCopy250);
+        TESTCASE(22,DateFmtCopy10000);
+        TESTCASE(23,DateFmtCreate250);
+        TESTCASE(24,DateFmtCreate10000);
+
 
         default: 
             name = ""; 
@@ -107,6 +122,64 @@ UPerfFunction* DateFormatPerfTest::Collation100000(){
 }
 
 
+UPerfFunction *DateFormatPerfTest::DIFCreate250() {
+    DIFCreateFunction* func = new DIFCreateFunction(250, locale);
+    return func;
+}
+
+UPerfFunction *DateFormatPerfTest::DIFCreate10000() {
+    DIFCreateFunction* func = new DIFCreateFunction(10000, locale);
+    return func;
+}
+
+UPerfFunction *DateFormatPerfTest::TimeZoneCreate250() {
+    return new TimeZoneCreateFunction(250, locale);
+}
+
+UPerfFunction *DateFormatPerfTest::TimeZoneCreate10000() {
+    return new TimeZoneCreateFunction(10000, locale);
+}
+
+UPerfFunction *DateFormatPerfTest::DTPatternGeneratorCreate250() {
+    return new DTPatternGeneratorCreateFunction(250, locale);
+}
+
+UPerfFunction *DateFormatPerfTest::DTPatternGeneratorCreate10000() {
+    return new DTPatternGeneratorCreateFunction(10000, locale);
+}
+
+UPerfFunction *DateFormatPerfTest::DTPatternGeneratorCopy250() {
+    return new DTPatternGeneratorCopyFunction(250, locale);
+}
+
+UPerfFunction *DateFormatPerfTest::DTPatternGeneratorCopy10000() {
+    return new DTPatternGeneratorCopyFunction(10000, locale);
+}
+
+UPerfFunction *DateFormatPerfTest::DTPatternGeneratorBestValue250() {
+    return new DTPatternGeneratorBestValueFunction(250, locale);
+}
+
+UPerfFunction *DateFormatPerfTest::DTPatternGeneratorBestValue10000() {
+    return new DTPatternGeneratorBestValueFunction(10000, locale);
+}
+
+UPerfFunction* DateFormatPerfTest::DateFmtCopy250(){
+    return new DateFmtCopyFunction(250, locale);
+}
+
+UPerfFunction* DateFormatPerfTest::DateFmtCopy10000(){
+    return new DateFmtCopyFunction(10000, locale);
+}
+
+UPerfFunction* DateFormatPerfTest::DateFmtCreate250(){
+    return new DateFmtCreateFunction(250, locale);
+}
+
+UPerfFunction* DateFormatPerfTest::DateFmtCreate10000(){
+    return new DateFmtCreateFunction(10000, locale);
+}
+
 
 int main(int argc, const char* argv[]){
 
index 7aeb316418d87f53d9b6bed46b693615c6402772..033405316002e82b341dea6d4500ffc74fa20130 100644 (file)
@@ -1,6 +1,6 @@
 /*
 **********************************************************************
-* Copyright (c) 2002-2011,International Business Machines
+* Copyright (c) 2002-2014,International Business Machines
 * Corporation and others.  All Rights Reserved.
 **********************************************************************
 **********************************************************************
@@ -14,6 +14,7 @@
 #include "unicode/unistr.h"
 #include "unicode/uperf.h"
 
+#include "unicode/dtitvfmt.h"
 #include "unicode/utypes.h"
 #include "unicode/datefmt.h"
 #include "unicode/calendar.h"
@@ -56,7 +57,7 @@ public:
        BreakItFunction(){num = -1;}
        BreakItFunction(int a, bool b){num = a; wordIteration = b;}
 
-       virtual void call(UErrorCode *status)
+       virtual void call(UErrorCode * status)
        {               
                BreakIterator* boundary;
 
@@ -231,6 +232,326 @@ public:
 
 };
 
+class DateFmtCreateFunction : public UPerfFunction
+{
+
+private:
+        int num;
+        char locale[25];
+public:
+
+        DateFmtCreateFunction(int a, const char* loc)
+        {
+                num = a;
+                strcpy(locale, loc);
+        }
+
+        virtual void call(UErrorCode* /* status */)
+        {
+
+                Locale loc(locale);
+                DateFormat *fmt;
+                // (dates are imported from datedata.h)
+                for(int j = 0; j < num; j++) {
+                    fmt = DateFormat::createDateTimeInstance(
+                            DateFormat::kShort, DateFormat::kFull, loc);
+                    delete fmt;
+                }
+        }
+
+        virtual long getOperationsPerIteration()
+        {
+                return num;
+        }
+
+};
+
+class DateFmtCopyFunction : public UPerfFunction
+{
+
+private:
+        int num;
+    char locale[25];
+public:
+
+        DateFmtCopyFunction()
+        {
+                num = -1;
+        }
+
+        DateFmtCopyFunction(int a, const char* loc)
+        {
+                num = a;
+        strcpy(locale, loc);
+        }
+
+        virtual void call(UErrorCode* /* status */)
+        {
+                Locale loc(locale);
+                UErrorCode status2 = U_ZERO_ERROR;
+                DateFormat *fmt = DateFormat::createDateTimeInstance(
+                            DateFormat::kShort, DateFormat::kFull, loc);
+                for(int j = 0; j < num; j++) {
+                    Format *cp = fmt->clone();
+                    delete cp;
+                }
+                delete fmt;
+        }
+
+        virtual long getOperationsPerIteration()
+        {
+                return num;
+        }
+
+        // Verify that a UErrorCode is successful; exit(1) if not
+        void check(UErrorCode& status, const char* msg) {
+                if (U_FAILURE(status)) {
+                        printf("ERROR: %s (%s)\n", u_errorName(status), msg);
+                        exit(1);
+                }
+        }
+
+};
+
+class DIFCreateFunction : public UPerfFunction
+{
+
+private:
+       int num;
+    char locale[25];
+public:
+       
+       DIFCreateFunction()
+       {
+               num = -1;
+       }
+
+       DIFCreateFunction(int a, const char* loc)
+       {
+               num = a;
+        strcpy(locale, loc);
+       }
+
+       virtual void call(UErrorCode* /* status */)
+       {
+               UErrorCode status2 = U_ZERO_ERROR;              
+               Calendar *cal;
+               TimeZone *zone;
+
+               cal = Calendar::createInstance(status2);
+               check(status2, "Calendar::createInstance");
+               zone = TimeZone::createTimeZone("GMT"); // Create a GMT zone
+               cal->adoptTimeZone(zone);
+               
+               Locale loc(locale);
+                UnicodeString skeleton("yMMMMdHms");
+
+               for(int j = 0; j < num; j++) {
+                    DateIntervalFormat* fmt(DateIntervalFormat::createInstance(skeleton, loc, status2));
+                    delete fmt;
+                }
+                delete cal;
+       }
+
+       virtual long getOperationsPerIteration()
+       {
+               return num;
+       }
+
+       // Verify that a UErrorCode is successful; exit(1) if not
+       void check(UErrorCode& status, const char* msg) {
+               if (U_FAILURE(status)) {
+                       printf("ERROR: %s (%s)\n", u_errorName(status), msg);
+                       exit(1);
+               }
+       }
+
+};
+
+class TimeZoneCreateFunction : public UPerfFunction
+{
+
+private:
+       int num;
+    char locale[25];
+public:
+       
+       TimeZoneCreateFunction()
+       {
+               num = -1;
+       }
+
+       TimeZoneCreateFunction(int a, const char* loc)
+       {
+               num = a;
+        strcpy(locale, loc);
+       }
+
+       virtual void call(UErrorCode* /* status */)
+       {
+               Locale loc(locale);
+                UnicodeString tzname("UTC");
+               for(int j = 0; j < num; j++) {
+                    TimeZone* tz(TimeZone::createTimeZone(tzname));
+                    delete tz;
+                }
+       }
+
+       virtual long getOperationsPerIteration()
+       {
+               return num;
+       }
+
+       // Verify that a UErrorCode is successful; exit(1) if not
+       void check(UErrorCode& status, const char* msg) {
+               if (U_FAILURE(status)) {
+                       printf("ERROR: %s (%s)\n", u_errorName(status), msg);
+                       exit(1);
+               }
+       }
+
+};
+
+class DTPatternGeneratorCreateFunction : public UPerfFunction
+{
+
+private:
+       int num;
+    char locale[25];
+public:
+       
+       DTPatternGeneratorCreateFunction()
+       {
+               num = -1;
+       }
+
+       DTPatternGeneratorCreateFunction(int a, const char* loc)
+       {
+               num = a;
+        strcpy(locale, loc);
+       }
+
+       virtual void call(UErrorCode* /* status */)
+       {
+               UErrorCode status2 = U_ZERO_ERROR;              
+               Locale loc(locale);
+
+               for(int j = 0; j < num; j++) {
+                    DateTimePatternGenerator* gen(DateTimePatternGenerator::createInstance(loc, status2));
+                    delete gen;
+                }
+       }
+
+       virtual long getOperationsPerIteration()
+       {
+               return num;
+       }
+
+       // Verify that a UErrorCode is successful; exit(1) if not
+       void check(UErrorCode& status, const char* msg) {
+               if (U_FAILURE(status)) {
+                       printf("ERROR: %s (%s)\n", u_errorName(status), msg);
+                       exit(1);
+               }
+       }
+
+};
+
+class DTPatternGeneratorCopyFunction : public UPerfFunction
+{
+
+private:
+       int num;
+    char locale[25];
+public:
+       
+       DTPatternGeneratorCopyFunction()
+       {
+               num = -1;
+       }
+
+       DTPatternGeneratorCopyFunction(int a, const char* loc)
+       {
+               num = a;
+        strcpy(locale, loc);
+       }
+
+       virtual void call(UErrorCode* /* status */)
+       {
+               UErrorCode status2 = U_ZERO_ERROR;              
+               Locale loc(locale);
+                DateTimePatternGenerator* gen(DateTimePatternGenerator::createInstance(loc, status2));
+
+               for(int j = 0; j < num; j++) {
+                    DateTimePatternGenerator *cl = gen->clone();
+                    delete cl;
+                }
+                delete gen;
+       }
+
+       virtual long getOperationsPerIteration()
+       {
+               return num;
+       }
+
+       // Verify that a UErrorCode is successful; exit(1) if not
+       void check(UErrorCode& status, const char* msg) {
+               if (U_FAILURE(status)) {
+                       printf("ERROR: %s (%s)\n", u_errorName(status), msg);
+                       exit(1);
+               }
+       }
+
+};
+
+class DTPatternGeneratorBestValueFunction : public UPerfFunction
+{
+
+private:
+       int num;
+    char locale[25];
+public:
+       
+       DTPatternGeneratorBestValueFunction()
+       {
+               num = -1;
+       }
+
+       DTPatternGeneratorBestValueFunction(int a, const char* loc)
+       {
+               num = a;
+        strcpy(locale, loc);
+       }
+
+       virtual void call(UErrorCode* /* status */)
+       {
+               UErrorCode status2 = U_ZERO_ERROR;              
+               Locale loc(locale);
+                DateTimePatternGenerator* gen(DateTimePatternGenerator::createInstance(loc, status2));
+                UnicodeString skeleton("yMMMMdHms");
+
+               for(int j = 0; j < num; j++) {
+                    gen->getBestPattern(skeleton, status2);
+                }
+                check(status2, "getBestPattern");
+                delete gen;
+       }
+
+       virtual long getOperationsPerIteration()
+       {
+               return num;
+       }
+
+       // Verify that a UErrorCode is successful; exit(1) if not
+       void check(UErrorCode& status, const char* msg) {
+               if (U_FAILURE(status)) {
+                       printf("ERROR: %s (%s)\n", u_errorName(status), msg);
+                       exit(1);
+               }
+       }
+
+};
+
 class NumFmtFunction : public UPerfFunction
 {
 
@@ -497,6 +818,10 @@ public:
        UPerfFunction* DateFmt250();
        UPerfFunction* DateFmt10000();
        UPerfFunction* DateFmt100000();
+       UPerfFunction* DateFmtCreate250();
+       UPerfFunction* DateFmtCreate10000();
+       UPerfFunction* DateFmtCopy250();
+       UPerfFunction* DateFmtCopy10000();
        UPerfFunction* BreakItWord250();
        UPerfFunction* BreakItWord10000();
        UPerfFunction* BreakItChar250();
@@ -505,6 +830,16 @@ public:
     UPerfFunction* NumFmt100000();
     UPerfFunction* Collation10000();
     UPerfFunction* Collation100000();
+    UPerfFunction* DIFCreate250();
+    UPerfFunction* DIFCreate10000();
+    UPerfFunction* TimeZoneCreate250();
+    UPerfFunction* TimeZoneCreate10000();
+    UPerfFunction* DTPatternGeneratorCreate250();
+    UPerfFunction* DTPatternGeneratorCreate10000();
+    UPerfFunction* DTPatternGeneratorCopy250();
+    UPerfFunction* DTPatternGeneratorCopy10000();
+    UPerfFunction* DTPatternGeneratorBestValue250();
+    UPerfFunction* DTPatternGeneratorBestValue10000();
 };
 
 #endif // DateFmtPerf