]> git.saurik.com Git - apple/icu.git/blobdiff - icuSources/i18n/datefmt.cpp
ICU-400.37.tar.gz
[apple/icu.git] / icuSources / i18n / datefmt.cpp
index 63b43aa67e2ba8ec98b7fb8312790b829700942e..842b910ba35f258cc30127cd0992239ea34b54c4 100644 (file)
@@ -1,29 +1,38 @@
 /*
-*******************************************************************************
-* Copyright (C) 1997-2003, International Business Machines Corporation and    *
-* others. All Rights Reserved.                                                *
-*******************************************************************************
-*
-* File DATEFMT.CPP
-*
-* Modification History:
-*
-*   Date        Name        Description
-*   02/19/97    aliu        Converted from java.
-*   03/31/97    aliu        Modified extensively to work with 50 locales.
-*   04/01/97    aliu        Added support for centuries.
-*   08/12/97    aliu        Fixed operator== to use Calendar::equivalentTo.
-*    07/20/98    stephen        Changed ParsePosition initialization
-********************************************************************************
-*/
+ *******************************************************************************
+ * Copyright (C) 1997-2008, International Business Machines Corporation and    *
+ * others. All Rights Reserved.                                                *
+ *******************************************************************************
+ *
+ * File DATEFMT.CPP
+ *
+ * Modification History:
+ *
+ *   Date        Name        Description
+ *   02/19/97    aliu        Converted from java.
+ *   03/31/97    aliu        Modified extensively to work with 50 locales.
+ *   04/01/97    aliu        Added support for centuries.
+ *   08/12/97    aliu        Fixed operator== to use Calendar::equivalentTo.
+ *   07/20/98    stephen     Changed ParsePosition initialization
+ ********************************************************************************
+ */
 
 #include "unicode/utypes.h"
 
 #if !UCONFIG_NO_FORMATTING
 
-#include "unicode/resbund.h"
+#include "unicode/ures.h"
 #include "unicode/datefmt.h"
 #include "unicode/smpdtfmt.h"
+#include "unicode/dtptngen.h"
+#include "reldtfmt.h"
+
+#include "cstring.h"
+#include "windtfmt.h"
+
+#if defined( U_DEBUG_CALSVC ) || defined (U_DEBUG_CAL)
+#include <stdio.h>
+#endif
 
 // *****************************************************************************
 // class DateFormat
@@ -86,14 +95,13 @@ DateFormat::operator==(const Format& other) const
     // which have confirmed that the other object being compared against is
     // an instance of a sublcass of DateFormat.  THIS IS IMPORTANT.
 
-    // We only dereference this pointer after we have confirmed below that
-    // 'other' is a DateFormat subclass.
+    // Format::operator== guarantees that this cast is safe
     DateFormat* fmt = (DateFormat*)&other;
 
     return (this == fmt) ||
-        ((getDynamicClassID() == other.getDynamicClassID()) &&
+        (Format::operator==(other) &&
          fCalendar&&(fCalendar->isEquivalentTo(*fmt->fCalendar)) &&
-         (fNumberFormat&&(*fNumberFormat == *fmt->fNumberFormat)) );
+         (fNumberFormat && *fNumberFormat == *fmt->fNumberFormat));
 }
 
 //----------------------------------------------------------------------
@@ -163,24 +171,32 @@ UDate
 DateFormat::parse(const UnicodeString& text,
                   ParsePosition& pos) const
 {
+    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;
-            UDate d = fCalendar->getTime(ec);
-            if (U_SUCCESS(ec)) {
-                return d; // Successful function exit
+            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;
             }
-            // 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);
         }
+
+        // Restore TimeZone
+        fCalendar->adoptTimeZone(tzsav);
     }
-    return 0; // Error return UDate is 0 (the epoch)
+    return d;
 }
 
 //----------------------------------------------------------------------
@@ -193,7 +209,13 @@ DateFormat::parse(const UnicodeString& text,
 
     ParsePosition pos(0);
     UDate result = parse(text, pos);
-    if (pos.getIndex() == 0) status = U_ILLEGAL_ARGUMENT_ERROR;
+    if (pos.getIndex() == 0) {
+#if defined (U_DEBUG_CAL)
+      fprintf(stderr, "%s:%d - - failed to parse  - err index %d\n"
+              , __FILE__, __LINE__, pos.getErrorIndex() );
+#endif
+      status = U_ILLEGAL_ARGUMENT_ERROR;
+    }
     return result;
 }
 
@@ -209,7 +231,7 @@ DateFormat::parseObject(const UnicodeString& source,
 
 //----------------------------------------------------------------------
 
-DateFormat*
+DateFormat* U_EXPORT2
 DateFormat::createTimeInstance(DateFormat::EStyle style,
                                const Locale& aLocale)
 {
@@ -218,48 +240,107 @@ DateFormat::createTimeInstance(DateFormat::EStyle style,
 
 //----------------------------------------------------------------------
 
-DateFormat*
+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);
+    // +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);
 }
 
 //----------------------------------------------------------------------
 
-DateFormat*
+DateFormat* U_EXPORT2
 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);
 }
 
 //----------------------------------------------------------------------
 
-DateFormat*
+DateFormat* U_EXPORT2
 DateFormat::createInstance()
 {
     return create(kShort, (EStyle) (kShort + kDateOffset), Locale::getDefault());
 }
 
