+// © 2016 and later: Unicode, Inc. and others.
+// License & terms of use: http://www.unicode.org/copyright.html
/*
*******************************************************************************
- * Copyright (C) 1997-2011, International Business Machines Corporation and *
+ * Copyright (C) 1997-2015, International Business Machines Corporation and *
* others. All Rights Reserved. *
*******************************************************************************
*
#include "unicode/datefmt.h"
#include "unicode/smpdtfmt.h"
#include "unicode/dtptngen.h"
+#include "unicode/udisplaycontext.h"
#include "reldtfmt.h"
+#include "sharedobject.h"
+#include "unifiedcache.h"
+#include "uarrsort.h"
#include "cstring.h"
#include "windtfmt.h"
U_NAMESPACE_BEGIN
+class U_I18N_API DateFmtBestPattern : public SharedObject {
+public:
+ UnicodeString fPattern;
+
+ DateFmtBestPattern(const UnicodeString &pattern)
+ : fPattern(pattern) { }
+ ~DateFmtBestPattern();
+};
+
+DateFmtBestPattern::~DateFmtBestPattern() {
+}
+
+template<> U_I18N_API
+const DateFmtBestPattern *LocaleCacheKey<DateFmtBestPattern>::createObject(
+ const void * /*creationContext*/, UErrorCode &status) const {
+ status = U_UNSUPPORTED_ERROR;
+ return NULL;
+}
+
+class U_I18N_API DateFmtBestPatternKey : public LocaleCacheKey<DateFmtBestPattern> {
+private:
+ UnicodeString fSkeleton;
+public:
+ DateFmtBestPatternKey(
+ const Locale &loc,
+ const UnicodeString &skeleton,
+ UErrorCode &status)
+ : LocaleCacheKey<DateFmtBestPattern>(loc),
+ fSkeleton(DateTimePatternGenerator::staticGetSkeleton(skeleton, status)) { }
+ DateFmtBestPatternKey(const DateFmtBestPatternKey &other) :
+ LocaleCacheKey<DateFmtBestPattern>(other),
+ fSkeleton(other.fSkeleton) { }
+ virtual ~DateFmtBestPatternKey();
+ virtual int32_t hashCode() const {
+ return (int32_t)(37u * (uint32_t)LocaleCacheKey<DateFmtBestPattern>::hashCode() + (uint32_t)fSkeleton.hashCode());
+ }
+ virtual UBool operator==(const CacheKeyBase &other) const {
+ // reflexive
+ if (this == &other) {
+ return TRUE;
+ }
+ if (!LocaleCacheKey<DateFmtBestPattern>::operator==(other)) {
+ return FALSE;
+ }
+ // We know that this and other are of same class if we get this far.
+ const DateFmtBestPatternKey &realOther =
+ static_cast<const DateFmtBestPatternKey &>(other);
+ return (realOther.fSkeleton == fSkeleton);
+ }
+ virtual CacheKeyBase *clone() const {
+ return new DateFmtBestPatternKey(*this);
+ }
+ virtual const DateFmtBestPattern *createObject(
+ const void * /*unused*/, UErrorCode &status) const {
+ LocalPointer<DateTimePatternGenerator> dtpg(
+ DateTimePatternGenerator::createInstance(fLoc, status));
+ if (U_FAILURE(status)) {
+ return NULL;
+ }
+
+ LocalPointer<DateFmtBestPattern> pattern(
+ new DateFmtBestPattern(
+ dtpg->getBestPattern(fSkeleton, status)),
+ status);
+ if (U_FAILURE(status)) {
+ return NULL;
+ }
+ DateFmtBestPattern *result = pattern.orphan();
+ result->addRef();
+ return result;
+ }
+};
+
+DateFmtBestPatternKey::~DateFmtBestPatternKey() { }
+
+
DateFormat::DateFormat()
: fCalendar(0),
- fNumberFormat(0)
+ fNumberFormat(0),
+ fCapitalizationContext(UDISPCTX_CAPITALIZATION_NONE)
{
}
DateFormat::DateFormat(const DateFormat& other)
: Format(other),
fCalendar(0),
- fNumberFormat(0)
+ fNumberFormat(0),
+ fCapitalizationContext(UDISPCTX_CAPITALIZATION_NONE)
{
*this = other;
}
} else {
fNumberFormat = NULL;
}
+ fBoolFlags = other.fBoolFlags;
+ fCapitalizationContext = other.fCapitalizationContext;
}
return *this;
}
return (this == fmt) ||
(Format::operator==(other) &&
fCalendar&&(fCalendar->isEquivalentTo(*fmt->fCalendar)) &&
- (fNumberFormat && *fNumberFormat == *fmt->fNumberFormat));
+ (fNumberFormat && *fNumberFormat == *fmt->fNumberFormat) &&
+ (fCapitalizationContext == fmt->fCapitalizationContext) );
}
//----------------------------------------------------------------------
{
// Note that any error information is just lost. That's okay
// for this convenience method.
- FieldPosition fpos(0);
+ FieldPosition fpos(FieldPosition::DONT_CARE);
return format(date, appendTo, fpos);
}
DateFormat::createTimeInstance(DateFormat::EStyle style,
const Locale& aLocale)
{
- return create(style, kNone, aLocale);
+ return createDateTimeInstance(kNone, style, aLocale);
}
//----------------------------------------------------------------------
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);
}
//----------------------------------------------------------------------
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* U_EXPORT2
DateFormat::createInstance()
{
- return create(kShort, (EStyle) (kShort + kDateOffset), Locale::getDefault());
+ return createDateTimeInstance(kShort, kShort, Locale::getDefault());
+}
+
+//----------------------------------------------------------------------
+
+UnicodeString U_EXPORT2
+DateFormat::getBestPattern(
+ const Locale &locale,
+ const UnicodeString &skeleton,
+ UErrorCode &status) {
+ UnifiedCache *cache = UnifiedCache::getInstance(status);
+ if (U_FAILURE(status)) {
+ return UnicodeString();
+ }
+ DateFmtBestPatternKey key(locale, skeleton, status);
+ const DateFmtBestPattern *patternPtr = NULL;
+ cache->get(key, patternPtr, status);
+ if (U_FAILURE(status)) {
+ return UnicodeString();
+ }
+ UnicodeString result(patternPtr->fPattern);
+ patternPtr->removeRef();
+ return result;
+}
+
+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;
+ }
+ Locale localeWithCalendar = locale;
+ localeWithCalendar.setKeywordValue("calendar", calendar->getType(), status);
+ if (U_FAILURE(status)) {
+ return NULL;
+ }
+ DateFormat *result = createInstanceForSkeleton(skeleton, localeWithCalendar, 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;
+ }
+ LocalPointer<DateFormat> df(
+ new SimpleDateFormat(
+ getBestPattern(locale, skeleton, status),
+ locale, status),
+ status);
+ return U_SUCCESS(status) ? df.orphan() : NULL;
+}
+
+DateFormat* U_EXPORT2
+DateFormat::createInstanceForSkeleton(
+ const UnicodeString& skeleton,
+ UErrorCode &status) {
+ return createInstanceForSkeleton(
+ skeleton, Locale::getDefault(), status);
}
//----------------------------------------------------------------------
DateFormat::create(EStyle timeStyle, EStyle dateStyle, const Locale& locale)
{
UErrorCode status = U_ZERO_ERROR;
-#if U_PLATFORM_HAS_WIN32_API
+#if U_PLATFORM_USES_ONLY_WIN32_API
char buffer[8];
int32_t count = locale.getKeywordValue("compat", buffer, sizeof(buffer), status);
void
DateFormat::setCalendar(const Calendar& newCalendar)
{
+ if (fCalendar && fCalendar->isEquivalentTo( newCalendar ))
+ return;
Calendar* newCalClone = newCalendar.clone();
if (newCalClone != NULL) {
adoptCalendar(newCalClone);
delete fNumberFormat;
fNumberFormat = newNumberFormat;
newNumberFormat->setParseIntegerOnly(TRUE);
+ newNumberFormat->setGroupingUsed(FALSE);
}
//----------------------------------------------------------------------
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();
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 static_cast<UBool>(fBoolFlags.get(attr));
+}
+
U_NAMESPACE_END
#endif /* #if !UCONFIG_NO_FORMATTING */