/*
-*******************************************************************************
-* 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
// 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));
}
//----------------------------------------------------------------------
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;
}
//----------------------------------------------------------------------
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;
}
//----------------------------------------------------------------------
-DateFormat*
+DateFormat* U_EXPORT2
DateFormat::createTimeInstance(DateFormat::EStyle style,
const Locale& aLocale)
{
//----------------------------------------------------------------------
-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;
//----------------------------------------------------------------------
-const Locale*
+const Locale* U_EXPORT2
DateFormat::getAvailableLocales(int32_t& count)
{
// Get the list of installed locales.
void
DateFormat::setCalendar(const Calendar& newCalendar)
{
- adoptCalendar(newCalendar.clone());
+ Calendar* newCalClone = newCalendar.clone();
+ if (newCalClone != NULL) {
+ adoptCalendar(newCalClone);
+ }
}
//----------------------------------------------------------------------
void
DateFormat::setNumberFormat(const NumberFormat& newNumberFormat)
{
- adoptNumberFormat((NumberFormat*)newNumberFormat.clone());
+ NumberFormat* newNumFmtClone = (NumberFormat*)newNumberFormat.clone();
+ if (newNumFmtClone != NULL) {
+ adoptNumberFormat(newNumFmtClone);
+ }
}
//----------------------------------------------------------------------
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);
+ }
}
//----------------------------------------------------------------------
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());
}
//----------------------------------------------------------------------
void
DateFormat::setLenient(UBool lenient)
{
- fCalendar->setLenient(lenient);
+ if (fCalendar != NULL) {
+ fCalendar->setLenient(lenient);
+ }
}
//----------------------------------------------------------------------
UBool
DateFormat::isLenient() const
{
- return fCalendar->isLenient();
+ if (fCalendar != NULL) {
+ return fCalendar->isLenient();
+ }
+ // fCalendar is rarely null
+ return FALSE;
}
U_NAMESPACE_END