mirror of
https://github.com/unicode-org/icu.git
synced 2025-04-07 06:25:30 +00:00
ICU-11872 new time formatting pattern chars b/B
Merging from the branch. X-SVN-Rev: 38370
This commit is contained in:
parent
15ed0f801d
commit
f713c0687c
18 changed files with 2044 additions and 406 deletions
|
@ -18,7 +18,7 @@
|
|||
#define __LOCALPOINTER_H__
|
||||
|
||||
/**
|
||||
* \file
|
||||
* \file
|
||||
* \brief C++ API: "Smart pointers" for use with and in ICU4C C++ code.
|
||||
*
|
||||
* These classes are inspired by
|
||||
|
@ -52,7 +52,7 @@ U_NAMESPACE_BEGIN
|
|||
* Destructor and adoptInstead().
|
||||
*
|
||||
* There is no operator T *() provided because the programmer must decide
|
||||
* whether to use getAlias() (without transfer of ownership) or orpan()
|
||||
* whether to use getAlias() (without transfer of ownership) or orphan()
|
||||
* (with transfer of ownership and NULLing of the pointer).
|
||||
*
|
||||
* @see LocalPointer
|
||||
|
|
|
@ -12,7 +12,7 @@
|
|||
* 04/01/97 aliu Creation.
|
||||
* 02/22/99 damiba overhaul.
|
||||
* 04/04/99 helena Fixed internal header inclusion.
|
||||
* 04/15/99 Madhu Updated Javadoc
|
||||
* 04/15/99 Madhu Updated Javadoc
|
||||
* 06/14/99 stephen Removed functions taking a filename suffix.
|
||||
* 07/20/99 stephen Language-independent ypedef to void*
|
||||
* 11/09/99 weiv Added ures_getLocale()
|
||||
|
@ -29,7 +29,7 @@
|
|||
|
||||
/**
|
||||
* \file
|
||||
* \brief C API: Resource Bundle
|
||||
* \brief C API: Resource Bundle
|
||||
*
|
||||
* <h2>C API: Resource Bundle</h2>
|
||||
*
|
||||
|
@ -40,7 +40,7 @@
|
|||
* <P>
|
||||
* Resource bundles in ICU4C are currently defined using text files which conform to the following
|
||||
* <a href="http://source.icu-project.org/repos/icu/icuhtml/trunk/design/bnf_rb.txt">BNF definition</a>.
|
||||
* More on resource bundle concepts and syntax can be found in the
|
||||
* More on resource bundle concepts and syntax can be found in the
|
||||
* <a href="http://icu-project.org/userguide/ResourceManagement.html">Users Guide</a>.
|
||||
* <P>
|
||||
*/
|
||||
|
@ -801,6 +801,7 @@ U_NAMESPACE_BEGIN
|
|||
*/
|
||||
inline UnicodeString
|
||||
ures_getUnicodeString(const UResourceBundle *resB, UErrorCode* status) {
|
||||
UnicodeString result;
|
||||
UnicodeString result;
|
||||
int32_t len = 0;
|
||||
const UChar *r = ures_getString(resB, &len, status);
|
||||
|
@ -848,6 +849,7 @@ ures_getNextUnicodeString(UResourceBundle *resB, const char ** key, UErrorCode*
|
|||
*/
|
||||
inline UnicodeString
|
||||
ures_getUnicodeStringByIndex(const UResourceBundle *resB, int32_t indexS, UErrorCode* status) {
|
||||
UnicodeString result;
|
||||
UnicodeString result;
|
||||
int32_t len = 0;
|
||||
const UChar* r = ures_getStringByIndex(resB, indexS, &len, status);
|
||||
|
@ -871,6 +873,7 @@ ures_getUnicodeStringByIndex(const UResourceBundle *resB, int32_t indexS, UError
|
|||
*/
|
||||
inline UnicodeString
|
||||
ures_getUnicodeStringByKey(const UResourceBundle *resB, const char* key, UErrorCode* status) {
|
||||
UnicodeString result;
|
||||
UnicodeString result;
|
||||
int32_t len = 0;
|
||||
const UChar* r = ures_getStringByKey(resB, key, &len, status);
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
**********************************************************************
|
||||
* Copyright (C) 1999-2013, International Business Machines
|
||||
* Copyright (C) 1999-2016, International Business Machines
|
||||
* Corporation and others. All Rights Reserved.
|
||||
**********************************************************************
|
||||
* Date Name Description
|
||||
|
@ -59,7 +59,7 @@ U_NAMESPACE_BEGIN
|
|||
*
|
||||
* <p>In order to implement methods such as contains() and indexOf(),
|
||||
* UVector needs a way to compare objects for equality. To do so, it
|
||||
* uses a comparison frunction, or "comparer." If the comparer is not
|
||||
* uses a comparison function, or "comparer." If the comparer is not
|
||||
* set, or is set to zero, then all such methods will act as if the
|
||||
* vector contains no element. That is, indexOf() will always return
|
||||
* -1, contains() will always return FALSE, etc.
|
||||
|
|
|
@ -99,7 +99,7 @@ sharedbreakiterator.o scientificnumberformatter.o digitgrouping.o \
|
|||
digitinterval.o digitformatter.o digitaffix.o valueformatter.o \
|
||||
digitaffixesandpadding.o pluralaffix.o precision.o \
|
||||
affixpatternparser.o smallintformatter.o decimfmtimpl.o \
|
||||
visibledigits.o
|
||||
visibledigits.o dayperiodrules.o
|
||||
|
||||
## Header files to install
|
||||
HEADERS = $(srcdir)/unicode/*.h
|
||||
|
|
547
icu4c/source/i18n/dayperiodrules.cpp
Normal file
547
icu4c/source/i18n/dayperiodrules.cpp
Normal file
|
@ -0,0 +1,547 @@
|
|||
/*
|
||||
*******************************************************************************
|
||||
* Copyright (C) 2016, International Business Machines
|
||||
* Corporation and others. All Rights Reserved.
|
||||
*******************************************************************************
|
||||
* dayperiodrules.cpp
|
||||
*
|
||||
* created on: 2016-01-20
|
||||
* created by: kazede
|
||||
*/
|
||||
|
||||
#include "dayperiodrules.h"
|
||||
|
||||
#include "unicode/ures.h"
|
||||
#include "cstr.h"
|
||||
#include "cstring.h"
|
||||
#include "ucln_in.h"
|
||||
#include "uhash.h"
|
||||
#include "umutex.h"
|
||||
#include "uresimp.h"
|
||||
|
||||
|
||||
U_NAMESPACE_BEGIN
|
||||
|
||||
namespace {
|
||||
|
||||
struct DayPeriodRulesData {
|
||||
DayPeriodRulesData() : localeToRuleSetNumMap(NULL), rules(NULL), maxRuleSetNum(0) {}
|
||||
|
||||
UHashtable *localeToRuleSetNumMap;
|
||||
DayPeriodRules *rules;
|
||||
int32_t maxRuleSetNum;
|
||||
} *data = NULL;
|
||||
|
||||
enum CutoffType {
|
||||
CUTOFF_TYPE_UNKNOWN = -1,
|
||||
CUTOFF_TYPE_BEFORE,
|
||||
CUTOFF_TYPE_AFTER, // TODO: AFTER is deprecated in CLDR 29. Remove.
|
||||
CUTOFF_TYPE_FROM,
|
||||
CUTOFF_TYPE_AT,
|
||||
};
|
||||
|
||||
} // namespace
|
||||
|
||||
struct DayPeriodRulesDataSink : public ResourceTableSink {
|
||||
// Initialize sub-sinks.
|
||||
DayPeriodRulesDataSink() :
|
||||
rulesSink(*this), ruleSetSink(*this), periodSink(*this), cutoffSink(*this) {
|
||||
for (int32_t i = 0; i < UPRV_LENGTHOF(cutoffs); ++i) { cutoffs[i] = 0; }
|
||||
}
|
||||
virtual ~DayPeriodRulesDataSink();
|
||||
|
||||
// Entry point.
|
||||
virtual ResourceTableSink *getOrCreateTableSink(const char *key, int32_t, UErrorCode &errorCode) {
|
||||
if (U_FAILURE(errorCode)) { return NULL; }
|
||||
|
||||
if (uprv_strcmp(key, "locales") == 0) {
|
||||
return &localesSink;
|
||||
} else if (uprv_strcmp(key, "rules") == 0) {
|
||||
// Allocate one more than needed to skip [0]. See comment in parseSetNum().
|
||||
data->rules = new DayPeriodRules[data->maxRuleSetNum + 1];
|
||||
if (data->rules == NULL) {
|
||||
errorCode = U_MEMORY_ALLOCATION_ERROR;
|
||||
return NULL;
|
||||
} else {
|
||||
return &rulesSink;
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// Data root -> locales.
|
||||
struct LocalesSink : public ResourceTableSink {
|
||||
virtual ~LocalesSink();
|
||||
|
||||
virtual void put(const char *key, const ResourceValue &value, UErrorCode &errorCode) {
|
||||
if (U_FAILURE(errorCode)) { return; }
|
||||
|
||||
UnicodeString setNum_str = value.getUnicodeString(errorCode);
|
||||
int32_t setNum = parseSetNum(setNum_str, errorCode);
|
||||
uhash_puti(data->localeToRuleSetNumMap, const_cast<char *>(key), setNum, &errorCode);
|
||||
}
|
||||
} localesSink;
|
||||
|
||||
// Data root -> rules.
|
||||
struct RulesSink : public ResourceTableSink {
|
||||
DayPeriodRulesDataSink &outer;
|
||||
RulesSink(DayPeriodRulesDataSink &outer) : outer(outer) {}
|
||||
virtual ~RulesSink();
|
||||
|
||||
virtual ResourceTableSink *getOrCreateTableSink(const char *key, int32_t, UErrorCode &errorCode) {
|
||||
if (U_FAILURE(errorCode)) { return NULL; }
|
||||
|
||||
outer.ruleSetNum = parseSetNum(key, errorCode);
|
||||
return &outer.ruleSetSink;
|
||||
}
|
||||
} rulesSink;
|
||||
|
||||
// Data root -> rules -> a rule set.
|
||||
struct RuleSetSink : public ResourceTableSink {
|
||||
DayPeriodRulesDataSink &outer;
|
||||
RuleSetSink(DayPeriodRulesDataSink &outer) : outer(outer) {}
|
||||
virtual ~RuleSetSink();
|
||||
|
||||
virtual ResourceTableSink *getOrCreateTableSink(const char *key, int32_t, UErrorCode &errorCode) {
|
||||
if (U_FAILURE(errorCode)) { return NULL; }
|
||||
|
||||
outer.period = DayPeriodRules::getDayPeriodFromString(key);
|
||||
if (outer.period == DayPeriodRules::DAYPERIOD_UNKNOWN) {
|
||||
errorCode = U_INVALID_FORMAT_ERROR;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return &outer.periodSink;
|
||||
}
|
||||
|
||||
virtual void leave(UErrorCode &errorCode) {
|
||||
if (U_FAILURE(errorCode)) { return; }
|
||||
|
||||
if (!data->rules[outer.ruleSetNum].allHoursAreSet()) {
|
||||
errorCode = U_INVALID_FORMAT_ERROR;
|
||||
}
|
||||
}
|
||||
} ruleSetSink;
|
||||
|
||||
// Data root -> rules -> a rule set -> a period (e.g. "morning1").
|
||||
// Key-value pairs (e.g. before{6:00}) will be captured here.
|
||||
// Arrays (e.g. before{6:00, 24:00}) will be redirected to the next sink.
|
||||
struct PeriodSink : public ResourceTableSink {
|
||||
DayPeriodRulesDataSink &outer;
|
||||
PeriodSink(DayPeriodRulesDataSink &outer) : outer(outer) {}
|
||||
virtual ~PeriodSink();
|
||||
|
||||
virtual void put(const char *key, const ResourceValue &value, UErrorCode &errorCode) {
|
||||
if (U_FAILURE(errorCode)) { return; }
|
||||
|
||||
CutoffType type = getCutoffTypeFromString(key);
|
||||
outer.addCutoff(type, value.getUnicodeString(errorCode), errorCode);
|
||||
}
|
||||
|
||||
virtual ResourceArraySink *getOrCreateArraySink(const char *key, int32_t, UErrorCode &errorCode) {
|
||||
if (U_FAILURE(errorCode)) { return NULL; }
|
||||
outer.cutoffType = getCutoffTypeFromString(key);
|
||||
return &outer.cutoffSink;
|
||||
}
|
||||
|
||||
virtual void leave(UErrorCode &errorCode) {
|
||||
if (U_FAILURE(errorCode)) { return; }
|
||||
|
||||
outer.setDayPeriodForHoursFromCutoffs(errorCode);
|
||||
for (int32_t i = 0; i < UPRV_LENGTHOF(outer.cutoffs); ++i) {
|
||||
outer.cutoffs[i] = 0;
|
||||
}
|
||||
}
|
||||
} periodSink;
|
||||
|
||||
// Data root -> rules -> a rule set -> a period -> a cutoff type.
|
||||
// Will enter this sink if 2+ times appear in a single cutoff type (e.g. before{6:00, 24:00}).
|
||||
struct CutoffSink : public ResourceArraySink {
|
||||
DayPeriodRulesDataSink &outer;
|
||||
CutoffSink(DayPeriodRulesDataSink &outer) : outer(outer) {}
|
||||
virtual ~CutoffSink();
|
||||
|
||||
virtual void put(int32_t, const ResourceValue &value, UErrorCode &errorCode) {
|
||||
outer.addCutoff(outer.cutoffType, value.getUnicodeString(errorCode), errorCode);
|
||||
}
|
||||
} cutoffSink;
|
||||
|
||||
// Members.
|
||||
int32_t cutoffs[25]; // [0] thru [24]: 24 is allowed in "before 24".
|
||||
|
||||
// "Path" to data.
|
||||
int32_t ruleSetNum;
|
||||
DayPeriodRules::DayPeriod period;
|
||||
CutoffType cutoffType;
|
||||
|
||||
// Helpers.
|
||||
static int32_t parseSetNum(const UnicodeString &setNumStr, UErrorCode &errorCode) {
|
||||
return parseSetNum(CStr(setNumStr)(), errorCode);
|
||||
}
|
||||
|
||||
static int32_t parseSetNum(const char *setNumStr, UErrorCode &errorCode) {
|
||||
if (U_FAILURE(errorCode)) { return -1; }
|
||||
|
||||
if (uprv_strncmp(setNumStr, "set", 3) != 0) {
|
||||
errorCode = U_INVALID_FORMAT_ERROR;
|
||||
return -1;
|
||||
}
|
||||
|
||||
int32_t i = 3;
|
||||
int32_t setNum = 0;
|
||||
while (setNumStr[i] != 0) {
|
||||
int32_t digit = setNumStr[i] - '0';
|
||||
if (digit < 0 || 9 < digit) {
|
||||
errorCode = U_INVALID_FORMAT_ERROR;
|
||||
return -1;
|
||||
}
|
||||
setNum = 10 * setNum + digit;
|
||||
++i;
|
||||
}
|
||||
|
||||
// Rule set number must not be zero. (0 is used to indicate "not found" by hashmap.)
|
||||
// Currently ICU data conveniently starts numbering rule sets from 1.
|
||||
if (setNum == 0) {
|
||||
errorCode = U_INVALID_FORMAT_ERROR;
|
||||
return -1;
|
||||
} else {
|
||||
return setNum;
|
||||
}
|
||||
}
|
||||
|
||||
void addCutoff(CutoffType type, UnicodeString hour_str, UErrorCode &errorCode) {
|
||||
if (U_FAILURE(errorCode)) { return; }
|
||||
|
||||
if (type == CUTOFF_TYPE_UNKNOWN) {
|
||||
errorCode = U_INVALID_FORMAT_ERROR;
|
||||
return;
|
||||
}
|
||||
|
||||
int32_t hour = parseHour(hour_str, errorCode);
|
||||
if (U_FAILURE(errorCode)) { return; }
|
||||
|
||||
cutoffs[hour] |= 1 << type;
|
||||
}
|
||||
|
||||
// Translate the cutoffs[] array to day period rules.
|
||||
void setDayPeriodForHoursFromCutoffs(UErrorCode &errorCode) {
|
||||
DayPeriodRules &rule = data->rules[ruleSetNum];
|
||||
|
||||
for (int32_t startHour = 0; startHour <= 24; ++startHour) {
|
||||
// AT cutoffs must be either midnight or noon.
|
||||
if (cutoffs[startHour] & (1 << CUTOFF_TYPE_AT)) {
|
||||
if (startHour == 0 && period == DayPeriodRules::DAYPERIOD_MIDNIGHT) {
|
||||
rule.fHasMidnight = TRUE;
|
||||
} else if (startHour == 12 && period == DayPeriodRules::DAYPERIOD_NOON) {
|
||||
rule.fHasNoon = TRUE;
|
||||
} else {
|
||||
errorCode = U_INVALID_FORMAT_ERROR; // Bad data.
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// FROM/AFTER and BEFORE must come in a pair.
|
||||
if (cutoffs[startHour] & (1 << CUTOFF_TYPE_FROM) ||
|
||||
cutoffs[startHour] & (1 << CUTOFF_TYPE_AFTER)) {
|
||||
for (int32_t hour = startHour + 1;; ++hour) {
|
||||
if (hour == startHour) {
|
||||
// We've gone around the array once and can't find a BEFORE.
|
||||
errorCode = U_INVALID_FORMAT_ERROR;
|
||||
return;
|
||||
}
|
||||
if (hour == 25) { hour = 0; }
|
||||
if (cutoffs[hour] & (1 << CUTOFF_TYPE_BEFORE)) {
|
||||
rule.add(startHour, hour, period);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Translate "before" to CUTOFF_TYPE_BEFORE, for example.
|
||||
static CutoffType getCutoffTypeFromString(const char *type_str) {
|
||||
if (uprv_strcmp(type_str, "from") == 0) {
|
||||
return CUTOFF_TYPE_FROM;
|
||||
} else if (uprv_strcmp(type_str, "before") == 0) {
|
||||
return CUTOFF_TYPE_BEFORE;
|
||||
} else if (uprv_strcmp(type_str, "after") == 0) {
|
||||
return CUTOFF_TYPE_AFTER;
|
||||
} else if (uprv_strcmp(type_str, "at") == 0) {
|
||||
return CUTOFF_TYPE_AT;
|
||||
} else {
|
||||
return CUTOFF_TYPE_UNKNOWN;
|
||||
}
|
||||
}
|
||||
|
||||
// Gets the numerical value of the hour from the Unicode string.
|
||||
static int32_t parseHour(const UnicodeString &time, UErrorCode &errorCode) {
|
||||
if (U_FAILURE(errorCode)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
int32_t hourLimit = time.length() - 3;
|
||||
// `time` must look like "x:00" or "xx:00".
|
||||
// If length is wrong or `time` doesn't end with ":00", error out.
|
||||
if ((hourLimit != 1 && hourLimit != 2) ||
|
||||
time[hourLimit] != 0x3A || time[hourLimit + 1] != 0x30 ||
|
||||
time[hourLimit + 2] != 0x30) {
|
||||
errorCode = U_INVALID_FORMAT_ERROR;
|
||||
return 0;
|
||||
}
|
||||
|
||||
// If `time` doesn't begin with a number in [0, 24], error out.
|
||||
// Note: "24:00" is possible in "before 24:00".
|
||||
int32_t hour = time[0] - 0x30;
|
||||
if (hour < 0 || 9 < hour) {
|
||||
errorCode = U_INVALID_FORMAT_ERROR;
|
||||
return 0;
|
||||
}
|
||||
if (hourLimit == 2) {
|
||||
int32_t hourDigit2 = time[1] - 0x30;
|
||||
if (hourDigit2 < 0 || 9 < hourDigit2) {
|
||||
errorCode = U_INVALID_FORMAT_ERROR;
|
||||
return 0;
|
||||
}
|
||||
hour = hour * 10 + hourDigit2;
|
||||
if (hour > 24) {
|
||||
errorCode = U_INVALID_FORMAT_ERROR;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
return hour;
|
||||
}
|
||||
}; // struct DayPeriodRulesDataSink
|
||||
|
||||
struct DayPeriodRulesCountSink : public ResourceTableSink {
|
||||
virtual ResourceTableSink *getOrCreateTableSink(const char *key, int32_t, UErrorCode &errorCode) {
|
||||
if (U_FAILURE(errorCode)) { return NULL; }
|
||||
|
||||
int32_t setNum = DayPeriodRulesDataSink::parseSetNum(key, errorCode);
|
||||
if (setNum > data->maxRuleSetNum) {
|
||||
data->maxRuleSetNum = setNum;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
};
|
||||
|
||||
// Out-of-line virtual destructors.
|
||||
DayPeriodRulesDataSink::LocalesSink::~LocalesSink() {}
|
||||
DayPeriodRulesDataSink::CutoffSink::~CutoffSink() {}
|
||||
DayPeriodRulesDataSink::PeriodSink::~PeriodSink() {}
|
||||
DayPeriodRulesDataSink::RuleSetSink::~RuleSetSink() {}
|
||||
DayPeriodRulesDataSink::RulesSink::~RulesSink() {}
|
||||
DayPeriodRulesDataSink::~DayPeriodRulesDataSink() {}
|
||||
|
||||
namespace {
|
||||
|
||||
UInitOnce initOnce = U_INITONCE_INITIALIZER;
|
||||
|
||||
UBool dayPeriodRulesCleanup() {
|
||||
delete[] data->rules;
|
||||
uhash_close(data->localeToRuleSetNumMap);
|
||||
delete data;
|
||||
data = NULL;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
void DayPeriodRules::load(UErrorCode &errorCode) {
|
||||
if (U_FAILURE(errorCode)) {
|
||||
return;
|
||||
}
|
||||
|
||||
data = new DayPeriodRulesData();
|
||||
data->localeToRuleSetNumMap = uhash_open(uhash_hashChars, uhash_compareChars, NULL, &errorCode);
|
||||
LocalUResourceBundlePointer rb_dayPeriods(ures_openDirect(NULL, "dayPeriods", &errorCode));
|
||||
|
||||
// Get the largest rule set number (so we allocate enough objects).
|
||||
DayPeriodRulesCountSink countSink;
|
||||
ures_getAllTableItemsWithFallback(rb_dayPeriods.getAlias(), "rules", countSink, errorCode);
|
||||
|
||||
// Populate rules.
|
||||
DayPeriodRulesDataSink sink;
|
||||
ures_getAllTableItemsWithFallback(rb_dayPeriods.getAlias(), "", sink, errorCode);
|
||||
|
||||
ucln_i18n_registerCleanup(UCLN_I18N_DAYPERIODRULES, dayPeriodRulesCleanup);
|
||||
}
|
||||
|
||||
const DayPeriodRules *DayPeriodRules::getInstance(const Locale &locale, UErrorCode &errorCode) {
|
||||
umtx_initOnce(initOnce, DayPeriodRules::load, errorCode);
|
||||
|
||||
// If the entire day period rules data doesn't conform to spec (even if the part we want
|
||||
// does), return NULL.
|
||||
if(U_FAILURE(errorCode)) { return NULL; }
|
||||
|
||||
const char *localeCode = locale.getName();
|
||||
char name[ULOC_FULLNAME_CAPACITY];
|
||||
char parentName[ULOC_FULLNAME_CAPACITY];
|
||||
|
||||
if (uprv_strlen(localeCode) < ULOC_FULLNAME_CAPACITY) {
|
||||
uprv_strcpy(name, localeCode);
|
||||
|
||||
// Treat empty string as root.
|
||||
if (*name == '\0') {
|
||||
uprv_strcpy(name, "root");
|
||||
}
|
||||
} else {
|
||||
errorCode = U_BUFFER_OVERFLOW_ERROR;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int32_t ruleSetNum = 0; // NB there is no rule set 0 and 0 is returned upon lookup failure.
|
||||
while (*name != '\0') {
|
||||
ruleSetNum = uhash_geti(data->localeToRuleSetNumMap, name);
|
||||
if (ruleSetNum == 0) {
|
||||
// name and parentName can't be the same pointer, so fill in parent then copy to child.
|
||||
uloc_getParent(name, parentName, ULOC_FULLNAME_CAPACITY, &errorCode);
|
||||
if (*parentName == '\0') {
|
||||
// Saves a lookup in the hash table.
|
||||
break;
|
||||
}
|
||||
uprv_strcpy(name, parentName);
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (ruleSetNum <= 0 || data->rules[ruleSetNum].getDayPeriodForHour(0) == DAYPERIOD_UNKNOWN) {
|
||||
// If day period for hour 0 is UNKNOWN then day period for all hours are UNKNOWN.
|
||||
// Data doesn't exist even with fallback.
|
||||
return NULL;
|
||||
} else {
|
||||
return &data->rules[ruleSetNum];
|
||||
}
|
||||
}
|
||||
|
||||
DayPeriodRules::DayPeriodRules() : fHasMidnight(FALSE), fHasNoon(FALSE) {
|
||||
for (int32_t i = 0; i < 24; ++i) {
|
||||
fDayPeriodForHour[i] = DayPeriodRules::DAYPERIOD_UNKNOWN;
|
||||
}
|
||||
}
|
||||
|
||||
double DayPeriodRules::getMidPointForDayPeriod(
|
||||
DayPeriodRules::DayPeriod dayPeriod, UErrorCode &errorCode) const {
|
||||
if (U_FAILURE(errorCode)) { return -1; }
|
||||
|
||||
int32_t startHour = getStartHourForDayPeriod(dayPeriod, errorCode);
|
||||
int32_t endHour = getEndHourForDayPeriod(dayPeriod, errorCode);
|
||||
// Can't obtain startHour or endHour; bail out.
|
||||
if (U_FAILURE(errorCode)) { return -1; }
|
||||
|
||||
double midPoint = (startHour + endHour) / 2.0;
|
||||
|
||||
if (startHour > endHour) {
|
||||
// dayPeriod wraps around midnight. Shift midPoint by 12 hours, in the direction that
|
||||
// lands it in [0, 24).
|
||||
midPoint += 12;
|
||||
if (midPoint >= 24) {
|
||||
midPoint -= 24;
|
||||
}
|
||||
}
|
||||
|
||||
return midPoint;
|
||||
}
|
||||
|
||||
int32_t DayPeriodRules::getStartHourForDayPeriod(
|
||||
DayPeriodRules::DayPeriod dayPeriod, UErrorCode &errorCode) const {
|
||||
if (U_FAILURE(errorCode)) { return -1; }
|
||||
|
||||
if (dayPeriod == DAYPERIOD_MIDNIGHT) { return 0; }
|
||||
if (dayPeriod == DAYPERIOD_NOON) { return 12; }
|
||||
|
||||
if (fDayPeriodForHour[0] == dayPeriod && fDayPeriodForHour[23] == dayPeriod) {
|
||||
// dayPeriod wraps around midnight. Start hour is later than end hour.
|
||||
for (int32_t i = 22; i >= 1; --i) {
|
||||
if (fDayPeriodForHour[i] != dayPeriod) {
|
||||
return (i + 1);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
for (int32_t i = 0; i <= 23; ++i) {
|
||||
if (fDayPeriodForHour[i] == dayPeriod) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// dayPeriod doesn't exist in rule set; set error and exit.
|
||||
errorCode = U_ILLEGAL_ARGUMENT_ERROR;
|
||||
return -1;
|
||||
}
|
||||
|
||||
int32_t DayPeriodRules::getEndHourForDayPeriod(
|
||||
DayPeriodRules::DayPeriod dayPeriod, UErrorCode &errorCode) const {
|
||||
if (U_FAILURE(errorCode)) { return -1; }
|
||||
|
||||
if (dayPeriod == DAYPERIOD_MIDNIGHT) { return 0; }
|
||||
if (dayPeriod == DAYPERIOD_NOON) { return 12; }
|
||||
|
||||
if (fDayPeriodForHour[0] == dayPeriod && fDayPeriodForHour[23] == dayPeriod) {
|
||||
// dayPeriod wraps around midnight. End hour is before start hour.
|
||||
for (int32_t i = 1; i <= 22; ++i) {
|
||||
if (fDayPeriodForHour[i] != dayPeriod) {
|
||||
// i o'clock is when a new period starts, therefore when the old period ends.
|
||||
return i;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
for (int32_t i = 23; i >= 0; --i) {
|
||||
if (fDayPeriodForHour[i] == dayPeriod) {
|
||||
return (i + 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// dayPeriod doesn't exist in rule set; set error and exit.
|
||||
errorCode = U_ILLEGAL_ARGUMENT_ERROR;
|
||||
return -1;
|
||||
}
|
||||
|
||||
DayPeriodRules::DayPeriod DayPeriodRules::getDayPeriodFromString(const char *type_str) {
|
||||
if (uprv_strcmp(type_str, "midnight") == 0) {
|
||||
return DAYPERIOD_MIDNIGHT;
|
||||
} else if (uprv_strcmp(type_str, "noon") == 0) {
|
||||
return DAYPERIOD_NOON;
|
||||
} else if (uprv_strcmp(type_str, "morning1") == 0) {
|
||||
return DAYPERIOD_MORNING1;
|
||||
} else if (uprv_strcmp(type_str, "afternoon1") == 0) {
|
||||
return DAYPERIOD_AFTERNOON1;
|
||||
} else if (uprv_strcmp(type_str, "evening1") == 0) {
|
||||
return DAYPERIOD_EVENING1;
|
||||
} else if (uprv_strcmp(type_str, "night1") == 0) {
|
||||
return DAYPERIOD_NIGHT1;
|
||||
} else if (uprv_strcmp(type_str, "morning2") == 0) {
|
||||
return DAYPERIOD_MORNING2;
|
||||
} else if (uprv_strcmp(type_str, "afternoon2") == 0) {
|
||||
return DAYPERIOD_AFTERNOON2;
|
||||
} else if (uprv_strcmp(type_str, "evening2") == 0) {
|
||||
return DAYPERIOD_EVENING2;
|
||||
} else if (uprv_strcmp(type_str, "night2") == 0) {
|
||||
return DAYPERIOD_NIGHT2;
|
||||
} else {
|
||||
return DAYPERIOD_UNKNOWN;
|
||||
}
|
||||
}
|
||||
|
||||
void DayPeriodRules::add(int32_t startHour, int32_t limitHour, DayPeriod period) {
|
||||
for (int32_t i = startHour; i != limitHour; ++i) {
|
||||
if (i == 24) { i = 0; }
|
||||
fDayPeriodForHour[i] = period;
|
||||
}
|
||||
}
|
||||
|
||||
UBool DayPeriodRules::allHoursAreSet() {
|
||||
for (int32_t i = 0; i < 24; ++i) {
|
||||
if (fDayPeriodForHour[i] == DAYPERIOD_UNKNOWN) { return FALSE; }
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
|
||||
U_NAMESPACE_END
|
85
icu4c/source/i18n/dayperiodrules.h
Normal file
85
icu4c/source/i18n/dayperiodrules.h
Normal file
|
@ -0,0 +1,85 @@
|
|||
/*
|
||||
*******************************************************************************
|
||||
* Copyright (C) 2016, International Business Machines
|
||||
* Corporation and others. All Rights Reserved.
|
||||
*******************************************************************************
|
||||
* dayperiodrules.h
|
||||
*
|
||||
* created on: 2016-01-20
|
||||
* created by: kazede
|
||||
*/
|
||||
|
||||
#ifndef DAYPERIODRULES_H
|
||||
#define DAYPERIODRULES_H
|
||||
|
||||
#include "unicode/locid.h"
|
||||
#include "unicode/unistr.h"
|
||||
#include "unicode/uobject.h"
|
||||
#include "unicode/utypes.h"
|
||||
#include "resource.h"
|
||||
#include "uhash.h"
|
||||
|
||||
|
||||
|
||||
U_NAMESPACE_BEGIN
|
||||
|
||||
struct DayPeriodRulesDataSink;
|
||||
|
||||
class DayPeriodRules : public UMemory {
|
||||
friend struct DayPeriodRulesDataSink;
|
||||
public:
|
||||
enum DayPeriod {
|
||||
DAYPERIOD_UNKNOWN = -1,
|
||||
DAYPERIOD_MIDNIGHT,
|
||||
DAYPERIOD_NOON,
|
||||
DAYPERIOD_MORNING1,
|
||||
DAYPERIOD_AFTERNOON1,
|
||||
DAYPERIOD_EVENING1,
|
||||
DAYPERIOD_NIGHT1,
|
||||
DAYPERIOD_MORNING2,
|
||||
DAYPERIOD_AFTERNOON2,
|
||||
DAYPERIOD_EVENING2,
|
||||
DAYPERIOD_NIGHT2
|
||||
};
|
||||
|
||||
static const DayPeriodRules *getInstance(const Locale &locale, UErrorCode &errorCode);
|
||||
|
||||
UBool hasMidnight() const { return fHasMidnight; }
|
||||
UBool hasNoon() const { return fHasNoon; }
|
||||
DayPeriod getDayPeriodForHour(int32_t hour) const { return fDayPeriodForHour[hour]; }
|
||||
|
||||
// Returns the center of dayPeriod. Half hours are indicated with a .5 .
|
||||
double getMidPointForDayPeriod(DayPeriod dayPeriod, UErrorCode &errorCode) const;
|
||||
|
||||
private:
|
||||
DayPeriodRules();
|
||||
|
||||
// Translates "morning1" to DAYPERIOD_MORNING1, for example.
|
||||
static DayPeriod getDayPeriodFromString(const char *type_str);
|
||||
|
||||
static void load(UErrorCode &errorCode);
|
||||
|
||||
// Sets period type for all hours in [startHour, limitHour).
|
||||
void add(int32_t startHour, int32_t limitHour, DayPeriod period);
|
||||
|
||||
// Returns TRUE if for all i, DayPeriodForHour[i] has a type other than UNKNOWN.
|
||||
// Values of HasNoon and HasMidnight do not affect the return value.
|
||||
UBool allHoursAreSet();
|
||||
|
||||
// Returns the hour that starts dayPeriod. Returns 0 for MIDNIGHT and 12 for NOON.
|
||||
int32_t getStartHourForDayPeriod(DayPeriod dayPeriod, UErrorCode &errorCode) const;
|
||||
|
||||
// Returns the hour that ends dayPeriod, i.e. that starts the next period.
|
||||
// E.g. if fDayPeriodForHour[13] thru [16] are AFTERNOON1, then this function returns 17 if
|
||||
// queried with AFTERNOON1.
|
||||
// Returns 0 for MIDNIGHT and 12 for NOON.
|
||||
int32_t getEndHourForDayPeriod(DayPeriod dayPeriod, UErrorCode &errorCode) const;
|
||||
|
||||
UBool fHasMidnight;
|
||||
UBool fHasNoon;
|
||||
DayPeriod fDayPeriodForHour[24];
|
||||
};
|
||||
|
||||
U_NAMESPACE_END
|
||||
|
||||
#endif /* DAYPERIODRULES_H */
|
|
@ -1,7 +1,7 @@
|
|||
/*
|
||||
*******************************************************************************
|
||||
* Copyright (C) 1997-2016, International Business Machines Corporation and
|
||||
* others. All Rights Reserved.
|
||||
* Copyright (C) 1997-2016, International Business Machines Corporation and *
|
||||
* others. All Rights Reserved. *
|
||||
*******************************************************************************
|
||||
*
|
||||
* File DTFMTSYM.CPP
|
||||
|
@ -52,9 +52,9 @@
|
|||
*/
|
||||
|
||||
#if UDAT_HAS_PATTERN_CHAR_FOR_TIME_SEPARATOR
|
||||
#define PATTERN_CHARS_LEN 36
|
||||
#define PATTERN_CHARS_LEN 38
|
||||
#else
|
||||
#define PATTERN_CHARS_LEN 35
|
||||
#define PATTERN_CHARS_LEN 37
|
||||
#endif
|
||||
|
||||
/**
|
||||
|
@ -62,19 +62,19 @@
|
|||
* locales use the same these unlocalized pattern characters.
|
||||
*/
|
||||
static const UChar gPatternChars[] = {
|
||||
#if UDAT_HAS_PATTERN_CHAR_FOR_TIME_SEPARATOR
|
||||
// GyMdkHmsSEDFwWahKzYeugAZvcLQqVUOXxr:
|
||||
#else
|
||||
// GyMdkHmsSEDFwWahKzYeugAZvcLQqVUOXxr
|
||||
#endif
|
||||
// if UDAT_HAS_PATTERN_CHAR_FOR_TIME_SEPARATOR:
|
||||
// GyMdkHmsSEDFwWahKzYeugAZvcLQqVUOXxrbB:
|
||||
// else:
|
||||
// GyMdkHmsSEDFwWahKzYeugAZvcLQqVUOXxrbB
|
||||
|
||||
0x47, 0x79, 0x4D, 0x64, 0x6B, 0x48, 0x6D, 0x73, 0x53, 0x45,
|
||||
0x44, 0x46, 0x77, 0x57, 0x61, 0x68, 0x4B, 0x7A, 0x59, 0x65,
|
||||
0x75, 0x67, 0x41, 0x5A, 0x76, 0x63, 0x4c, 0x51, 0x71, 0x56,
|
||||
0x55, 0x4F, 0x58, 0x78, 0x72, 0x62, 0x42,
|
||||
#if UDAT_HAS_PATTERN_CHAR_FOR_TIME_SEPARATOR
|
||||
0x55, 0x4F, 0x58, 0x78, 0x72, 0x3a, 0
|
||||
#else
|
||||
0x55, 0x4F, 0x58, 0x78, 0x72, 0
|
||||
0x3a,
|
||||
#endif
|
||||
0
|
||||
};
|
||||
|
||||
//------------------------------------------------------
|
||||
|
@ -216,6 +216,7 @@ static const char gQuartersTag[]="quarters";
|
|||
static const char gNumberElementsTag[]="NumberElements";
|
||||
static const char gSymbolsTag[]="symbols";
|
||||
static const char gTimeSeparatorTag[]="timeSeparator";
|
||||
static const char gDayPeriodTag[]="dayPeriod";
|
||||
|
||||
// static const char gZoneStringsTag[]="zoneStrings";
|
||||
|
||||
|
@ -384,6 +385,18 @@ DateFormatSymbols::copyData(const DateFormatSymbols& other) {
|
|||
assignArray(fShortQuarters, fShortQuartersCount, other.fShortQuarters, other.fShortQuartersCount);
|
||||
assignArray(fStandaloneQuarters, fStandaloneQuartersCount, other.fStandaloneQuarters, other.fStandaloneQuartersCount);
|
||||
assignArray(fStandaloneShortQuarters, fStandaloneShortQuartersCount, other.fStandaloneShortQuarters, other.fStandaloneShortQuartersCount);
|
||||
assignArray(fWideDayPeriods, fWideDayPeriodsCount,
|
||||
other.fWideDayPeriods, other.fWideDayPeriodsCount);
|
||||
assignArray(fNarrowDayPeriods, fNarrowDayPeriodsCount,
|
||||
other.fNarrowDayPeriods, other.fNarrowDayPeriodsCount);
|
||||
assignArray(fAbbreviatedDayPeriods, fAbbreviatedDayPeriodsCount,
|
||||
other.fAbbreviatedDayPeriods, other.fAbbreviatedDayPeriodsCount);
|
||||
assignArray(fStandaloneWideDayPeriods, fStandaloneWideDayPeriodsCount,
|
||||
other.fStandaloneWideDayPeriods, other.fStandaloneWideDayPeriodsCount);
|
||||
assignArray(fStandaloneNarrowDayPeriods, fStandaloneNarrowDayPeriodsCount,
|
||||
other.fStandaloneNarrowDayPeriods, other.fStandaloneNarrowDayPeriodsCount);
|
||||
assignArray(fStandaloneAbbreviatedDayPeriods, fStandaloneAbbreviatedDayPeriodsCount,
|
||||
other.fStandaloneAbbreviatedDayPeriods, other.fStandaloneAbbreviatedDayPeriodsCount);
|
||||
if (other.fLeapMonthPatterns != NULL) {
|
||||
assignArray(fLeapMonthPatterns, fLeapMonthPatternsCount, other.fLeapMonthPatterns, other.fLeapMonthPatternsCount);
|
||||
} else {
|
||||
|
@ -402,7 +415,7 @@ DateFormatSymbols::copyData(const DateFormatSymbols& other) {
|
|||
fShortZodiacNames = NULL;
|
||||
fShortZodiacNamesCount = 0;
|
||||
}
|
||||
|
||||
|
||||
if (other.fZoneStrings != NULL) {
|
||||
fZoneStringsColCount = other.fZoneStringsColCount;
|
||||
fZoneStringsRowCount = other.fZoneStringsRowCount;
|
||||
|
@ -419,7 +432,7 @@ DateFormatSymbols::copyData(const DateFormatSymbols& other) {
|
|||
|
||||
// fastCopyFrom() - see assignArray comments
|
||||
fLocalPatternChars.fastCopyFrom(other.fLocalPatternChars);
|
||||
|
||||
|
||||
uprv_memcpy(fCapitalization, other.fCapitalization, sizeof(fCapitalization));
|
||||
}
|
||||
|
||||
|
@ -441,32 +454,38 @@ DateFormatSymbols::~DateFormatSymbols()
|
|||
|
||||
void DateFormatSymbols::dispose()
|
||||
{
|
||||
if (fEras) delete[] fEras;
|
||||
if (fEraNames) delete[] fEraNames;
|
||||
if (fNarrowEras) delete[] fNarrowEras;
|
||||
if (fMonths) delete[] fMonths;
|
||||
if (fShortMonths) delete[] fShortMonths;
|
||||
if (fNarrowMonths) delete[] fNarrowMonths;
|
||||
if (fStandaloneMonths) delete[] fStandaloneMonths;
|
||||
if (fStandaloneShortMonths) delete[] fStandaloneShortMonths;
|
||||
if (fStandaloneNarrowMonths) delete[] fStandaloneNarrowMonths;
|
||||
if (fWeekdays) delete[] fWeekdays;
|
||||
if (fShortWeekdays) delete[] fShortWeekdays;
|
||||
if (fShorterWeekdays) delete[] fShorterWeekdays;
|
||||
if (fNarrowWeekdays) delete[] fNarrowWeekdays;
|
||||
if (fStandaloneWeekdays) delete[] fStandaloneWeekdays;
|
||||
if (fStandaloneShortWeekdays) delete[] fStandaloneShortWeekdays;
|
||||
if (fStandaloneShorterWeekdays) delete[] fStandaloneShorterWeekdays;
|
||||
if (fStandaloneNarrowWeekdays) delete[] fStandaloneNarrowWeekdays;
|
||||
if (fAmPms) delete[] fAmPms;
|
||||
if (fNarrowAmPms) delete[] fNarrowAmPms;
|
||||
if (fQuarters) delete[] fQuarters;
|
||||
if (fShortQuarters) delete[] fShortQuarters;
|
||||
if (fStandaloneQuarters) delete[] fStandaloneQuarters;
|
||||
if (fStandaloneShortQuarters) delete[] fStandaloneShortQuarters;
|
||||
if (fLeapMonthPatterns) delete[] fLeapMonthPatterns;
|
||||
if (fShortYearNames) delete[] fShortYearNames;
|
||||
if (fShortZodiacNames) delete[] fShortZodiacNames;
|
||||
delete[] fEras;
|
||||
delete[] fEraNames;
|
||||
delete[] fNarrowEras;
|
||||
delete[] fMonths;
|
||||
delete[] fShortMonths;
|
||||
delete[] fNarrowMonths;
|
||||
delete[] fStandaloneMonths;
|
||||
delete[] fStandaloneShortMonths;
|
||||
delete[] fStandaloneNarrowMonths;
|
||||
delete[] fWeekdays;
|
||||
delete[] fShortWeekdays;
|
||||
delete[] fShorterWeekdays;
|
||||
delete[] fNarrowWeekdays;
|
||||
delete[] fStandaloneWeekdays;
|
||||
delete[] fStandaloneShortWeekdays;
|
||||
delete[] fStandaloneShorterWeekdays;
|
||||
delete[] fStandaloneNarrowWeekdays;
|
||||
delete[] fAmPms;
|
||||
delete[] fNarrowAmPms;
|
||||
delete[] fQuarters;
|
||||
delete[] fShortQuarters;
|
||||
delete[] fStandaloneQuarters;
|
||||
delete[] fStandaloneShortQuarters;
|
||||
delete[] fLeapMonthPatterns;
|
||||
delete[] fShortYearNames;
|
||||
delete[] fShortZodiacNames;
|
||||
delete[] fAbbreviatedDayPeriods;
|
||||
delete[] fWideDayPeriods;
|
||||
delete[] fNarrowDayPeriods;
|
||||
delete[] fStandaloneAbbreviatedDayPeriods;
|
||||
delete[] fStandaloneWideDayPeriods;
|
||||
delete[] fStandaloneNarrowDayPeriods;
|
||||
|
||||
disposeZoneStrings();
|
||||
}
|
||||
|
@ -539,6 +558,12 @@ DateFormatSymbols::operator==(const DateFormatSymbols& other) const
|
|||
fLeapMonthPatternsCount == other.fLeapMonthPatternsCount &&
|
||||
fShortYearNamesCount == other.fShortYearNamesCount &&
|
||||
fShortZodiacNamesCount == other.fShortZodiacNamesCount &&
|
||||
fAbbreviatedDayPeriodsCount == other.fAbbreviatedDayPeriodsCount &&
|
||||
fWideDayPeriodsCount == other.fWideDayPeriodsCount &&
|
||||
fNarrowDayPeriodsCount == other.fNarrowDayPeriodsCount &&
|
||||
fStandaloneAbbreviatedDayPeriodsCount == other.fStandaloneAbbreviatedDayPeriodsCount &&
|
||||
fStandaloneWideDayPeriodsCount == other.fStandaloneWideDayPeriodsCount &&
|
||||
fStandaloneNarrowDayPeriodsCount == other.fStandaloneNarrowDayPeriodsCount &&
|
||||
(uprv_memcmp(fCapitalization, other.fCapitalization, sizeof(fCapitalization))==0))
|
||||
{
|
||||
// Now compare the arrays themselves
|
||||
|
@ -568,7 +593,16 @@ DateFormatSymbols::operator==(const DateFormatSymbols& other) const
|
|||
arrayCompare(fStandaloneShortQuarters, other.fStandaloneShortQuarters, fStandaloneShortQuartersCount) &&
|
||||
arrayCompare(fLeapMonthPatterns, other.fLeapMonthPatterns, fLeapMonthPatternsCount) &&
|
||||
arrayCompare(fShortYearNames, other.fShortYearNames, fShortYearNamesCount) &&
|
||||
arrayCompare(fShortZodiacNames, other.fShortZodiacNames, fShortZodiacNamesCount))
|
||||
arrayCompare(fShortZodiacNames, other.fShortZodiacNames, fShortZodiacNamesCount) &&
|
||||
arrayCompare(fAbbreviatedDayPeriods, other.fAbbreviatedDayPeriods, fAbbreviatedDayPeriodsCount) &&
|
||||
arrayCompare(fWideDayPeriods, other.fWideDayPeriods, fWideDayPeriodsCount) &&
|
||||
arrayCompare(fNarrowDayPeriods, other.fNarrowDayPeriods, fNarrowDayPeriodsCount) &&
|
||||
arrayCompare(fStandaloneAbbreviatedDayPeriods, other.fStandaloneAbbreviatedDayPeriods,
|
||||
fStandaloneAbbreviatedDayPeriodsCount) &&
|
||||
arrayCompare(fStandaloneWideDayPeriods, other.fStandaloneWideDayPeriods,
|
||||
fStandaloneWideDayPeriodsCount) &&
|
||||
arrayCompare(fStandaloneNarrowDayPeriods, other.fStandaloneNarrowDayPeriods,
|
||||
fStandaloneWideDayPeriodsCount))
|
||||
{
|
||||
// Compare the contents of fZoneStrings
|
||||
if (fZoneStrings == NULL && other.fZoneStrings == NULL) {
|
||||
|
@ -964,7 +998,7 @@ DateFormatSymbols::setMonths(const UnicodeString* monthsArray, int32_t count, Dt
|
|||
fNarrowMonths = newUnicodeStringArray(count);
|
||||
uprv_arrayCopy( monthsArray,fNarrowMonths,count);
|
||||
fNarrowMonthsCount = count;
|
||||
break;
|
||||
break;
|
||||
default :
|
||||
break;
|
||||
}
|
||||
|
@ -991,7 +1025,7 @@ DateFormatSymbols::setMonths(const UnicodeString* monthsArray, int32_t count, Dt
|
|||
fStandaloneNarrowMonths = newUnicodeStringArray(count);
|
||||
uprv_arrayCopy( monthsArray,fStandaloneNarrowMonths,count);
|
||||
fStandaloneNarrowMonthsCount = count;
|
||||
break;
|
||||
break;
|
||||
default :
|
||||
break;
|
||||
}
|
||||
|
@ -1065,7 +1099,7 @@ DateFormatSymbols::setWeekdays(const UnicodeString* weekdaysArray, int32_t count
|
|||
fNarrowWeekdays = newUnicodeStringArray(count);
|
||||
uprv_arrayCopy(weekdaysArray, fNarrowWeekdays, count);
|
||||
fNarrowWeekdaysCount = count;
|
||||
break;
|
||||
break;
|
||||
case DT_WIDTH_COUNT :
|
||||
break;
|
||||
}
|
||||
|
@ -1099,7 +1133,7 @@ DateFormatSymbols::setWeekdays(const UnicodeString* weekdaysArray, int32_t count
|
|||
fStandaloneNarrowWeekdays = newUnicodeStringArray(count);
|
||||
uprv_arrayCopy(weekdaysArray, fStandaloneNarrowWeekdays, count);
|
||||
fStandaloneNarrowWeekdaysCount = count;
|
||||
break;
|
||||
break;
|
||||
case DT_WIDTH_COUNT :
|
||||
break;
|
||||
}
|
||||
|
@ -1141,7 +1175,7 @@ DateFormatSymbols::setQuarters(const UnicodeString* quartersArray, int32_t count
|
|||
uprv_arrayCopy( quartersArray,fNarrowQuarters,count);
|
||||
fNarrowQuartersCount = count;
|
||||
*/
|
||||
break;
|
||||
break;
|
||||
default :
|
||||
break;
|
||||
}
|
||||
|
@ -1170,7 +1204,7 @@ DateFormatSymbols::setQuarters(const UnicodeString* quartersArray, int32_t count
|
|||
uprv_arrayCopy( quartersArray,fStandaloneNarrowQuarters,count);
|
||||
fStandaloneNarrowQuartersCount = count;
|
||||
*/
|
||||
break;
|
||||
break;
|
||||
default :
|
||||
break;
|
||||
}
|
||||
|
@ -1472,6 +1506,42 @@ static const ContextUsageTypeNameToEnumValue contextUsageTypeMap[] = {
|
|||
{ NULL, (DateFormatSymbols::ECapitalizationContextUsageType)0 },
|
||||
};
|
||||
|
||||
// Resource keys to look up localized strings for day periods.
|
||||
// The first one must be midnight and the second must be noon, so that their indices coincide
|
||||
// with the am/pm field. Formatting and parsing code for day periods relies on this coincidence.
|
||||
static const char *dayPeriodKeys[] = {"midnight", "noon",
|
||||
"morning1", "afternoon1", "evening1", "night1",
|
||||
"morning2", "afternoon2", "evening2", "night2"};
|
||||
|
||||
UnicodeString* loadDayPeriodStrings(CalendarData &calData, const char *tag, UBool standalone,
|
||||
int32_t &stringCount, UErrorCode &status) {
|
||||
if (U_FAILURE(status)) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
UResourceBundle *dayPeriodData;
|
||||
|
||||
if (standalone) {
|
||||
dayPeriodData = calData.getByKey3(gDayPeriodTag, gNamesStandaloneTag, tag, status);
|
||||
} else {
|
||||
dayPeriodData = calData.getByKey2(gDayPeriodTag, tag, status);
|
||||
}
|
||||
|
||||
stringCount = UPRV_LENGTHOF(dayPeriodKeys);
|
||||
UnicodeString *strings = new UnicodeString[stringCount];
|
||||
for (int32_t i = 0; i < stringCount; ++i) {
|
||||
//TODO: Check if there are fallbacks/aliases defined in the data; e.g., if there
|
||||
//is no wide string, then use the narrow one?
|
||||
strings[i].fastCopyFrom(ures_getUnicodeStringByKey(dayPeriodData, dayPeriodKeys[i], &status));
|
||||
if (U_FAILURE(status)) {
|
||||
// string[i] will be bogus if ures_getUnicodeString() returns with an error,
|
||||
// which is just the behavior we want. Simply reset the error code.
|
||||
status = U_ZERO_ERROR;
|
||||
}
|
||||
}
|
||||
return strings;
|
||||
}
|
||||
|
||||
void
|
||||
DateFormatSymbols::initializeData(const Locale& locale, const char *type, UErrorCode& status, UBool useLastResortData)
|
||||
{
|
||||
|
@ -1536,6 +1606,18 @@ DateFormatSymbols::initializeData(const Locale& locale, const char *type, UError
|
|||
fZoneStringsColCount = 0;
|
||||
fZoneStrings = NULL;
|
||||
fLocaleZoneStrings = NULL;
|
||||
fAbbreviatedDayPeriods = NULL;
|
||||
fAbbreviatedDayPeriodsCount = 0;
|
||||
fWideDayPeriods = NULL;
|
||||
fWideDayPeriodsCount = 0;
|
||||
fNarrowDayPeriods = NULL;
|
||||
fNarrowDayPeriodsCount = 0;
|
||||
fStandaloneAbbreviatedDayPeriods = NULL;
|
||||
fStandaloneAbbreviatedDayPeriodsCount = 0;
|
||||
fStandaloneWideDayPeriods = NULL;
|
||||
fStandaloneWideDayPeriodsCount = 0;
|
||||
fStandaloneNarrowDayPeriods = NULL;
|
||||
fStandaloneNarrowDayPeriodsCount = 0;
|
||||
uprv_memset(fCapitalization, 0, sizeof(fCapitalization));
|
||||
|
||||
// We need to preserve the requested locale for
|
||||
|
@ -1543,7 +1625,7 @@ DateFormatSymbols::initializeData(const Locale& locale, const char *type, UError
|
|||
// is region sensitive, thus, bundle locale bundle's locale
|
||||
// is not sufficient.
|
||||
fZSFLocale = locale;
|
||||
|
||||
|
||||
if (U_FAILURE(status)) return;
|
||||
|
||||
/**
|
||||
|
@ -1693,6 +1775,19 @@ DateFormatSymbols::initializeData(const Locale& locale, const char *type, UError
|
|||
fTimeSeparator.setTo(DateFormatSymbols::DEFAULT_TIME_SEPARATOR);
|
||||
}
|
||||
|
||||
fWideDayPeriods = loadDayPeriodStrings(calData, gNamesWideTag, FALSE,
|
||||
fWideDayPeriodsCount, status);
|
||||
fNarrowDayPeriods = loadDayPeriodStrings(calData, gNamesNarrowTag, FALSE,
|
||||
fNarrowDayPeriodsCount, status);
|
||||
fAbbreviatedDayPeriods = loadDayPeriodStrings(calData, gNamesAbbrTag, FALSE,
|
||||
fAbbreviatedDayPeriodsCount, status);
|
||||
fStandaloneWideDayPeriods = loadDayPeriodStrings(calData, gNamesWideTag, TRUE,
|
||||
fStandaloneWideDayPeriodsCount, status);
|
||||
fStandaloneNarrowDayPeriods = loadDayPeriodStrings(calData, gNamesNarrowTag, TRUE,
|
||||
fStandaloneNarrowDayPeriodsCount, status);
|
||||
fStandaloneAbbreviatedDayPeriods = loadDayPeriodStrings(calData, gNamesAbbrTag, TRUE,
|
||||
fStandaloneAbbreviatedDayPeriodsCount, status);
|
||||
|
||||
UResourceBundle *weekdaysData = NULL; // Data closed by calData
|
||||
UResourceBundle *abbrWeekdaysData = NULL; // Data closed by calData
|
||||
UResourceBundle *shorterWeekdaysData = NULL; // Data closed by calData
|
||||
|
@ -1990,7 +2085,7 @@ cleanup:
|
|||
ures_close(narrowEras);
|
||||
}
|
||||
|
||||
Locale
|
||||
Locale
|
||||
DateFormatSymbols::getLocale(ULocDataLocaleType type, UErrorCode& status) const {
|
||||
U_LOCALE_BASED(locBased, *this);
|
||||
return locBased.getLocale(type, status);
|
||||
|
|
|
@ -310,6 +310,7 @@
|
|||
<ClCompile Include="currunit.cpp" />
|
||||
<ClCompile Include="dangical.cpp" />
|
||||
<ClCompile Include="datefmt.cpp" />
|
||||
<ClCompile Include="dayperiodrules.cpp" />
|
||||
<ClCompile Include="dcfmtsym.cpp" />
|
||||
<ClCompile Include="decContext.c" />
|
||||
<ClCompile Include="decfmtst.cpp" />
|
||||
|
@ -608,6 +609,7 @@
|
|||
<ClInclude Include="collationsettings.h" />
|
||||
<ClInclude Include="collationtailoring.h" />
|
||||
<ClInclude Include="collationweights.h" />
|
||||
<ClInclude Include="dayperiodrules.h" />
|
||||
<ClInclude Include="dcfmtimp.h" />
|
||||
<ClInclude Include="numsys_impl.h" />
|
||||
<ClInclude Include="region_impl.h" />
|
||||
|
|
|
@ -57,6 +57,9 @@
|
|||
<ClCompile Include="affixpatternparser.cpp">
|
||||
<Filter>formatting</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="dayperiodrules.cpp">
|
||||
<Filter>formatting</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="decimfmtimpl.cpp">
|
||||
<Filter>formatting</Filter>
|
||||
</ClCompile>
|
||||
|
@ -691,6 +694,9 @@
|
|||
<ClInclude Include="dangical.h">
|
||||
<Filter>formatting</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="dayperiodrules.h">
|
||||
<Filter>formatting</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="decContext.h">
|
||||
<Filter>formatting</Filter>
|
||||
</ClInclude>
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
/*
|
||||
*******************************************************************************
|
||||
* Copyright (C) 1997-2016, International Business Machines Corporation and
|
||||
* others. All Rights Reserved.
|
||||
* Copyright (C) 1997-2016, International Business Machines Corporation and *
|
||||
* others. All Rights Reserved. *
|
||||
*******************************************************************************
|
||||
*
|
||||
* File SMPDTFMT.CPP
|
||||
|
@ -17,7 +17,7 @@
|
|||
* Removed getZoneIndex (added in DateFormatSymbols)
|
||||
* Removed subParseLong
|
||||
* Removed chk
|
||||
* 02/22/99 stephen Removed character literals for EBCDIC safety
|
||||
* 02/22/99 stephen Removed character literals for EBCDIC safety
|
||||
* 10/14/99 aliu Updated 2-digit year parsing so that only "00" thru
|
||||
* "99" are recognized. {j28 4182066}
|
||||
* 11/15/99 weiv Added support for week of year/day of week format
|
||||
|
@ -63,6 +63,10 @@
|
|||
#include "smpdtfst.h"
|
||||
#include "sharednumberformat.h"
|
||||
#include "ustr_imp.h"
|
||||
#include "charstr.h"
|
||||
#include "uvector.h"
|
||||
#include "cstr.h"
|
||||
#include "dayperiodrules.h"
|
||||
|
||||
#if defined( U_DEBUG_CALSVC ) || defined (U_DEBUG_CAL)
|
||||
#include <stdio.h>
|
||||
|
@ -622,6 +626,8 @@ SimpleDateFormat& SimpleDateFormat::operator=(const SimpleDateFormat& other)
|
|||
fHaveDefaultCentury = other.fHaveDefaultCentury;
|
||||
|
||||
fPattern = other.fPattern;
|
||||
fHasMinute = other.fHasMinute;
|
||||
fHasSecond = other.fHasSecond;
|
||||
|
||||
// TimeZoneFormat in ICU4C only depends on a locale for now
|
||||
if (fLocale != other.fLocale) {
|
||||
|
@ -889,6 +895,8 @@ SimpleDateFormat::initialize(const Locale& locale,
|
|||
{
|
||||
status = U_MISSING_RESOURCE_ERROR;
|
||||
}
|
||||
|
||||
parsePattern();
|
||||
}
|
||||
|
||||
/* Initialize the fields we use to disambiguate ambiguous years. Separate
|
||||
|
@ -969,7 +977,7 @@ SimpleDateFormat::_format(Calendar& cal, UnicodeString& appendTo,
|
|||
FieldPositionHandler& handler, UErrorCode& status) const
|
||||
{
|
||||
if ( U_FAILURE(status) ) {
|
||||
return appendTo;
|
||||
return appendTo;
|
||||
}
|
||||
Calendar* workCal = &cal;
|
||||
Calendar* calClone = NULL;
|
||||
|
@ -1161,6 +1169,7 @@ SimpleDateFormat::fgPatternIndexToCalendarField[] =
|
|||
/*O*/ UCAL_ZONE_OFFSET,
|
||||
/*Xx*/ UCAL_ZONE_OFFSET, UCAL_ZONE_OFFSET,
|
||||
/*r*/ UCAL_EXTENDED_YEAR,
|
||||
/*bB*/ UCAL_FIELD_COUNT, UCAL_FIELD_COUNT, // no mappings to calendar fields
|
||||
#if UDAT_HAS_PATTERN_CHAR_FOR_TIME_SEPARATOR
|
||||
/*:*/ UCAL_FIELD_COUNT, /* => no useful mapping to any calendar field */
|
||||
#else
|
||||
|
@ -1189,6 +1198,7 @@ SimpleDateFormat::fgPatternIndexToDateFormatField[] = {
|
|||
/*O*/ UDAT_TIMEZONE_LOCALIZED_GMT_OFFSET_FIELD,
|
||||
/*Xx*/ UDAT_TIMEZONE_ISO_FIELD, UDAT_TIMEZONE_ISO_LOCAL_FIELD,
|
||||
/*r*/ UDAT_RELATED_YEAR_FIELD,
|
||||
/*bB*/ UDAT_AM_PM_MIDNIGHT_NOON_FIELD, UDAT_FLEXIBLE_DAY_PERIOD_FIELD,
|
||||
#if UDAT_HAS_PATTERN_CHAR_FOR_TIME_SEPARATOR
|
||||
/*:*/ UDAT_TIME_SEPARATOR_FIELD,
|
||||
#else
|
||||
|
@ -1419,7 +1429,7 @@ SimpleDateFormat::subFormat(UnicodeString &appendTo,
|
|||
return;
|
||||
}
|
||||
UnicodeString hebr("hebr", 4, US_INV);
|
||||
|
||||
|
||||
switch (patternCharIndex) {
|
||||
|
||||
// for any "G" symbol, write out the appropriate era string
|
||||
|
@ -1788,6 +1798,126 @@ SimpleDateFormat::subFormat(UnicodeString &appendTo,
|
|||
zeroPaddingNumber(currentNumberFormat,appendTo, (value/3) + 1, count, maxIntCount);
|
||||
break;
|
||||
|
||||
case UDAT_AM_PM_MIDNIGHT_NOON_FIELD:
|
||||
{
|
||||
const UnicodeString *toAppend = NULL;
|
||||
int32_t hour = cal.get(UCAL_HOUR_OF_DAY, status);
|
||||
|
||||
// For "midnight" and "noon":
|
||||
// Time, as displayed, must be exactly noon or midnight.
|
||||
// This means minutes and seconds, if present, must be zero.
|
||||
if ((hour == 0 || hour == 12) &&
|
||||
(!fHasMinute || cal.get(UCAL_MINUTE, status) == 0) &&
|
||||
(!fHasSecond || cal.get(UCAL_SECOND, status) == 0)) {
|
||||
// Stealing am/pm value to use as our array index.
|
||||
// It works out: am/midnight are both 0, pm/noon are both 1,
|
||||
// 12 am is 12 midnight, and 12 pm is 12 noon.
|
||||
int32_t value = cal.get(UCAL_AM_PM, status);
|
||||
|
||||
if (count <= 3) {
|
||||
toAppend = &fSymbols->fAbbreviatedDayPeriods[value];
|
||||
} else if (count == 4 || count > 5) {
|
||||
toAppend = &fSymbols->fWideDayPeriods[value];
|
||||
} else { // count == 5
|
||||
toAppend = &fSymbols->fNarrowDayPeriods[value];
|
||||
}
|
||||
}
|
||||
|
||||
// toAppend is NULL if time isn't exactly midnight or noon (as displayed).
|
||||
// toAppend is bogus if time is midnight or noon, but no localized string exists.
|
||||
// In either case, fall back to am/pm.
|
||||
if (toAppend == NULL || toAppend->isBogus()) {
|
||||
// Reformat with identical arguments except ch, now changed to 'a'.
|
||||
subFormat(appendTo, 0x61, count, capitalizationContext, fieldNum,
|
||||
handler, cal, mutableNFs, status);
|
||||
} else {
|
||||
appendTo += *toAppend;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case UDAT_FLEXIBLE_DAY_PERIOD_FIELD:
|
||||
{
|
||||
// TODO: Maybe fetch the DayperiodRules during initialization (instead of at the first
|
||||
// loading of an instance) if a relevant pattern character (b or B) is used.
|
||||
const DayPeriodRules *ruleSet = DayPeriodRules::getInstance(this->getSmpFmtLocale(), status);
|
||||
if (U_FAILURE(status)) {
|
||||
// Data doesn't conform to spec, therefore loading failed.
|
||||
break;
|
||||
}
|
||||
if (ruleSet == NULL) {
|
||||
// Data doesn't exist for the locale we're looking for.
|
||||
// Falling back to am/pm.
|
||||
subFormat(appendTo, 0x61, count, capitalizationContext, fieldNum,
|
||||
handler, cal, mutableNFs, status);
|
||||
break;
|
||||
}
|
||||
|
||||
// Get current display time.
|
||||
int32_t hour = cal.get(UCAL_HOUR_OF_DAY, status);
|
||||
int32_t minute = 0;
|
||||
if (fHasMinute) {
|
||||
minute = cal.get(UCAL_MINUTE, status);
|
||||
}
|
||||
int32_t second = 0;
|
||||
if (fHasSecond) {
|
||||
second = cal.get(UCAL_SECOND, status);
|
||||
}
|
||||
|
||||
// Determine day period.
|
||||
DayPeriodRules::DayPeriod periodType;
|
||||
if (hour == 0 && minute == 0 && second == 0 && ruleSet->hasMidnight()) {
|
||||
periodType = DayPeriodRules::DAYPERIOD_MIDNIGHT;
|
||||
} else if (hour == 12 && minute == 0 && second == 0 && ruleSet->hasNoon()) {
|
||||
periodType = DayPeriodRules::DAYPERIOD_NOON;
|
||||
} else {
|
||||
periodType = ruleSet->getDayPeriodForHour(hour);
|
||||
}
|
||||
|
||||
// Rule set exists, therefore periodType can't be UNKNOWN.
|
||||
// Get localized string.
|
||||
U_ASSERT(periodType != DayPeriodRules::DAYPERIOD_UNKNOWN);
|
||||
UnicodeString *toAppend = NULL;
|
||||
|
||||
int32_t index = (int32_t)periodType;
|
||||
if (count <= 3) {
|
||||
toAppend = &fSymbols->fAbbreviatedDayPeriods[index]; // i.e. short
|
||||
} else if (count == 4 || count > 5) {
|
||||
toAppend = &fSymbols->fWideDayPeriods[index];
|
||||
} else { // count == 5
|
||||
toAppend = &fSymbols->fNarrowDayPeriods[index];
|
||||
}
|
||||
|
||||
// Fallback schedule:
|
||||
// Midnight/Noon -> General Periods -> AM/PM.
|
||||
|
||||
// Midnight/Noon -> General Periods.
|
||||
if (toAppend->isBogus() &&
|
||||
(periodType == DayPeriodRules::DAYPERIOD_MIDNIGHT || periodType == DayPeriodRules::DAYPERIOD_NOON)) {
|
||||
periodType = ruleSet->getDayPeriodForHour(hour);
|
||||
index = (int32_t)periodType;
|
||||
|
||||
if (count <= 3) {
|
||||
toAppend = &fSymbols->fAbbreviatedDayPeriods[index]; // i.e. short
|
||||
} else if (count == 4 || count > 5) {
|
||||
toAppend = &fSymbols->fWideDayPeriods[index];
|
||||
} else { // count == 5
|
||||
toAppend = &fSymbols->fNarrowDayPeriods[index];
|
||||
}
|
||||
}
|
||||
|
||||
// General Periods -> AM/PM.
|
||||
if (toAppend->isBogus()) {
|
||||
subFormat(appendTo, 0x61, count, capitalizationContext, fieldNum,
|
||||
handler, cal, mutableNFs, status);
|
||||
}
|
||||
else {
|
||||
appendTo += *toAppend;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
// all of the other pattern symbols can be formatted as simple numbers with
|
||||
// appropriate zero padding
|
||||
|
@ -1830,7 +1960,7 @@ void SimpleDateFormat::adoptNumberFormat(NumberFormat *formatToAdopt) {
|
|||
fixNumberFormatForDates(*formatToAdopt);
|
||||
delete fNumberFormat;
|
||||
fNumberFormat = formatToAdopt;
|
||||
|
||||
|
||||
// We successfully set the default number format. Now delete the overrides
|
||||
// (can't fail).
|
||||
if (fSharedNumberFormatters) {
|
||||
|
@ -1956,6 +2086,9 @@ SimpleDateFormat::parse(const UnicodeString& text, Calendar& cal, ParsePosition&
|
|||
}
|
||||
int32_t start = pos;
|
||||
|
||||
// Hold the day period until everything else is parsed, because we need
|
||||
// the hour to interpret time correctly.
|
||||
int32_t dayPeriodInt = -1;
|
||||
|
||||
UBool ambiguousYear[] = { FALSE };
|
||||
int32_t saveHebrewMonth = -1;
|
||||
|
@ -1994,7 +2127,7 @@ SimpleDateFormat::parse(const UnicodeString& text, Calendar& cal, ParsePosition&
|
|||
goto ExitParse;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (fSymbols->fLeapMonthPatterns != NULL && fSymbols->fLeapMonthPatternsCount >= DateFormatSymbols::kMonthPatternsCount) {
|
||||
numericLeapMonthFormatter = new MessageFormat(fSymbols->fLeapMonthPatterns[DateFormatSymbols::kLeapMonthPatternNumeric], fLocale, status);
|
||||
if (numericLeapMonthFormatter == NULL) {
|
||||
|
@ -2070,7 +2203,7 @@ SimpleDateFormat::parse(const UnicodeString& text, Calendar& cal, ParsePosition&
|
|||
// fields.
|
||||
else if (ch != 0x6C) { // pattern char 'l' (SMALL LETTER L) just gets ignored
|
||||
int32_t s = subParse(text, pos, ch, count,
|
||||
FALSE, TRUE, ambiguousYear, saveHebrewMonth, *workCal, i, numericLeapMonthFormatter, &tzTimeType, mutableNFs);
|
||||
FALSE, TRUE, ambiguousYear, saveHebrewMonth, *workCal, i, numericLeapMonthFormatter, &tzTimeType, mutableNFs, &dayPeriodInt);
|
||||
|
||||
if (s == -pos-1) {
|
||||
// era not present, in special cases allow this to continue
|
||||
|
@ -2106,7 +2239,7 @@ SimpleDateFormat::parse(const UnicodeString& text, Calendar& cal, ParsePosition&
|
|||
else {
|
||||
|
||||
abutPat = -1; // End of any abutting fields
|
||||
|
||||
|
||||
if (! matchLiterals(fPattern, i, text, pos, getBooleanAttribute(UDAT_PARSE_ALLOW_WHITESPACE, status), getBooleanAttribute(UDAT_PARSE_PARTIAL_LITERAL_MATCH, status), isLenient())) {
|
||||
status = U_PARSE_ERROR;
|
||||
goto ExitParse;
|
||||
|
@ -2122,6 +2255,76 @@ SimpleDateFormat::parse(const UnicodeString& text, Calendar& cal, ParsePosition&
|
|||
}
|
||||
}
|
||||
|
||||
// If dayPeriod is set, use it in conjunction with hour-of-day to determine am/pm.
|
||||
if (dayPeriodInt >= 0) {
|
||||
DayPeriodRules::DayPeriod dayPeriod = (DayPeriodRules::DayPeriod)dayPeriodInt;
|
||||
const DayPeriodRules *ruleSet = DayPeriodRules::getInstance(this->getSmpFmtLocale(), status);
|
||||
|
||||
if (!cal.isSet(UCAL_HOUR) && !cal.isSet(UCAL_HOUR_OF_DAY)) {
|
||||
// If hour is not set, set time to the midpoint of current day period, overwriting
|
||||
// minutes if it's set.
|
||||
double midPoint = ruleSet->getMidPointForDayPeriod(dayPeriod, status);
|
||||
|
||||
// If we can't get midPoint we do nothing.
|
||||
if (U_SUCCESS(status)) {
|
||||
// Truncate midPoint toward zero to get the hour.
|
||||
// Any leftover means it was a half-hour.
|
||||
int32_t midPointHour = (int32_t) midPoint;
|
||||
int32_t midPointMinute = (midPoint - midPointHour) > 0 ? 30 : 0;
|
||||
|
||||
// No need to set am/pm because hour-of-day is set last therefore takes precedence.
|
||||
cal.set(UCAL_HOUR_OF_DAY, midPointHour);
|
||||
cal.set(UCAL_MINUTE, midPointMinute);
|
||||
}
|
||||
} else {
|
||||
int hourOfDay;
|
||||
|
||||
if (cal.isSet(UCAL_HOUR_OF_DAY)) { // Hour is parsed in 24-hour format.
|
||||
hourOfDay = cal.get(UCAL_HOUR_OF_DAY, status);
|
||||
} else { // Hour is parsed in 12-hour format.
|
||||
hourOfDay = cal.get(UCAL_HOUR, status);
|
||||
// cal.get() turns 12 to 0 for 12-hour time; change 0 to 12
|
||||
// so 0 unambiguously means a 24-hour time from above.
|
||||
if (hourOfDay == 0) { hourOfDay = 12; }
|
||||
}
|
||||
assert(0 <= hourOfDay && hourOfDay <= 23);
|
||||
|
||||
|
||||
// If hour-of-day is 0 or 13 thru 23 then input time in unambiguously in 24-hour format.
|
||||
if (hourOfDay == 0 || (13 <= hourOfDay && hourOfDay <= 23)) {
|
||||
// Make hour-of-day take precedence over (hour + am/pm) by setting it again.
|
||||
cal.set(UCAL_HOUR_OF_DAY, hourOfDay);
|
||||
} else {
|
||||
// We have a 12-hour time and need to choose between am and pm.
|
||||
// Behave as if dayPeriod spanned 6 hours each way from its center point.
|
||||
// This will parse correctly for consistent time + period (e.g. 10 at night) as
|
||||
// well as provide a reasonable recovery for inconsistent time + period (e.g.
|
||||
// 9 in the afternoon).
|
||||
|
||||
// Assume current time is in the AM.
|
||||
// - Change 12 back to 0 for easier handling of 12am.
|
||||
// - Append minutes as fractional hours because e.g. 8:15 and 8:45 could be parsed
|
||||
// into different half-days if center of dayPeriod is at 14:30.
|
||||
// - cal.get(MINUTE) will return 0 if MINUTE is unset, which works.
|
||||
if (hourOfDay == 12) { hourOfDay = 0; }
|
||||
double currentHour = hourOfDay + (cal.get(UCAL_MINUTE, status)) / 60.0;
|
||||
double midPointHour = ruleSet->getMidPointForDayPeriod(dayPeriod, status);
|
||||
|
||||
if (U_SUCCESS(status)) {
|
||||
double hoursAheadMidPoint = currentHour - midPointHour;
|
||||
|
||||
// Assume current time is in the AM.
|
||||
if (-6 <= hoursAheadMidPoint && hoursAheadMidPoint < 6) {
|
||||
// Assumption holds; set time as such.
|
||||
cal.set(UCAL_AM_PM, 0);
|
||||
} else {
|
||||
cal.set(UCAL_AM_PM, 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// At this point the fields of Calendar have been set. Calendar
|
||||
// will fill in default values for missing fields when the time
|
||||
// is computed.
|
||||
|
@ -2346,6 +2549,29 @@ int32_t SimpleDateFormat::matchQuarterString(const UnicodeString& text,
|
|||
return -start;
|
||||
}
|
||||
|
||||
int32_t SimpleDateFormat::matchDayPeriodStrings(const UnicodeString& text, int32_t start,
|
||||
const UnicodeString* data, int32_t dataCount,
|
||||
int32_t &dayPeriod) const
|
||||
{
|
||||
|
||||
int32_t bestMatchLength = 0, bestMatch = -1;
|
||||
|
||||
for (int32_t i = 0; i < dataCount; ++i) {
|
||||
int32_t matchLength = 0;
|
||||
if ((matchLength = matchStringWithOptionalDot(text, start, data[i])) > bestMatchLength) {
|
||||
bestMatchLength = matchLength;
|
||||
bestMatch = i;
|
||||
}
|
||||
}
|
||||
|
||||
if (bestMatch >= 0) {
|
||||
dayPeriod = bestMatch;
|
||||
return start + bestMatchLength;
|
||||
}
|
||||
|
||||
return -start;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
UBool SimpleDateFormat::matchLiterals(const UnicodeString &pattern,
|
||||
int32_t &patternOffset,
|
||||
|
@ -2356,17 +2582,17 @@ UBool SimpleDateFormat::matchLiterals(const UnicodeString &pattern,
|
|||
UBool oldLeniency)
|
||||
{
|
||||
UBool inQuote = FALSE;
|
||||
UnicodeString literal;
|
||||
UnicodeString literal;
|
||||
int32_t i = patternOffset;
|
||||
|
||||
// scan pattern looking for contiguous literal characters
|
||||
for ( ; i < pattern.length(); i += 1) {
|
||||
UChar ch = pattern.charAt(i);
|
||||
|
||||
|
||||
if (!inQuote && isSyntaxChar(ch)) {
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
if (ch == QUOTE) {
|
||||
// Match a quote literal ('') inside OR outside of quotes
|
||||
if ((i + 1) < pattern.length() && pattern.charAt(i + 1) == QUOTE) {
|
||||
|
@ -2376,47 +2602,47 @@ UBool SimpleDateFormat::matchLiterals(const UnicodeString &pattern,
|
|||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
literal += ch;
|
||||
}
|
||||
|
||||
|
||||
// at this point, literal contains the literal text
|
||||
// and i is the index of the next non-literal pattern character.
|
||||
int32_t p;
|
||||
int32_t t = textOffset;
|
||||
|
||||
|
||||
if (whitespaceLenient) {
|
||||
// trim leading, trailing whitespace from
|
||||
// the literal text
|
||||
literal.trim();
|
||||
|
||||
|
||||
// ignore any leading whitespace in the text
|
||||
while (t < text.length() && u_isWhitespace(text.charAt(t))) {
|
||||
t += 1;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
for (p = 0; p < literal.length() && t < text.length();) {
|
||||
UBool needWhitespace = FALSE;
|
||||
|
||||
|
||||
while (p < literal.length() && PatternProps::isWhiteSpace(literal.charAt(p))) {
|
||||
needWhitespace = TRUE;
|
||||
p += 1;
|
||||
}
|
||||
|
||||
|
||||
if (needWhitespace) {
|
||||
int32_t tStart = t;
|
||||
|
||||
|
||||
while (t < text.length()) {
|
||||
UChar tch = text.charAt(t);
|
||||
|
||||
|
||||
if (!u_isUWhiteSpace(tch) && !PatternProps::isWhiteSpace(tch)) {
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
t += 1;
|
||||
}
|
||||
|
||||
|
||||
// TODO: should we require internal spaces
|
||||
// in lenient mode? (There won't be any
|
||||
// leading or trailing spaces)
|
||||
|
@ -2425,7 +2651,7 @@ UBool SimpleDateFormat::matchLiterals(const UnicodeString &pattern,
|
|||
// an error in strict mode
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
|
||||
// In strict mode, this run of whitespace
|
||||
// may have been at the end.
|
||||
if (p >= literal.length()) {
|
||||
|
@ -2443,26 +2669,26 @@ UBool SimpleDateFormat::matchLiterals(const UnicodeString &pattern,
|
|||
++t;
|
||||
continue; // Do not update p.
|
||||
}
|
||||
// if it is actual whitespace and we're whitespace lenient it's OK
|
||||
|
||||
// if it is actual whitespace and we're whitespace lenient it's OK
|
||||
|
||||
UChar wsc = text.charAt(t);
|
||||
if(PatternProps::isWhiteSpace(wsc)) {
|
||||
// Lenient mode and it's just whitespace we skip it
|
||||
++t;
|
||||
continue; // Do not update p.
|
||||
}
|
||||
}
|
||||
}
|
||||
// hack around oldleniency being a bit of a catch-all bucket and we're just adding support specifically for paritial matches
|
||||
if(partialMatchLenient && oldLeniency) {
|
||||
if(partialMatchLenient && oldLeniency) {
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
++p;
|
||||
++t;
|
||||
}
|
||||
|
||||
|
||||
// At this point if we're in strict mode we have a complete match.
|
||||
// If we're in lenient mode we may have a partial match, or no
|
||||
// match at all.
|
||||
|
@ -2474,20 +2700,20 @@ UBool SimpleDateFormat::matchLiterals(const UnicodeString &pattern,
|
|||
if (patternCharIndex != UDAT_FIELD_COUNT) {
|
||||
ignorables = SimpleDateFormatStaticSets::getIgnorables(patternCharIndex);
|
||||
}
|
||||
|
||||
|
||||
for (t = textOffset; t < text.length(); t += 1) {
|
||||
UChar ch = text.charAt(t);
|
||||
|
||||
|
||||
if (ignorables == NULL || !ignorables->contains(ch)) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// if we get here, we've got a complete match.
|
||||
patternOffset = i - 1;
|
||||
textOffset = t;
|
||||
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
@ -2595,7 +2821,8 @@ SimpleDateFormat::set2DigitYearStart(UDate d, UErrorCode& status)
|
|||
*/
|
||||
int32_t SimpleDateFormat::subParse(const UnicodeString& text, int32_t& start, UChar ch, int32_t count,
|
||||
UBool obeyCount, UBool allowNegative, UBool ambiguousYear[], int32_t& saveHebrewMonth, Calendar& cal,
|
||||
int32_t patLoc, MessageFormat * numericLeapMonthFormatter, UTimeZoneFormatTimeType *tzTimeType, SimpleDateFormatMutableNFs &mutableNFs) const
|
||||
int32_t patLoc, MessageFormat * numericLeapMonthFormatter, UTimeZoneFormatTimeType *tzTimeType, SimpleDateFormatMutableNFs &mutableNFs,
|
||||
int32_t *dayPeriod) const
|
||||
{
|
||||
Formattable number;
|
||||
int32_t value = 0;
|
||||
|
@ -2702,7 +2929,7 @@ int32_t SimpleDateFormat::subParse(const UnicodeString& text, int32_t& start, UC
|
|||
if (txtLoc > parseStart) {
|
||||
value = number.getLong();
|
||||
gotNumber = TRUE;
|
||||
|
||||
|
||||
// suffix processing
|
||||
if (value < 0 ) {
|
||||
txtLoc = checkIntSuffix(text, txtLoc, patLoc+1, TRUE);
|
||||
|
@ -2725,7 +2952,7 @@ int32_t SimpleDateFormat::subParse(const UnicodeString& text, int32_t& start, UC
|
|||
pos.setIndex(txtLoc);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Make sure that we got a number if
|
||||
// we want one, and didn't get one
|
||||
// if we don't want one.
|
||||
|
@ -2738,9 +2965,9 @@ int32_t SimpleDateFormat::subParse(const UnicodeString& text, int32_t& start, UC
|
|||
if (value < 0 || value > 24) {
|
||||
return -start;
|
||||
}
|
||||
|
||||
|
||||
// fall through to gotNumber check
|
||||
|
||||
|
||||
case UDAT_YEAR_FIELD:
|
||||
case UDAT_YEAR_WOY_FIELD:
|
||||
case UDAT_FRACTIONAL_SECOND_FIELD:
|
||||
|
@ -2748,9 +2975,9 @@ int32_t SimpleDateFormat::subParse(const UnicodeString& text, int32_t& start, UC
|
|||
if (! gotNumber) {
|
||||
return -start;
|
||||
}
|
||||
|
||||
|
||||
break;
|
||||
|
||||
|
||||
default:
|
||||
// we check the rest of the fields below.
|
||||
break;
|
||||
|
@ -2929,9 +3156,9 @@ int32_t SimpleDateFormat::subParse(const UnicodeString& text, int32_t& start, UC
|
|||
// [We computed 'value' above.]
|
||||
if (value == cal.getMaximum(UCAL_HOUR_OF_DAY) + 1)
|
||||
value = 0;
|
||||
|
||||
|
||||
// fall through to set field
|
||||
|
||||
|
||||
case UDAT_HOUR_OF_DAY0_FIELD:
|
||||
cal.set(UCAL_HOUR_OF_DAY, value);
|
||||
return pos.getIndex();
|
||||
|
@ -3054,9 +3281,9 @@ int32_t SimpleDateFormat::subParse(const UnicodeString& text, int32_t& start, UC
|
|||
// [We computed 'value' above.]
|
||||
if (value == cal.getLeastMaximum(UCAL_HOUR)+1)
|
||||
value = 0;
|
||||
|
||||
|
||||
// fall through to set field
|
||||
|
||||
|
||||
case UDAT_HOUR0_FIELD:
|
||||
cal.set(UCAL_HOUR, value);
|
||||
return pos.getIndex();
|
||||
|
@ -3246,7 +3473,7 @@ int32_t SimpleDateFormat::subParse(const UnicodeString& text, int32_t& start, UC
|
|||
}
|
||||
// currently no pattern character is defined for UDAT_TIME_SEPARATOR_FIELD
|
||||
// so we should not get here. Leave support in for future definition.
|
||||
case UDAT_TIME_SEPARATOR_FIELD: //
|
||||
case UDAT_TIME_SEPARATOR_FIELD:
|
||||
{
|
||||
static const UChar def_sep = DateFormatSymbols::DEFAULT_TIME_SEPARATOR;
|
||||
static const UChar alt_sep = DateFormatSymbols::ALTERNATE_TIME_SEPARATOR;
|
||||
|
@ -3269,6 +3496,70 @@ int32_t SimpleDateFormat::subParse(const UnicodeString& text, int32_t& start, UC
|
|||
return matchString(text, start, UCAL_FIELD_COUNT /* => nothing to set */, data, count, NULL, cal);
|
||||
}
|
||||
|
||||
case UDAT_AM_PM_MIDNIGHT_NOON_FIELD:
|
||||
{
|
||||
U_ASSERT(dayPeriod != NULL);
|
||||
int32_t ampmStart = subParse(text, start, 0x61, count,
|
||||
obeyCount, allowNegative, ambiguousYear, saveHebrewMonth, cal,
|
||||
patLoc, numericLeapMonthFormatter, tzTimeType, mutableNFs);
|
||||
|
||||
if (ampmStart > 0) {
|
||||
return ampmStart;
|
||||
} else {
|
||||
int32_t newStart = 0;
|
||||
|
||||
// Only match the first two strings from the day period strings array.
|
||||
if (getBooleanAttribute(UDAT_PARSE_MULTIPLE_PATTERNS_FOR_MATCH, status) || count == 3) {
|
||||
if ((newStart = matchDayPeriodStrings(text, start, fSymbols->fAbbreviatedDayPeriods,
|
||||
2, *dayPeriod)) > 0) {
|
||||
return newStart;
|
||||
}
|
||||
}
|
||||
if (getBooleanAttribute(UDAT_PARSE_MULTIPLE_PATTERNS_FOR_MATCH, status) || count == 5) {
|
||||
if ((newStart = matchDayPeriodStrings(text, start, fSymbols->fNarrowDayPeriods,
|
||||
2, *dayPeriod)) > 0) {
|
||||
return newStart;
|
||||
}
|
||||
}
|
||||
// count == 4, but allow other counts
|
||||
if (getBooleanAttribute(UDAT_PARSE_MULTIPLE_PATTERNS_FOR_MATCH, status)) {
|
||||
if ((newStart = matchDayPeriodStrings(text, start, fSymbols->fWideDayPeriods,
|
||||
2, *dayPeriod)) > 0) {
|
||||
return newStart;
|
||||
}
|
||||
}
|
||||
|
||||
return -start;
|
||||
}
|
||||
}
|
||||
|
||||
case UDAT_FLEXIBLE_DAY_PERIOD_FIELD:
|
||||
{
|
||||
U_ASSERT(dayPeriod != NULL);
|
||||
int32_t newStart = 0;
|
||||
|
||||
if (getBooleanAttribute(UDAT_PARSE_MULTIPLE_PATTERNS_FOR_MATCH, status) || count == 3) {
|
||||
if ((newStart = matchDayPeriodStrings(text, start, fSymbols->fAbbreviatedDayPeriods,
|
||||
fSymbols->fAbbreviatedDayPeriodsCount, *dayPeriod)) > 0) {
|
||||
return newStart;
|
||||
}
|
||||
}
|
||||
if (getBooleanAttribute(UDAT_PARSE_MULTIPLE_PATTERNS_FOR_MATCH, status) || count == 5) {
|
||||
if ((newStart = matchDayPeriodStrings(text, start, fSymbols->fNarrowDayPeriods,
|
||||
fSymbols->fNarrowDayPeriodsCount, *dayPeriod)) > 0) {
|
||||
return newStart;
|
||||
}
|
||||
}
|
||||
if (getBooleanAttribute(UDAT_PARSE_MULTIPLE_PATTERNS_FOR_MATCH, status) || count == 4) {
|
||||
if ((newStart = matchDayPeriodStrings(text, start, fSymbols->fWideDayPeriods,
|
||||
fSymbols->fWideDayPeriodsCount, *dayPeriod)) > 0) {
|
||||
return newStart;
|
||||
}
|
||||
}
|
||||
|
||||
return -start;
|
||||
}
|
||||
|
||||
default:
|
||||
// Handle "generic" fields
|
||||
// this is now handled below, outside the switch block
|
||||
|
@ -3408,7 +3699,7 @@ void SimpleDateFormat::translatePattern(const UnicodeString& originalPattern,
|
|||
UErrorCode& status)
|
||||
{
|
||||
// run through the pattern and convert any pattern symbols from the version
|
||||
// in "from" to the corresponding character ion "to". This code takes
|
||||
// in "from" to the corresponding character in "to". This code takes
|
||||
// quoted strings into account (it doesn't try to translate them), and it signals
|
||||
// an error if a particular "pattern character" doesn't appear in "from".
|
||||
// Depending on the values of "from" and "to" this can convert from generic
|
||||
|
@ -3472,6 +3763,7 @@ void
|
|||
SimpleDateFormat::applyPattern(const UnicodeString& pattern)
|
||||
{
|
||||
fPattern = pattern;
|
||||
parsePattern();
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
|
@ -3799,6 +4091,28 @@ SimpleDateFormat::tzFormat() const {
|
|||
return fTimeZoneFormat;
|
||||
}
|
||||
|
||||
void SimpleDateFormat::parsePattern() {
|
||||
fHasMinute = FALSE;
|
||||
fHasSecond = FALSE;
|
||||
|
||||
int len = fPattern.length();
|
||||
UBool inQuote = FALSE;
|
||||
for (int32_t i = 0; i < len; ++i) {
|
||||
UChar ch = fPattern[i];
|
||||
if (ch == QUOTE) {
|
||||
inQuote = !inQuote;
|
||||
}
|
||||
if (!inQuote) {
|
||||
if (ch == 0x6D) { // 0x6D == 'm'
|
||||
fHasMinute = TRUE;
|
||||
}
|
||||
if (ch == 0x73) { // 0x73 == 's'
|
||||
fHasSecond = TRUE;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
U_NAMESPACE_END
|
||||
|
||||
#endif /* #if !UCONFIG_NO_FORMATTING */
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
* Copyright (C) 2001-2016, International Business Machines
|
||||
* Corporation and others. All Rights Reserved.
|
||||
******************************************************************************
|
||||
* file name: ucln_cmn.h
|
||||
* file name: ucln_in.h
|
||||
* encoding: US-ASCII
|
||||
* tab size: 8 (not used)
|
||||
* indentation:4
|
||||
|
@ -42,6 +42,7 @@ typedef enum ECleanupI18NType {
|
|||
UCLN_I18N_TIMEZONE,
|
||||
UCLN_I18N_DECFMT,
|
||||
UCLN_I18N_NUMFMT,
|
||||
UCLN_I18N_DAYPERIODRULES,
|
||||
UCLN_I18N_SMPDTFMT,
|
||||
UCLN_I18N_USEARCH,
|
||||
UCLN_I18N_COLLATOR,
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/*
|
||||
/*
|
||||
********************************************************************************
|
||||
* Copyright (C) 1997-2016, International Business Machines
|
||||
* Corporation and others. All Rights Reserved.
|
||||
|
@ -14,10 +14,10 @@
|
|||
* Changed to match C++ conventions
|
||||
********************************************************************************
|
||||
*/
|
||||
|
||||
|
||||
#ifndef DTFMTSYM_H
|
||||
#define DTFMTSYM_H
|
||||
|
||||
|
||||
#include "unicode/utypes.h"
|
||||
|
||||
#if !UCONFIG_NO_FORMATTING
|
||||
|
@ -29,7 +29,7 @@
|
|||
#include "unicode/ures.h"
|
||||
|
||||
/**
|
||||
* \file
|
||||
* \file
|
||||
* \brief C++ API: Symbols for formatting dates.
|
||||
*/
|
||||
|
||||
|
@ -115,7 +115,7 @@ public:
|
|||
* data for the default locale, it will return a last-resort object
|
||||
* based on hard-coded strings.
|
||||
*
|
||||
* @param type Type of calendar (as returned by Calendar::getType).
|
||||
* @param type Type of calendar (as returned by Calendar::getType).
|
||||
* Will be used to access the correct set of strings.
|
||||
* (NULL or empty string defaults to "gregorian".)
|
||||
* @param status Status code. Failure
|
||||
|
@ -130,7 +130,7 @@ public:
|
|||
* resources for the given locale, in the default calendar (Gregorian).
|
||||
*
|
||||
* @param locale Locale to load format data from.
|
||||
* @param type Type of calendar (as returned by Calendar::getType).
|
||||
* @param type Type of calendar (as returned by Calendar::getType).
|
||||
* Will be used to access the correct set of strings.
|
||||
* (NULL or empty string defaults to "gregorian".)
|
||||
* @param status Status code. Failure
|
||||
|
@ -850,6 +850,42 @@ private:
|
|||
*/
|
||||
UBool fCapitalization[kCapContextUsageTypeCount][2];
|
||||
|
||||
/**
|
||||
* Abbreviated (== short) day period strings.
|
||||
*/
|
||||
UnicodeString *fAbbreviatedDayPeriods;
|
||||
int32_t fAbbreviatedDayPeriodsCount;
|
||||
|
||||
/**
|
||||
* Wide day period strings.
|
||||
*/
|
||||
UnicodeString *fWideDayPeriods;
|
||||
int32_t fWideDayPeriodsCount;
|
||||
|
||||
/**
|
||||
* Narrow day period strings.
|
||||
*/
|
||||
UnicodeString *fNarrowDayPeriods;
|
||||
int32_t fNarrowDayPeriodsCount;
|
||||
|
||||
/**
|
||||
* Stand-alone abbreviated (== short) day period strings.
|
||||
*/
|
||||
UnicodeString *fStandaloneAbbreviatedDayPeriods;
|
||||
int32_t fStandaloneAbbreviatedDayPeriodsCount;
|
||||
|
||||
/**
|
||||
* Stand-alone wide day period strings.
|
||||
*/
|
||||
UnicodeString *fStandaloneWideDayPeriods;
|
||||
int32_t fStandaloneWideDayPeriodsCount;
|
||||
|
||||
/**
|
||||
* Stand-alone narrow day period strings.
|
||||
*/
|
||||
UnicodeString *fStandaloneNarrowDayPeriods;
|
||||
int32_t fStandaloneNarrowDayPeriodsCount;
|
||||
|
||||
private:
|
||||
/** valid/actual locale information
|
||||
* these are always ICU locales, so the length should not be a problem
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (C) 1997-2015, International Business Machines Corporation and
|
||||
* Copyright (C) 1997-2016, International Business Machines Corporation and
|
||||
* others. All Rights Reserved.
|
||||
*******************************************************************************
|
||||
*
|
||||
|
@ -89,7 +89,7 @@ class SimpleDateFormatMutableNFs;
|
|||
* <td style="text-align: center" rowspan="3">G</td>
|
||||
* <td style="text-align: center">1..3</td>
|
||||
* <td>AD</td>
|
||||
* <td rowspan="3">Era - Replaced with the Era string for the current date. One to three letters for the
|
||||
* <td rowspan="3">Era - Replaced with the Era string for the current date. One to three letters for the
|
||||
* abbreviated form, four letters for the long (wide) form, five for the narrow form.</td>
|
||||
* </tr>
|
||||
* <tr>
|
||||
|
@ -218,7 +218,7 @@ class SimpleDateFormatMutableNFs;
|
|||
* <td rowspan="3" style="text-align: center">q</td>
|
||||
* <td style="text-align: center">1..2</td>
|
||||
* <td>02</td>
|
||||
* <td rowspan="3"><b>Stand-Alone</b> Quarter - Use one or two for the numerical quarter, three for the abbreviation,
|
||||
* <td rowspan="3"><b>Stand-Alone</b> Quarter - Use one or two for the numerical quarter, three for the abbreviation,
|
||||
* or four for the full name (five for the narrow name is not yet supported).</td>
|
||||
* </tr>
|
||||
* <tr>
|
||||
|
@ -254,7 +254,7 @@ class SimpleDateFormatMutableNFs;
|
|||
* <td rowspan="4" style="text-align: center">L</td>
|
||||
* <td style="text-align: center">1..2</td>
|
||||
* <td>09</td>
|
||||
* <td rowspan="4"><b>Stand-Alone</b> Month - Use one or two for the numerical month, three for the abbreviation,
|
||||
* <td rowspan="4"><b>Stand-Alone</b> Month - Use one or two for the numerical month, three for the abbreviation,
|
||||
* four for the full (wide) name, or 5 for the narrow name. With two ("LL"), the month number is zero-padded if
|
||||
* necessary (e.g. "08")</td>
|
||||
* </tr>
|
||||
|
@ -310,7 +310,7 @@ class SimpleDateFormatMutableNFs;
|
|||
* <td>2451334</td>
|
||||
* <td>Modified Julian day. This is different from the conventional Julian day number in two regards.
|
||||
* First, it demarcates days at local zone midnight, rather than noon GMT. Second, it is a local number;
|
||||
* that is, it depends on the local time zone. It can be thought of as a single number that encompasses
|
||||
* that is, it depends on the local time zone. It can be thought of as a single number that encompasses
|
||||
* all the date-related fields.</td>
|
||||
* </tr>
|
||||
* <tr>
|
||||
|
@ -319,7 +319,7 @@ class SimpleDateFormatMutableNFs;
|
|||
* <td rowspan="4" style="text-align: center">E</td>
|
||||
* <td style="text-align: center">1..3</td>
|
||||
* <td>Tue</td>
|
||||
* <td rowspan="4">Day of week - Use one through three letters for the short day, four for the full (wide) name,
|
||||
* <td rowspan="4">Day of week - Use one through three letters for the short day, four for the full (wide) name,
|
||||
* five for the narrow name, or six for the short name.</td>
|
||||
* </tr>
|
||||
* <tr>
|
||||
|
@ -539,7 +539,7 @@ class SimpleDateFormatMutableNFs;
|
|||
* <td>The <i>generic location format</i>.
|
||||
* Where that is unavailable, falls back to the <i>long localized GMT format</i> ("OOOO";
|
||||
* Note: Fallback is only necessary with a GMT-style Time Zone ID, like Etc/GMT-830.)<br>
|
||||
* This is especially useful when presenting possible timezone choices for user selection,
|
||||
* This is especially useful when presenting possible timezone choices for user selection,
|
||||
* since the naming is more uniform than the "v" format.</td>
|
||||
* </tr>
|
||||
* <tr>
|
||||
|
@ -1126,15 +1126,15 @@ public:
|
|||
* @param value The UDisplayContext value to set.
|
||||
* @param status Input/output status. If at entry this indicates a failure
|
||||
* status, the function will do nothing; otherwise this will be
|
||||
* updated with any new status from the function.
|
||||
* updated with any new status from the function.
|
||||
* @stable ICU 53
|
||||
*/
|
||||
virtual void setContext(UDisplayContext value, UErrorCode& status);
|
||||
|
||||
|
||||
/**
|
||||
* Overrides base class method and
|
||||
* This method clears per field NumberFormat instances
|
||||
* previously set by {@see adoptNumberFormat(const UnicodeString&, NumberFormat*, UErrorCode)}
|
||||
* This method clears per field NumberFormat instances
|
||||
* previously set by {@see adoptNumberFormat(const UnicodeString&, NumberFormat*, UErrorCode)}
|
||||
* @param adoptNF the NumbeferFormat used
|
||||
* @stable ICU 54
|
||||
*/
|
||||
|
@ -1144,7 +1144,7 @@ public:
|
|||
* Allow the user to set the NumberFormat for several fields
|
||||
* It can be a single field like: "y"(year) or "M"(month)
|
||||
* It can be several field combined together: "yM"(year and month)
|
||||
* Note:
|
||||
* Note:
|
||||
* 1 symbol field is enough for multiple symbol field (so "y" will override "yy", "yyy")
|
||||
* If the field is not numeric, then override has no effect (like "MMM" will use abbreviation, not numerical field)
|
||||
* Per field NumberFormat can also be cleared in {@see DateFormat::setNumberFormat(const NumberFormat& newNumberFormat)}
|
||||
|
@ -1269,7 +1269,7 @@ private:
|
|||
* having a number of digits between "minDigits" and
|
||||
* "maxDigits". Uses the DateFormat's NumberFormat.
|
||||
*
|
||||
* @param currentNumberFormat
|
||||
* @param currentNumberFormat
|
||||
* @param appendTo Output parameter to receive result.
|
||||
* Formatted number is appended to existing contents.
|
||||
* @param value Value to format.
|
||||
|
@ -1357,7 +1357,14 @@ private:
|
|||
*/
|
||||
int32_t matchQuarterString(const UnicodeString& text, int32_t start, UCalendarDateFields field,
|
||||
const UnicodeString* stringArray, int32_t stringArrayCount, Calendar& cal) const;
|
||||
|
||||
|
||||
/**
|
||||
* Used by subParse() to match localized day period strings.
|
||||
*/
|
||||
int32_t matchDayPeriodStrings(const UnicodeString& text, int32_t start,
|
||||
const UnicodeString* stringArray, int32_t stringArrayCount,
|
||||
int32_t &dayPeriod) const;
|
||||
|
||||
/**
|
||||
* Private function used by subParse to match literal pattern text.
|
||||
*
|
||||
|
@ -1374,9 +1381,9 @@ private:
|
|||
* @return <code>TRUE</code> if the literal text could be matched, <code>FALSE</code> otherwise.
|
||||
*/
|
||||
static UBool matchLiterals(const UnicodeString &pattern, int32_t &patternOffset,
|
||||
const UnicodeString &text, int32_t &textOffset,
|
||||
const UnicodeString &text, int32_t &textOffset,
|
||||
UBool whitespaceLenient, UBool partialMatchLenient, UBool oldLeniency);
|
||||
|
||||
|
||||
/**
|
||||
* Private member function that converts the parsed date strings into
|
||||
* timeFields. Returns -start (for ParsePosition) if failed.
|
||||
|
@ -1399,7 +1406,8 @@ private:
|
|||
*/
|
||||
int32_t subParse(const UnicodeString& text, int32_t& start, UChar ch, int32_t count,
|
||||
UBool obeyCount, UBool allowNegative, UBool ambiguousYear[], int32_t& saveHebrewMonth, Calendar& cal,
|
||||
int32_t patLoc, MessageFormat * numericLeapMonthFormatter, UTimeZoneFormatTimeType *tzTimeType, SimpleDateFormatMutableNFs &mutableNFs) const;
|
||||
int32_t patLoc, MessageFormat * numericLeapMonthFormatter, UTimeZoneFormatTimeType *tzTimeType, SimpleDateFormatMutableNFs &mutableNFs,
|
||||
int32_t *dayPeriod=NULL) const;
|
||||
|
||||
void parseInt(const UnicodeString& text,
|
||||
Formattable& number,
|
||||
|
@ -1556,6 +1564,14 @@ private:
|
|||
*/
|
||||
UDate fDefaultCenturyStart;
|
||||
|
||||
UBool fHasMinute;
|
||||
UBool fHasSecond;
|
||||
|
||||
/**
|
||||
* Sets fHasMinutes and fHasSeconds.
|
||||
*/
|
||||
void parsePattern();
|
||||
|
||||
/**
|
||||
* See documentation for defaultCenturyStart.
|
||||
*/
|
||||
|
|
|
@ -759,7 +759,21 @@ typedef enum UDateFormatField {
|
|||
* @internal ICU 53
|
||||
*/
|
||||
UDAT_RELATED_YEAR_FIELD = 34,
|
||||
#endif /* U_HIDE_INTERNAL_API */
|
||||
#endif /* U_HIDE_INTERNAL_API */
|
||||
|
||||
/**
|
||||
* FieldPosition selector for 'b' field alignment.
|
||||
* Displays midnight and noon for 12am and 12pm, respectively, if available;
|
||||
* otherwise fall back to AM / PM.
|
||||
* @draft ICU 57
|
||||
*/
|
||||
UDAT_AM_PM_MIDNIGHT_NOON_FIELD = 35,
|
||||
|
||||
/* FieldPosition selector for 'B' field alignment.
|
||||
* Displays flexible day periods, such as "in the morning", if available.
|
||||
* @draft ICU 57
|
||||
*/
|
||||
UDAT_FLEXIBLE_DAY_PERIOD_FIELD = 36,
|
||||
|
||||
/**
|
||||
* FieldPosition and UFieldPosition selector for time separator,
|
||||
|
@ -767,7 +781,8 @@ typedef enum UDateFormatField {
|
|||
* defined for this.
|
||||
* @stable ICU 55
|
||||
*/
|
||||
UDAT_TIME_SEPARATOR_FIELD = 35,
|
||||
UDAT_TIME_SEPARATOR_FIELD = 37,
|
||||
|
||||
|
||||
/**
|
||||
* Number of FieldPosition and UFieldPosition selectors for
|
||||
|
@ -777,7 +792,7 @@ typedef enum UDateFormatField {
|
|||
* in the future.
|
||||
* @stable ICU 3.0
|
||||
*/
|
||||
UDAT_FIELD_COUNT = 36
|
||||
UDAT_FIELD_COUNT = 38
|
||||
|
||||
} UDateFormatField;
|
||||
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/********************************************************************
|
||||
* COPYRIGHT:
|
||||
* COPYRIGHT:
|
||||
* Copyright (c) 1997-2016, International Business Machines Corporation and
|
||||
* others. All Rights Reserved.
|
||||
********************************************************************/
|
||||
|
@ -8,7 +8,7 @@
|
|||
* File CDATTST.C
|
||||
*
|
||||
* Modification History:
|
||||
* Name Description
|
||||
* Name Description
|
||||
* Madhu Katragadda Creation
|
||||
*********************************************************************************
|
||||
*/
|
||||
|
@ -90,24 +90,24 @@ static void TestDateFormat()
|
|||
fr = udat_open(UDAT_FULL, UDAT_DEFAULT, "fr_FR", NULL,0, NULL, 0,&status);
|
||||
if(U_FAILURE(status))
|
||||
{
|
||||
log_data_err("FAIL: error in creating the dateformat using full time style with french locale -> %s (Are you missing data?)\n",
|
||||
log_data_err("FAIL: error in creating the dateformat using full time style with french locale -> %s (Are you missing data?)\n",
|
||||
myErrorName(status) );
|
||||
return;
|
||||
}
|
||||
/* this is supposed to open default date format, but later on it treats it like it is "en_US"
|
||||
/* this is supposed to open default date format, but later on it treats it like it is "en_US"
|
||||
- very bad if you try to run the tests on machine where default locale is NOT "en_US" */
|
||||
/* def = udat_open(UDAT_SHORT, UDAT_SHORT, NULL, NULL, 0, &status); */
|
||||
def = udat_open(UDAT_SHORT, UDAT_SHORT, "en_US", NULL, 0,NULL, 0, &status);
|
||||
if(U_FAILURE(status))
|
||||
{
|
||||
log_err("FAIL: error in creating the dateformat using short date and time style\n %s\n",
|
||||
log_err("FAIL: error in creating the dateformat using short date and time style\n %s\n",
|
||||
myErrorName(status) );
|
||||
return;
|
||||
}
|
||||
it = udat_open(UDAT_DEFAULT, UDAT_MEDIUM, "it_IT", NULL, 0, NULL, 0,&status);
|
||||
if(U_FAILURE(status))
|
||||
{
|
||||
log_err("FAIL: error in creating the dateformat using medium date style with italian locale\n %s\n",
|
||||
log_err("FAIL: error in creating the dateformat using medium date style with italian locale\n %s\n",
|
||||
myErrorName(status) );
|
||||
return;
|
||||
}
|
||||
|
@ -122,20 +122,20 @@ static void TestDateFormat()
|
|||
def1 = udat_open(UDAT_SHORT, UDAT_SHORT, NULL, NULL, 0,NULL, 0, &status);
|
||||
if(U_FAILURE(status))
|
||||
{
|
||||
log_err("FAIL: error in creating the dateformat using short date and time style\n %s\n",
|
||||
log_err("FAIL: error in creating the dateformat using short date and time style\n %s\n",
|
||||
myErrorName(status) );
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
/*Testing udat_getAvailable() and udat_countAvailable()*/
|
||||
/*Testing udat_getAvailable() and udat_countAvailable()*/
|
||||
log_verbose("\nTesting getAvailableLocales and countAvailable()\n");
|
||||
numlocales=udat_countAvailable();
|
||||
/* use something sensible w/o hardcoding the count */
|
||||
if(numlocales < 0)
|
||||
log_data_err("FAIL: error in countAvailable\n");
|
||||
log_verbose("The number of locales for which date/time formatting patterns are available is %d\n", numlocales);
|
||||
|
||||
|
||||
for(i=0;i<numlocales;i++) {
|
||||
UErrorCode subStatus = U_ZERO_ERROR;
|
||||
log_verbose("Testing open of %s\n", udat_getAvailable(i));
|
||||
|
@ -154,7 +154,7 @@ static void TestDateFormat()
|
|||
}
|
||||
/*if(def != copy)
|
||||
log_err("Error in udat_clone");*/ /*how should i check for equality???? */
|
||||
|
||||
|
||||
/*Testing udat_format()*/
|
||||
log_verbose("\nTesting the udat_format() function of date format\n");
|
||||
u_uastrcpy(temp, "7/10/96, 4:05 PM");
|
||||
|
@ -189,7 +189,7 @@ static void TestDateFormat()
|
|||
log_err("FAIL: Date Format for US locale failed using udat_format() - expected %s got %s\n", xbuf, gbuf);
|
||||
}
|
||||
/*format using fr */
|
||||
|
||||
|
||||
u_unescape("10 juil. 1996 \\u00E0 16:05:28 heure d\\u2019\\u00E9t\\u00E9 du Pacifique", temp, 50);
|
||||
if(result != NULL) {
|
||||
free(result);
|
||||
|
@ -203,12 +203,12 @@ static void TestDateFormat()
|
|||
|
||||
/*format using it */
|
||||
u_uastrcpy(temp, "10 lug 1996, 16:05:28");
|
||||
|
||||
{
|
||||
|
||||
{
|
||||
UChar *fmtted;
|
||||
char g[100];
|
||||
char x[100];
|
||||
|
||||
|
||||
fmtted = myDateFormat(it,d);
|
||||
u_austrcpy(g, fmtted);
|
||||
u_austrcpy(x, temp);
|
||||
|
@ -218,13 +218,13 @@ static void TestDateFormat()
|
|||
log_data_err("FAIL: Date Format for italian locale failed using udat_format() - wanted %s, got %s\n", x, g);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*Testing parsing using udat_parse()*/
|
||||
log_verbose("\nTesting parsing using udat_parse()\n");
|
||||
u_uastrcpy(temp,"2/3/76, 2:50 AM");
|
||||
parsepos=0;
|
||||
status=U_ZERO_ERROR;
|
||||
|
||||
|
||||
d1=udat_parse(def, temp, u_strlen(temp), &parsepos, &status);
|
||||
if(U_FAILURE(status))
|
||||
{
|
||||
|
@ -233,8 +233,8 @@ static void TestDateFormat()
|
|||
else
|
||||
log_verbose("PASS: parsing succesful\n");
|
||||
/*format it back and check for equality */
|
||||
|
||||
|
||||
|
||||
|
||||
if(u_strcmp(myDateFormat(def, d1),temp)!=0)
|
||||
log_err("FAIL: error in parsing\n");
|
||||
|
||||
|
@ -242,7 +242,7 @@ static void TestDateFormat()
|
|||
log_verbose("\nTesting parsing using udat_parse()\n");
|
||||
u_uastrcpy(temp,"2/Don't parse this part");
|
||||
status=U_ZERO_ERROR;
|
||||
|
||||
|
||||
d1=udat_parse(def, temp, u_strlen(temp), NULL, &status);
|
||||
if(status != U_PARSE_ERROR)
|
||||
{
|
||||
|
@ -250,9 +250,9 @@ static void TestDateFormat()
|
|||
}
|
||||
else
|
||||
log_verbose("PASS: parsing succesful\n");
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/*Testing udat_openPattern() */
|
||||
status=U_ZERO_ERROR;
|
||||
log_verbose("\nTesting the udat_openPattern with a specified pattern\n");
|
||||
|
@ -260,13 +260,13 @@ static void TestDateFormat()
|
|||
fr_pat=udat_open(UDAT_PATTERN, UDAT_PATTERN,"fr_FR",NULL,0,temp, u_strlen(temp), &status);
|
||||
if(U_FAILURE(status))
|
||||
{
|
||||
log_err("FAIL: Error in creating a date format using udat_openPattern \n %s\n",
|
||||
log_err("FAIL: Error in creating a date format using udat_openPattern \n %s\n",
|
||||
myErrorName(status) );
|
||||
}
|
||||
else
|
||||
log_verbose("PASS: creating dateformat using udat_openPattern() succesful\n");
|
||||
|
||||
|
||||
|
||||
/*Testing applyPattern and toPattern */
|
||||
log_verbose("\nTesting applyPattern and toPattern()\n");
|
||||
udat_applyPattern(def1, FALSE, temp, u_strlen(temp));
|
||||
|
@ -283,25 +283,25 @@ static void TestDateFormat()
|
|||
}
|
||||
if(U_FAILURE(status))
|
||||
{
|
||||
log_err("FAIL: error in extracting the pattern from UNumberFormat\n %s\n",
|
||||
log_err("FAIL: error in extracting the pattern from UNumberFormat\n %s\n",
|
||||
myErrorName(status) );
|
||||
}
|
||||
if(u_strcmp(result, temp)!=0)
|
||||
log_err("FAIL: Error in extracting the pattern\n");
|
||||
else
|
||||
log_verbose("PASS: applyPattern and toPattern work fine\n");
|
||||
|
||||
|
||||
if(result != NULL) {
|
||||
free(result);
|
||||
free(result);
|
||||
result = NULL;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/*Testing getter and setter functions*/
|
||||
/*isLenient and setLenient()*/
|
||||
log_verbose("\nTesting the isLenient and setLenient properties\n");
|
||||
udat_setLenient(fr, udat_isLenient(it));
|
||||
if(udat_isLenient(fr) != udat_isLenient(it))
|
||||
if(udat_isLenient(fr) != udat_isLenient(it))
|
||||
log_err("ERROR: setLenient() failed\n");
|
||||
else
|
||||
log_verbose("PASS: setLenient() successful\n");
|
||||
|
@ -332,7 +332,7 @@ static void TestDateFormat()
|
|||
else
|
||||
log_verbose("PASS: set2DigitYearStart successful\n");
|
||||
|
||||
|
||||
|
||||
|
||||
/*Test getNumberFormat() and setNumberFormat() */
|
||||
log_verbose("\nTesting the get and set NumberFormat properties of date format\n");
|
||||
|
@ -343,7 +343,7 @@ static void TestDateFormat()
|
|||
log_err("FAIL: error in setNumberFormat or getNumberFormat()\n");
|
||||
else
|
||||
log_verbose("PASS:setNumberFormat and getNumberFormat succesful\n");
|
||||
|
||||
|
||||
/*Test getNumberFormat() and adoptNumberFormat() */
|
||||
log_verbose("\nTesting the get and adopt NumberFormat properties of date format\n");
|
||||
adoptNF= unum_open(UNUM_DEFAULT, NULL, 0, NULL, NULL, &status);
|
||||
|
@ -368,18 +368,18 @@ static void TestDateFormat()
|
|||
/*Test getCalendar and setCalendar*/
|
||||
log_verbose("\nTesting the udat_getCalendar() and udat_setCalendar() properties\n");
|
||||
cal=udat_getCalendar(fr_pat);
|
||||
|
||||
|
||||
|
||||
|
||||
udat_setCalendar(def1, cal);
|
||||
if(!ucal_equivalentTo(udat_getCalendar(fr_pat), udat_getCalendar(def1)))
|
||||
log_err("FAIL: Error in setting and getting the calendar\n");
|
||||
else
|
||||
log_verbose("PASS: getting and setting calendar successful\n");
|
||||
|
||||
|
||||
if(result!=NULL) {
|
||||
free(result);
|
||||
}
|
||||
|
||||
|
||||
/*Closing the UDateForamt */
|
||||
udat_close(def);
|
||||
udat_close(fr);
|
||||
|
@ -388,7 +388,7 @@ static void TestDateFormat()
|
|||
udat_close(def1);
|
||||
udat_close(fr_pat);
|
||||
udat_close(copy);
|
||||
|
||||
|
||||
ctest_resetTimeZone();
|
||||
}
|
||||
|
||||
|
@ -520,7 +520,7 @@ static void TestRelativeDateFormat()
|
|||
log_err("udat_parse timeStyle SHORT dateStyle (%d | UDAT_RELATIVE) fails, error %s, expect approx %.1f, got %.1f, parsePos %d\n",
|
||||
*stylePtr, myErrorName(status), dateToUse, dateResult, parsePos );
|
||||
status = U_ZERO_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
udat_format(fmtRelDate, dateToUse, strDate, kDateOrTimeOutMax, NULL, &status);
|
||||
if ( U_FAILURE(status) ) {
|
||||
|
@ -536,7 +536,7 @@ static void TestRelativeDateFormat()
|
|||
log_err("udat_parse timeStyle NONE dateStyle (%d | UDAT_RELATIVE) fails, error %s, expect approx %.1f, got %.1f, parsePos %d\n",
|
||||
*stylePtr, myErrorName(status), dateToUse, dateResult, parsePos );
|
||||
status = U_ZERO_ERROR;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
udat_format(fmtTime, dateToUse, strTime, kDateOrTimeOutMax, NULL, &status);
|
||||
|
@ -570,31 +570,31 @@ static void TestSymbols()
|
|||
{
|
||||
UDateFormat *def, *fr, *zhChiCal;
|
||||
UErrorCode status = U_ZERO_ERROR;
|
||||
UChar *value=NULL;
|
||||
UChar *value=NULL;
|
||||
UChar *result = NULL;
|
||||
int32_t resultlength;
|
||||
int32_t resultlengthout;
|
||||
UChar *pattern;
|
||||
|
||||
|
||||
|
||||
/*creating a dateformat with french locale */
|
||||
log_verbose("\ncreating a date format with french locale\n");
|
||||
fr = udat_open(UDAT_FULL, UDAT_DEFAULT, "fr_FR", NULL, 0, NULL, 0, &status);
|
||||
if(U_FAILURE(status))
|
||||
{
|
||||
log_data_err("error in creating the dateformat using full time style with french locale -> %s (Are you missing data?)\n",
|
||||
log_data_err("error in creating the dateformat using full time style with french locale -> %s (Are you missing data?)\n",
|
||||
myErrorName(status) );
|
||||
return;
|
||||
}
|
||||
/*creating a default dateformat */
|
||||
log_verbose("\ncreating a date format with default locale\n");
|
||||
/* this is supposed to open default date format, but later on it treats it like it is "en_US"
|
||||
/* this is supposed to open default date format, but later on it treats it like it is "en_US"
|
||||
- very bad if you try to run the tests on machine where default locale is NOT "en_US" */
|
||||
/* def = udat_open(UDAT_DEFAULT,UDAT_DEFAULT ,NULL, NULL, 0, &status); */
|
||||
def = udat_open(UDAT_DEFAULT,UDAT_DEFAULT ,"en_US", NULL, 0, NULL, 0, &status);
|
||||
if(U_FAILURE(status))
|
||||
{
|
||||
log_err("error in creating the dateformat using short date and time style\n %s\n",
|
||||
log_err("error in creating the dateformat using short date and time style\n %s\n",
|
||||
myErrorName(status) );
|
||||
return;
|
||||
}
|
||||
|
@ -603,16 +603,16 @@ static void TestSymbols()
|
|||
zhChiCal = udat_open(UDAT_NONE, UDAT_FULL, "zh@calendar=chinese", NULL, 0, NULL, 0, &status);
|
||||
if(U_FAILURE(status))
|
||||
{
|
||||
log_data_err("error in creating the dateformat using full date, no time, locale zh@calendar=chinese -> %s (Are you missing data?)\n",
|
||||
log_data_err("error in creating the dateformat using full date, no time, locale zh@calendar=chinese -> %s (Are you missing data?)\n",
|
||||
myErrorName(status) );
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/*Testing countSymbols, getSymbols and setSymbols*/
|
||||
log_verbose("\nTesting countSymbols\n");
|
||||
/*since the month names has the last string empty and week names are 1 based 1.e first string in the weeknames array is empty */
|
||||
if(udat_countSymbols(def, UDAT_ERAS)!=2 || udat_countSymbols(def, UDAT_MONTHS)!=12 ||
|
||||
if(udat_countSymbols(def, UDAT_ERAS)!=2 || udat_countSymbols(def, UDAT_MONTHS)!=12 ||
|
||||
udat_countSymbols(def, UDAT_SHORT_MONTHS)!=12 || udat_countSymbols(def, UDAT_WEEKDAYS)!=8 ||
|
||||
udat_countSymbols(def, UDAT_SHORT_WEEKDAYS)!=8 || udat_countSymbols(def, UDAT_AM_PMS)!=2 ||
|
||||
udat_countSymbols(def, UDAT_QUARTERS) != 4 || udat_countSymbols(def, UDAT_SHORT_QUARTERS) != 4 ||
|
||||
|
@ -640,7 +640,7 @@ static void TestSymbols()
|
|||
}
|
||||
result=(UChar*)malloc(sizeof(UChar) * resultlength);
|
||||
udat_getSymbols(fr, UDAT_WEEKDAYS, 5, result, resultlength, &status);
|
||||
|
||||
|
||||
}
|
||||
if(U_FAILURE(status))
|
||||
{
|
||||
|
@ -677,9 +677,9 @@ static void TestSymbols()
|
|||
VerifygetSymbols(zhChiCal, UDAT_ZODIAC_NAMES_ABBREVIATED, 0, "\\u9F20");
|
||||
VerifygetSymbols(zhChiCal, UDAT_ZODIAC_NAMES_WIDE, 11, "\\u732A");
|
||||
#if UDAT_HAS_PATTERN_CHAR_FOR_TIME_SEPARATOR
|
||||
VerifygetSymbols(def,UDAT_LOCALIZED_CHARS, 0, "GyMdkHmsSEDFwWahKzYeugAZvcLQqVUOXxr:");
|
||||
VerifygetSymbols(def,UDAT_LOCALIZED_CHARS, 0, "GyMdkHmsSEDFwWahKzYeugAZvcLQqVUOXxrbB:");
|
||||
#else
|
||||
VerifygetSymbols(def,UDAT_LOCALIZED_CHARS, 0, "GyMdkHmsSEDFwWahKzYeugAZvcLQqVUOXxr");
|
||||
VerifygetSymbols(def,UDAT_LOCALIZED_CHARS, 0, "GyMdkHmsSEDFwWahKzYeugAZvcLQqVUOXxrbB");
|
||||
#endif
|
||||
|
||||
|
||||
|
@ -687,8 +687,8 @@ static void TestSymbols()
|
|||
free(result);
|
||||
result = NULL;
|
||||
}
|
||||
free(pattern);
|
||||
|
||||
free(pattern);
|
||||
|
||||
log_verbose("\nTesting setSymbols\n");
|
||||
/*applying the pattern so that setSymbolss works */
|
||||
resultlength=0;
|
||||
|
@ -702,10 +702,10 @@ free(pattern);
|
|||
}
|
||||
if(U_FAILURE(status))
|
||||
{
|
||||
log_err("FAIL: error in extracting the pattern from UNumberFormat\n %s\n",
|
||||
log_err("FAIL: error in extracting the pattern from UNumberFormat\n %s\n",
|
||||
myErrorName(status) );
|
||||
}
|
||||
|
||||
|
||||
udat_applyPattern(def, FALSE, pattern, u_strlen(pattern));
|
||||
resultlength=0;
|
||||
resultlengthout=udat_toPattern(def, FALSE, NULL, resultlength,&status);
|
||||
|
@ -722,7 +722,7 @@ free(pattern);
|
|||
}
|
||||
if(U_FAILURE(status))
|
||||
{
|
||||
log_err("FAIL: error in extracting the pattern from UNumberFormat\n %s\n",
|
||||
log_err("FAIL: error in extracting the pattern from UNumberFormat\n %s\n",
|
||||
myErrorName(status) );
|
||||
}
|
||||
if(u_strcmp(result, pattern)==0)
|
||||
|
@ -743,12 +743,12 @@ free(pattern);
|
|||
}
|
||||
result=(UChar*)malloc(sizeof(UChar) * resultlength);
|
||||
udat_getSymbols(fr, UDAT_MONTHS, 11, result, resultlength, &status);
|
||||
|
||||
|
||||
}
|
||||
if(U_FAILURE(status))
|
||||
log_err("FAIL: error in getSymbols() %s\n", myErrorName(status) );
|
||||
resultlength=resultlengthout+1;
|
||||
|
||||
|
||||
udat_setSymbols(def, UDAT_MONTHS, 11, result, resultlength, &status);
|
||||
if(U_FAILURE(status))
|
||||
{
|
||||
|
@ -756,7 +756,7 @@ free(pattern);
|
|||
}
|
||||
else
|
||||
log_verbose("PASS: SetSymbols successful\n");
|
||||
|
||||
|
||||
resultlength=0;
|
||||
resultlengthout=udat_getSymbols(def, UDAT_MONTHS, 11, NULL, resultlength, &status);
|
||||
if(status==U_BUFFER_OVERFLOW_ERROR){
|
||||
|
@ -767,13 +767,13 @@ free(pattern);
|
|||
}
|
||||
if(U_FAILURE(status))
|
||||
log_err("FAIL: error in retrieving the value using getSymbols i.e roundtrip\n");
|
||||
|
||||
|
||||
if(u_strcmp(result, value)!=0)
|
||||
log_data_err("FAIL: Error in settting and getting symbols\n");
|
||||
else
|
||||
log_verbose("PASS: setSymbols successful\n");
|
||||
|
||||
|
||||
|
||||
|
||||
/*run series of tests to test setSymbols regressively*/
|
||||
log_verbose("\nTesting setSymbols regressively\n");
|
||||
VerifysetSymbols(def, UDAT_ERAS, 0, "BeforeChrist");
|
||||
|
@ -812,7 +812,7 @@ free(pattern);
|
|||
|
||||
|
||||
/*closing*/
|
||||
|
||||
|
||||
udat_close(fr);
|
||||
udat_close(def);
|
||||
udat_close(zhChiCal);
|
||||
|
@ -821,7 +821,7 @@ free(pattern);
|
|||
result = NULL;
|
||||
}
|
||||
free(value);
|
||||
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -845,7 +845,7 @@ static void TestDateFormatCalendar() {
|
|||
/* Create a formatter for date fields. */
|
||||
date = udat_open(UDAT_NONE, UDAT_SHORT, "en_US", NULL, 0, NULL, 0, &ec);
|
||||
if (U_FAILURE(ec)) {
|
||||
log_data_err("FAIL: udat_open(NONE, SHORT, en_US) failed with %s (Are you missing data?)\n",
|
||||
log_data_err("FAIL: udat_open(NONE, SHORT, en_US) failed with %s (Are you missing data?)\n",
|
||||
u_errorName(ec));
|
||||
goto FAIL;
|
||||
}
|
||||
|
@ -853,7 +853,7 @@ static void TestDateFormatCalendar() {
|
|||
/* Create a formatter for time fields. */
|
||||
time = udat_open(UDAT_SHORT, UDAT_NONE, "en_US", NULL, 0, NULL, 0, &ec);
|
||||
if (U_FAILURE(ec)) {
|
||||
log_err("FAIL: udat_open(SHORT, NONE, en_US) failed with %s\n",
|
||||
log_err("FAIL: udat_open(SHORT, NONE, en_US) failed with %s\n",
|
||||
u_errorName(ec));
|
||||
goto FAIL;
|
||||
}
|
||||
|
@ -861,7 +861,7 @@ static void TestDateFormatCalendar() {
|
|||
/* Create a full format for output */
|
||||
full = udat_open(UDAT_FULL, UDAT_FULL, "en_US", NULL, 0, NULL, 0, &ec);
|
||||
if (U_FAILURE(ec)) {
|
||||
log_err("FAIL: udat_open(FULL, FULL, en_US) failed with %s\n",
|
||||
log_err("FAIL: udat_open(FULL, FULL, en_US) failed with %s\n",
|
||||
u_errorName(ec));
|
||||
goto FAIL;
|
||||
}
|
||||
|
@ -869,7 +869,7 @@ static void TestDateFormatCalendar() {
|
|||
/* Create a calendar */
|
||||
cal = ucal_open(NULL, 0, "en_US", UCAL_GREGORIAN, &ec);
|
||||
if (U_FAILURE(ec)) {
|
||||
log_err("FAIL: ucal_open(en_US) failed with %s\n",
|
||||
log_err("FAIL: ucal_open(en_US) failed with %s\n",
|
||||
u_errorName(ec));
|
||||
goto FAIL;
|
||||
}
|
||||
|
@ -940,7 +940,7 @@ static void TestDateFormatCalendar() {
|
|||
log_err("FAIL: Parsed result: %s, exp 4/5/2001 5:45 PM\n", cbuf);
|
||||
}
|
||||
|
||||
FAIL:
|
||||
FAIL:
|
||||
udat_close(date);
|
||||
udat_close(time);
|
||||
udat_close(full);
|
||||
|
@ -1057,7 +1057,7 @@ static void VerifygetSymbols(UDateFormat* datfor, UDateFormatSymbolType type, in
|
|||
UChar *result=NULL;
|
||||
int32_t resultlength, resultlengthout;
|
||||
int32_t patternSize = strlen(expected) + 1;
|
||||
|
||||
|
||||
pattern=(UChar*)malloc(sizeof(UChar) * patternSize);
|
||||
u_unescape(expected, pattern, patternSize);
|
||||
resultlength=0;
|
||||
|
@ -1068,7 +1068,7 @@ static void VerifygetSymbols(UDateFormat* datfor, UDateFormatSymbolType type, in
|
|||
resultlength=resultlengthout+1;
|
||||
result=(UChar*)malloc(sizeof(UChar) * resultlength);
|
||||
udat_getSymbols(datfor, type, idx, result, resultlength, &status);
|
||||
|
||||
|
||||
}
|
||||
if(U_FAILURE(status))
|
||||
{
|
||||
|
@ -1078,7 +1078,7 @@ static void VerifygetSymbols(UDateFormat* datfor, UDateFormatSymbolType type, in
|
|||
if(u_strcmp(result, pattern)==0)
|
||||
log_verbose("PASS: getSymbols retrieved the right value\n");
|
||||
else{
|
||||
log_data_err("FAIL: getSymbols retrieved the wrong value\n Expected %s Got %s\n", expected,
|
||||
log_data_err("FAIL: getSymbols retrieved the wrong value\n Expected %s Got %s\n", expected,
|
||||
aescstrdup(result,-1) );
|
||||
}
|
||||
free(result);
|
||||
|
@ -1111,11 +1111,11 @@ static void VerifysetSymbols(UDateFormat* datfor, UDateFormatSymbolType type, in
|
|||
udat_getSymbols(datfor, type, idx, result, resultlength, &status);
|
||||
}
|
||||
if(U_FAILURE(status)){
|
||||
log_err("FAIL: error in retrieving the value using getSymbols after setting it previously\n %s\n",
|
||||
log_err("FAIL: error in retrieving the value using getSymbols after setting it previously\n %s\n",
|
||||
myErrorName(status) );
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
if(u_strcmp(result, value)!=0){
|
||||
log_err("FAIL:Error in setting and then getting symbols\n Expected %s Got %s\n", expected,
|
||||
aescstrdup(result,-1) );
|
||||
|
@ -1134,7 +1134,7 @@ static void VerifygetsetSymbols(UDateFormat* from, UDateFormat* to, UDateFormatS
|
|||
UChar *value=NULL;
|
||||
int32_t resultlength, resultlengthout;
|
||||
UErrorCode status = U_ZERO_ERROR;
|
||||
|
||||
|
||||
resultlength=0;
|
||||
resultlengthout=udat_getSymbols(from, type, idx , NULL, resultlength, &status);
|
||||
if(status==U_BUFFER_OVERFLOW_ERROR){
|
||||
|
@ -1147,7 +1147,7 @@ static void VerifygetsetSymbols(UDateFormat* from, UDateFormat* to, UDateFormatS
|
|||
log_err("FAIL: error in getSymbols() %s\n", myErrorName(status) );
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
resultlength=resultlengthout+1;
|
||||
udat_setSymbols(to, type, idx, result, resultlength, &status);
|
||||
if(U_FAILURE(status))
|
||||
|
@ -1165,11 +1165,11 @@ static void VerifygetsetSymbols(UDateFormat* from, UDateFormat* to, UDateFormatS
|
|||
udat_getSymbols(to, type, idx, value, resultlength, &status);
|
||||
}
|
||||
if(U_FAILURE(status)){
|
||||
log_err("FAIL: error in retrieving the value using getSymbols i.e roundtrip\n %s\n",
|
||||
log_err("FAIL: error in retrieving the value using getSymbols i.e roundtrip\n %s\n",
|
||||
myErrorName(status) );
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
if(u_strcmp(result, value)!=0){
|
||||
log_data_err("FAIL:Error in setting and then getting symbols\n Expected %s Got %s\n", austrdup(result),
|
||||
austrdup(value) );
|
||||
|
@ -1187,7 +1187,7 @@ static UChar* myNumformat(const UNumberFormat* numfor, double d)
|
|||
UChar *result2=NULL;
|
||||
int32_t resultlength, resultlengthneeded;
|
||||
UErrorCode status = U_ZERO_ERROR;
|
||||
|
||||
|
||||
resultlength=0;
|
||||
resultlengthneeded=unum_formatDouble(numfor, d, NULL, resultlength, NULL, &status);
|
||||
if(status==U_BUFFER_OVERFLOW_ERROR)
|
||||
|
@ -1203,7 +1203,7 @@ static UChar* myNumformat(const UNumberFormat* numfor, double d)
|
|||
log_err("FAIL: Error in formatting using unum_format(.....) %s\n", myErrorName(status) );
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
return result2;
|
||||
}
|
||||
|
||||
|
@ -1277,7 +1277,7 @@ static void TestExtremeDates() {
|
|||
|
||||
/* There is no need to test larger values from 1e+30 to 1e+300;
|
||||
the failures occur around 1e+27, and never above 1e+30. */
|
||||
|
||||
|
||||
ec = U_ZERO_ERROR;
|
||||
fmt = udat_open(UDAT_LONG, UDAT_LONG, "en_US",
|
||||
0, 0, 0, 0, &ec);
|
||||
|
@ -1327,12 +1327,12 @@ static void TestRelativeCrash(void) {
|
|||
UErrorCode subStatus = U_ZERO_ERROR;
|
||||
what = "udat_set2DigitYearStart";
|
||||
log_verbose("Trying %s on a relative date..\n", what);
|
||||
udat_set2DigitYearStart(icudf, aDate, &subStatus);
|
||||
udat_set2DigitYearStart(icudf, aDate, &subStatus);
|
||||
if(subStatus == expectStatus) {
|
||||
log_verbose("Success: did not crash on %s, but got %s.\n", what, u_errorName(subStatus));
|
||||
} else {
|
||||
log_err("FAIL: didn't crash on %s, but got success %s instead of %s. \n", what, u_errorName(subStatus), u_errorName(expectStatus));
|
||||
}
|
||||
}
|
||||
}
|
||||
{
|
||||
/* clone works polymorphically. try it anyways */
|
||||
|
@ -1346,42 +1346,42 @@ static void TestRelativeCrash(void) {
|
|||
udat_close(oth); /* ? */
|
||||
} else {
|
||||
log_err("FAIL: didn't crash on %s, but got %s instead of %s. \n", what, u_errorName(subStatus), u_errorName(expectStatus));
|
||||
}
|
||||
}
|
||||
}
|
||||
{
|
||||
UErrorCode subStatus = U_ZERO_ERROR;
|
||||
what = "udat_get2DigitYearStart";
|
||||
log_verbose("Trying %s on a relative date..\n", what);
|
||||
udat_get2DigitYearStart(icudf, &subStatus);
|
||||
udat_get2DigitYearStart(icudf, &subStatus);
|
||||
if(subStatus == expectStatus) {
|
||||
log_verbose("Success: did not crash on %s, but got %s.\n", what, u_errorName(subStatus));
|
||||
} else {
|
||||
log_err("FAIL: didn't crash on %s, but got success %s instead of %s. \n", what, u_errorName(subStatus), u_errorName(expectStatus));
|
||||
}
|
||||
}
|
||||
}
|
||||
{
|
||||
/* Now udat_toPattern works for relative date formatters, unless localized is TRUE */
|
||||
UErrorCode subStatus = U_ZERO_ERROR;
|
||||
what = "udat_toPattern";
|
||||
log_verbose("Trying %s on a relative date..\n", what);
|
||||
udat_toPattern(icudf, TRUE,NULL,0, &subStatus);
|
||||
udat_toPattern(icudf, TRUE,NULL,0, &subStatus);
|
||||
if(subStatus == expectStatus) {
|
||||
log_verbose("Success: did not crash on %s, but got %s.\n", what, u_errorName(subStatus));
|
||||
} else {
|
||||
log_err("FAIL: didn't crash on %s, but got success %s instead of %s. \n", what, u_errorName(subStatus), u_errorName(expectStatus));
|
||||
}
|
||||
}
|
||||
}
|
||||
{
|
||||
UErrorCode subStatus = U_ZERO_ERROR;
|
||||
what = "udat_applyPattern";
|
||||
log_verbose("Trying %s on a relative date..\n", what);
|
||||
udat_applyPattern(icudf, FALSE,tzName,-1);
|
||||
udat_applyPattern(icudf, FALSE,tzName,-1);
|
||||
subStatus = U_ILLEGAL_ARGUMENT_ERROR; /* what it should be, if this took an errorcode. */
|
||||
if(subStatus == expectStatus) {
|
||||
log_verbose("Success: did not crash on %s, but got %s.\n", what, u_errorName(subStatus));
|
||||
} else {
|
||||
log_err("FAIL: didn't crash on %s, but got success %s instead of %s. \n", what, u_errorName(subStatus), u_errorName(expectStatus));
|
||||
}
|
||||
}
|
||||
}
|
||||
{
|
||||
UChar erabuf[32];
|
||||
|
@ -1393,7 +1393,7 @@ static void TestRelativeCrash(void) {
|
|||
log_verbose("Success: %s returned %s.\n", what, u_errorName(subStatus));
|
||||
} else {
|
||||
log_err("FAIL: didn't crash on %s, but got %s instead of U_ZERO_ERROR.\n", what, u_errorName(subStatus));
|
||||
}
|
||||
}
|
||||
}
|
||||
{
|
||||
UErrorCode subStatus = U_ZERO_ERROR;
|
||||
|
@ -1405,21 +1405,21 @@ static void TestRelativeCrash(void) {
|
|||
log_verbose("Success: did not crash on %s, but got %s.\n", what, u_errorName(subStatus));
|
||||
} else {
|
||||
log_err("FAIL: didn't crash on %s, but got success %s instead of %s. \n", what, u_errorName(subStatus), u_errorName(expectStatus));
|
||||
}
|
||||
}
|
||||
}
|
||||
{
|
||||
UErrorCode subStatus = U_ZERO_ERROR;
|
||||
what = "udat_countSymbols";
|
||||
log_verbose("Trying %s on a relative date..\n", what);
|
||||
udat_countSymbols(icudf, UDAT_ERAS);
|
||||
udat_countSymbols(icudf, UDAT_ERAS);
|
||||
subStatus = U_ILLEGAL_ARGUMENT_ERROR; /* should have an errorcode. */
|
||||
if(subStatus == expectStatus) {
|
||||
log_verbose("Success: did not crash on %s, but got %s.\n", what, u_errorName(subStatus));
|
||||
} else {
|
||||
log_err("FAIL: didn't crash on %s, but got success %s instead of %s. \n", what, u_errorName(subStatus), u_errorName(expectStatus));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
udat_close(icudf);
|
||||
} else {
|
||||
log_data_err("FAIL: err calling udat_open() ->%s (Are you missing data?)\n", u_errorName(status));
|
||||
|
@ -1599,9 +1599,9 @@ static void TestContext(void) {
|
|||
}
|
||||
|
||||
|
||||
// overrideNumberFormat[i][0] is to tell which field to set,
|
||||
// overrideNumberFormat[i][0] is to tell which field to set,
|
||||
// overrideNumberFormat[i][1] is the expected result
|
||||
static const char * overrideNumberFormat[][2] = {
|
||||
static const char * overrideNumberFormat[][2] = {
|
||||
{"", "\\u521D\\u4E03 \\u521D\\u4E8C"},
|
||||
{"d", "07 \\u521D\\u4E8C"},
|
||||
{"do", "07 \\u521D\\u4E8C"},
|
||||
|
@ -1652,7 +1652,7 @@ static void TestOverrideNumberFormat(void) {
|
|||
unum_close(overrideFmt);
|
||||
}
|
||||
udat_close(fmt);
|
||||
|
||||
|
||||
for (i=0; i<UPRV_LENGTHOF(overrideNumberFormat); i++){
|
||||
UChar ubuf[kUbufMax];
|
||||
UDateFormat* fmt2;
|
||||
|
@ -1696,7 +1696,7 @@ static void TestOverrideNumberFormat(void) {
|
|||
udat_format(fmt2, july022008, ubuf, kUbufMax, NULL, &status);
|
||||
assertSuccess("udat_format() july022008", &status);
|
||||
|
||||
if (u_strncmp(ubuf, expected, kUbufMax) != 0)
|
||||
if (u_strncmp(ubuf, expected, kUbufMax) != 0)
|
||||
log_err("fail: udat_format for locale, expected %s, got %s\n",
|
||||
u_austrncpy(bbuf1,expected,kUbufMax), u_austrncpy(bbuf2,ubuf,kUbufMax) );
|
||||
|
||||
|
@ -1787,7 +1787,7 @@ static void TestFormatForFields(void) {
|
|||
int32_t ulen, field, beginPos, endPos;
|
||||
UChar ubuf[kUBufFieldsLen];
|
||||
const FieldsData * fptr;
|
||||
|
||||
|
||||
status = U_ZERO_ERROR;
|
||||
ulen = udat_formatForFields(udfmt, date2015Feb25, ubuf, kUBufFieldsLen, fpositer, &status);
|
||||
if ( U_FAILURE(status) ) {
|
||||
|
@ -1810,7 +1810,7 @@ static void TestFormatForFields(void) {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
ucal_setMillis(ucal, date2015Feb25, &status);
|
||||
status = U_ZERO_ERROR;
|
||||
ulen = udat_formatCalendarForFields(udfmt, ucal, ubuf, kUBufFieldsLen, fpositer, &status);
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -1,12 +1,12 @@
|
|||
/********************************************************************
|
||||
* COPYRIGHT:
|
||||
* Copyright (c) 1997-2015, International Business Machines Corporation and
|
||||
* COPYRIGHT:
|
||||
* Copyright (c) 1997-2016, International Business Machines Corporation and
|
||||
* others. All Rights Reserved.
|
||||
********************************************************************/
|
||||
|
||||
#ifndef _DATEFORMATTEST_
|
||||
#define _DATEFORMATTEST_
|
||||
|
||||
|
||||
#include "unicode/utypes.h"
|
||||
|
||||
#if !UCONFIG_NO_FORMATTING
|
||||
|
@ -15,7 +15,7 @@
|
|||
#include "unicode/smpdtfmt.h"
|
||||
#include "caltztst.h"
|
||||
|
||||
/**
|
||||
/**
|
||||
* Performs many different tests for DateFormat and SimpleDateFormat
|
||||
**/
|
||||
class DateFormatTest: public CalendarTimeZoneTest {
|
||||
|
@ -40,23 +40,23 @@ public:
|
|||
* Test the parsing of 2-digit years.
|
||||
*/
|
||||
virtual void TestTwoDigitYearDSTParse(void);
|
||||
|
||||
|
||||
public: // package
|
||||
// internal utility routine (genrates escape sequences for characters)
|
||||
static UnicodeString& escape(UnicodeString& s);
|
||||
|
||||
|
||||
public:
|
||||
/**
|
||||
* Verify that returned field position indices are correct.
|
||||
*/
|
||||
void TestFieldPosition(void);
|
||||
|
||||
|
||||
void TestGeneral();
|
||||
|
||||
public: // package
|
||||
// internal utility function
|
||||
static void getFieldText(DateFormat* df, int32_t field, UDate date, UnicodeString& str);
|
||||
|
||||
|
||||
public:
|
||||
/**
|
||||
* Verify that strings which contain incomplete specifications are parsed
|
||||
|
@ -64,11 +64,11 @@ public:
|
|||
* returning an appropriate error.
|
||||
*/
|
||||
virtual void TestPartialParse994(void);
|
||||
|
||||
|
||||
public: // package
|
||||
// internal test subroutine, used by TestPartialParse994
|
||||
virtual void tryPat994(SimpleDateFormat* format, const char* pat, const char* str, UDate expected);
|
||||
|
||||
|
||||
public:
|
||||
/**
|
||||
* Verify the behavior of patterns in which digits for different fields run together
|
||||
|
@ -80,11 +80,11 @@ public:
|
|||
* without intervening separators.
|
||||
*/
|
||||
virtual void TestRunTogetherPattern917(void);
|
||||
|
||||
|
||||
public: // package
|
||||
// internal test subroutine, used by TestRunTogetherPattern917
|
||||
virtual void testIt917(SimpleDateFormat* fmt, UnicodeString& str, UDate expected);
|
||||
|
||||
|
||||
public:
|
||||
/**
|
||||
* Verify the handling of Czech June and July, which have the unique attribute that
|
||||
|
@ -99,11 +99,11 @@ public:
|
|||
* Test the day of year pattern.
|
||||
*/
|
||||
virtual void TestDayOfYearPattern195(void);
|
||||
|
||||
|
||||
public: // package
|
||||
// interl test subroutine, used by TestDayOfYearPattern195
|
||||
virtual void tryPattern(SimpleDateFormat& sdf, UDate d, const char* pattern, UDate expected);
|
||||
|
||||
|
||||
public:
|
||||
/**
|
||||
* Test the handling of single quotes in patterns.
|
||||
|
@ -113,7 +113,7 @@ public:
|
|||
* Verify the correct behavior when handling invalid input strings.
|
||||
*/
|
||||
virtual void TestBadInput135(void);
|
||||
|
||||
|
||||
public:
|
||||
/**
|
||||
* Verify the correct behavior when parsing an array of inputs against an
|
||||
|
@ -125,11 +125,11 @@ public:
|
|||
* Test the parsing of two-digit years.
|
||||
*/
|
||||
virtual void TestTwoDigitYear(void);
|
||||
|
||||
|
||||
public: // package
|
||||
// internal test subroutine, used by TestTwoDigitYear
|
||||
virtual void parse2DigitYear(DateFormat& fmt, const char* str, UDate expected);
|
||||
|
||||
|
||||
public:
|
||||
/**
|
||||
* Test the formatting of time zones.
|
||||
|
@ -209,11 +209,11 @@ public:
|
|||
void TestStandAloneMonths(void);
|
||||
|
||||
void TestQuarters(void);
|
||||
|
||||
|
||||
void TestZTimeZoneParsing(void);
|
||||
|
||||
void TestRelativeClone(void);
|
||||
|
||||
|
||||
void TestHostClone(void);
|
||||
|
||||
void TestHebrewClone(void);
|
||||
|
@ -252,6 +252,12 @@ public:
|
|||
|
||||
void TestPatternFromSkeleton();
|
||||
|
||||
void TestAmPmMidnightNoon();
|
||||
void TestFlexibleDayPeriod();
|
||||
void TestDayPeriodWithLocales();
|
||||
void TestMinuteSecondFieldsInOddPlaces();
|
||||
void TestDayPeriodParsing();
|
||||
|
||||
private:
|
||||
UBool showParse(DateFormat &format, const UnicodeString &formattedString);
|
||||
|
||||
|
@ -262,7 +268,7 @@ public:
|
|||
void TestNumberAsStringParsing(void);
|
||||
|
||||
private:
|
||||
void TestRelative(int daysdelta,
|
||||
void TestRelative(int daysdelta,
|
||||
const Locale& loc,
|
||||
const char *expectChars);
|
||||
|
||||
|
@ -275,9 +281,10 @@ public:
|
|||
|
||||
void expectFormat(const char **data, int32_t data_length,
|
||||
const Locale &locale);
|
||||
|
||||
};
|
||||
|
||||
#endif /* #if !UCONFIG_NO_FORMATTING */
|
||||
|
||||
|
||||
#endif // _DATEFORMATTEST_
|
||||
//eof
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
|
||||
/********************************************************************
|
||||
* COPYRIGHT:
|
||||
* Copyright (c) 1997-2014, International Business Machines Corporation and
|
||||
* COPYRIGHT:
|
||||
* Copyright (c) 1997-2016, International Business Machines Corporation and
|
||||
* others. All Rights Reserved.
|
||||
********************************************************************/
|
||||
|
||||
|
@ -22,7 +22,7 @@ void IntlTestSimpleDateFormatAPI::runIndexedTest( int32_t index, UBool exec, con
|
|||
{
|
||||
if (exec) logln("TestSuite SimpleDateFormatAPI");
|
||||
switch (index) {
|
||||
case 0: name = "SimpleDateFormat API test";
|
||||
case 0: name = "SimpleDateFormat API test";
|
||||
if (exec) {
|
||||
logln("SimpleDateFormat API test---"); logln("");
|
||||
UErrorCode status = U_ZERO_ERROR;
|
||||
|
@ -271,8 +271,8 @@ void IntlTestSimpleDateFormatAPI::testAPI(/*char *par*/)
|
|||
}
|
||||
|
||||
// ====== Test ticket 11295 getNumberFormatForField returns wild pointer
|
||||
if (object.getNumberFormatForField('B') != NULL) {
|
||||
errln("B is not a valid field, "
|
||||
if (object.getNumberFormatForField('N') != NULL) {
|
||||
errln("N is not a valid field, "
|
||||
"getNumberFormatForField should return NULL");
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue