intl/icu/source/i18n/datefmt.cpp

Wed, 31 Dec 2014 06:09:35 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 06:09:35 +0100
changeset 0
6474c204b198
permissions
-rw-r--r--

Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.

     1 /*
     2  *******************************************************************************
     3  * Copyright (C) 1997-2013, International Business Machines Corporation and    *
     4  * others. All Rights Reserved.                                                *
     5  *******************************************************************************
     6  *
     7  * File DATEFMT.CPP
     8  *
     9  * Modification History:
    10  *
    11  *   Date        Name        Description
    12  *   02/19/97    aliu        Converted from java.
    13  *   03/31/97    aliu        Modified extensively to work with 50 locales.
    14  *   04/01/97    aliu        Added support for centuries.
    15  *   08/12/97    aliu        Fixed operator== to use Calendar::equivalentTo.
    16  *   07/20/98    stephen     Changed ParsePosition initialization
    17  ********************************************************************************
    18  */
    20 #include "unicode/utypes.h"
    22 #if !UCONFIG_NO_FORMATTING
    24 #include "unicode/ures.h"
    25 #include "unicode/datefmt.h"
    26 #include "unicode/smpdtfmt.h"
    27 #include "unicode/dtptngen.h"
    28 #include "reldtfmt.h"
    30 #include "cstring.h"
    31 #include "windtfmt.h"
    33 #if defined( U_DEBUG_CALSVC ) || defined (U_DEBUG_CAL)
    34 #include <stdio.h>
    35 #endif
    37 // *****************************************************************************
    38 // class DateFormat
    39 // *****************************************************************************
    41 U_NAMESPACE_BEGIN
    43 DateFormat::DateFormat()
    44 :   fCalendar(0),
    45     fNumberFormat(0)
    46 {
    47 }
    49 //----------------------------------------------------------------------
    51 DateFormat::DateFormat(const DateFormat& other)
    52 :   Format(other),
    53     fCalendar(0),
    54     fNumberFormat(0)
    55 {
    56     *this = other;
    57 }
    59 //----------------------------------------------------------------------
    61 DateFormat& DateFormat::operator=(const DateFormat& other)
    62 {
    63     if (this != &other)
    64     {
    65         delete fCalendar;
    66         delete fNumberFormat;
    67         if(other.fCalendar) {
    68           fCalendar = other.fCalendar->clone();
    69         } else {
    70           fCalendar = NULL;
    71         }
    72         if(other.fNumberFormat) {
    73           fNumberFormat = (NumberFormat*)other.fNumberFormat->clone();
    74         } else {
    75           fNumberFormat = NULL;
    76         }
    77         fBoolFlags = other.fBoolFlags;
    78     }
    79     return *this;
    80 }
    82 //----------------------------------------------------------------------
    84 DateFormat::~DateFormat()
    85 {
    86     delete fCalendar;
    87     delete fNumberFormat;
    88 }
    90 //----------------------------------------------------------------------
    92 UBool
    93 DateFormat::operator==(const Format& other) const
    94 {
    95     // This protected comparison operator should only be called by subclasses
    96     // which have confirmed that the other object being compared against is
    97     // an instance of a sublcass of DateFormat.  THIS IS IMPORTANT.
    99     // Format::operator== guarantees that this cast is safe
   100     DateFormat* fmt = (DateFormat*)&other;
   102     return (this == fmt) ||
   103         (Format::operator==(other) &&
   104          fCalendar&&(fCalendar->isEquivalentTo(*fmt->fCalendar)) &&
   105          (fNumberFormat && *fNumberFormat == *fmt->fNumberFormat));
   106 }
   108 //----------------------------------------------------------------------
   110 UnicodeString&
   111 DateFormat::format(const Formattable& obj,
   112                    UnicodeString& appendTo,
   113                    FieldPosition& fieldPosition,
   114                    UErrorCode& status) const
   115 {
   116     if (U_FAILURE(status)) return appendTo;
   118     // if the type of the Formattable is double or long, treat it as if it were a Date
   119     UDate date = 0;
   120     switch (obj.getType())
   121     {
   122     case Formattable::kDate:
   123         date = obj.getDate();
   124         break;
   125     case Formattable::kDouble:
   126         date = (UDate)obj.getDouble();
   127         break;
   128     case Formattable::kLong:
   129         date = (UDate)obj.getLong();
   130         break;
   131     default:
   132         status = U_ILLEGAL_ARGUMENT_ERROR;
   133         return appendTo;
   134     }
   136     // Is this right?
   137     //if (fieldPosition.getBeginIndex() == fieldPosition.getEndIndex())
   138     //  status = U_ILLEGAL_ARGUMENT_ERROR;
   140     return format(date, appendTo, fieldPosition);
   141 }
   143 //----------------------------------------------------------------------
   145 UnicodeString&
   146 DateFormat::format(const Formattable& obj,
   147                    UnicodeString& appendTo,
   148                    FieldPositionIterator* posIter,
   149                    UErrorCode& status) const
   150 {
   151     if (U_FAILURE(status)) return appendTo;
   153     // if the type of the Formattable is double or long, treat it as if it were a Date
   154     UDate date = 0;
   155     switch (obj.getType())
   156     {
   157     case Formattable::kDate:
   158         date = obj.getDate();
   159         break;
   160     case Formattable::kDouble:
   161         date = (UDate)obj.getDouble();
   162         break;
   163     case Formattable::kLong:
   164         date = (UDate)obj.getLong();
   165         break;
   166     default:
   167         status = U_ILLEGAL_ARGUMENT_ERROR;
   168         return appendTo;
   169     }
   171     // Is this right?
   172     //if (fieldPosition.getBeginIndex() == fieldPosition.getEndIndex())
   173     //  status = U_ILLEGAL_ARGUMENT_ERROR;
   175     return format(date, appendTo, posIter, status);
   176 }
   178 //----------------------------------------------------------------------
   180 // Default implementation for backwards compatibility, subclasses should implement.
   181 UnicodeString&
   182 DateFormat::format(Calendar& /* unused cal */,
   183                    UnicodeString& appendTo,
   184                    FieldPositionIterator* /* unused posIter */,
   185                    UErrorCode& status) const {
   186     if (U_SUCCESS(status)) {
   187         status = U_UNSUPPORTED_ERROR;
   188     }
   189     return appendTo;
   190 }
   192 //----------------------------------------------------------------------
   194 UnicodeString&
   195 DateFormat::format(UDate date, UnicodeString& appendTo, FieldPosition& fieldPosition) const {
   196     if (fCalendar != NULL) {
   197         // Use a clone of our calendar instance
   198         Calendar* calClone = fCalendar->clone();
   199         if (calClone != NULL) {
   200             UErrorCode ec = U_ZERO_ERROR;
   201             calClone->setTime(date, ec);
   202             if (U_SUCCESS(ec)) {
   203                 format(*calClone, appendTo, fieldPosition);
   204             }
   205             delete calClone;
   206         }
   207     }
   208     return appendTo;
   209 }
   211 //----------------------------------------------------------------------
   213 UnicodeString&
   214 DateFormat::format(UDate date, UnicodeString& appendTo, FieldPositionIterator* posIter,
   215                    UErrorCode& status) const {
   216     if (fCalendar != NULL) {
   217         Calendar* calClone = fCalendar->clone();
   218         if (calClone != NULL) {
   219             calClone->setTime(date, status);
   220             if (U_SUCCESS(status)) {
   221                format(*calClone, appendTo, posIter, status);
   222             }
   223             delete calClone;
   224         }
   225     }
   226     return appendTo;
   227 }
   229 //----------------------------------------------------------------------
   231 UnicodeString&
   232 DateFormat::format(UDate date, UnicodeString& appendTo) const
   233 {
   234     // Note that any error information is just lost.  That's okay
   235     // for this convenience method.
   236     FieldPosition fpos(0);
   237     return format(date, appendTo, fpos);
   238 }
   240 //----------------------------------------------------------------------
   242 UDate
   243 DateFormat::parse(const UnicodeString& text,
   244                   ParsePosition& pos) const
   245 {
   246     UDate d = 0; // Error return UDate is 0 (the epoch)
   247     if (fCalendar != NULL) {
   248         Calendar* calClone = fCalendar->clone();
   249         if (calClone != NULL) {
   250             int32_t start = pos.getIndex();
   251             calClone->clear();
   252             parse(text, *calClone, pos);
   253             if (pos.getIndex() != start) {
   254                 UErrorCode ec = U_ZERO_ERROR;
   255                 d = calClone->getTime(ec);
   256                 if (U_FAILURE(ec)) {
   257                     // We arrive here if fCalendar => calClone is non-lenient and
   258                     // there is an out-of-range field.  We don't know which field
   259                     // was illegal so we set the error index to the start.
   260                     pos.setIndex(start);
   261                     pos.setErrorIndex(start);
   262                     d = 0;
   263                 }
   264             }
   265             delete calClone;
   266         }
   267     }
   268     return d;
   269 }
   271 //----------------------------------------------------------------------
   273 UDate
   274 DateFormat::parse(const UnicodeString& text,
   275                   UErrorCode& status) const
   276 {
   277     if (U_FAILURE(status)) return 0;
   279     ParsePosition pos(0);
   280     UDate result = parse(text, pos);
   281     if (pos.getIndex() == 0) {
   282 #if defined (U_DEBUG_CAL)
   283       fprintf(stderr, "%s:%d - - failed to parse  - err index %d\n"
   284               , __FILE__, __LINE__, pos.getErrorIndex() );
   285 #endif
   286       status = U_ILLEGAL_ARGUMENT_ERROR;
   287     }
   288     return result;
   289 }
   291 //----------------------------------------------------------------------
   293 void
   294 DateFormat::parseObject(const UnicodeString& source,
   295                         Formattable& result,
   296                         ParsePosition& pos) const
   297 {
   298     result.setDate(parse(source, pos));
   299 }
   301 //----------------------------------------------------------------------
   303 DateFormat* U_EXPORT2
   304 DateFormat::createTimeInstance(DateFormat::EStyle style,
   305                                const Locale& aLocale)
   306 {
   307     return create(style, kNone, aLocale);
   308 }
   310 //----------------------------------------------------------------------
   312 DateFormat* U_EXPORT2
   313 DateFormat::createDateInstance(DateFormat::EStyle style,
   314                                const Locale& aLocale)
   315 {
   316     // +4 to set the correct index for getting data out of
   317     // LocaleElements.
   318     if(style != kNone)
   319     {
   320         style = (EStyle) (style + kDateOffset);
   321     }
   322     return create(kNone, (EStyle) (style), aLocale);
   323 }
   325 //----------------------------------------------------------------------
   327 DateFormat* U_EXPORT2
   328 DateFormat::createDateTimeInstance(EStyle dateStyle,
   329                                    EStyle timeStyle,
   330                                    const Locale& aLocale)
   331 {
   332     if(dateStyle != kNone)
   333     {
   334         dateStyle = (EStyle) (dateStyle + kDateOffset);
   335     }
   336     return create(timeStyle, dateStyle, aLocale);
   337 }
   339 //----------------------------------------------------------------------
   341 DateFormat* U_EXPORT2
   342 DateFormat::createInstance()
   343 {
   344     return create(kShort, (EStyle) (kShort + kDateOffset), Locale::getDefault());
   345 }
   347 //----------------------------------------------------------------------
   349 DateFormat* U_EXPORT2
   350 DateFormat::create(EStyle timeStyle, EStyle dateStyle, const Locale& locale)
   351 {
   352     UErrorCode status = U_ZERO_ERROR;
   353 #if U_PLATFORM_HAS_WIN32_API
   354     char buffer[8];
   355     int32_t count = locale.getKeywordValue("compat", buffer, sizeof(buffer), status);
   357     // if the locale has "@compat=host", create a host-specific DateFormat...
   358     if (count > 0 && uprv_strcmp(buffer, "host") == 0) {
   359         Win32DateFormat *f = new Win32DateFormat(timeStyle, dateStyle, locale, status);
   361         if (U_SUCCESS(status)) {
   362             return f;
   363         }
   365         delete f;
   366     }
   367 #endif
   369     // is it relative?
   370     if(/*((timeStyle!=UDAT_NONE)&&(timeStyle & UDAT_RELATIVE)) || */((dateStyle!=kNone)&&((dateStyle-kDateOffset) & UDAT_RELATIVE))) {
   371         RelativeDateFormat *r = new RelativeDateFormat((UDateFormatStyle)timeStyle, (UDateFormatStyle)(dateStyle-kDateOffset), locale, status);
   372         if(U_SUCCESS(status)) return r;
   373         delete r;
   374         status = U_ZERO_ERROR;
   375     }
   377     // Try to create a SimpleDateFormat of the desired style.
   378     SimpleDateFormat *f = new SimpleDateFormat(timeStyle, dateStyle, locale, status);
   379     if (U_SUCCESS(status)) return f;
   380     delete f;
   382     // If that fails, try to create a format using the default pattern and
   383     // the DateFormatSymbols for this locale.
   384     status = U_ZERO_ERROR;
   385     f = new SimpleDateFormat(locale, status);
   386     if (U_SUCCESS(status)) return f;
   387     delete f;
   389     // This should never really happen, because the preceding constructor
   390     // should always succeed.  If the resource data is unavailable, a last
   391     // resort object should be returned.
   392     return 0;
   393 }
   395 //----------------------------------------------------------------------
   397 const Locale* U_EXPORT2
   398 DateFormat::getAvailableLocales(int32_t& count)
   399 {
   400     // Get the list of installed locales.
   401     // Even if root has the correct date format for this locale,
   402     // it's still a valid locale (we don't worry about data fallbacks).
   403     return Locale::getAvailableLocales(count);
   404 }
   406 //----------------------------------------------------------------------
   408 void
   409 DateFormat::adoptCalendar(Calendar* newCalendar)
   410 {
   411     delete fCalendar;
   412     fCalendar = newCalendar;
   413 }
   415 //----------------------------------------------------------------------
   416 void
   417 DateFormat::setCalendar(const Calendar& newCalendar)
   418 {
   419     Calendar* newCalClone = newCalendar.clone();
   420     if (newCalClone != NULL) {
   421         adoptCalendar(newCalClone);
   422     }
   423 }
   425 //----------------------------------------------------------------------
   427 const Calendar*
   428 DateFormat::getCalendar() const
   429 {
   430     return fCalendar;
   431 }
   433 //----------------------------------------------------------------------
   435 void
   436 DateFormat::adoptNumberFormat(NumberFormat* newNumberFormat)
   437 {
   438     delete fNumberFormat;
   439     fNumberFormat = newNumberFormat;
   440     newNumberFormat->setParseIntegerOnly(TRUE);
   441 }
   442 //----------------------------------------------------------------------
   444 void
   445 DateFormat::setNumberFormat(const NumberFormat& newNumberFormat)
   446 {
   447     NumberFormat* newNumFmtClone = (NumberFormat*)newNumberFormat.clone();
   448     if (newNumFmtClone != NULL) {
   449         adoptNumberFormat(newNumFmtClone);
   450     }
   451 }
   453 //----------------------------------------------------------------------
   455 const NumberFormat*
   456 DateFormat::getNumberFormat() const
   457 {
   458     return fNumberFormat;
   459 }
   461 //----------------------------------------------------------------------
   463 void
   464 DateFormat::adoptTimeZone(TimeZone* zone)
   465 {
   466     if (fCalendar != NULL) {
   467         fCalendar->adoptTimeZone(zone);
   468     }
   469 }
   470 //----------------------------------------------------------------------
   472 void
   473 DateFormat::setTimeZone(const TimeZone& zone)
   474 {
   475     if (fCalendar != NULL) {
   476         fCalendar->setTimeZone(zone);
   477     }
   478 }
   480 //----------------------------------------------------------------------
   482 const TimeZone&
   483 DateFormat::getTimeZone() const
   484 {
   485     if (fCalendar != NULL) {
   486         return fCalendar->getTimeZone();
   487     }
   488     // If calendar doesn't exists, create default timezone.
   489     // fCalendar is rarely null
   490     return *(TimeZone::createDefault());
   491 }
   493 //----------------------------------------------------------------------
   495 void
   496 DateFormat::setLenient(UBool lenient)
   497 {
   498     if (fCalendar != NULL) {
   499         fCalendar->setLenient(lenient);
   500     }
   501 }
   503 //----------------------------------------------------------------------
   505 UBool
   506 DateFormat::isLenient() const
   507 {
   508     if (fCalendar != NULL) {
   509         return fCalendar->isLenient();
   510     }
   511     // fCalendar is rarely null
   512     return FALSE;
   513 }
   515 //----------------------------------------------------------------------
   517 DateFormat& 
   518 DateFormat::setBooleanAttribute(UDateFormatBooleanAttribute attr,
   519     									UBool newValue,
   520     									UErrorCode &status) {
   521     if(!fBoolFlags.isValidValue(newValue)) {
   522         status = U_ILLEGAL_ARGUMENT_ERROR;
   523     } else {
   524         fBoolFlags.set(attr, newValue);
   525     }
   527     return *this;
   528 }
   530 //----------------------------------------------------------------------
   532 UBool 
   533 DateFormat::getBooleanAttribute(UDateFormatBooleanAttribute attr, UErrorCode &/*status*/) const {
   535     return fBoolFlags.get(attr);
   536 }
   538 U_NAMESPACE_END
   540 #endif /* #if !UCONFIG_NO_FORMATTING */
   542 //eof

mercurial