]> git.saurik.com Git - apple/icu.git/blobdiff - icuSources/i18n/datefmt.cpp
ICU-551.51.4.tar.gz
[apple/icu.git] / icuSources / i18n / datefmt.cpp
index 9280d2038e662d2b5ce623dff824f51e5a27a9c2..7006e10317a8cc95cee09019b939040baf2c586a 100644 (file)
@@ -1,6 +1,6 @@
 /*
  *******************************************************************************
- * Copyright (C) 1997-2010, International Business Machines Corporation and    *
+ * Copyright (C) 1997-2014, International Business Machines Corporation and    *
  * others. All Rights Reserved.                                                *
  *******************************************************************************
  *
@@ -25,6 +25,7 @@
 #include "unicode/datefmt.h"
 #include "unicode/smpdtfmt.h"
 #include "unicode/dtptngen.h"
+#include "unicode/udisplaycontext.h"
 #include "reldtfmt.h"
 
 #include "cstring.h"
@@ -42,7 +43,8 @@ U_NAMESPACE_BEGIN
 
 DateFormat::DateFormat()
 :   fCalendar(0),
-    fNumberFormat(0)
+    fNumberFormat(0),
+    fCapitalizationContext(UDISPCTX_CAPITALIZATION_NONE)
 {
 }
 
@@ -51,7 +53,8 @@ DateFormat::DateFormat()
 DateFormat::DateFormat(const DateFormat& other)
 :   Format(other),
     fCalendar(0),
-    fNumberFormat(0)
+    fNumberFormat(0),
+    fCapitalizationContext(UDISPCTX_CAPITALIZATION_NONE)
 {
     *this = other;
 }
@@ -74,6 +77,8 @@ DateFormat& DateFormat::operator=(const DateFormat& other)
         } else {
           fNumberFormat = NULL;
         }
+        fBoolFlags = other.fBoolFlags;
+        fCapitalizationContext = other.fCapitalizationContext;
     }
     return *this;
 }
@@ -101,7 +106,8 @@ DateFormat::operator==(const Format& other) const
     return (this == fmt) ||
         (Format::operator==(other) &&
          fCalendar&&(fCalendar->isEquivalentTo(*fmt->fCalendar)) &&
-         (fNumberFormat && *fNumberFormat == *fmt->fNumberFormat));
+         (fNumberFormat && *fNumberFormat == *fmt->fNumberFormat) &&
+         (fCapitalizationContext == fmt->fCapitalizationContext) );
 }
 
 //----------------------------------------------------------------------
@@ -193,11 +199,15 @@ DateFormat::format(Calendar& /* unused cal */,
 UnicodeString&
 DateFormat::format(UDate date, UnicodeString& appendTo, FieldPosition& fieldPosition) const {
     if (fCalendar != NULL) {
-        // Use our calendar instance
-        UErrorCode ec = U_ZERO_ERROR;
-        fCalendar->setTime(date, ec);
-        if (U_SUCCESS(ec)) {
-            return format(*fCalendar, appendTo, fieldPosition);
+        // Use a clone of our calendar instance
+        Calendar* calClone = fCalendar->clone();
+        if (calClone != NULL) {
+            UErrorCode ec = U_ZERO_ERROR;
+            calClone->setTime(date, ec);
+            if (U_SUCCESS(ec)) {
+                format(*calClone, appendTo, fieldPosition);
+            }
+            delete calClone;
         }
     }
     return appendTo;
@@ -209,9 +219,13 @@ UnicodeString&
 DateFormat::format(UDate date, UnicodeString& appendTo, FieldPositionIterator* posIter,
                    UErrorCode& status) const {
     if (fCalendar != NULL) {
-        fCalendar->setTime(date, status);
-        if (U_SUCCESS(status)) {
-            return format(*fCalendar, appendTo, posIter, status);
+        Calendar* calClone = fCalendar->clone();
+        if (calClone != NULL) {
+            calClone->setTime(date, status);
+            if (U_SUCCESS(status)) {
+               format(*calClone, appendTo, posIter, status);
+            }
+            delete calClone;
         }
     }
     return appendTo;
@@ -236,28 +250,25 @@ DateFormat::parse(const UnicodeString& text,
 {
     UDate d = 0; // Error return UDate is 0 (the epoch)
     if (fCalendar != NULL) {
-        int32_t start = pos.getIndex();
-
-        // Parse may update TimeZone used by the calendar.
-        TimeZone *tzsav = (TimeZone*)fCalendar->getTimeZone().clone();
-
-        fCalendar->clear();
-        parse(text, *fCalendar, pos);
-        if (pos.getIndex() != start) {
-            UErrorCode ec = U_ZERO_ERROR;
-            d = fCalendar->getTime(ec);
-            if (U_FAILURE(ec)) {
-                // We arrive here if fCalendar is non-lenient and there
-                // is an out-of-range field.  We don't know which field
-                // was illegal so we set the error index to the start.
-                pos.setIndex(start);
-                pos.setErrorIndex(start);
-                d = 0;
+        Calendar* calClone = fCalendar->clone();
+        if (calClone != NULL) {
+            int32_t start = pos.getIndex();
+            calClone->clear();
+            parse(text, *calClone, pos);
+            if (pos.getIndex() != start) {
+                UErrorCode ec = U_ZERO_ERROR;
+                d = calClone->getTime(ec);
+                if (U_FAILURE(ec)) {
+                    // We arrive here if fCalendar => calClone is non-lenient and
+                    // there is an out-of-range field.  We don't know which field
+                    // was illegal so we set the error index to the start.
+                    pos.setIndex(start);
+                    pos.setErrorIndex(start);
+                    d = 0;
+                }
             }
+            delete calClone;
         }
-
-        // Restore TimeZone
-        fCalendar->adoptTimeZone(tzsav);
     }
     return d;
 }
@@ -298,7 +309,7 @@ DateFormat* U_EXPORT2
 DateFormat::createTimeInstance(DateFormat::EStyle style,
                                const Locale& aLocale)
 {
-    return create(style, kNone, aLocale);
+    return createDateTimeInstance(kNone, style, aLocale);
 }
 
 //----------------------------------------------------------------------
@@ -307,13 +318,7 @@ 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);
+    return createDateTimeInstance(style, kNone, aLocale);
 }
 
 //----------------------------------------------------------------------
@@ -323,11 +328,11 @@ DateFormat::createDateTimeInstance(EStyle dateStyle,
                                    EStyle timeStyle,
                                    const Locale& aLocale)
 {
-    if(dateStyle != kNone)
-    {
-        dateStyle = (EStyle) (dateStyle + kDateOffset);
-    }
-    return create(timeStyle, dateStyle, aLocale);
+   if(dateStyle != kNone)
+   {
+       dateStyle = (EStyle) (dateStyle + kDateOffset);
+   }
+   return create(timeStyle, dateStyle, aLocale);
 }
 
 //----------------------------------------------------------------------
@@ -335,7 +340,77 @@ DateFormat::createDateTimeInstance(EStyle dateStyle,
 DateFormat* U_EXPORT2
 DateFormat::createInstance()
 {
-    return create(kShort, (EStyle) (kShort + kDateOffset), Locale::getDefault());
+    return createDateTimeInstance(kShort, kShort, Locale::getDefault());
+}
+
+//----------------------------------------------------------------------
+
+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;
+    }
+    DateFormat *result = createInstanceForSkeleton(skeleton, locale, 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) {
+    LocalPointer<DateTimePatternGenerator> gen(
+            DateTimePatternGenerator::createInstance(locale, status));
+    if (U_FAILURE(status)) {
+        return NULL;
+    }
+    return internalCreateInstanceForSkeleton(
+            skeleton, locale, *gen, status);
+}
+
+DateFormat* U_EXPORT2
+DateFormat::createInstanceForSkeleton(
+        const UnicodeString& skeleton,
+        UErrorCode &status) {
+    return createInstanceForSkeleton(
+            skeleton, Locale::getDefault(), status);
+}
+
+DateFormat* U_EXPORT2
+DateFormat::internalCreateInstanceForSkeleton(
+        const UnicodeString& skeleton,
+        const Locale &locale,
+        DateTimePatternGenerator &gen,
+        UErrorCode &status) {
+    if (U_FAILURE(status)) {
+        return NULL;
+    }
+    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;
 }
 
 //----------------------------------------------------------------------
@@ -344,7 +419,7 @@ DateFormat* U_EXPORT2
 DateFormat::create(EStyle timeStyle, EStyle dateStyle, const Locale& locale)
 {
     UErrorCode status = U_ZERO_ERROR;
-#ifdef U_WINDOWS
+#if U_PLATFORM_HAS_WIN32_API
     char buffer[8];
     int32_t count = locale.getKeywordValue("compat", buffer, sizeof(buffer), status);
 
@@ -492,12 +567,38 @@ DateFormat::setLenient(UBool lenient)
     if (fCalendar != NULL) {
         fCalendar->setLenient(lenient);
     }
+    UErrorCode status = U_ZERO_ERROR;
+    setBooleanAttribute(UDAT_PARSE_ALLOW_WHITESPACE, lenient, status);
+    setBooleanAttribute(UDAT_PARSE_ALLOW_NUMERIC, lenient, status);
 }
 
 //----------------------------------------------------------------------
 
 UBool
 DateFormat::isLenient() const
+{
+    UBool lenient = TRUE;
+    if (fCalendar != NULL) {
+        lenient = fCalendar->isLenient();
+    }
+    UErrorCode status = U_ZERO_ERROR;
+    return lenient
+        && getBooleanAttribute(UDAT_PARSE_ALLOW_WHITESPACE, status)
+        && getBooleanAttribute(UDAT_PARSE_ALLOW_NUMERIC, status);
+}
+
+void
+DateFormat::setCalendarLenient(UBool lenient)
+{
+    if (fCalendar != NULL) {
+        fCalendar->setLenient(lenient);
+    }
+}
+
+//----------------------------------------------------------------------
+
+UBool
+DateFormat::isCalendarLenient() const
 {
     if (fCalendar != NULL) {
         return fCalendar->isLenient();
@@ -506,6 +607,61 @@ DateFormat::isLenient() const
     return FALSE;
 }
 
+
+//----------------------------------------------------------------------
+
+
+void DateFormat::setContext(UDisplayContext value, UErrorCode& status)
+{
+    if (U_FAILURE(status))
+        return;
+    if ( (UDisplayContextType)((uint32_t)value >> 8) == UDISPCTX_TYPE_CAPITALIZATION ) {
+        fCapitalizationContext = value;
+    } else {
+        status = U_ILLEGAL_ARGUMENT_ERROR;
+   }
+}
+
+
+//----------------------------------------------------------------------
+
+
+UDisplayContext DateFormat::getContext(UDisplayContextType type, UErrorCode& status) const
+{
+    if (U_FAILURE(status))
+        return (UDisplayContext)0;
+    if (type != UDISPCTX_TYPE_CAPITALIZATION) {
+        status = U_ILLEGAL_ARGUMENT_ERROR;
+        return (UDisplayContext)0;
+    }
+    return fCapitalizationContext;
+}
+
+
+//----------------------------------------------------------------------
+
+
+DateFormat& 
+DateFormat::setBooleanAttribute(UDateFormatBooleanAttribute attr,
+                                                                       UBool newValue,
+                                                                       UErrorCode &status) {
+    if(!fBoolFlags.isValidValue(newValue)) {
+        status = U_ILLEGAL_ARGUMENT_ERROR;
+    } else {
+        fBoolFlags.set(attr, newValue);
+    }
+
+    return *this;
+}
+
+//----------------------------------------------------------------------
+
+UBool 
+DateFormat::getBooleanAttribute(UDateFormatBooleanAttribute attr, UErrorCode &/*status*/) const {
+
+    return fBoolFlags.get(attr);
+}
+
 U_NAMESPACE_END
 
 #endif /* #if !UCONFIG_NO_FORMATTING */