+//----------------------------------------------------------------------
+DateFormat* U_EXPORT2
+DateFormat::createPatternInstance(const UnicodeString& skeleton,
+                                  const Locale& locale,
+                                  UErrorCode& status) 
+{
+    if ( U_FAILURE(status) ) {
+        return NULL;
+    }
+
+    DateTimePatternGenerator* dtptg = 
+               DateTimePatternGenerator::createInstance(locale, status);
+    if ( dtptg == NULL ) {
+        status = U_MEMORY_ALLOCATION_ERROR;
+        delete dtptg;
+        return NULL;
+    }
+    if ( U_FAILURE(status) ) {
+        delete dtptg;
+        return NULL;
+    }
+
+    const UnicodeString pattern = dtptg->getBestPattern(skeleton, status);
+    delete dtptg;
+    if ( U_FAILURE(status) ) {
+        return NULL;
+    }
+    SimpleDateFormat* dtfmt = new SimpleDateFormat(pattern, locale, status);
+    if ( U_FAILURE(status) ) {
+        delete dtfmt;
+        return NULL;
+    }
+    return dtfmt;
+}
+
 //----------------------------------------------------------------------
 
-DateFormat*
+DateFormat* U_EXPORT2
 DateFormat::create(EStyle timeStyle, EStyle dateStyle, const Locale& locale)
 {
-    // Try to create a SimpleDateFormat of the desired style.
     UErrorCode status = U_ZERO_ERROR;
+#ifdef U_WINDOWS
+    char buffer[8];
+    int32_t count = locale.getKeywordValue("compat", buffer, sizeof(buffer), status);
+
+    // if the locale has "@compat=host", create a host-specific DateFormat...
+    if (count > 0 && uprv_strcmp(buffer, "host") == 0) {
+        Win32DateFormat *f = new Win32DateFormat(timeStyle, dateStyle, locale, status);
+
+        if (U_SUCCESS(status)) {
+            return f;
+        }
+
+        delete f;
+    }
+#endif
+
+    // is it relative?
+    if(/*((timeStyle!=UDAT_NONE)&&(timeStyle & UDAT_RELATIVE)) || */((dateStyle!=kNone)&&((dateStyle-kDateOffset) & UDAT_RELATIVE))) {
+        RelativeDateFormat *r = new RelativeDateFormat((UDateFormatStyle)timeStyle, (UDateFormatStyle)(dateStyle-kDateOffset), locale, status);
+        if(U_SUCCESS(status)) return r;
+        delete r;
+        status = U_ZERO_ERROR;
+    }
+
+    // Try to create a SimpleDateFormat of the desired style.
     SimpleDateFormat *f = new SimpleDateFormat(timeStyle, dateStyle, locale, status);
     if (U_SUCCESS(status)) return f;
     delete f;
@@ -279,7 +360,7 @@ DateFormat::create(EStyle timeStyle, EStyle dateStyle, const Locale& locale)
 
 //----------------------------------------------------------------------
 
-const Locale*
+const Locale* U_EXPORT2
 DateFormat::getAvailableLocales(int32_t& count)
 {
     // Get the list of installed locales.
@@ -301,7 +382,10 @@ DateFormat::adoptCalendar(Calendar* newCalendar)
 void
 DateFormat::setCalendar(const Calendar& newCalendar)
 {
-    adoptCalendar(newCalendar.clone());
+    Calendar* newCalClone = newCalendar.clone();
+    if (newCalClone != NULL) {
+        adoptCalendar(newCalClone);
+    }
 }
 
 //----------------------------------------------------------------------
@@ -326,7 +410,10 @@ DateFormat::adoptNumberFormat(NumberFormat* newNumberFormat)
 void
 DateFormat::setNumberFormat(const NumberFormat& newNumberFormat)
 {
-    adoptNumberFormat((NumberFormat*)newNumberFormat.clone());
+    NumberFormat* newNumFmtClone = (NumberFormat*)newNumberFormat.clone();
+    if (newNumFmtClone != NULL) {
+        adoptNumberFormat(newNumFmtClone);
+    }
 }
 
 //----------------------------------------------------------------------
@@ -342,14 +429,18 @@ DateFormat::getNumberFormat() const
 void
 DateFormat::adoptTimeZone(TimeZone* zone)
 {
-    fCalendar->adoptTimeZone(zone);
+    if (fCalendar != NULL) {
+        fCalendar->adoptTimeZone(zone);
+    }
 }
 //----------------------------------------------------------------------
 
 void
 DateFormat::setTimeZone(const TimeZone& zone)
 {
-    fCalendar->setTimeZone(zone);
+    if (fCalendar != NULL) {
+        fCalendar->setTimeZone(zone);
+    }
 }
 
 //----------------------------------------------------------------------
@@ -357,7 +448,12 @@ DateFormat::setTimeZone(const TimeZone& zone)
 const TimeZone&
 DateFormat::getTimeZone() const
 {
-    return fCalendar->getTimeZone();
+    if (fCalendar != NULL) {
+        return fCalendar->getTimeZone();
+    }
+    // If calendar doesn't exists, create default timezone.
+    // fCalendar is rarely null
+    return *(TimeZone::createDefault());
 }
 
 //----------------------------------------------------------------------
@@ -365,7 +461,9 @@ DateFormat::getTimeZone() const
 void
 DateFormat::setLenient(UBool lenient)
 {
-    fCalendar->setLenient(lenient);
+    if (fCalendar != NULL) {
+        fCalendar->setLenient(lenient);
+    }
 }
 
 //----------------------------------------------------------------------
@@ -373,7 +471,11 @@ DateFormat::setLenient(UBool lenient)
 UBool
 DateFormat::isLenient() const
 {
-    return fCalendar->isLenient();
+    if (fCalendar != NULL) {
+        return fCalendar->isLenient();
+    }
+    // fCalendar is rarely null
+    return FALSE;
 }
 
 U_NAMESPACE_END