mirror of
https://github.com/unicode-org/icu.git
synced 2025-04-07 06:25:30 +00:00
ICU-8513 Merging TimeZoneNames/TimeZoneFormat APIs (as 49 technology preview) into trunk.
X-SVN-Rev: 31469
This commit is contained in:
parent
733a433be7
commit
1641940f00
23 changed files with 4034 additions and 1616 deletions
|
@ -174,12 +174,10 @@ Global
|
|||
{77C78066-746F-4EA6-B3FE-B8C8A4A97891}.Release|x64.Build.0 = Release|x64
|
||||
{0178B127-6269-407D-B112-93877BB62776}.Debug|Win32.ActiveCfg = Debug|Win32
|
||||
{0178B127-6269-407D-B112-93877BB62776}.Debug|Win32.Build.0 = Debug|Win32
|
||||
{0178B127-6269-407D-B112-93877BB62776}.Debug|x64.ActiveCfg = Debug|x64
|
||||
{0178B127-6269-407D-B112-93877BB62776}.Debug|x64.Build.0 = Debug|x64
|
||||
{0178B127-6269-407D-B112-93877BB62776}.Debug|x64.ActiveCfg = Debug|Win32
|
||||
{0178B127-6269-407D-B112-93877BB62776}.Release|Win32.ActiveCfg = Release|Win32
|
||||
{0178B127-6269-407D-B112-93877BB62776}.Release|Win32.Build.0 = Release|Win32
|
||||
{0178B127-6269-407D-B112-93877BB62776}.Release|x64.ActiveCfg = Release|x64
|
||||
{0178B127-6269-407D-B112-93877BB62776}.Release|x64.Build.0 = Release|x64
|
||||
{0178B127-6269-407D-B112-93877BB62776}.Release|x64.ActiveCfg = Release|Win32
|
||||
{73632960-B3A6-464D-83A3-4B43365F19B8}.Debug|Win32.ActiveCfg = Debug|Win32
|
||||
{73632960-B3A6-464D-83A3-4B43365F19B8}.Debug|Win32.Build.0 = Debug|Win32
|
||||
{73632960-B3A6-464D-83A3-4B43365F19B8}.Debug|x64.ActiveCfg = Debug|x64
|
||||
|
|
|
@ -26,6 +26,7 @@
|
|||
#include "unicode/dtfmtsym.h"
|
||||
#include "unicode/smpdtfmt.h"
|
||||
#include "unicode/msgfmt.h"
|
||||
#include "unicode/tznames.h"
|
||||
#include "cpputils.h"
|
||||
#include "ucln_in.h"
|
||||
#include "umutex.h"
|
||||
|
@ -36,7 +37,6 @@
|
|||
#include "hash.h"
|
||||
#include "uresimp.h"
|
||||
#include "ureslocs.h"
|
||||
#include "tznames.h"
|
||||
|
||||
// *****************************************************************************
|
||||
// class DateFormatSymbols
|
||||
|
@ -120,31 +120,6 @@ static const UChar gLastResortEras[2][3] =
|
|||
{0x0041, 0x0044, 0x0000} /* "AD" */
|
||||
};
|
||||
|
||||
// Not used now
|
||||
//// These are the zone strings of last resort.
|
||||
//static const UChar gLastResortZoneStrings[5][4] =
|
||||
//{
|
||||
// {0x0047, 0x004D, 0x0054, 0x0000}, /* "GMT" */
|
||||
// {0x0047, 0x004D, 0x0054, 0x0000}, /* "GMT" */
|
||||
// {0x0047, 0x004D, 0x0054, 0x0000}, /* "GMT" */
|
||||
// {0x0047, 0x004D, 0x0054, 0x0000}, /* "GMT" */
|
||||
// {0x0047, 0x004D, 0x0054, 0x0000}, /* "GMT" */
|
||||
//};
|
||||
|
||||
static const UChar gLastResortGmtZero[] =
|
||||
{0x0047, 0x004D, 0x0054, 0x0000}; /* GMT */
|
||||
|
||||
static const UChar gLastResortGmtFormat[] =
|
||||
{0x0047, 0x004D, 0x0054, 0x007B, 0x0030, 0x007D, 0x0000}; /* GMT{0} */
|
||||
|
||||
static const UChar gLastResortGmtHourFormats[4][10] =
|
||||
{
|
||||
{0x002D, 0x0048, 0x0048, 0x003A, 0x006D, 0x006D, 0x003A, 0x0073, 0x0073, 0x0000}, /* -HH:mm:ss */
|
||||
{0x002D, 0x0048, 0x0048, 0x003A, 0x006D, 0x006D, 0x0000, 0x0000, 0x0000, 0x0000}, /* -HH:mm */
|
||||
{0x002B, 0x0048, 0x0048, 0x003A, 0x006D, 0x006D, 0x003A, 0x0073, 0x0073, 0x0000}, /* +HH:mm:ss */
|
||||
{0x002B, 0x0048, 0x0048, 0x003A, 0x006D, 0x006D, 0x0000, 0x0000, 0x0000, 0x0000} /* +HH:mm */
|
||||
};
|
||||
|
||||
/* Sizes for the last resort string arrays */
|
||||
typedef enum LastResortSize {
|
||||
kMonthNum = 13,
|
||||
|
@ -197,9 +172,6 @@ static const char gAmPmMarkersTag[]="AmPmMarkers";
|
|||
static const char gQuartersTag[]="quarters";
|
||||
|
||||
static const char gZoneStringsTag[]="zoneStrings";
|
||||
static const char gGmtZeroFormatTag[] = "gmtZeroFormat";
|
||||
static const char gGmtFormatTag[]="gmtFormat";
|
||||
static const char gHourFormatTag[]="hourFormat";
|
||||
|
||||
static const char gLocalPatternCharsTag[]="localPatternChars";
|
||||
|
||||
|
@ -352,9 +324,6 @@ DateFormatSymbols::copyData(const DateFormatSymbols& other) {
|
|||
fShortYearNames = NULL;
|
||||
fShortYearNamesCount = 0;
|
||||
}
|
||||
fGmtZero = other.fGmtZero;
|
||||
fGmtFormat = other.fGmtFormat;
|
||||
assignArray(fGmtHourFormats, fGmtHourFormatsCount, other.fGmtHourFormats, other.fGmtHourFormatsCount);
|
||||
|
||||
if (other.fZoneStrings != NULL) {
|
||||
fZoneStringsColCount = other.fZoneStringsColCount;
|
||||
|
@ -416,7 +385,6 @@ void DateFormatSymbols::dispose()
|
|||
if (fStandaloneShortQuarters) delete[] fStandaloneShortQuarters;
|
||||
if (fLeapMonthPatterns) delete[] fLeapMonthPatterns;
|
||||
if (fShortYearNames) delete[] fShortYearNames;
|
||||
if (fGmtHourFormats) delete[] fGmtHourFormats;
|
||||
|
||||
disposeZoneStrings();
|
||||
}
|
||||
|
@ -485,9 +453,6 @@ DateFormatSymbols::operator==(const DateFormatSymbols& other) const
|
|||
fStandaloneShortQuartersCount == other.fStandaloneShortQuartersCount &&
|
||||
fLeapMonthPatternsCount == other.fLeapMonthPatternsCount &&
|
||||
fShortYearNamesCount == other.fShortYearNamesCount &&
|
||||
fGmtHourFormatsCount == other.fGmtHourFormatsCount &&
|
||||
fGmtZero == other.fGmtZero &&
|
||||
fGmtFormat == other.fGmtFormat &&
|
||||
(uprv_memcmp(fCapitalization, other.fCapitalization, sizeof(fCapitalization))==0))
|
||||
{
|
||||
// Now compare the arrays themselves
|
||||
|
@ -512,8 +477,7 @@ DateFormatSymbols::operator==(const DateFormatSymbols& other) const
|
|||
arrayCompare(fStandaloneQuarters, other.fStandaloneQuarters, fStandaloneQuartersCount) &&
|
||||
arrayCompare(fStandaloneShortQuarters, other.fStandaloneShortQuarters, fStandaloneShortQuartersCount) &&
|
||||
arrayCompare(fLeapMonthPatterns, other.fLeapMonthPatterns, fLeapMonthPatternsCount) &&
|
||||
arrayCompare(fShortYearNames, other.fShortYearNames, fShortYearNamesCount) &&
|
||||
arrayCompare(fGmtHourFormats, other.fGmtHourFormats, fGmtHourFormatsCount))
|
||||
arrayCompare(fShortYearNames, other.fShortYearNames, fShortYearNamesCount))
|
||||
{
|
||||
// Compare the contents of fZoneStrings
|
||||
if (fZoneStrings == NULL && other.fZoneStrings == NULL) {
|
||||
|
@ -1333,8 +1297,6 @@ DateFormatSymbols::initializeData(const Locale& locale, const char *type, UError
|
|||
fLeapMonthPatternsCount = 0;
|
||||
fShortYearNames = NULL;
|
||||
fShortYearNamesCount = 0;
|
||||
fGmtHourFormats = NULL;
|
||||
fGmtHourFormatsCount = 0;
|
||||
fZoneStringsRowCount = 0;
|
||||
fZoneStringsColCount = 0;
|
||||
fZoneStrings = NULL;
|
||||
|
@ -1356,12 +1318,6 @@ DateFormatSymbols::initializeData(const Locale& locale, const char *type, UError
|
|||
*/
|
||||
CalendarData calData(locale, type, status);
|
||||
|
||||
/**
|
||||
* Use the localeBundle for getting zone GMT formatting patterns
|
||||
*/
|
||||
UResourceBundle *zoneBundle = ures_open(U_ICUDATA_ZONE, locale.getName(), &status);
|
||||
UResourceBundle *zoneStringsArray = ures_getByKeyWithFallback(zoneBundle, gZoneStringsTag, NULL, &status);
|
||||
|
||||
// load the first data item
|
||||
UResourceBundle *erasMain = calData.getByKey(gErasTag, status);
|
||||
UResourceBundle *eras = ures_getByKeyWithFallback(erasMain, gNamesAbbrTag, NULL, &status);
|
||||
|
@ -1488,9 +1444,6 @@ DateFormatSymbols::initializeData(const Locale& locale, const char *type, UError
|
|||
initField(&fShortQuarters, fShortQuartersCount, (const UChar *)gLastResortQuarters, kQuarterNum, kQuarterLen, status);
|
||||
initField(&fStandaloneQuarters, fStandaloneQuartersCount, (const UChar *)gLastResortQuarters, kQuarterNum, kQuarterLen, status);
|
||||
initField(&fStandaloneShortQuarters, fStandaloneShortQuartersCount, (const UChar *)gLastResortQuarters, kQuarterNum, kQuarterLen, status);
|
||||
initField(&fGmtHourFormats, fGmtHourFormatsCount, (const UChar *)gLastResortGmtHourFormats, kGmtHourNum, kGmtHourLen, status);
|
||||
fGmtZero.setTo(TRUE, gLastResortGmtZero, -1);
|
||||
fGmtFormat.setTo(TRUE, gLastResortGmtFormat, -1);
|
||||
fLocalPatternChars.setTo(TRUE, gPatternChars, PATTERN_CHARS_LEN);
|
||||
}
|
||||
goto cleanup;
|
||||
|
@ -1555,50 +1508,6 @@ DateFormatSymbols::initializeData(const Locale& locale, const char *type, UError
|
|||
initField(&fStandaloneShortQuarters, fStandaloneShortQuartersCount, calData.getByKey2(gQuartersTag, gNamesAbbrTag, status), status);
|
||||
}
|
||||
|
||||
// GMT zero
|
||||
resStr = ures_getStringByKeyWithFallback(zoneStringsArray, gGmtZeroFormatTag, &len, &status);
|
||||
if (len > 0) {
|
||||
fGmtZero.setTo(TRUE, resStr, len);
|
||||
}
|
||||
|
||||
// GMT format patterns
|
||||
resStr = ures_getStringByKeyWithFallback(zoneStringsArray, gGmtFormatTag, &len, &status);
|
||||
if (len > 0) {
|
||||
fGmtFormat.setTo(TRUE, resStr, len);
|
||||
}
|
||||
|
||||
resStr = ures_getStringByKeyWithFallback(zoneStringsArray, gHourFormatTag, &len, &status);
|
||||
if (len > 0) {
|
||||
UChar *sep = u_strchr(resStr, (UChar)0x003B /* ';' */);
|
||||
if (sep != NULL) {
|
||||
fGmtHourFormats = newUnicodeStringArray(GMT_HOUR_COUNT);
|
||||
if (fGmtHourFormats == NULL) {
|
||||
status = U_MEMORY_ALLOCATION_ERROR;
|
||||
} else {
|
||||
fGmtHourFormatsCount = GMT_HOUR_COUNT;
|
||||
fGmtHourFormats[GMT_NEGATIVE_HM].setTo(TRUE, sep + 1, -1);
|
||||
fGmtHourFormats[GMT_POSITIVE_HM].setTo(FALSE, resStr, (int32_t)(sep - resStr));
|
||||
|
||||
// CLDR 1.5 does not have GMT offset pattern including second field.
|
||||
// For now, append "ss" to the end.
|
||||
if (fGmtHourFormats[GMT_NEGATIVE_HM].indexOf((UChar)0x003A /* ':' */) != -1) {
|
||||
fGmtHourFormats[GMT_NEGATIVE_HMS] = fGmtHourFormats[GMT_NEGATIVE_HM] + UNICODE_STRING_SIMPLE(":ss");
|
||||
} else if (fGmtHourFormats[GMT_NEGATIVE_HM].indexOf((UChar)0x002E /* '.' */) != -1) {
|
||||
fGmtHourFormats[GMT_NEGATIVE_HMS] = fGmtHourFormats[GMT_NEGATIVE_HM] + UNICODE_STRING_SIMPLE(".ss");
|
||||
} else {
|
||||
fGmtHourFormats[GMT_NEGATIVE_HMS] = fGmtHourFormats[GMT_NEGATIVE_HM] + UNICODE_STRING_SIMPLE("ss");
|
||||
}
|
||||
if (fGmtHourFormats[GMT_POSITIVE_HM].indexOf((UChar)0x003A /* ':' */) != -1) {
|
||||
fGmtHourFormats[GMT_POSITIVE_HMS] = fGmtHourFormats[GMT_POSITIVE_HM] + UNICODE_STRING_SIMPLE(":ss");
|
||||
} else if (fGmtHourFormats[GMT_POSITIVE_HM].indexOf((UChar)0x002E /* '.' */) != -1) {
|
||||
fGmtHourFormats[GMT_POSITIVE_HMS] = fGmtHourFormats[GMT_POSITIVE_HM] + UNICODE_STRING_SIMPLE(".ss");
|
||||
} else {
|
||||
fGmtHourFormats[GMT_POSITIVE_HMS] = fGmtHourFormats[GMT_POSITIVE_HM] + UNICODE_STRING_SIMPLE("ss");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// ICU 3.8 or later version no longer uses localized date-time pattern characters by default (ticket#5597)
|
||||
/*
|
||||
// fastCopyFrom()/setTo() - see assignArray comments
|
||||
|
@ -1737,8 +1646,6 @@ cleanup:
|
|||
ures_close(eras);
|
||||
ures_close(eraNames);
|
||||
ures_close(narrowEras);
|
||||
ures_close(zoneStringsArray);
|
||||
ures_close(zoneBundle);
|
||||
}
|
||||
|
||||
Locale
|
||||
|
|
|
@ -579,9 +579,7 @@
|
|||
<Outputs Condition="'$(Configuration)|$(Platform)'=='Release|x64'">..\..\include\unicode\%(Filename)%(Extension);%(Outputs)</Outputs>
|
||||
</CustomBuild>
|
||||
<ClInclude Include="numsys_impl.h" />
|
||||
<ClInclude Include="tzfmt.h" />
|
||||
<ClInclude Include="tzgnames.h" />
|
||||
<ClInclude Include="tznames.h" />
|
||||
<ClInclude Include="tznames_impl.h" />
|
||||
<ClInclude Include="ucol_bld.h" />
|
||||
<ClInclude Include="ucol_cnt.h" />
|
||||
|
@ -617,6 +615,14 @@
|
|||
</Command>
|
||||
<Outputs Condition="'$(Configuration)|$(Platform)'=='Release|x64'">..\..\include\unicode\%(Filename)%(Extension);%(Outputs)</Outputs>
|
||||
</CustomBuild>
|
||||
<CustomBuild Include="unicode\tzfmt.h">
|
||||
<Command Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">copy "%(FullPath)" ..\..\include\unicode</Command>
|
||||
<Outputs Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">..\..\include\unicode\%(Filename)%(Extension);%(Outputs)</Outputs>
|
||||
</CustomBuild>
|
||||
<CustomBuild Include="unicode\tznames.h">
|
||||
<Outputs Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">..\..\include\unicode\%(Filename)%(Extension);%(Outputs)</Outputs>
|
||||
<Command Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">copy "%(FullPath)" ..\..\include\unicode</Command>
|
||||
</CustomBuild>
|
||||
<ClInclude Include="usrchimp.h" />
|
||||
<ClInclude Include="astro.h" />
|
||||
<CustomBuild Include="unicode\basictz.h">
|
||||
|
|
|
@ -768,15 +768,9 @@
|
|||
<ClInclude Include="uspoof_wsconf.h">
|
||||
<Filter>spoof</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="tzfmt.h">
|
||||
<Filter>formatting</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="tzgnames.h">
|
||||
<Filter>formatting</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="tznames.h">
|
||||
<Filter>formatting</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="tznames_impl.h">
|
||||
<Filter>formatting</Filter>
|
||||
</ClInclude>
|
||||
|
@ -1001,5 +995,11 @@
|
|||
<CustomBuild Include="unicode\alphaindex.h">
|
||||
<Filter>collation</Filter>
|
||||
</CustomBuild>
|
||||
<CustomBuild Include="unicode\tzfmt.h">
|
||||
<Filter>formatting</Filter>
|
||||
</CustomBuild>
|
||||
<CustomBuild Include="unicode\tznames.h">
|
||||
<Filter>formatting</Filter>
|
||||
</CustomBuild>
|
||||
</ItemGroup>
|
||||
</Project>
|
|
@ -45,6 +45,7 @@
|
|||
#include "unicode/basictz.h"
|
||||
#include "unicode/simpletz.h"
|
||||
#include "unicode/rbtz.h"
|
||||
#include "unicode/tzfmt.h"
|
||||
#include "unicode/utf16.h"
|
||||
#include "unicode/vtzone.h"
|
||||
#include "olsontz.h"
|
||||
|
@ -56,7 +57,6 @@
|
|||
#include "uassert.h"
|
||||
#include "cmemory.h"
|
||||
#include "umutex.h"
|
||||
#include "tzfmt.h"
|
||||
#include <float.h>
|
||||
#include "smpdtfst.h"
|
||||
|
||||
|
@ -212,15 +212,6 @@ UOBJECT_DEFINE_RTTI_IMPLEMENTATION(SimpleDateFormat)
|
|||
SimpleDateFormat::~SimpleDateFormat()
|
||||
{
|
||||
delete fSymbols;
|
||||
if (fGMTFormatters) {
|
||||
for (int32_t i = 0; i < kNumGMTFormatters; i++) {
|
||||
if (fGMTFormatters[i]) {
|
||||
delete fGMTFormatters[i];
|
||||
}
|
||||
}
|
||||
uprv_free(fGMTFormatters);
|
||||
|
||||
}
|
||||
if (fNumberFormatters) {
|
||||
uprv_free(fNumberFormatters);
|
||||
}
|
||||
|
@ -242,7 +233,6 @@ SimpleDateFormat::SimpleDateFormat(UErrorCode& status)
|
|||
: fLocale(Locale::getDefault()),
|
||||
fSymbols(NULL),
|
||||
fTimeZoneFormat(NULL),
|
||||
fGMTFormatters(NULL),
|
||||
fNumberFormatters(NULL),
|
||||
fOverrideList(NULL),
|
||||
fDefaultCapitalizationContext(UDAT_CAPITALIZATION_UNKNOWN)
|
||||
|
@ -259,7 +249,6 @@ SimpleDateFormat::SimpleDateFormat(const UnicodeString& pattern,
|
|||
fLocale(Locale::getDefault()),
|
||||
fSymbols(NULL),
|
||||
fTimeZoneFormat(NULL),
|
||||
fGMTFormatters(NULL),
|
||||
fNumberFormatters(NULL),
|
||||
fOverrideList(NULL),
|
||||
fDefaultCapitalizationContext(UDAT_CAPITALIZATION_UNKNOWN)
|
||||
|
@ -280,7 +269,6 @@ SimpleDateFormat::SimpleDateFormat(const UnicodeString& pattern,
|
|||
fLocale(Locale::getDefault()),
|
||||
fSymbols(NULL),
|
||||
fTimeZoneFormat(NULL),
|
||||
fGMTFormatters(NULL),
|
||||
fNumberFormatters(NULL),
|
||||
fOverrideList(NULL),
|
||||
fDefaultCapitalizationContext(UDAT_CAPITALIZATION_UNKNOWN)
|
||||
|
@ -303,7 +291,6 @@ SimpleDateFormat::SimpleDateFormat(const UnicodeString& pattern,
|
|||
: fPattern(pattern),
|
||||
fLocale(locale),
|
||||
fTimeZoneFormat(NULL),
|
||||
fGMTFormatters(NULL),
|
||||
fNumberFormatters(NULL),
|
||||
fOverrideList(NULL),
|
||||
fDefaultCapitalizationContext(UDAT_CAPITALIZATION_UNKNOWN)
|
||||
|
@ -326,7 +313,6 @@ SimpleDateFormat::SimpleDateFormat(const UnicodeString& pattern,
|
|||
: fPattern(pattern),
|
||||
fLocale(locale),
|
||||
fTimeZoneFormat(NULL),
|
||||
fGMTFormatters(NULL),
|
||||
fNumberFormatters(NULL),
|
||||
fOverrideList(NULL),
|
||||
fDefaultCapitalizationContext(UDAT_CAPITALIZATION_UNKNOWN)
|
||||
|
@ -352,7 +338,6 @@ SimpleDateFormat::SimpleDateFormat(const UnicodeString& pattern,
|
|||
fLocale(Locale::getDefault()),
|
||||
fSymbols(symbolsToAdopt),
|
||||
fTimeZoneFormat(NULL),
|
||||
fGMTFormatters(NULL),
|
||||
fNumberFormatters(NULL),
|
||||
fOverrideList(NULL),
|
||||
fDefaultCapitalizationContext(UDAT_CAPITALIZATION_UNKNOWN)
|
||||
|
@ -375,7 +360,6 @@ SimpleDateFormat::SimpleDateFormat(const UnicodeString& pattern,
|
|||
fLocale(Locale::getDefault()),
|
||||
fSymbols(new DateFormatSymbols(symbols)),
|
||||
fTimeZoneFormat(NULL),
|
||||
fGMTFormatters(NULL),
|
||||
fNumberFormatters(NULL),
|
||||
fOverrideList(NULL),
|
||||
fDefaultCapitalizationContext(UDAT_CAPITALIZATION_UNKNOWN)
|
||||
|
@ -399,7 +383,6 @@ SimpleDateFormat::SimpleDateFormat(EStyle timeStyle,
|
|||
: fLocale(locale),
|
||||
fSymbols(NULL),
|
||||
fTimeZoneFormat(NULL),
|
||||
fGMTFormatters(NULL),
|
||||
fNumberFormatters(NULL),
|
||||
fOverrideList(NULL),
|
||||
fDefaultCapitalizationContext(UDAT_CAPITALIZATION_UNKNOWN)
|
||||
|
@ -423,7 +406,6 @@ SimpleDateFormat::SimpleDateFormat(const Locale& locale,
|
|||
fLocale(locale),
|
||||
fSymbols(NULL),
|
||||
fTimeZoneFormat(NULL),
|
||||
fGMTFormatters(NULL),
|
||||
fNumberFormatters(NULL),
|
||||
fOverrideList(NULL),
|
||||
fDefaultCapitalizationContext(UDAT_CAPITALIZATION_UNKNOWN)
|
||||
|
@ -458,7 +440,6 @@ SimpleDateFormat::SimpleDateFormat(const SimpleDateFormat& other)
|
|||
: DateFormat(other),
|
||||
fSymbols(NULL),
|
||||
fTimeZoneFormat(NULL),
|
||||
fGMTFormatters(NULL),
|
||||
fNumberFormatters(NULL),
|
||||
fOverrideList(NULL),
|
||||
fDefaultCapitalizationContext(UDAT_CAPITALIZATION_UNKNOWN)
|
||||
|
@ -1042,374 +1023,7 @@ _appendSymbolWithMonthPattern(UnicodeString& dst, int32_t value, const UnicodeSt
|
|||
}
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------
|
||||
void
|
||||
SimpleDateFormat::appendGMT(NumberFormat *currentNumberFormat,UnicodeString &appendTo, Calendar& cal, UErrorCode& status) const{
|
||||
int32_t offset = cal.get(UCAL_ZONE_OFFSET, status) + cal.get(UCAL_DST_OFFSET, status);
|
||||
if (U_FAILURE(status)) {
|
||||
return;
|
||||
}
|
||||
if (offset == 0) {
|
||||
// use GMT zero format
|
||||
appendTo += fSymbols->fGmtZero;
|
||||
} else {
|
||||
if (isDefaultGMTFormat()) {
|
||||
formatGMTDefault(currentNumberFormat,appendTo, offset);
|
||||
} else {
|
||||
((SimpleDateFormat*)this)->initGMTFormatters(status);
|
||||
if (U_SUCCESS(status)) {
|
||||
int32_t type;
|
||||
if (offset < 0) {
|
||||
offset = -offset;
|
||||
type = (offset % U_MILLIS_PER_MINUTE) == 0 ? kGMTNegativeHM : kGMTNegativeHMS;
|
||||
} else {
|
||||
type = (offset % U_MILLIS_PER_MINUTE) == 0 ? kGMTPositiveHM : kGMTPositiveHMS;
|
||||
}
|
||||
Formattable param(offset, Formattable::kIsDate);
|
||||
FieldPosition fpos(0);
|
||||
fGMTFormatters[type]->format(¶m, 1, appendTo, fpos, status);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int32_t
|
||||
SimpleDateFormat::parseGMT(const UnicodeString &text, ParsePosition &pos) const {
|
||||
if (!isDefaultGMTFormat()) {
|
||||
int32_t start = pos.getIndex();
|
||||
|
||||
// Quick check
|
||||
UBool prefixMatch = FALSE;
|
||||
int32_t prefixLen = fSymbols->fGmtFormat.indexOf((UChar)0x007B /* '{' */);
|
||||
if (prefixLen > 0 && text.compare(start, prefixLen, fSymbols->fGmtFormat, 0, prefixLen) == 0) {
|
||||
prefixMatch = TRUE;
|
||||
}
|
||||
if (prefixMatch) {
|
||||
// Prefix matched
|
||||
UErrorCode status = U_ZERO_ERROR;
|
||||
((SimpleDateFormat*)this)->initGMTFormatters(status);
|
||||
if (U_SUCCESS(status)) {
|
||||
Formattable parsed;
|
||||
int32_t parsedCount;
|
||||
|
||||
// Try negative Hms
|
||||
fGMTFormatters[kGMTNegativeHMS]->parseObject(text, parsed, pos);
|
||||
if (pos.getErrorIndex() == -1 &&
|
||||
(pos.getIndex() - start) >= fGMTFormatHmsMinLen[kGMTNegativeHMSMinLenIdx]) {
|
||||
parsed.getArray(parsedCount);
|
||||
if (parsedCount == 1 && parsed[0].getType() == Formattable::kDate) {
|
||||
return (int32_t)(-1 * (int64_t)parsed[0].getDate());
|
||||
}
|
||||
}
|
||||
|
||||
// Reset ParsePosition
|
||||
pos.setIndex(start);
|
||||
pos.setErrorIndex(-1);
|
||||
|
||||
// Try positive Hms
|
||||
fGMTFormatters[kGMTPositiveHMS]->parseObject(text, parsed, pos);
|
||||
if (pos.getErrorIndex() == -1 &&
|
||||
(pos.getIndex() - start) >= fGMTFormatHmsMinLen[kGMTPositiveHMSMinLenIdx]) {
|
||||
parsed.getArray(parsedCount);
|
||||
if (parsedCount == 1 && parsed[0].getType() == Formattable::kDate) {
|
||||
return (int32_t)((int64_t)parsed[0].getDate());
|
||||
}
|
||||
}
|
||||
|
||||
// Reset ParsePosition
|
||||
pos.setIndex(start);
|
||||
pos.setErrorIndex(-1);
|
||||
|
||||
// Try negative Hm
|
||||
fGMTFormatters[kGMTNegativeHM]->parseObject(text, parsed, pos);
|
||||
if (pos.getErrorIndex() == -1 && pos.getIndex() > start) {
|
||||
parsed.getArray(parsedCount);
|
||||
if (parsedCount == 1 && parsed[0].getType() == Formattable::kDate) {
|
||||
return (int32_t)(-1 * (int64_t)parsed[0].getDate());
|
||||
}
|
||||
}
|
||||
|
||||
// Reset ParsePosition
|
||||
pos.setIndex(start);
|
||||
pos.setErrorIndex(-1);
|
||||
|
||||
// Try positive Hm
|
||||
fGMTFormatters[kGMTPositiveHM]->parseObject(text, parsed, pos);
|
||||
if (pos.getErrorIndex() == -1 && pos.getIndex() > start) {
|
||||
parsed.getArray(parsedCount);
|
||||
if (parsedCount == 1 && parsed[0].getType() == Formattable::kDate) {
|
||||
return (int32_t)((int64_t)parsed[0].getDate());
|
||||
}
|
||||
}
|
||||
|
||||
// Reset ParsePosition
|
||||
pos.setIndex(start);
|
||||
pos.setErrorIndex(-1);
|
||||
}
|
||||
// fall through to the default GMT parsing method
|
||||
}
|
||||
}
|
||||
return parseGMTDefault(text, pos);
|
||||
}
|
||||
|
||||
void
|
||||
SimpleDateFormat::formatGMTDefault(NumberFormat *currentNumberFormat,UnicodeString &appendTo, int32_t offset) const {
|
||||
if (offset < 0) {
|
||||
appendTo.append(gGmtMinus, 4);
|
||||
offset = -offset; // suppress the '-' sign for text display.
|
||||
}else{
|
||||
appendTo.append(gGmtPlus, 4);
|
||||
}
|
||||
|
||||
offset /= U_MILLIS_PER_SECOND; // now in seconds
|
||||
int32_t sec = offset % 60;
|
||||
offset /= 60;
|
||||
int32_t min = offset % 60;
|
||||
int32_t hour = offset / 60;
|
||||
|
||||
|
||||
zeroPaddingNumber(currentNumberFormat,appendTo, hour, 2, 2);
|
||||
appendTo += (UChar)0x003A /*':'*/;
|
||||
zeroPaddingNumber(currentNumberFormat,appendTo, min, 2, 2);
|
||||
if (sec != 0) {
|
||||
appendTo += (UChar)0x003A /*':'*/;
|
||||
zeroPaddingNumber(currentNumberFormat,appendTo, sec, 2, 2);
|
||||
}
|
||||
}
|
||||
|
||||
int32_t
|
||||
SimpleDateFormat::parseGMTDefault(const UnicodeString &text, ParsePosition &pos) const {
|
||||
int32_t start = pos.getIndex();
|
||||
NumberFormat *currentNumberFormat = getNumberFormatByIndex(UDAT_TIMEZONE_RFC_FIELD);
|
||||
|
||||
if (start + kUtLen + 1 >= text.length()) {
|
||||
pos.setErrorIndex(start);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int32_t cur = start;
|
||||
// "GMT"
|
||||
if (text.compare(start, kGmtLen, gGmt) == 0) {
|
||||
cur += kGmtLen;
|
||||
} else if (text.compare(start, kUtLen, gUt) == 0) {
|
||||
cur += kUtLen;
|
||||
} else {
|
||||
pos.setErrorIndex(start);
|
||||
return 0;
|
||||
}
|
||||
// Sign
|
||||
UBool negative = FALSE;
|
||||
if (text.charAt(cur) == (UChar)0x002D /* minus */) {
|
||||
negative = TRUE;
|
||||
} else if (text.charAt(cur) != (UChar)0x002B /* plus */) {
|
||||
pos.setErrorIndex(cur);
|
||||
return 0;
|
||||
}
|
||||
cur++;
|
||||
|
||||
// Numbers
|
||||
int32_t numLen;
|
||||
pos.setIndex(cur);
|
||||
|
||||
Formattable number;
|
||||
parseInt(text, number, 6, pos, FALSE,currentNumberFormat);
|
||||
numLen = pos.getIndex() - cur;
|
||||
|
||||
if (numLen <= 0) {
|
||||
pos.setIndex(start);
|
||||
pos.setErrorIndex(cur);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int32_t numVal = number.getLong();
|
||||
|
||||
int32_t hour = 0;
|
||||
int32_t min = 0;
|
||||
int32_t sec = 0;
|
||||
|
||||
if (numLen <= 2) {
|
||||
// H[H][:mm[:ss]]
|
||||
hour = numVal;
|
||||
cur += numLen;
|
||||
if (cur + 2 < text.length() && text.charAt(cur) == (UChar)0x003A /* colon */) {
|
||||
cur++;
|
||||
pos.setIndex(cur);
|
||||
parseInt(text, number, 2, pos, FALSE,currentNumberFormat);
|
||||
numLen = pos.getIndex() - cur;
|
||||
if (numLen == 2) {
|
||||
// got minute field
|
||||
min = number.getLong();
|
||||
cur += numLen;
|
||||
if (cur + 2 < text.length() && text.charAt(cur) == (UChar)0x003A /* colon */) {
|
||||
cur++;
|
||||
pos.setIndex(cur);
|
||||
parseInt(text, number, 2, pos, FALSE,currentNumberFormat);
|
||||
numLen = pos.getIndex() - cur;
|
||||
if (numLen == 2) {
|
||||
// got second field
|
||||
sec = number.getLong();
|
||||
} else {
|
||||
// reset position
|
||||
pos.setIndex(cur - 1);
|
||||
pos.setErrorIndex(-1);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// reset postion
|
||||
pos.setIndex(cur - 1);
|
||||
pos.setErrorIndex(-1);
|
||||
}
|
||||
}
|
||||
} else if (numLen == 3 || numLen == 4) {
|
||||
// Hmm or HHmm
|
||||
hour = numVal / 100;
|
||||
min = numVal % 100;
|
||||
} else if (numLen == 5 || numLen == 6) {
|
||||
// Hmmss or HHmmss
|
||||
hour = numVal / 10000;
|
||||
min = (numVal % 10000) / 100;
|
||||
sec = numVal % 100;
|
||||
} else {
|
||||
// HHmmss followed by bogus numbers
|
||||
pos.setIndex(cur + 6);
|
||||
|
||||
int32_t shift = numLen - 6;
|
||||
while (shift > 0) {
|
||||
numVal /= 10;
|
||||
shift--;
|
||||
}
|
||||
hour = numVal / 10000;
|
||||
min = (numVal % 10000) / 100;
|
||||
sec = numVal % 100;
|
||||
}
|
||||
|
||||
int32_t offset = ((hour*60 + min)*60 + sec)*1000;
|
||||
if (negative) {
|
||||
offset = -offset;
|
||||
}
|
||||
return offset;
|
||||
}
|
||||
|
||||
UBool
|
||||
SimpleDateFormat::isDefaultGMTFormat() const {
|
||||
// GMT pattern
|
||||
if (fSymbols->fGmtFormat.length() == 0) {
|
||||
// No GMT pattern is set
|
||||
return TRUE;
|
||||
} else if (fSymbols->fGmtFormat.compare(gDefGmtPat, kGmtPatLen) != 0) {
|
||||
return FALSE;
|
||||
}
|
||||
// Hour patterns
|
||||
if (fSymbols->fGmtHourFormats == NULL || fSymbols->fGmtHourFormatsCount != DateFormatSymbols::GMT_HOUR_COUNT) {
|
||||
// No Hour pattern is set
|
||||
return TRUE;
|
||||
} else if ((fSymbols->fGmtHourFormats[DateFormatSymbols::GMT_NEGATIVE_HMS].compare(gDefGmtNegHmsPat, kNegHmsLen) != 0)
|
||||
|| (fSymbols->fGmtHourFormats[DateFormatSymbols::GMT_NEGATIVE_HM].compare(gDefGmtNegHmPat, kNegHmLen) != 0)
|
||||
|| (fSymbols->fGmtHourFormats[DateFormatSymbols::GMT_POSITIVE_HMS].compare(gDefGmtPosHmsPat, kPosHmsLen) != 0)
|
||||
|| (fSymbols->fGmtHourFormats[DateFormatSymbols::GMT_POSITIVE_HM].compare(gDefGmtPosHmPat, kPosHmLen) != 0)) {
|
||||
return FALSE;
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
void
|
||||
SimpleDateFormat::formatRFC822TZ(UnicodeString &appendTo, int32_t offset) const {
|
||||
UChar sign = 0x002B /* '+' */;
|
||||
if (offset < 0) {
|
||||
offset = -offset;
|
||||
sign = 0x002D /* '-' */;
|
||||
}
|
||||
appendTo.append(sign);
|
||||
|
||||
int32_t offsetH = offset / U_MILLIS_PER_HOUR;
|
||||
offset = offset % U_MILLIS_PER_HOUR;
|
||||
int32_t offsetM = offset / U_MILLIS_PER_MINUTE;
|
||||
offset = offset % U_MILLIS_PER_MINUTE;
|
||||
int32_t offsetS = offset / U_MILLIS_PER_SECOND;
|
||||
|
||||
int32_t num = 0, denom = 0;
|
||||
if (offsetS == 0) {
|
||||
offset = offsetH*100 + offsetM; // HHmm
|
||||
num = offset % 10000;
|
||||
denom = 1000;
|
||||
} else {
|
||||
offset = offsetH*10000 + offsetM*100 + offsetS; // HHmmss
|
||||
num = offset % 1000000;
|
||||
denom = 100000;
|
||||
}
|
||||
while (denom >= 1) {
|
||||
UChar digit = (UChar)0x0030 + (num / denom);
|
||||
appendTo.append(digit);
|
||||
num = num % denom;
|
||||
denom /= 10;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
SimpleDateFormat::initGMTFormatters(UErrorCode &status) {
|
||||
if (U_FAILURE(status)) {
|
||||
return;
|
||||
}
|
||||
umtx_lock(&LOCK);
|
||||
if (fGMTFormatters == NULL) {
|
||||
fGMTFormatters = (MessageFormat**)uprv_malloc(kNumGMTFormatters * sizeof(MessageFormat*));
|
||||
if (fGMTFormatters) {
|
||||
for (int32_t i = 0; i < kNumGMTFormatters; i++) {
|
||||
const UnicodeString *hourPattern = NULL; //initialized it to avoid warning
|
||||
switch (i) {
|
||||
case kGMTNegativeHMS:
|
||||
hourPattern = &(fSymbols->fGmtHourFormats[DateFormatSymbols::GMT_NEGATIVE_HMS]);
|
||||
break;
|
||||
case kGMTNegativeHM:
|
||||
hourPattern = &(fSymbols->fGmtHourFormats[DateFormatSymbols::GMT_NEGATIVE_HM]);
|
||||
break;
|
||||
case kGMTPositiveHMS:
|
||||
hourPattern = &(fSymbols->fGmtHourFormats[DateFormatSymbols::GMT_POSITIVE_HMS]);
|
||||
break;
|
||||
case kGMTPositiveHM:
|
||||
hourPattern = &(fSymbols->fGmtHourFormats[DateFormatSymbols::GMT_POSITIVE_HM]);
|
||||
break;
|
||||
}
|
||||
fGMTFormatters[i] = new MessageFormat(fSymbols->fGmtFormat, status);
|
||||
GregorianCalendar *gcal = new GregorianCalendar(TimeZone::createTimeZone(UnicodeString(gEtcUTC)), status);
|
||||
if (U_FAILURE(status)) {
|
||||
break;
|
||||
}
|
||||
SimpleDateFormat *sdf = (SimpleDateFormat*)this->clone();
|
||||
sdf->adoptCalendar(gcal);
|
||||
sdf->applyPattern(*hourPattern);
|
||||
|
||||
// This prevents an hours format pattern like "-HH:mm:ss" from matching
|
||||
// in a string like "GMT-07:00 10:08:11 PM"
|
||||
sdf->setLenient(FALSE);
|
||||
|
||||
fGMTFormatters[i]->adoptFormat(0, sdf);
|
||||
|
||||
// For parsing, we only allow Hms patterns to be equal or longer
|
||||
// than its length with fixed minutes/seconds digits.
|
||||
// See #6880
|
||||
if (i == kGMTNegativeHMS || i == kGMTPositiveHMS) {
|
||||
UnicodeString tmp;
|
||||
Formattable tmpParam(60*60*1000, Formattable::kIsDate);
|
||||
FieldPosition fpos(0);
|
||||
fGMTFormatters[i]->format(&tmpParam, 1, tmp, fpos, status);
|
||||
if (U_FAILURE(status)) {
|
||||
break;
|
||||
}
|
||||
if (i == kGMTNegativeHMS) {
|
||||
fGMTFormatHmsMinLen[kGMTNegativeHMSMinLenIdx] = tmp.length();
|
||||
} else {
|
||||
fGMTFormatHmsMinLen[kGMTPositiveHMSMinLenIdx] = tmp.length();
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
status = U_MEMORY_ALLOCATION_ERROR;
|
||||
}
|
||||
}
|
||||
umtx_unlock(&LOCK);
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
void
|
||||
SimpleDateFormat::initNumberFormatters(const Locale &locale,UErrorCode &status) {
|
||||
if (U_FAILURE(status)) {
|
||||
|
@ -1627,11 +1241,11 @@ SimpleDateFormat::subFormat(UnicodeString &appendTo,
|
|||
break;
|
||||
|
||||
case UDAT_YEAR_NAME_FIELD:
|
||||
if (fSymbols->fShortYearNames != NULL && value <= fSymbols->fShortYearNamesCount) {
|
||||
if (fSymbols->fShortYearNames != NULL && value <= fSymbols->fShortYearNamesCount) {
|
||||
// the Calendar YEAR field runs 1 through 60 for cyclic years
|
||||
_appendSymbol(appendTo, value - 1, fSymbols->fShortYearNames, fSymbols->fShortYearNamesCount);
|
||||
break;
|
||||
}
|
||||
}
|
||||
// else fall through to numeric year handling, do not break here
|
||||
|
||||
// OLD: for "yyyy", write out the whole year; for "yy", write out the last 2 digits
|
||||
|
@ -1817,12 +1431,24 @@ SimpleDateFormat::subFormat(UnicodeString &appendTo,
|
|||
case UDAT_TIMEZONE_FIELD:
|
||||
case UDAT_TIMEZONE_GENERIC_FIELD:
|
||||
case UDAT_TIMEZONE_SPECIAL_FIELD:
|
||||
case UDAT_TIMEZONE_RFC_FIELD: // 'Z' - TIMEZONE_RFC
|
||||
{
|
||||
UnicodeString zoneString;
|
||||
const TimeZone& tz = cal.getTimeZone();
|
||||
UDate date = cal.getTime(status);
|
||||
if (U_SUCCESS(status)) {
|
||||
if (patternCharIndex == UDAT_TIMEZONE_FIELD) {
|
||||
if (patternCharIndex == UDAT_TIMEZONE_RFC_FIELD) {
|
||||
if (count < 4) {
|
||||
// "Z"
|
||||
tzFormat()->format(UTZFMT_STYLE_RFC822, tz, date, zoneString);
|
||||
} else if (count == 5) {
|
||||
// "ZZZZZ"
|
||||
tzFormat()->format(UTZFMT_STYLE_ISO8601, tz, date, zoneString);
|
||||
} else {
|
||||
// "ZZ", "ZZZ", "ZZZZ"
|
||||
tzFormat()->format(UTZFMT_STYLE_LOCALIZED_GMT, tz, date, zoneString);
|
||||
}
|
||||
} else if (patternCharIndex == UDAT_TIMEZONE_FIELD) {
|
||||
if (count < 4) {
|
||||
// "z", "zz", "zzz"
|
||||
tzFormat()->format(UTZFMT_STYLE_SPECIFIC_SHORT, tz, date, zoneString);
|
||||
|
@ -1849,27 +1475,12 @@ SimpleDateFormat::subFormat(UnicodeString &appendTo,
|
|||
capContextUsageType = DateFormatSymbols::kCapContextUsageMetazoneShort;
|
||||
} else if (count == 4) {
|
||||
// "VVVV"
|
||||
tzFormat()->format(UTZFMT_STYLE_LOCATION, tz, date, zoneString);
|
||||
tzFormat()->format(UTZFMT_STYLE_GENERIC_LOCATION, tz, date, zoneString);
|
||||
capContextUsageType = DateFormatSymbols::kCapContextUsageZoneLong;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (zoneString.isEmpty()) {
|
||||
appendGMT(currentNumberFormat,appendTo, cal, status);
|
||||
} else {
|
||||
appendTo += zoneString;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case UDAT_TIMEZONE_RFC_FIELD: // 'Z' - TIMEZONE_RFC
|
||||
if (count < 4) {
|
||||
// RFC822 format, must use ASCII digits
|
||||
value = (cal.get(UCAL_ZONE_OFFSET, status) + cal.get(UCAL_DST_OFFSET, status));
|
||||
formatRFC822TZ(appendTo, value);
|
||||
} else {
|
||||
// long form, localized GMT pattern
|
||||
appendGMT(currentNumberFormat,appendTo, cal, status);
|
||||
appendTo += zoneString;
|
||||
}
|
||||
break;
|
||||
|
||||
|
@ -1987,7 +1598,7 @@ SimpleDateFormat::parse(const UnicodeString& text, Calendar& cal, ParsePosition&
|
|||
UBool lenient = isLenient();
|
||||
|
||||
// hack, reset tztype, cast away const
|
||||
((SimpleDateFormat*)this)->tztype = TZTYPE_UNK;
|
||||
((SimpleDateFormat*)this)->tztype = UTZFMT_TIME_TYPE_UNKNOWN;
|
||||
|
||||
// For parsing abutting numeric fields. 'abutPat' is the
|
||||
// offset into 'pattern' of the first of 2 or more abutting
|
||||
|
@ -2189,7 +1800,7 @@ SimpleDateFormat::parse(const UnicodeString& text, Calendar& cal, ParsePosition&
|
|||
// when the two-digit year is equal to the start year, and thus might fall at the
|
||||
// front or the back of the default century. This only works because we adjust
|
||||
// the year correctly to start with in other cases -- see subParse().
|
||||
if (ambiguousYear[0] || tztype != TZTYPE_UNK) // If this is true then the two-digit year == the default start year
|
||||
if (ambiguousYear[0] || tztype != UTZFMT_TIME_TYPE_UNKNOWN) // If this is true then the two-digit year == the default start year
|
||||
{
|
||||
// We need a copy of the fields, and we need to avoid triggering a call to
|
||||
// complete(), which will recalculate the fields. Since we can't access
|
||||
|
@ -2212,7 +1823,7 @@ SimpleDateFormat::parse(const UnicodeString& text, Calendar& cal, ParsePosition&
|
|||
delete copy;
|
||||
}
|
||||
|
||||
if (tztype != TZTYPE_UNK) {
|
||||
if (tztype != UTZFMT_TIME_TYPE_UNKNOWN) {
|
||||
copy = cal.clone();
|
||||
// Check for failed cloning.
|
||||
if (copy == NULL) {
|
||||
|
@ -2238,7 +1849,7 @@ SimpleDateFormat::parse(const UnicodeString& text, Calendar& cal, ParsePosition&
|
|||
// matches the rule used by the parsed time zone.
|
||||
int32_t raw, dst;
|
||||
if (btz != NULL) {
|
||||
if (tztype == TZTYPE_STD) {
|
||||
if (tztype == UTZFMT_TIME_TYPE_STANDARD) {
|
||||
btz->getOffsetFromLocal(localMillis,
|
||||
BasicTimeZone::kStandard, BasicTimeZone::kStandard, raw, dst, status);
|
||||
} else {
|
||||
|
@ -2253,7 +1864,7 @@ SimpleDateFormat::parse(const UnicodeString& text, Calendar& cal, ParsePosition&
|
|||
|
||||
// Now, compare the results with parsed type, either standard or daylight saving time
|
||||
int32_t resolvedSavings = dst;
|
||||
if (tztype == TZTYPE_STD) {
|
||||
if (tztype == UTZFMT_TIME_TYPE_STANDARD) {
|
||||
if (dst != 0) {
|
||||
// Override DST_OFFSET = 0 in the result calendar
|
||||
resolvedSavings = 0;
|
||||
|
@ -3166,178 +2777,51 @@ int32_t SimpleDateFormat::subParse(const UnicodeString& text, int32_t& start, UC
|
|||
break;
|
||||
|
||||
case UDAT_TIMEZONE_FIELD:
|
||||
case UDAT_TIMEZONE_RFC_FIELD:
|
||||
case UDAT_TIMEZONE_GENERIC_FIELD:
|
||||
case UDAT_TIMEZONE_SPECIAL_FIELD:
|
||||
{
|
||||
int32_t offset = 0;
|
||||
UBool parsed = FALSE;
|
||||
|
||||
// Step 1
|
||||
// Check if this is a long GMT offset string (either localized or default)
|
||||
offset = parseGMT(text, pos);
|
||||
if (pos.getIndex() - start > 0) {
|
||||
parsed = TRUE;
|
||||
}
|
||||
if (!parsed) {
|
||||
// Step 2
|
||||
// Check if this is an RFC822 time zone offset.
|
||||
// ICU supports the standard RFC822 format [+|-]HHmm
|
||||
// and its extended form [+|-]HHmmSS.
|
||||
do {
|
||||
int32_t sign = 0;
|
||||
UChar signChar = text.charAt(start);
|
||||
if (signChar == (UChar)0x002B /* '+' */) {
|
||||
sign = 1;
|
||||
} else if (signChar == (UChar)0x002D /* '-' */) {
|
||||
sign = -1;
|
||||
} else {
|
||||
// Not an RFC822 offset string
|
||||
break;
|
||||
}
|
||||
|
||||
// Parse digits
|
||||
int32_t orgPos = start + 1;
|
||||
pos.setIndex(orgPos);
|
||||
parseInt(text, number, 6, pos, FALSE,currentNumberFormat);
|
||||
int32_t numLen = pos.getIndex() - orgPos;
|
||||
if (numLen <= 0) {
|
||||
break;
|
||||
}
|
||||
|
||||
// Followings are possible format (excluding sign char)
|
||||
// HHmmSS
|
||||
// HmmSS
|
||||
// HHmm
|
||||
// Hmm
|
||||
// HH
|
||||
// H
|
||||
int32_t val = number.getLong();
|
||||
int32_t hour = 0, min = 0, sec = 0;
|
||||
switch(numLen) {
|
||||
case 1: // H
|
||||
case 2: // HH
|
||||
hour = val;
|
||||
break;
|
||||
case 3: // Hmm
|
||||
case 4: // HHmm
|
||||
hour = val / 100;
|
||||
min = val % 100;
|
||||
break;
|
||||
case 5: // Hmmss
|
||||
case 6: // HHmmss
|
||||
hour = val / 10000;
|
||||
min = (val % 10000) / 100;
|
||||
sec = val % 100;
|
||||
break;
|
||||
}
|
||||
if (hour > 23 || min > 59 || sec > 59) {
|
||||
// Invalid value range
|
||||
break;
|
||||
}
|
||||
offset = (((hour * 60) + min) * 60 + sec) * 1000 * sign;
|
||||
parsed = TRUE;
|
||||
} while (FALSE);
|
||||
|
||||
if (!parsed) {
|
||||
// Failed to parse. Reset the position.
|
||||
pos.setIndex(start);
|
||||
}
|
||||
}
|
||||
|
||||
if (parsed) {
|
||||
// offset was successfully parsed as either a long GMT string or RFC822 zone offset
|
||||
// string. Create normalized zone ID for the offset.
|
||||
|
||||
UnicodeString tzID(gGmt);
|
||||
formatRFC822TZ(tzID, offset);
|
||||
//TimeZone *customTZ = TimeZone::createTimeZone(tzID);
|
||||
TimeZone *customTZ = new SimpleTimeZone(offset, tzID); // faster than TimeZone::createTimeZone
|
||||
cal.adoptTimeZone(customTZ);
|
||||
|
||||
UTimeZoneFormatTimeType tzTimeType = UTZFMT_TIME_TYPE_UNKNOWN;
|
||||
UTimeZoneFormatStyle style = (count < 4) ? UTZFMT_STYLE_SPECIFIC_SHORT : UTZFMT_STYLE_SPECIFIC_LONG;
|
||||
TimeZone *tz = tzFormat()->parse(style, text, pos, &tzTimeType);
|
||||
if (tz != NULL) {
|
||||
((SimpleDateFormat*)this)->tztype = tzTimeType;
|
||||
cal.adoptTimeZone(tz);
|
||||
return pos.getIndex();
|
||||
}
|
||||
|
||||
// Step 3
|
||||
// Is this standalone Localized GMT zero or GMT/UT/UTC?
|
||||
int32_t gmtLen = 0;
|
||||
if (text.compare(start, fSymbols->fGmtZero.length(), fSymbols->fGmtZero) == 0) {
|
||||
gmtLen = fSymbols->fGmtZero.length();
|
||||
} else if (text.compare(start, kGmtLen, gGmt) == 0) {
|
||||
gmtLen = kGmtLen;
|
||||
} else if (text.compare(start, kUtcLen, gUtc) == 0) {
|
||||
gmtLen = kUtcLen;
|
||||
} else if (text.compare(start, kUtLen, gUt) == 0) {
|
||||
gmtLen = kUtLen;
|
||||
}
|
||||
// If we parse the string to the end, we can exit here.
|
||||
// If any characters follow, we still need to proceed to the
|
||||
// next step. Otherwise, all time zone names starting with GMT/UT/UTC
|
||||
// (for example, "UTT") will fail.
|
||||
if (gmtLen > 0 && ((text.length() - start) == gmtLen)) {
|
||||
TimeZone *tz = TimeZone::createTimeZone(UNICODE_STRING("Etc/GMT", 7));
|
||||
}
|
||||
break;
|
||||
case UDAT_TIMEZONE_RFC_FIELD:
|
||||
{
|
||||
UTimeZoneFormatTimeType tzTimeType = UTZFMT_TIME_TYPE_UNKNOWN;
|
||||
UTimeZoneFormatStyle style = (count < 4) ? UTZFMT_STYLE_RFC822 : ((count == 5) ? UTZFMT_STYLE_ISO8601: UTZFMT_STYLE_LOCALIZED_GMT);
|
||||
TimeZone *tz = tzFormat()->parse(style, text, pos, &tzTimeType);
|
||||
if (tz != NULL) {
|
||||
((SimpleDateFormat*)this)->tztype = tzTimeType;
|
||||
cal.adoptTimeZone(tz);
|
||||
return start + gmtLen;
|
||||
return pos.getIndex();
|
||||
}
|
||||
|
||||
// Step 4
|
||||
// At this point, check for named time zones by looking through
|
||||
// the locale data.
|
||||
if (patternCharIndex != UDAT_TIMEZONE_RFC_FIELD) {
|
||||
UTimeZoneTimeType parsedTimeType = UTZFMT_TIME_TYPE_UNKNOWN;
|
||||
ParsePosition tmpPos(start);
|
||||
UnicodeString parsedID;
|
||||
|
||||
switch (patternCharIndex) {
|
||||
case UDAT_TIMEZONE_FIELD:
|
||||
if (count < 4) {
|
||||
tzFormat()->parse(UTZFMT_STYLE_SPECIFIC_SHORT, text, tmpPos, parsedID, &parsedTimeType);
|
||||
} else {
|
||||
tzFormat()->parse(UTZFMT_STYLE_SPECIFIC_LONG, text, tmpPos, parsedID, &parsedTimeType);
|
||||
}
|
||||
break;
|
||||
case UDAT_TIMEZONE_GENERIC_FIELD:
|
||||
if (count < 4) {
|
||||
tzFormat()->parse(UTZFMT_STYLE_GENERIC_SHORT, text, tmpPos, parsedID, &parsedTimeType);
|
||||
} else {
|
||||
tzFormat()->parse(UTZFMT_STYLE_GENERIC_LONG, text, tmpPos, parsedID, &parsedTimeType);
|
||||
}
|
||||
break;
|
||||
case UDAT_TIMEZONE_SPECIAL_FIELD:
|
||||
if (count < 4) {
|
||||
tzFormat()->parse(UTZFMT_STYLE_SPECIFIC_SHORT, text, tmpPos, parsedID, &parsedTimeType);
|
||||
} else {
|
||||
tzFormat()->parse(UTZFMT_STYLE_LOCATION, text, tmpPos, parsedID, &parsedTimeType);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
if (tmpPos.getErrorIndex() < 0) {
|
||||
if (parsedTimeType == UTZFMT_TIME_TYPE_STANDARD) {
|
||||
((SimpleDateFormat*)this)->tztype = TZTYPE_STD;
|
||||
} else if (parsedTimeType == UTZFMT_TIME_TYPE_DAYLIGHT) {
|
||||
((SimpleDateFormat*)this)->tztype = TZTYPE_DST;
|
||||
}
|
||||
|
||||
UnicodeString current;
|
||||
cal.getTimeZone().getID(current);
|
||||
if (parsedID != current) {
|
||||
TimeZone *tz = TimeZone::createTimeZone(parsedID);
|
||||
cal.adoptTimeZone(tz);
|
||||
}
|
||||
return tmpPos.getIndex();
|
||||
}
|
||||
}
|
||||
// Step 5
|
||||
// If we saw standalone GMT zero pattern, then use GMT.
|
||||
if (gmtLen > 0) {
|
||||
TimeZone *tz = TimeZone::createTimeZone(UNICODE_STRING("Etc/GMT", 7));
|
||||
return -start;
|
||||
}
|
||||
case UDAT_TIMEZONE_GENERIC_FIELD:
|
||||
{
|
||||
UTimeZoneFormatTimeType tzTimeType = UTZFMT_TIME_TYPE_UNKNOWN;
|
||||
UTimeZoneFormatStyle style = (count < 4) ? UTZFMT_STYLE_GENERIC_SHORT : UTZFMT_STYLE_GENERIC_LONG;
|
||||
TimeZone *tz = tzFormat()->parse(style, text, pos, &tzTimeType);
|
||||
if (tz != NULL) {
|
||||
((SimpleDateFormat*)this)->tztype = tzTimeType;
|
||||
cal.adoptTimeZone(tz);
|
||||
return start + gmtLen;
|
||||
return pos.getIndex();
|
||||
}
|
||||
return -start;
|
||||
}
|
||||
case UDAT_TIMEZONE_SPECIAL_FIELD:
|
||||
{
|
||||
UTimeZoneFormatTimeType tzTimeType = UTZFMT_TIME_TYPE_UNKNOWN;
|
||||
UTimeZoneFormatStyle style = (count < 4) ? UTZFMT_STYLE_SPECIFIC_SHORT : UTZFMT_STYLE_GENERIC_LOCATION;
|
||||
TimeZone *tz = tzFormat()->parse(style, text, pos, &tzTimeType);
|
||||
if (tz != NULL) {
|
||||
((SimpleDateFormat*)this)->tztype = tzTimeType;
|
||||
cal.adoptTimeZone(tz);
|
||||
return pos.getIndex();
|
||||
}
|
||||
|
||||
// complete failure
|
||||
return -start;
|
||||
}
|
||||
|
||||
|
@ -3579,6 +3063,27 @@ SimpleDateFormat::setDateFormatSymbols(const DateFormatSymbols& newFormatSymbols
|
|||
fSymbols = new DateFormatSymbols(newFormatSymbols);
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
const TimeZoneFormat*
|
||||
SimpleDateFormat::getTimeZoneFormat(void) const {
|
||||
return (const TimeZoneFormat*)tzFormat();
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
void
|
||||
SimpleDateFormat::adoptTimeZoneFormat(TimeZoneFormat* timeZoneFormatToAdopt)
|
||||
{
|
||||
delete fTimeZoneFormat;
|
||||
fTimeZoneFormat = timeZoneFormatToAdopt;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
void
|
||||
SimpleDateFormat::setTimeZoneFormat(const TimeZoneFormat& newTimeZoneFormat)
|
||||
{
|
||||
delete fTimeZoneFormat;
|
||||
fTimeZoneFormat = new TimeZoneFormat(newTimeZoneFormat);
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
|
||||
|
@ -3845,6 +3350,7 @@ SimpleDateFormat::tzFormat() const {
|
|||
}
|
||||
return fTimeZoneFormat;
|
||||
}
|
||||
|
||||
U_NAMESPACE_END
|
||||
|
||||
#endif /* #if !UCONFIG_NO_FORMATTING */
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
*******************************************************************************
|
||||
* Copyright (C) 1997-2011, International Business Machines Corporation and *
|
||||
* Copyright (C) 1997-2012, International Business Machines Corporation and *
|
||||
* others. All Rights Reserved. *
|
||||
*******************************************************************************
|
||||
*
|
||||
|
@ -68,10 +68,11 @@ static char gStrBuf[256];
|
|||
#if !UCONFIG_NO_FORMATTING
|
||||
|
||||
#include "unicode/simpletz.h"
|
||||
#include "unicode/smpdtfmt.h"
|
||||
#include "unicode/calendar.h"
|
||||
#include "unicode/gregocal.h"
|
||||
#include "unicode/ures.h"
|
||||
#include "unicode/tzfmt.h"
|
||||
#include "unicode/numfmt.h"
|
||||
#include "gregoimp.h"
|
||||
#include "uresimp.h" // struct UResourceBundle
|
||||
#include "olsontz.h"
|
||||
|
@ -1238,127 +1239,75 @@ TimeZone::getDSTSavings()const {
|
|||
UnicodeString&
|
||||
TimeZone::getDisplayName(UBool daylight, EDisplayType style, const Locale& locale, UnicodeString& result) const
|
||||
{
|
||||
// SRL TODO: cache the SDF, just like java.
|
||||
UErrorCode status = U_ZERO_ERROR;
|
||||
#ifdef U_DEBUG_TZ
|
||||
char buf[128];
|
||||
fID.extract(0, sizeof(buf)-1, buf, sizeof(buf), "");
|
||||
#endif
|
||||
UDate date = Calendar::getNow();
|
||||
UTimeZoneFormatTimeType timeType;
|
||||
int32_t offset;
|
||||
|
||||
// select the proper format string
|
||||
const UChar* patUChars;
|
||||
switch(style){
|
||||
case LONG:
|
||||
patUChars = ZZZZ_STR;
|
||||
break;
|
||||
case SHORT_GENERIC:
|
||||
patUChars = V_STR;
|
||||
break;
|
||||
case LONG_GENERIC:
|
||||
patUChars = VVVV_STR;
|
||||
break;
|
||||
case SHORT_GMT:
|
||||
patUChars = Z_UC_STR;
|
||||
break;
|
||||
case LONG_GMT:
|
||||
patUChars = ZZZZ_UC_STR;
|
||||
break;
|
||||
case SHORT_COMMONLY_USED:
|
||||
//patUChars = V_UC_STR;
|
||||
patUChars = Z_STR;
|
||||
break;
|
||||
case GENERIC_LOCATION:
|
||||
patUChars = VVVV_UC_STR;
|
||||
break;
|
||||
default: // SHORT
|
||||
//patUChars = Z_STR;
|
||||
patUChars = V_UC_STR;
|
||||
break;
|
||||
}
|
||||
UnicodeString pat(TRUE, patUChars, -1);
|
||||
|
||||
SimpleDateFormat format(pat, locale, status);
|
||||
U_DEBUG_TZ_MSG(("getDisplayName(%s)\n", buf));
|
||||
if(!U_SUCCESS(status))
|
||||
{
|
||||
#ifdef U_DEBUG_TZ
|
||||
char buf2[128];
|
||||
result.extract(0, sizeof(buf2)-1, buf2, sizeof(buf2), "");
|
||||
U_DEBUG_TZ_MSG(("getDisplayName(%s) -> %s\n", buf, buf2));
|
||||
#endif
|
||||
return result.remove();
|
||||
}
|
||||
|
||||
UDate d = Calendar::getNow();
|
||||
int32_t rawOffset;
|
||||
int32_t dstOffset;
|
||||
this->getOffset(d, FALSE, rawOffset, dstOffset, status);
|
||||
if (U_FAILURE(status)) {
|
||||
return result.remove();
|
||||
}
|
||||
|
||||
if ((daylight && dstOffset != 0) ||
|
||||
(!daylight && dstOffset == 0) ||
|
||||
(style == SHORT_GENERIC) ||
|
||||
(style == LONG_GENERIC)
|
||||
) {
|
||||
// Current time and the request (daylight / not daylight) agree.
|
||||
format.setTimeZone(*this);
|
||||
return format.format(d, result);
|
||||
}
|
||||
|
||||
// Create a new SimpleTimeZone as a stand-in for this zone; the
|
||||
// stand-in will have no DST, or DST during July, but the same ID and offset,
|
||||
// and hence the same display name.
|
||||
// We don't cache these because they're small and cheap to create.
|
||||
UnicodeString tempID;
|
||||
getID(tempID);
|
||||
SimpleTimeZone *tz = NULL;
|
||||
if(daylight && useDaylightTime()){
|
||||
// The display name for daylight saving time was requested, but currently not in DST
|
||||
// Set a fixed date (July 1) in this Gregorian year
|
||||
GregorianCalendar cal(*this, status);
|
||||
if (U_FAILURE(status)) {
|
||||
return result.remove();
|
||||
if (style == GENERIC_LOCATION || style == LONG_GENERIC || style == SHORT_GENERIC) {
|
||||
LocalPointer<TimeZoneFormat> tzfmt(TimeZoneFormat::createInstance(locale, status));
|
||||
// Generic format
|
||||
switch (style) {
|
||||
case GENERIC_LOCATION:
|
||||
tzfmt->format(UTZFMT_STYLE_GENERIC_LOCATION, *this, date, result, &timeType);
|
||||
break;
|
||||
case LONG_GENERIC:
|
||||
tzfmt->format(UTZFMT_STYLE_GENERIC_LONG, *this, date, result, &timeType);
|
||||
break;
|
||||
case SHORT_GENERIC:
|
||||
tzfmt->format(UTZFMT_STYLE_GENERIC_SHORT, *this, date, result, &timeType);
|
||||
break;
|
||||
default:
|
||||
U_ASSERT(FALSE);
|
||||
}
|
||||
cal.set(UCAL_MONTH, UCAL_JULY);
|
||||
cal.set(UCAL_DATE, 1);
|
||||
|
||||
// Get July 1 date
|
||||
d = cal.getTime(status);
|
||||
|
||||
// Check if it is in DST
|
||||
if (cal.get(UCAL_DST_OFFSET, status) == 0) {
|
||||
// We need to create a fake time zone
|
||||
tz = new SimpleTimeZone(rawOffset, tempID,
|
||||
UCAL_JUNE, 1, 0, 0,
|
||||
UCAL_AUGUST, 1, 0, 0,
|
||||
getDSTSavings(), status);
|
||||
if (U_FAILURE(status) || tz == NULL) {
|
||||
if (U_SUCCESS(status)) {
|
||||
status = U_MEMORY_ALLOCATION_ERROR;
|
||||
}
|
||||
return result.remove();
|
||||
}
|
||||
format.adoptTimeZone(tz);
|
||||
} else {
|
||||
format.setTimeZone(*this);
|
||||
// Generic format many use Localized GMT as the final fallback.
|
||||
// When Localized GMT format is used, the result might not be
|
||||
// appropriate for the requested daylight value.
|
||||
if ((daylight && timeType == UTZFMT_TIME_TYPE_STANDARD) || (!daylight && timeType == UTZFMT_TIME_TYPE_DAYLIGHT)) {
|
||||
offset = daylight ? getRawOffset() + getDSTSavings() : getRawOffset();
|
||||
tzfmt->formatOffsetLocalizedGMT(offset, result, status);
|
||||
}
|
||||
} else if (style == LONG_GMT || style == SHORT_GMT) {
|
||||
LocalPointer<TimeZoneFormat> tzfmt(TimeZoneFormat::createInstance(locale, status));
|
||||
offset = daylight && useDaylightTime() ? getRawOffset() + getDSTSavings() : getRawOffset();
|
||||
switch (style) {
|
||||
case LONG_GMT:
|
||||
tzfmt->formatOffsetLocalizedGMT(offset, result, status);
|
||||
break;
|
||||
case SHORT_GMT:
|
||||
tzfmt->formatOffsetRFC822(offset, result, status);
|
||||
break;
|
||||
default:
|
||||
U_ASSERT(FALSE);
|
||||
}
|
||||
|
||||
} else {
|
||||
// The display name for standard time was requested, but currently in DST
|
||||
// or display name for daylight saving time was requested, but this zone no longer
|
||||
// observes DST.
|
||||
tz = new SimpleTimeZone(rawOffset, tempID);
|
||||
if (U_FAILURE(status) || tz == NULL) {
|
||||
if (U_SUCCESS(status)) {
|
||||
status = U_MEMORY_ALLOCATION_ERROR;
|
||||
}
|
||||
return result.remove();
|
||||
U_ASSERT(style == LONG || style == SHORT || style == SHORT_COMMONLY_USED);
|
||||
UTimeZoneNameType nameType = UTZNM_UNKNOWN;
|
||||
switch (style) {
|
||||
case LONG:
|
||||
nameType = daylight ? UTZNM_LONG_DAYLIGHT : UTZNM_LONG_STANDARD;
|
||||
break;
|
||||
case SHORT:
|
||||
case SHORT_COMMONLY_USED:
|
||||
nameType = daylight ? UTZNM_SHORT_DAYLIGHT : UTZNM_SHORT_STANDARD;
|
||||
break;
|
||||
default:
|
||||
U_ASSERT(FALSE);
|
||||
}
|
||||
LocalPointer<TimeZoneNames> tznames(TimeZoneNames::createInstance(locale, status));
|
||||
UnicodeString canonicalID(ZoneMeta::getCanonicalCLDRID(*this));
|
||||
tznames->getDisplayName(canonicalID, nameType, date, result);
|
||||
if (result.isEmpty()) {
|
||||
// Fallback to localized GMT
|
||||
LocalPointer<TimeZoneFormat> tzfmt(TimeZoneFormat::createInstance(locale, status));
|
||||
offset = daylight && useDaylightTime() ? getRawOffset() + getDSTSavings() : getRawOffset();
|
||||
tzfmt->formatOffsetLocalizedGMT(offset, result, status);
|
||||
}
|
||||
format.adoptTimeZone(tz);
|
||||
}
|
||||
|
||||
format.format(d, result, status);
|
||||
if (U_FAILURE(status)) {
|
||||
result.remove();
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -1,64 +0,0 @@
|
|||
/*
|
||||
*******************************************************************************
|
||||
* Copyright (C) 2011, International Business Machines Corporation and *
|
||||
* others. All Rights Reserved. *
|
||||
*******************************************************************************
|
||||
*/
|
||||
#ifndef __TZFMT_H
|
||||
#define __TZFMT_H
|
||||
|
||||
#include "unicode/utypes.h"
|
||||
|
||||
#if !UCONFIG_NO_FORMATTING
|
||||
|
||||
#include "unicode/uobject.h"
|
||||
#include "unicode/uloc.h"
|
||||
#include "unicode/unistr.h"
|
||||
#include "unicode/format.h"
|
||||
#include "unicode/timezone.h"
|
||||
#include "tznames.h"
|
||||
|
||||
U_CDECL_BEGIN
|
||||
|
||||
typedef enum UTimeZoneFormatStyle {
|
||||
UTZFMT_STYLE_LOCATION,
|
||||
UTZFMT_STYLE_GENERIC_LONG,
|
||||
UTZFMT_STYLE_GENERIC_SHORT,
|
||||
UTZFMT_STYLE_SPECIFIC_LONG,
|
||||
UTZFMT_STYLE_SPECIFIC_SHORT
|
||||
} UTimeZoneFormatStyle;
|
||||
|
||||
typedef enum UTimeZoneTimeType {
|
||||
UTZFMT_TIME_TYPE_UNKNOWN,
|
||||
UTZFMT_TIME_TYPE_STANDARD,
|
||||
UTZFMT_TIME_TYPE_DAYLIGHT
|
||||
} UTimeZoneTimeType;
|
||||
|
||||
U_CDECL_END
|
||||
|
||||
U_NAMESPACE_BEGIN
|
||||
|
||||
class TimeZoneNames;
|
||||
|
||||
class U_I18N_API TimeZoneFormat : public UMemory {
|
||||
public:
|
||||
virtual ~TimeZoneFormat();
|
||||
|
||||
static TimeZoneFormat* U_EXPORT2 createInstance(const Locale& locale, UErrorCode& status);
|
||||
|
||||
virtual const TimeZoneNames* getTimeZoneNames() const = 0;
|
||||
|
||||
virtual UnicodeString& format(UTimeZoneFormatStyle style, const TimeZone& tz, UDate date,
|
||||
UnicodeString& name, UTimeZoneTimeType* timeType = NULL) const = 0;
|
||||
|
||||
virtual UnicodeString& parse(UTimeZoneFormatStyle style, const UnicodeString& text, ParsePosition& pos,
|
||||
UnicodeString& tzID, UTimeZoneTimeType* timeType = NULL) const = 0;
|
||||
|
||||
TimeZone* parse(UTimeZoneFormatStyle style, const UnicodeString& text, ParsePosition& pos,
|
||||
UTimeZoneTimeType* timeType = NULL) const;
|
||||
};
|
||||
|
||||
U_NAMESPACE_END
|
||||
|
||||
#endif
|
||||
#endif
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
*******************************************************************************
|
||||
* Copyright (C) 2012, International Business Machines Corporation and
|
||||
* Copyright (C) 2011-2012, International Business Machines Corporation and
|
||||
* others. All Rights Reserved.
|
||||
*******************************************************************************
|
||||
*/
|
||||
|
@ -28,6 +28,7 @@
|
|||
#include "zonemeta.h"
|
||||
#include "tznames_impl.h"
|
||||
#include "olsontz.h"
|
||||
#include "ucln_in.h"
|
||||
|
||||
U_NAMESPACE_BEGIN
|
||||
|
||||
|
@ -112,7 +113,7 @@ typedef struct GNameInfo {
|
|||
typedef struct GMatchInfo {
|
||||
const GNameInfo* gnameInfo;
|
||||
int32_t matchLength;
|
||||
UTimeZoneTimeType timeType;
|
||||
UTimeZoneFormatTimeType timeType;
|
||||
} ZMatchInfo;
|
||||
|
||||
U_CDECL_END
|
||||
|
@ -120,6 +121,20 @@ U_CDECL_END
|
|||
// ---------------------------------------------------
|
||||
// The class stores time zone generic name match information
|
||||
// ---------------------------------------------------
|
||||
class TimeZoneGenericNameMatchInfo : public UMemory {
|
||||
public:
|
||||
TimeZoneGenericNameMatchInfo(UVector* matches);
|
||||
~TimeZoneGenericNameMatchInfo();
|
||||
|
||||
int32_t size() const;
|
||||
UTimeZoneGenericNameType getGenericNameType(int32_t index) const;
|
||||
int32_t getMatchLength(int32_t index) const;
|
||||
UnicodeString& getTimeZoneID(int32_t index, UnicodeString& tzID) const;
|
||||
|
||||
private:
|
||||
UVector* fMatches; // vector of MatchEntry
|
||||
};
|
||||
|
||||
TimeZoneGenericNameMatchInfo::TimeZoneGenericNameMatchInfo(UVector* matches)
|
||||
: fMatches(matches) {
|
||||
}
|
||||
|
@ -252,14 +267,69 @@ GNameSearchHandler::getMatches(int32_t& maxMatchLen) {
|
|||
return results;
|
||||
}
|
||||
|
||||
class TZGNCore : public UMemory {
|
||||
public:
|
||||
TZGNCore(const Locale& locale, UErrorCode& status);
|
||||
virtual ~TZGNCore();
|
||||
|
||||
UnicodeString& getDisplayName(const TimeZone& tz, UTimeZoneGenericNameType type,
|
||||
UDate date, UnicodeString& name) const;
|
||||
|
||||
UnicodeString& getGenericLocationName(const UnicodeString& tzCanonicalID, UnicodeString& name) const;
|
||||
|
||||
int32_t findBestMatch(const UnicodeString& text, int32_t start, uint32_t types,
|
||||
UnicodeString& tzID, UTimeZoneFormatTimeType& timeType, UErrorCode& status) const;
|
||||
|
||||
private:
|
||||
Locale fLocale;
|
||||
UMTX fLock;
|
||||
const TimeZoneNames* fTimeZoneNames;
|
||||
UHashtable* fLocationNamesMap;
|
||||
UHashtable* fPartialLocationNamesMap;
|
||||
|
||||
MessageFormat* fRegionFormat;
|
||||
MessageFormat* fFallbackRegionFormat;
|
||||
MessageFormat* fFallbackFormat;
|
||||
|
||||
LocaleDisplayNames* fLocaleDisplayNames;
|
||||
ZNStringPool fStringPool;
|
||||
|
||||
TextTrieMap fGNamesTrie;
|
||||
UBool fGNamesTrieFullyLoaded;
|
||||
|
||||
char fTargetRegion[ULOC_COUNTRY_CAPACITY];
|
||||
|
||||
void initialize(const Locale& locale, UErrorCode& status);
|
||||
void cleanup();
|
||||
|
||||
void loadStrings(const UnicodeString& tzCanonicalID);
|
||||
|
||||
const UChar* getGenericLocationName(const UnicodeString& tzCanonicalID);
|
||||
|
||||
UnicodeString& formatGenericNonLocationName(const TimeZone& tz, UTimeZoneGenericNameType type,
|
||||
UDate date, UnicodeString& name) const;
|
||||
|
||||
UnicodeString& getPartialLocationName(const UnicodeString& tzCanonicalID,
|
||||
const UnicodeString& mzID, UBool isLong, const UnicodeString& mzDisplayName,
|
||||
UnicodeString& name) const;
|
||||
|
||||
const UChar* getPartialLocationName(const UnicodeString& tzCanonicalID,
|
||||
const UnicodeString& mzID, UBool isLong, const UnicodeString& mzDisplayName);
|
||||
|
||||
TimeZoneGenericNameMatchInfo* findLocal(const UnicodeString& text, int32_t start, uint32_t types, UErrorCode& status) const;
|
||||
|
||||
TimeZoneNames::MatchInfoCollection* findTimeZoneNames(const UnicodeString& text, int32_t start, uint32_t types, UErrorCode& status) const;
|
||||
};
|
||||
|
||||
|
||||
// ---------------------------------------------------
|
||||
// TimeZoneGenericNames
|
||||
// TZGNCore - core implmentation of TimeZoneGenericNames
|
||||
//
|
||||
// TimeZoneGenericNames is parallel to TimeZoneNames,
|
||||
// but handles run-time generated time zone names.
|
||||
// This is the main part of this module.
|
||||
// ---------------------------------------------------
|
||||
TimeZoneGenericNames::TimeZoneGenericNames(const Locale& locale, UErrorCode& status)
|
||||
TZGNCore::TZGNCore(const Locale& locale, UErrorCode& status)
|
||||
: fLocale(locale),
|
||||
fLock(NULL),
|
||||
fTimeZoneNames(NULL),
|
||||
|
@ -275,13 +345,13 @@ TimeZoneGenericNames::TimeZoneGenericNames(const Locale& locale, UErrorCode& sta
|
|||
initialize(locale, status);
|
||||
}
|
||||
|
||||
TimeZoneGenericNames::~TimeZoneGenericNames() {
|
||||
TZGNCore::~TZGNCore() {
|
||||
cleanup();
|
||||
umtx_destroy(&fLock);
|
||||
}
|
||||
|
||||
void
|
||||
TimeZoneGenericNames::initialize(const Locale& locale, UErrorCode& status) {
|
||||
TZGNCore::initialize(const Locale& locale, UErrorCode& status) {
|
||||
if (U_FAILURE(status)) {
|
||||
return;
|
||||
}
|
||||
|
@ -384,7 +454,7 @@ TimeZoneGenericNames::initialize(const Locale& locale, UErrorCode& status) {
|
|||
}
|
||||
|
||||
void
|
||||
TimeZoneGenericNames::cleanup() {
|
||||
TZGNCore::cleanup() {
|
||||
if (fRegionFormat != NULL) {
|
||||
delete fRegionFormat;
|
||||
}
|
||||
|
@ -405,8 +475,9 @@ TimeZoneGenericNames::cleanup() {
|
|||
uhash_close(fPartialLocationNamesMap);
|
||||
}
|
||||
|
||||
|
||||
UnicodeString&
|
||||
TimeZoneGenericNames::getDisplayName(const TimeZone& tz, UTimeZoneGenericNameType type, UDate date, UnicodeString& name) const {
|
||||
TZGNCore::getDisplayName(const TimeZone& tz, UTimeZoneGenericNameType type, UDate date, UnicodeString& name) const {
|
||||
name.setToBogus();
|
||||
switch (type) {
|
||||
case UTZGNM_LOCATION:
|
||||
|
@ -434,14 +505,14 @@ TimeZoneGenericNames::getDisplayName(const TimeZone& tz, UTimeZoneGenericNameTyp
|
|||
}
|
||||
|
||||
UnicodeString&
|
||||
TimeZoneGenericNames::getGenericLocationName(const UnicodeString& tzCanonicalID, UnicodeString& name) const {
|
||||
TZGNCore::getGenericLocationName(const UnicodeString& tzCanonicalID, UnicodeString& name) const {
|
||||
if (tzCanonicalID.isEmpty()) {
|
||||
name.setToBogus();
|
||||
return name;
|
||||
}
|
||||
|
||||
const UChar *locname = NULL;
|
||||
TimeZoneGenericNames *nonConstThis = const_cast<TimeZoneGenericNames *>(this);
|
||||
TZGNCore *nonConstThis = const_cast<TZGNCore *>(this);
|
||||
umtx_lock(&nonConstThis->fLock);
|
||||
{
|
||||
locname = nonConstThis->getGenericLocationName(tzCanonicalID);
|
||||
|
@ -451,7 +522,7 @@ TimeZoneGenericNames::getGenericLocationName(const UnicodeString& tzCanonicalID,
|
|||
if (locname == NULL) {
|
||||
name.setToBogus();
|
||||
} else {
|
||||
name.setTo(TRUE, locname, -1);
|
||||
name.setTo(locname, u_strlen(locname));
|
||||
}
|
||||
|
||||
return name;
|
||||
|
@ -461,7 +532,7 @@ TimeZoneGenericNames::getGenericLocationName(const UnicodeString& tzCanonicalID,
|
|||
* This method updates the cache and must be called with a lock
|
||||
*/
|
||||
const UChar*
|
||||
TimeZoneGenericNames::getGenericLocationName(const UnicodeString& tzCanonicalID) {
|
||||
TZGNCore::getGenericLocationName(const UnicodeString& tzCanonicalID) {
|
||||
U_ASSERT(!tzCanonicalID.isEmpty());
|
||||
if (tzCanonicalID.length() > ZID_KEY_MAX) {
|
||||
return NULL;
|
||||
|
@ -556,7 +627,7 @@ TimeZoneGenericNames::getGenericLocationName(const UnicodeString& tzCanonicalID)
|
|||
}
|
||||
|
||||
UnicodeString&
|
||||
TimeZoneGenericNames::formatGenericNonLocationName(const TimeZone& tz, UTimeZoneGenericNameType type, UDate date, UnicodeString& name) const {
|
||||
TZGNCore::formatGenericNonLocationName(const TimeZone& tz, UTimeZoneGenericNameType type, UDate date, UnicodeString& name) const {
|
||||
U_ASSERT(type == UTZGNM_LONG || type == UTZGNM_SHORT);
|
||||
name.setToBogus();
|
||||
|
||||
|
@ -694,7 +765,7 @@ TimeZoneGenericNames::formatGenericNonLocationName(const TimeZone& tz, UTimeZone
|
|||
}
|
||||
|
||||
UnicodeString&
|
||||
TimeZoneGenericNames::getPartialLocationName(const UnicodeString& tzCanonicalID,
|
||||
TZGNCore::getPartialLocationName(const UnicodeString& tzCanonicalID,
|
||||
const UnicodeString& mzID, UBool isLong, const UnicodeString& mzDisplayName,
|
||||
UnicodeString& name) const {
|
||||
name.setToBogus();
|
||||
|
@ -703,7 +774,7 @@ TimeZoneGenericNames::getPartialLocationName(const UnicodeString& tzCanonicalID,
|
|||
}
|
||||
|
||||
const UChar *uplname = NULL;
|
||||
TimeZoneGenericNames *nonConstThis = const_cast<TimeZoneGenericNames *>(this);
|
||||
TZGNCore *nonConstThis = const_cast<TZGNCore *>(this);
|
||||
umtx_lock(&nonConstThis->fLock);
|
||||
{
|
||||
uplname = nonConstThis->getPartialLocationName(tzCanonicalID, mzID, isLong, mzDisplayName);
|
||||
|
@ -722,7 +793,7 @@ TimeZoneGenericNames::getPartialLocationName(const UnicodeString& tzCanonicalID,
|
|||
* This method updates the cache and must be called with a lock
|
||||
*/
|
||||
const UChar*
|
||||
TimeZoneGenericNames::getPartialLocationName(const UnicodeString& tzCanonicalID,
|
||||
TZGNCore::getPartialLocationName(const UnicodeString& tzCanonicalID,
|
||||
const UnicodeString& mzID, UBool isLong, const UnicodeString& mzDisplayName) {
|
||||
U_ASSERT(!tzCanonicalID.isEmpty());
|
||||
U_ASSERT(!mzID.isEmpty());
|
||||
|
@ -810,7 +881,7 @@ TimeZoneGenericNames::getPartialLocationName(const UnicodeString& tzCanonicalID,
|
|||
* except initializer.
|
||||
*/
|
||||
void
|
||||
TimeZoneGenericNames::loadStrings(const UnicodeString& tzCanonicalID) {
|
||||
TZGNCore::loadStrings(const UnicodeString& tzCanonicalID) {
|
||||
// load the generic location name
|
||||
getGenericLocationName(tzCanonicalID);
|
||||
|
||||
|
@ -851,8 +922,8 @@ TimeZoneGenericNames::loadStrings(const UnicodeString& tzCanonicalID) {
|
|||
}
|
||||
|
||||
int32_t
|
||||
TimeZoneGenericNames::findBestMatch(const UnicodeString& text, int32_t start, uint32_t types,
|
||||
UnicodeString& tzID, UTimeZoneTimeType& timeType, UErrorCode& status) const {
|
||||
TZGNCore::findBestMatch(const UnicodeString& text, int32_t start, uint32_t types,
|
||||
UnicodeString& tzID, UTimeZoneFormatTimeType& timeType, UErrorCode& status) const {
|
||||
timeType = UTZFMT_TIME_TYPE_UNKNOWN;
|
||||
tzID.setToBogus();
|
||||
|
||||
|
@ -861,13 +932,13 @@ TimeZoneGenericNames::findBestMatch(const UnicodeString& text, int32_t start, ui
|
|||
}
|
||||
|
||||
// Find matches in the TimeZoneNames first
|
||||
TimeZoneNameMatchInfo *tznamesMatches = findTimeZoneNames(text, start, types, status);
|
||||
TimeZoneNames::MatchInfoCollection *tznamesMatches = findTimeZoneNames(text, start, types, status);
|
||||
if (U_FAILURE(status)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
int32_t bestMatchLen = 0;
|
||||
UTimeZoneTimeType bestMatchTimeType = UTZFMT_TIME_TYPE_UNKNOWN;
|
||||
UTimeZoneFormatTimeType bestMatchTimeType = UTZFMT_TIME_TYPE_UNKNOWN;
|
||||
UnicodeString bestMatchTzID;
|
||||
// UBool isLongStandard = FALSE; // workaround - see the comments below
|
||||
UBool isStandard = FALSE; // TODO: Temporary hack (on hack) for short standard name/location name conflict (found in zh_Hant), should be removed after CLDR 21m1 integration
|
||||
|
@ -875,17 +946,19 @@ TimeZoneGenericNames::findBestMatch(const UnicodeString& text, int32_t start, ui
|
|||
if (tznamesMatches != NULL) {
|
||||
UnicodeString mzID;
|
||||
for (int32_t i = 0; i < tznamesMatches->size(); i++) {
|
||||
int32_t len = tznamesMatches->getMatchLength(i);
|
||||
int32_t len = tznamesMatches->getMatchLengthAt(i);
|
||||
if (len > bestMatchLen) {
|
||||
bestMatchLen = len;
|
||||
tznamesMatches->getTimeZoneID(i, bestMatchTzID);
|
||||
if (bestMatchTzID.isEmpty()) {
|
||||
if (!tznamesMatches->getTimeZoneIDAt(i, bestMatchTzID)) {
|
||||
// name for a meta zone
|
||||
tznamesMatches->getMetaZoneID(i, mzID);
|
||||
U_ASSERT(mzID.length() > 0);
|
||||
fTimeZoneNames->getReferenceZoneID(mzID, fTargetRegion, bestMatchTzID);
|
||||
if (tznamesMatches->getMetaZoneIDAt(i, mzID)) {
|
||||
fTimeZoneNames->getReferenceZoneID(mzID, fTargetRegion, bestMatchTzID);
|
||||
}
|
||||
}
|
||||
UTimeZoneNameType nameType = tznamesMatches->getNameTypeAt(i);
|
||||
if (U_FAILURE(status)) {
|
||||
break;
|
||||
}
|
||||
UTimeZoneNameType nameType = tznamesMatches->getNameType(i);
|
||||
switch (nameType) {
|
||||
case UTZNM_LONG_STANDARD:
|
||||
// isLongStandard = TRUE;
|
||||
|
@ -903,6 +976,9 @@ TimeZoneGenericNames::findBestMatch(const UnicodeString& text, int32_t start, ui
|
|||
}
|
||||
}
|
||||
delete tznamesMatches;
|
||||
if (U_FAILURE(status)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (bestMatchLen == (text.length() - start)) {
|
||||
// Full match
|
||||
|
@ -967,10 +1043,10 @@ TimeZoneGenericNames::findBestMatch(const UnicodeString& text, int32_t start, ui
|
|||
}
|
||||
|
||||
TimeZoneGenericNameMatchInfo*
|
||||
TimeZoneGenericNames::findLocal(const UnicodeString& text, int32_t start, uint32_t types, UErrorCode& status) const {
|
||||
TZGNCore::findLocal(const UnicodeString& text, int32_t start, uint32_t types, UErrorCode& status) const {
|
||||
GNameSearchHandler handler(types);
|
||||
|
||||
TimeZoneGenericNames *nonConstThis = const_cast<TimeZoneGenericNames *>(this);
|
||||
TZGNCore *nonConstThis = const_cast<TZGNCore *>(this);
|
||||
|
||||
umtx_lock(&nonConstThis->fLock);
|
||||
{
|
||||
|
@ -1051,10 +1127,8 @@ TimeZoneGenericNames::findLocal(const UnicodeString& text, int32_t start, uint32
|
|||
return gmatchInfo;
|
||||
}
|
||||
|
||||
TimeZoneNameMatchInfo*
|
||||
TimeZoneGenericNames::findTimeZoneNames(const UnicodeString& text, int32_t start, uint32_t types, UErrorCode& status) const {
|
||||
TimeZoneNameMatchInfo *matchInfo = NULL;
|
||||
|
||||
TimeZoneNames::MatchInfoCollection*
|
||||
TZGNCore::findTimeZoneNames(const UnicodeString& text, int32_t start, uint32_t types, UErrorCode& status) const {
|
||||
// Check if the target name typs is really in the TimeZoneNames
|
||||
uint32_t nameTypes = 0;
|
||||
if (types & UTZGNM_LONG) {
|
||||
|
@ -1066,10 +1140,236 @@ TimeZoneGenericNames::findTimeZoneNames(const UnicodeString& text, int32_t start
|
|||
|
||||
if (types) {
|
||||
// Find matches in the TimeZoneNames
|
||||
matchInfo = fTimeZoneNames->find(text, start, nameTypes, status);
|
||||
return fTimeZoneNames->find(text, start, nameTypes, status);
|
||||
}
|
||||
|
||||
return matchInfo;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
typedef struct TZGNCoreRef {
|
||||
TZGNCore* obj;
|
||||
int32_t refCount;
|
||||
double lastAccess;
|
||||
} TZGNCoreRef;
|
||||
|
||||
// TZGNCore object cache handling
|
||||
static UMTX gTZGNLock = NULL;
|
||||
static UHashtable *gTZGNCoreCache = NULL;
|
||||
static UBool gTZGNCoreCacheInitialized = FALSE;
|
||||
|
||||
// Access count - incremented every time up to SWEEP_INTERVAL,
|
||||
// then reset to 0
|
||||
static int32_t gAccessCount = 0;
|
||||
|
||||
// Interval for calling the cache sweep function - every 100 times
|
||||
#define SWEEP_INTERVAL 100
|
||||
|
||||
// Cache expiration in millisecond. When a cached entry is no
|
||||
// longer referenced and exceeding this threshold since last
|
||||
// access time, then the cache entry will be deleted by the sweep
|
||||
// function. For now, 3 minutes.
|
||||
#define CACHE_EXPIRATION 180000.0
|
||||
|
||||
U_CDECL_BEGIN
|
||||
/**
|
||||
* Cleanup callback func
|
||||
*/
|
||||
static UBool U_CALLCONV tzgnCore_cleanup(void)
|
||||
{
|
||||
umtx_destroy(&gTZGNLock);
|
||||
|
||||
if (gTZGNCoreCache != NULL) {
|
||||
uhash_close(gTZGNCoreCache);
|
||||
gTZGNCoreCache = NULL;
|
||||
}
|
||||
gTZGNCoreCacheInitialized = FALSE;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Deleter for TZGNCoreRef
|
||||
*/
|
||||
static void U_CALLCONV
|
||||
deleteTZGNCoreRef(void *obj) {
|
||||
icu::TZGNCoreRef *entry = (icu::TZGNCoreRef*)obj;
|
||||
delete (icu::TZGNCore*) entry->obj;
|
||||
uprv_free(entry);
|
||||
}
|
||||
U_CDECL_END
|
||||
|
||||
/**
|
||||
* Function used for removing unreferrenced cache entries exceeding
|
||||
* the expiration time. This function must be called with in the mutex
|
||||
* block.
|
||||
*/
|
||||
static void sweepCache() {
|
||||
int32_t pos = -1;
|
||||
const UHashElement* elem;
|
||||
double now = (double)uprv_getUTCtime();
|
||||
|
||||
while ((elem = uhash_nextElement(gTZGNCoreCache, &pos))) {
|
||||
TZGNCoreRef *entry = (TZGNCoreRef *)elem->value.pointer;
|
||||
if (entry->refCount <= 0 && (now - entry->lastAccess) > CACHE_EXPIRATION) {
|
||||
// delete this entry
|
||||
uhash_removeElement(gTZGNCoreCache, elem);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
TimeZoneGenericNames::TimeZoneGenericNames()
|
||||
: fRef(0) {
|
||||
}
|
||||
|
||||
TimeZoneGenericNames::~TimeZoneGenericNames() {
|
||||
umtx_lock(&gTZGNLock);
|
||||
{
|
||||
U_ASSERT(fRef->refCount > 0);
|
||||
// Just decrement the reference count
|
||||
fRef->refCount--;
|
||||
}
|
||||
umtx_unlock(&gTZGNLock);
|
||||
}
|
||||
|
||||
TimeZoneGenericNames*
|
||||
TimeZoneGenericNames::createInstance(const Locale& locale, UErrorCode& status) {
|
||||
if (U_FAILURE(status)) {
|
||||
return NULL;
|
||||
}
|
||||
TimeZoneGenericNames* instance = new TimeZoneGenericNames();
|
||||
if (instance == NULL) {
|
||||
status = U_MEMORY_ALLOCATION_ERROR;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
UBool initialized;
|
||||
UMTX_CHECK(&gTZGNLock, gTZGNCoreCacheInitialized, initialized);
|
||||
if (!initialized) {
|
||||
// Create empty hashtable
|
||||
umtx_lock(&gTZGNLock);
|
||||
{
|
||||
if (!gTZGNCoreCacheInitialized) {
|
||||
gTZGNCoreCache = uhash_open(uhash_hashChars, uhash_compareChars, NULL, &status);
|
||||
if (U_SUCCESS(status)) {
|
||||
uhash_setKeyDeleter(gTZGNCoreCache, uprv_free);
|
||||
uhash_setValueDeleter(gTZGNCoreCache, deleteTZGNCoreRef);
|
||||
gTZGNCoreCacheInitialized = TRUE;
|
||||
ucln_i18n_registerCleanup(UCLN_I18N_TIMEZONEGENERICNAMES, tzgnCore_cleanup);
|
||||
}
|
||||
}
|
||||
}
|
||||
umtx_unlock(&gTZGNLock);
|
||||
|
||||
if (U_FAILURE(status)) {
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
// Check the cache, if not available, create new one and cache
|
||||
TZGNCoreRef *cacheEntry = NULL;
|
||||
umtx_lock(&gTZGNLock);
|
||||
{
|
||||
const char *key = locale.getName();
|
||||
cacheEntry = (TZGNCoreRef *)uhash_get(gTZGNCoreCache, key);
|
||||
if (cacheEntry == NULL) {
|
||||
TZGNCore *tzgnCore = NULL;
|
||||
char *newKey = NULL;
|
||||
|
||||
tzgnCore = new TZGNCore(locale, status);
|
||||
if (tzgnCore == NULL) {
|
||||
status = U_MEMORY_ALLOCATION_ERROR;
|
||||
}
|
||||
if (U_SUCCESS(status)) {
|
||||
newKey = (char *)uprv_malloc(uprv_strlen(key) + 1);
|
||||
if (newKey == NULL) {
|
||||
status = U_MEMORY_ALLOCATION_ERROR;
|
||||
} else {
|
||||
uprv_strcpy(newKey, key);
|
||||
}
|
||||
}
|
||||
if (U_SUCCESS(status)) {
|
||||
cacheEntry = (TZGNCoreRef *)uprv_malloc(sizeof(TZGNCoreRef));
|
||||
if (cacheEntry == NULL) {
|
||||
status = U_MEMORY_ALLOCATION_ERROR;
|
||||
} else {
|
||||
cacheEntry->obj = tzgnCore;
|
||||
cacheEntry->refCount = 1;
|
||||
cacheEntry->lastAccess = (double)uprv_getUTCtime();
|
||||
|
||||
uhash_put(gTZGNCoreCache, newKey, cacheEntry, &status);
|
||||
}
|
||||
}
|
||||
if (U_FAILURE(status)) {
|
||||
if (tzgnCore != NULL) {
|
||||
delete tzgnCore;
|
||||
}
|
||||
if (newKey != NULL) {
|
||||
uprv_free(newKey);
|
||||
}
|
||||
if (cacheEntry != NULL) {
|
||||
uprv_free(cacheEntry);
|
||||
}
|
||||
cacheEntry = NULL;
|
||||
}
|
||||
} else {
|
||||
// Update the reference count
|
||||
cacheEntry->refCount++;
|
||||
cacheEntry->lastAccess = (double)uprv_getUTCtime();
|
||||
}
|
||||
gAccessCount++;
|
||||
if (gAccessCount >= SWEEP_INTERVAL) {
|
||||
// sweep
|
||||
sweepCache();
|
||||
gAccessCount = 0;
|
||||
}
|
||||
}
|
||||
umtx_unlock(&gTZGNLock);
|
||||
|
||||
if (cacheEntry == NULL) {
|
||||
delete instance;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
instance->fRef = cacheEntry;
|
||||
return instance;
|
||||
}
|
||||
|
||||
UBool
|
||||
TimeZoneGenericNames::operator==(const TimeZoneGenericNames& other) const {
|
||||
// Just compare if the other object also use the same
|
||||
// ref entry
|
||||
return fRef == other.fRef;
|
||||
}
|
||||
|
||||
TimeZoneGenericNames*
|
||||
TimeZoneGenericNames::clone() const {
|
||||
TimeZoneGenericNames* other = new TimeZoneGenericNames();
|
||||
if (other) {
|
||||
umtx_lock(&gTZGNLock);
|
||||
{
|
||||
// Just increments the reference count
|
||||
fRef->refCount++;
|
||||
other->fRef = fRef;
|
||||
}
|
||||
umtx_unlock(&gTZGNLock);
|
||||
}
|
||||
return other;
|
||||
}
|
||||
|
||||
UnicodeString&
|
||||
TimeZoneGenericNames::getDisplayName(const TimeZone& tz, UTimeZoneGenericNameType type,
|
||||
UDate date, UnicodeString& name) const {
|
||||
return fRef->obj->getDisplayName(tz, type, date, name);
|
||||
}
|
||||
|
||||
UnicodeString&
|
||||
TimeZoneGenericNames::getGenericLocationName(const UnicodeString& tzCanonicalID, UnicodeString& name) const {
|
||||
return fRef->obj->getGenericLocationName(tzCanonicalID, name);
|
||||
}
|
||||
|
||||
int32_t
|
||||
TimeZoneGenericNames::findBestMatch(const UnicodeString& text, int32_t start, uint32_t types,
|
||||
UnicodeString& tzID, UTimeZoneFormatTimeType& timeType, UErrorCode& status) const {
|
||||
return fRef->obj->findBestMatch(text, start, types, tzID, timeType, status);
|
||||
}
|
||||
|
||||
U_NAMESPACE_END
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
*******************************************************************************
|
||||
* Copyright (C) 2011, International Business Machines Corporation and *
|
||||
* Copyright (C) 2011-2012, International Business Machines Corporation and *
|
||||
* others. All Rights Reserved. *
|
||||
*******************************************************************************
|
||||
*/
|
||||
|
@ -17,13 +17,9 @@
|
|||
#if !UCONFIG_NO_FORMATTING
|
||||
|
||||
#include "unicode/locid.h"
|
||||
#include "unicode/timezone.h"
|
||||
#include "unicode/unistr.h"
|
||||
#include "tznames.h"
|
||||
#include "tznames_impl.h"
|
||||
#include "tzfmt.h"
|
||||
#include "uhash.h"
|
||||
#include "umutex.h"
|
||||
#include "unicode/tzfmt.h"
|
||||
#include "unicode/tznames.h"
|
||||
|
||||
U_CDECL_BEGIN
|
||||
|
||||
|
@ -38,76 +34,30 @@ U_CDECL_END
|
|||
|
||||
U_NAMESPACE_BEGIN
|
||||
|
||||
class LocaleDisplayNames;
|
||||
class MessageFormat;
|
||||
class TimeZone;
|
||||
|
||||
class TimeZoneGenericNameMatchInfo : public UMemory {
|
||||
public:
|
||||
TimeZoneGenericNameMatchInfo(UVector* matches);
|
||||
~TimeZoneGenericNameMatchInfo();
|
||||
|
||||
int32_t size() const;
|
||||
UTimeZoneGenericNameType getGenericNameType(int32_t index) const;
|
||||
int32_t getMatchLength(int32_t index) const;
|
||||
UnicodeString& getTimeZoneID(int32_t index, UnicodeString& tzID) const;
|
||||
|
||||
private:
|
||||
UVector* fMatches; // vector of MatchEntry
|
||||
};
|
||||
struct TZGNCoreRef;
|
||||
|
||||
class U_I18N_API TimeZoneGenericNames : public UMemory {
|
||||
public:
|
||||
TimeZoneGenericNames(const Locale& locale, UErrorCode& status);
|
||||
virtual ~TimeZoneGenericNames();
|
||||
|
||||
static TimeZoneGenericNames* createInstance(const Locale& locale, UErrorCode& status);
|
||||
|
||||
virtual UBool operator==(const TimeZoneGenericNames& other) const;
|
||||
virtual UBool operator!=(const TimeZoneGenericNames& other) const {return !operator==(other);};
|
||||
virtual TimeZoneGenericNames* clone() const;
|
||||
|
||||
UnicodeString& getDisplayName(const TimeZone& tz, UTimeZoneGenericNameType type,
|
||||
UDate date, UnicodeString& name) const;
|
||||
|
||||
UnicodeString& getGenericLocationName(const UnicodeString& tzCanonicalID, UnicodeString& name) const;
|
||||
|
||||
int32_t findBestMatch(const UnicodeString& text, int32_t start, uint32_t types,
|
||||
UnicodeString& tzID, UTimeZoneTimeType& timeType, UErrorCode& status) const;
|
||||
UnicodeString& tzID, UTimeZoneFormatTimeType& timeType, UErrorCode& status) const;
|
||||
|
||||
private:
|
||||
Locale fLocale;
|
||||
UMTX fLock;
|
||||
const TimeZoneNames* fTimeZoneNames;
|
||||
UHashtable* fLocationNamesMap;
|
||||
UHashtable* fPartialLocationNamesMap;
|
||||
|
||||
MessageFormat* fRegionFormat;
|
||||
MessageFormat* fFallbackRegionFormat;
|
||||
MessageFormat* fFallbackFormat;
|
||||
|
||||
LocaleDisplayNames* fLocaleDisplayNames;
|
||||
ZNStringPool fStringPool;
|
||||
|
||||
TextTrieMap fGNamesTrie;
|
||||
UBool fGNamesTrieFullyLoaded;
|
||||
|
||||
char fTargetRegion[ULOC_COUNTRY_CAPACITY];
|
||||
|
||||
void initialize(const Locale& locale, UErrorCode& status);
|
||||
void cleanup();
|
||||
|
||||
void loadStrings(const UnicodeString& tzCanonicalID);
|
||||
|
||||
const UChar* getGenericLocationName(const UnicodeString& tzCanonicalID);
|
||||
|
||||
UnicodeString& formatGenericNonLocationName(const TimeZone& tz, UTimeZoneGenericNameType type,
|
||||
UDate date, UnicodeString& name) const;
|
||||
|
||||
UnicodeString& getPartialLocationName(const UnicodeString& tzCanonicalID,
|
||||
const UnicodeString& mzID, UBool isLong, const UnicodeString& mzDisplayName,
|
||||
UnicodeString& name) const;
|
||||
|
||||
const UChar* getPartialLocationName(const UnicodeString& tzCanonicalID,
|
||||
const UnicodeString& mzID, UBool isLong, const UnicodeString& mzDisplayName);
|
||||
|
||||
TimeZoneGenericNameMatchInfo* findLocal(const UnicodeString& text, int32_t start, uint32_t types, UErrorCode& status) const;
|
||||
|
||||
TimeZoneNameMatchInfo* findTimeZoneNames(const UnicodeString& text, int32_t start, uint32_t types, UErrorCode& status) const;
|
||||
TimeZoneGenericNames();
|
||||
TZGNCoreRef* fRef;
|
||||
};
|
||||
|
||||
U_NAMESPACE_END
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
*******************************************************************************
|
||||
* Copyright (C) 2011, International Business Machines Corporation and *
|
||||
* Copyright (C) 2011-2012, International Business Machines Corporation and *
|
||||
* others. All Rights Reserved. *
|
||||
*******************************************************************************
|
||||
*/
|
||||
|
@ -9,18 +9,18 @@
|
|||
|
||||
#if !UCONFIG_NO_FORMATTING
|
||||
|
||||
#include "tznames.h"
|
||||
#include "tznames_impl.h"
|
||||
|
||||
#include "unicode/locid.h"
|
||||
#include "unicode/tznames.h"
|
||||
#include "unicode/uenum.h"
|
||||
#include "cmemory.h"
|
||||
#include "cstring.h"
|
||||
#include "putilimp.h"
|
||||
#include "tznames_impl.h"
|
||||
#include "uassert.h"
|
||||
#include "ucln_in.h"
|
||||
#include "uhash.h"
|
||||
#include "umutex.h"
|
||||
#include "uvector.h"
|
||||
|
||||
|
||||
U_NAMESPACE_BEGIN
|
||||
|
@ -102,14 +102,18 @@ static void sweepCache() {
|
|||
}
|
||||
}
|
||||
|
||||
TimeZoneNameMatchInfo::~TimeZoneNameMatchInfo() {
|
||||
}
|
||||
|
||||
// ---------------------------------------------------
|
||||
// TimeZoneNamesDelegate
|
||||
// ---------------------------------------------------
|
||||
class TimeZoneNamesDelegate : public TimeZoneNames {
|
||||
public:
|
||||
TimeZoneNamesDelegate(const Locale& locale, UErrorCode& status);
|
||||
virtual ~TimeZoneNamesDelegate();
|
||||
|
||||
virtual UBool operator==(const TimeZoneNames& other) const;
|
||||
virtual UBool operator!=(const TimeZoneNames& other) const {return !operator==(other);};
|
||||
virtual TimeZoneNames* clone() const;
|
||||
|
||||
StringEnumeration* getAvailableMetaZoneIDs(UErrorCode& status) const;
|
||||
StringEnumeration* getAvailableMetaZoneIDs(const UnicodeString& tzID, UErrorCode& status) const;
|
||||
UnicodeString& getMetaZoneID(const UnicodeString& tzID, UDate date, UnicodeString& mzID) const;
|
||||
|
@ -120,11 +124,16 @@ public:
|
|||
|
||||
UnicodeString& getExemplarLocationName(const UnicodeString& tzID, UnicodeString& name) const;
|
||||
|
||||
TimeZoneNameMatchInfo* find(const UnicodeString& text, int32_t start, uint32_t types, UErrorCode& status) const;
|
||||
MatchInfoCollection* find(const UnicodeString& text, int32_t start, uint32_t types, UErrorCode& status) const;
|
||||
private:
|
||||
TimeZoneNamesDelegate();
|
||||
TimeZoneNamesCacheEntry* fTZnamesCacheEntry;
|
||||
};
|
||||
|
||||
TimeZoneNamesDelegate::TimeZoneNamesDelegate()
|
||||
: fTZnamesCacheEntry(0) {
|
||||
}
|
||||
|
||||
TimeZoneNamesDelegate::TimeZoneNamesDelegate(const Locale& locale, UErrorCode& status) {
|
||||
UBool initialized;
|
||||
UMTX_CHECK(&gTimeZoneNamesLock, gTimeZoneNamesCacheInitialized, initialized);
|
||||
|
@ -215,13 +224,44 @@ TimeZoneNamesDelegate::TimeZoneNamesDelegate(const Locale& locale, UErrorCode& s
|
|||
TimeZoneNamesDelegate::~TimeZoneNamesDelegate() {
|
||||
umtx_lock(&gTimeZoneNamesLock);
|
||||
{
|
||||
U_ASSERT(fTZnamesCacheEntry->refCount > 0);
|
||||
// Just decrement the reference count
|
||||
fTZnamesCacheEntry->refCount--;
|
||||
if (fTZnamesCacheEntry) {
|
||||
U_ASSERT(fTZnamesCacheEntry->refCount > 0);
|
||||
// Just decrement the reference count
|
||||
fTZnamesCacheEntry->refCount--;
|
||||
}
|
||||
}
|
||||
umtx_unlock(&gTimeZoneNamesLock);
|
||||
}
|
||||
|
||||
UBool
|
||||
TimeZoneNamesDelegate::operator==(const TimeZoneNames& other) const {
|
||||
if (this == &other) {
|
||||
return TRUE;
|
||||
}
|
||||
// Just compare if the other object also use the same
|
||||
// cache entry
|
||||
const TimeZoneNamesDelegate* rhs = dynamic_cast<const TimeZoneNamesDelegate*>(&other);
|
||||
if (rhs) {
|
||||
return fTZnamesCacheEntry == rhs->fTZnamesCacheEntry;
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
TimeZoneNames*
|
||||
TimeZoneNamesDelegate::clone() const {
|
||||
TimeZoneNamesDelegate* other = new TimeZoneNamesDelegate();
|
||||
if (other != NULL) {
|
||||
umtx_lock(&gTimeZoneNamesLock);
|
||||
{
|
||||
// Just increment the reference count
|
||||
fTZnamesCacheEntry->refCount++;
|
||||
other->fTZnamesCacheEntry = fTZnamesCacheEntry;
|
||||
}
|
||||
umtx_unlock(&gTimeZoneNamesLock);
|
||||
}
|
||||
return other;
|
||||
}
|
||||
|
||||
StringEnumeration*
|
||||
TimeZoneNamesDelegate::getAvailableMetaZoneIDs(UErrorCode& status) const {
|
||||
return fTZnamesCacheEntry->names->getAvailableMetaZoneIDs(status);
|
||||
|
@ -257,12 +297,15 @@ TimeZoneNamesDelegate::getExemplarLocationName(const UnicodeString& tzID, Unicod
|
|||
return fTZnamesCacheEntry->names->getExemplarLocationName(tzID, name);
|
||||
}
|
||||
|
||||
TimeZoneNameMatchInfo*
|
||||
TimeZoneNames::MatchInfoCollection*
|
||||
TimeZoneNamesDelegate::find(const UnicodeString& text, int32_t start, uint32_t types, UErrorCode& status) const {
|
||||
return fTZnamesCacheEntry->names->find(text, start, types, status);
|
||||
}
|
||||
|
||||
|
||||
// ---------------------------------------------------
|
||||
// TimeZoneNames base class
|
||||
// ---------------------------------------------------
|
||||
UOBJECT_DEFINE_NO_RTTI_IMPLEMENTATION(TimeZoneNames)
|
||||
|
||||
TimeZoneNames::~TimeZoneNames() {
|
||||
}
|
||||
|
@ -302,5 +345,146 @@ TimeZoneNames::getDisplayName(const UnicodeString& tzID, UTimeZoneNameType type,
|
|||
return name;
|
||||
}
|
||||
|
||||
|
||||
struct MatchInfo : UMemory {
|
||||
UTimeZoneNameType nameType;
|
||||
UnicodeString id;
|
||||
int32_t matchLength;
|
||||
UBool isTZID;
|
||||
|
||||
MatchInfo(UTimeZoneNameType nameType, int32_t matchLength, const UnicodeString* tzID, const UnicodeString* mzID) {
|
||||
this->nameType = nameType;
|
||||
this->matchLength = matchLength;
|
||||
if (tzID != NULL) {
|
||||
this->id.setTo(*tzID);
|
||||
this->isTZID = TRUE;
|
||||
} else {
|
||||
this->id.setTo(*mzID);
|
||||
this->isTZID = FALSE;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
U_CDECL_BEGIN
|
||||
static void U_CALLCONV
|
||||
deleteMatchInfo(void *obj) {
|
||||
delete static_cast<MatchInfo *>(obj);
|
||||
}
|
||||
U_CDECL_END
|
||||
|
||||
// ---------------------------------------------------
|
||||
// MatchInfoCollection class
|
||||
// ---------------------------------------------------
|
||||
TimeZoneNames::MatchInfoCollection::MatchInfoCollection()
|
||||
: fMatches(NULL) {
|
||||
}
|
||||
|
||||
TimeZoneNames::MatchInfoCollection::~MatchInfoCollection() {
|
||||
if (fMatches != NULL) {
|
||||
delete fMatches;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
TimeZoneNames::MatchInfoCollection::addZone(UTimeZoneNameType nameType, int32_t matchLength,
|
||||
const UnicodeString& tzID, UErrorCode& status) {
|
||||
if (U_FAILURE(status)) {
|
||||
return;
|
||||
}
|
||||
MatchInfo* matchInfo = new MatchInfo(nameType, matchLength, &tzID, NULL);
|
||||
if (matchInfo == NULL) {
|
||||
status = U_MEMORY_ALLOCATION_ERROR;
|
||||
return;
|
||||
}
|
||||
matches(status)->addElement(matchInfo, status);
|
||||
if (U_FAILURE(status)) {
|
||||
delete matchInfo;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
TimeZoneNames::MatchInfoCollection::addMetaZone(UTimeZoneNameType nameType, int32_t matchLength,
|
||||
const UnicodeString& mzID, UErrorCode& status) {
|
||||
if (U_FAILURE(status)) {
|
||||
return;
|
||||
}
|
||||
MatchInfo* matchInfo = new MatchInfo(nameType, matchLength, NULL, &mzID);
|
||||
if (matchInfo == NULL) {
|
||||
status = U_MEMORY_ALLOCATION_ERROR;
|
||||
return;
|
||||
}
|
||||
matches(status)->addElement(matchInfo, status);
|
||||
if (U_FAILURE(status)) {
|
||||
delete matchInfo;
|
||||
}
|
||||
}
|
||||
|
||||
int32_t
|
||||
TimeZoneNames::MatchInfoCollection::size() const {
|
||||
if (fMatches == NULL) {
|
||||
return 0;
|
||||
}
|
||||
return fMatches->size();
|
||||
}
|
||||
|
||||
UTimeZoneNameType
|
||||
TimeZoneNames::MatchInfoCollection::getNameTypeAt(int32_t idx) const {
|
||||
const MatchInfo* match = (const MatchInfo*)fMatches->elementAt(idx);
|
||||
if (match) {
|
||||
return match->nameType;
|
||||
}
|
||||
return UTZNM_UNKNOWN;
|
||||
}
|
||||
|
||||
int32_t
|
||||
TimeZoneNames::MatchInfoCollection::getMatchLengthAt(int32_t idx) const {
|
||||
const MatchInfo* match = (const MatchInfo*)fMatches->elementAt(idx);
|
||||
if (match) {
|
||||
return match->matchLength;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
UBool
|
||||
TimeZoneNames::MatchInfoCollection::getTimeZoneIDAt(int32_t idx, UnicodeString& tzID) const {
|
||||
tzID.remove();
|
||||
const MatchInfo* match = (const MatchInfo*)fMatches->elementAt(idx);
|
||||
if (match && match->isTZID) {
|
||||
tzID.setTo(match->id);
|
||||
return TRUE;
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
UBool
|
||||
TimeZoneNames::MatchInfoCollection::getMetaZoneIDAt(int32_t idx, UnicodeString& mzID) const {
|
||||
mzID.remove();
|
||||
const MatchInfo* match = (const MatchInfo*)fMatches->elementAt(idx);
|
||||
if (match && !match->isTZID) {
|
||||
mzID.setTo(match->id);
|
||||
return TRUE;
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
UVector*
|
||||
TimeZoneNames::MatchInfoCollection::matches(UErrorCode& status) {
|
||||
if (U_FAILURE(status)) {
|
||||
return NULL;
|
||||
}
|
||||
if (fMatches != NULL) {
|
||||
return fMatches;
|
||||
}
|
||||
fMatches = new UVector(deleteMatchInfo, NULL, status);
|
||||
if (fMatches == NULL) {
|
||||
status = U_MEMORY_ALLOCATION_ERROR;
|
||||
} else if (U_FAILURE(status)) {
|
||||
delete fMatches;
|
||||
fMatches = NULL;
|
||||
}
|
||||
return fMatches;
|
||||
}
|
||||
|
||||
|
||||
U_NAMESPACE_END
|
||||
#endif
|
||||
|
|
|
@ -1,71 +0,0 @@
|
|||
/*
|
||||
*******************************************************************************
|
||||
* Copyright (C) 2011, International Business Machines Corporation and *
|
||||
* others. All Rights Reserved. *
|
||||
*******************************************************************************
|
||||
*/
|
||||
#ifndef __TZNAMES_H
|
||||
#define __TZNAMES_H
|
||||
|
||||
/**
|
||||
* \file
|
||||
* \brief C API: Time zone names class
|
||||
*/
|
||||
#include "unicode/utypes.h"
|
||||
|
||||
#if !UCONFIG_NO_FORMATTING
|
||||
|
||||
#include "unicode/uloc.h"
|
||||
#include "unicode/unistr.h"
|
||||
|
||||
U_CDECL_BEGIN
|
||||
|
||||
typedef enum UTimeZoneNameType {
|
||||
UTZNM_UNKNOWN = 0x00,
|
||||
UTZNM_LONG_GENERIC = 0x01,
|
||||
UTZNM_LONG_STANDARD = 0x02,
|
||||
UTZNM_LONG_DAYLIGHT = 0x04,
|
||||
UTZNM_SHORT_GENERIC = 0x08,
|
||||
UTZNM_SHORT_STANDARD = 0x10,
|
||||
UTZNM_SHORT_DAYLIGHT = 0x20
|
||||
} UTimeZoneNameType;
|
||||
|
||||
U_CDECL_END
|
||||
|
||||
U_NAMESPACE_BEGIN
|
||||
|
||||
class U_I18N_API TimeZoneNameMatchInfo : public UMemory {
|
||||
public:
|
||||
virtual ~TimeZoneNameMatchInfo();
|
||||
|
||||
virtual int32_t size() const = 0;
|
||||
virtual UTimeZoneNameType getNameType(int32_t index) const = 0;
|
||||
virtual int32_t getMatchLength(int32_t index) const = 0;
|
||||
virtual UnicodeString& getTimeZoneID(int32_t index, UnicodeString& tzID) const = 0;
|
||||
virtual UnicodeString& getMetaZoneID(int32_t index, UnicodeString& mzID) const = 0;
|
||||
};
|
||||
|
||||
class U_I18N_API TimeZoneNames : public UMemory {
|
||||
public:
|
||||
virtual ~TimeZoneNames();
|
||||
|
||||
static TimeZoneNames* U_EXPORT2 createInstance(const Locale& locale, UErrorCode& status);
|
||||
|
||||
virtual StringEnumeration* getAvailableMetaZoneIDs(UErrorCode& status) const = 0;
|
||||
virtual StringEnumeration* getAvailableMetaZoneIDs(const UnicodeString& tzID, UErrorCode& status) const = 0;
|
||||
|
||||
virtual UnicodeString& getMetaZoneID(const UnicodeString& tzID, UDate date, UnicodeString& mzID) const = 0;
|
||||
virtual UnicodeString& getReferenceZoneID(const UnicodeString& mzID, const char* region, UnicodeString& tzID) const = 0;
|
||||
|
||||
virtual UnicodeString& getMetaZoneDisplayName(const UnicodeString& mzID, UTimeZoneNameType type, UnicodeString& name) const = 0;
|
||||
virtual UnicodeString& getTimeZoneDisplayName(const UnicodeString& tzID, UTimeZoneNameType type, UnicodeString& name) const = 0;
|
||||
|
||||
virtual UnicodeString& getExemplarLocationName(const UnicodeString& tzID, UnicodeString& name) const;
|
||||
virtual UnicodeString& getDisplayName(const UnicodeString& tzID, UTimeZoneNameType type, UDate date, UnicodeString& name) const;
|
||||
|
||||
virtual TimeZoneNameMatchInfo* find(const UnicodeString& text, int32_t start, uint32_t types, UErrorCode& status) const = 0;
|
||||
};
|
||||
|
||||
U_NAMESPACE_END
|
||||
#endif
|
||||
#endif
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
*******************************************************************************
|
||||
* Copyright (C) 2011, International Business Machines Corporation and
|
||||
* Copyright (C) 2011-2012, International Business Machines Corporation and
|
||||
* others. All Rights Reserved.
|
||||
*******************************************************************************
|
||||
*
|
||||
|
@ -52,7 +52,7 @@ static const UTimeZoneNameType ALL_NAME_TYPES[] = {
|
|||
#define DEFAULT_CHARACTERNODE_CAPACITY 1
|
||||
|
||||
// ---------------------------------------------------
|
||||
// CaracterNode class implementation
|
||||
// CharacterNode class implementation
|
||||
// ---------------------------------------------------
|
||||
void CharacterNode::clear() {
|
||||
uprv_memset(this, 0, sizeof(*this));
|
||||
|
@ -722,81 +722,6 @@ typedef struct ZMatchInfo {
|
|||
} ZMatchInfo;
|
||||
U_CDECL_END
|
||||
|
||||
// ---------------------------------------------------
|
||||
// The class stores time zone name match information
|
||||
// ---------------------------------------------------
|
||||
class TimeZoneNameMatchInfoImpl : public TimeZoneNameMatchInfo {
|
||||
public:
|
||||
TimeZoneNameMatchInfoImpl(UVector* matches);
|
||||
~TimeZoneNameMatchInfoImpl();
|
||||
|
||||
int32_t size() const;
|
||||
UTimeZoneNameType getNameType(int32_t index) const;
|
||||
int32_t getMatchLength(int32_t index) const;
|
||||
UnicodeString& getTimeZoneID(int32_t index, UnicodeString& tzID) const;
|
||||
UnicodeString& getMetaZoneID(int32_t index, UnicodeString& mzID) const;
|
||||
|
||||
private:
|
||||
UVector* fMatches; // vector of MatchEntry
|
||||
};
|
||||
|
||||
TimeZoneNameMatchInfoImpl::TimeZoneNameMatchInfoImpl(UVector* matches)
|
||||
: fMatches(matches) {
|
||||
}
|
||||
|
||||
TimeZoneNameMatchInfoImpl::~TimeZoneNameMatchInfoImpl() {
|
||||
if (fMatches != NULL) {
|
||||
delete fMatches;
|
||||
}
|
||||
}
|
||||
|
||||
int32_t
|
||||
TimeZoneNameMatchInfoImpl::size() const {
|
||||
if (fMatches == NULL) {
|
||||
return 0;
|
||||
}
|
||||
return fMatches->size();
|
||||
}
|
||||
|
||||
UTimeZoneNameType
|
||||
TimeZoneNameMatchInfoImpl::getNameType(int32_t index) const {
|
||||
ZMatchInfo *minfo = (ZMatchInfo *)fMatches->elementAt(index);
|
||||
if (minfo != NULL) {
|
||||
return minfo->znameInfo->type;
|
||||
}
|
||||
return UTZNM_UNKNOWN;
|
||||
}
|
||||
|
||||
int32_t
|
||||
TimeZoneNameMatchInfoImpl::getMatchLength(int32_t index) const {
|
||||
ZMatchInfo *minfo = (ZMatchInfo *)fMatches->elementAt(index);
|
||||
if (minfo != NULL) {
|
||||
return minfo->matchLength;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
UnicodeString&
|
||||
TimeZoneNameMatchInfoImpl::getTimeZoneID(int32_t index, UnicodeString& tzID) const {
|
||||
ZMatchInfo *minfo = (ZMatchInfo *)fMatches->elementAt(index);
|
||||
if (minfo != NULL && minfo->znameInfo->tzID != NULL) {
|
||||
tzID.setTo(TRUE, minfo->znameInfo->tzID, -1);
|
||||
} else {
|
||||
tzID.setToBogus();
|
||||
}
|
||||
return tzID;
|
||||
}
|
||||
|
||||
UnicodeString&
|
||||
TimeZoneNameMatchInfoImpl::getMetaZoneID(int32_t index, UnicodeString& mzID) const {
|
||||
ZMatchInfo *minfo = (ZMatchInfo *)fMatches->elementAt(index);
|
||||
if (minfo != NULL && minfo->znameInfo->mzID != NULL) {
|
||||
mzID.setTo(TRUE, minfo->znameInfo->mzID, -1);
|
||||
} else {
|
||||
mzID.setToBogus();
|
||||
}
|
||||
return mzID;
|
||||
}
|
||||
|
||||
// ---------------------------------------------------
|
||||
// ZNameSearchHandler
|
||||
|
@ -807,16 +732,16 @@ public:
|
|||
virtual ~ZNameSearchHandler();
|
||||
|
||||
UBool handleMatch(int32_t matchLength, const CharacterNode *node, UErrorCode &status);
|
||||
UVector* getMatches(int32_t& maxMatchLen);
|
||||
TimeZoneNames::MatchInfoCollection* getMatches(int32_t& maxMatchLen);
|
||||
|
||||
private:
|
||||
uint32_t fTypes;
|
||||
UVector* fResults;
|
||||
int32_t fMaxMatchLen;
|
||||
TimeZoneNames::MatchInfoCollection* fResults;
|
||||
};
|
||||
|
||||
ZNameSearchHandler::ZNameSearchHandler(uint32_t types)
|
||||
: fTypes(types), fResults(NULL), fMaxMatchLen(0) {
|
||||
: fTypes(types), fMaxMatchLen(0), fResults(NULL) {
|
||||
}
|
||||
|
||||
ZNameSearchHandler::~ZNameSearchHandler() {
|
||||
|
@ -840,28 +765,21 @@ ZNameSearchHandler::handleMatch(int32_t matchLength, const CharacterNode *node,
|
|||
if ((nameinfo->type & fTypes) != 0) {
|
||||
// matches a requested type
|
||||
if (fResults == NULL) {
|
||||
fResults = new UVector(uprv_free, NULL, status);
|
||||
fResults = new TimeZoneNames::MatchInfoCollection();
|
||||
if (fResults == NULL) {
|
||||
status = U_MEMORY_ALLOCATION_ERROR;
|
||||
}
|
||||
}
|
||||
if (U_SUCCESS(status)) {
|
||||
U_ASSERT(fResults != NULL);
|
||||
ZMatchInfo *zmatch = (ZMatchInfo *)uprv_malloc(sizeof(ZMatchInfo));
|
||||
if (zmatch == NULL) {
|
||||
status = U_MEMORY_ALLOCATION_ERROR;
|
||||
if (nameinfo->tzID) {
|
||||
fResults->addZone(nameinfo->type, matchLength, UnicodeString(nameinfo->tzID, -1), status);
|
||||
} else {
|
||||
// add the match to the vector
|
||||
zmatch->znameInfo = nameinfo;
|
||||
zmatch->matchLength = matchLength;
|
||||
fResults->addElement(zmatch, status);
|
||||
if (U_FAILURE(status)) {
|
||||
uprv_free(zmatch);
|
||||
} else {
|
||||
if (matchLength > fMaxMatchLen) {
|
||||
fMaxMatchLen = matchLength;
|
||||
}
|
||||
}
|
||||
U_ASSERT(nameinfo->mzID);
|
||||
fResults->addMetaZone(nameinfo->type, matchLength, UnicodeString(nameinfo->mzID, -1), status);
|
||||
}
|
||||
if (U_SUCCESS(status) && matchLength > fMaxMatchLen) {
|
||||
fMaxMatchLen = matchLength;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -870,10 +788,10 @@ ZNameSearchHandler::handleMatch(int32_t matchLength, const CharacterNode *node,
|
|||
return TRUE;
|
||||
}
|
||||
|
||||
UVector*
|
||||
TimeZoneNames::MatchInfoCollection*
|
||||
ZNameSearchHandler::getMatches(int32_t& maxMatchLen) {
|
||||
// give the ownership to the caller
|
||||
UVector *results = fResults;
|
||||
TimeZoneNames::MatchInfoCollection* results = fResults;
|
||||
maxMatchLen = fMaxMatchLen;
|
||||
|
||||
// reset
|
||||
|
@ -1012,6 +930,21 @@ TimeZoneNamesImpl::cleanup() {
|
|||
}
|
||||
}
|
||||
|
||||
UBool
|
||||
TimeZoneNamesImpl::operator==(const TimeZoneNames& other) const {
|
||||
if (this == &other) {
|
||||
return TRUE;
|
||||
}
|
||||
// No implementation for now
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
TimeZoneNames*
|
||||
TimeZoneNamesImpl::clone() const {
|
||||
UErrorCode status = U_ZERO_ERROR;
|
||||
return new TimeZoneNamesImpl(fLocale, status);
|
||||
}
|
||||
|
||||
StringEnumeration*
|
||||
TimeZoneNamesImpl::getAvailableMetaZoneIDs(UErrorCode& status) const {
|
||||
if (U_FAILURE(status)) {
|
||||
|
@ -1307,7 +1240,7 @@ TimeZoneNamesImpl::loadTimeZoneNames(const UnicodeString& tzID) {
|
|||
return tznames;
|
||||
}
|
||||
|
||||
TimeZoneNameMatchInfo*
|
||||
TimeZoneNames::MatchInfoCollection*
|
||||
TimeZoneNamesImpl::find(const UnicodeString& text, int32_t start, uint32_t types, UErrorCode& status) const {
|
||||
ZNameSearchHandler handler(types);
|
||||
|
||||
|
@ -1323,24 +1256,14 @@ TimeZoneNamesImpl::find(const UnicodeString& text, int32_t start, uint32_t types
|
|||
return NULL;
|
||||
}
|
||||
|
||||
TimeZoneNameMatchInfoImpl *matchInfo = NULL;
|
||||
|
||||
int32_t maxLen = 0;
|
||||
UVector *results = handler.getMatches(maxLen);
|
||||
if (results != NULL && ((maxLen == (text.length() - start)) || fNamesTrieFullyLoaded)) {
|
||||
TimeZoneNames::MatchInfoCollection* matches = handler.getMatches(maxLen);
|
||||
if (matches != NULL && ((maxLen == (text.length() - start)) || fNamesTrieFullyLoaded)) {
|
||||
// perfect match
|
||||
matchInfo = new TimeZoneNameMatchInfoImpl(results);
|
||||
if (matchInfo == NULL) {
|
||||
status = U_MEMORY_ALLOCATION_ERROR;
|
||||
delete results;
|
||||
return NULL;
|
||||
}
|
||||
return matchInfo;
|
||||
return matches;
|
||||
}
|
||||
|
||||
if (results != NULL) {
|
||||
delete results;
|
||||
}
|
||||
delete matches;
|
||||
|
||||
// All names are not yet loaded into the trie
|
||||
umtx_lock(&nonConstThis->fLock);
|
||||
|
@ -1380,20 +1303,9 @@ TimeZoneNamesImpl::find(const UnicodeString& text, int32_t start, uint32_t types
|
|||
}
|
||||
umtx_unlock(&nonConstThis->fLock);
|
||||
|
||||
results = handler.getMatches(maxLen);
|
||||
if (results != NULL && maxLen > 0) {
|
||||
matchInfo = new TimeZoneNameMatchInfoImpl(results);
|
||||
if (matchInfo == NULL) {
|
||||
status = U_MEMORY_ALLOCATION_ERROR;
|
||||
delete results;
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
return matchInfo;
|
||||
return handler.getMatches(maxLen);
|
||||
}
|
||||
|
||||
|
||||
U_NAMESPACE_END
|
||||
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
*******************************************************************************
|
||||
* Copyright (C) 2011, International Business Machines Corporation and *
|
||||
* Copyright (C) 2011-2012, International Business Machines Corporation and *
|
||||
* others. All Rights Reserved. *
|
||||
*******************************************************************************
|
||||
*/
|
||||
|
@ -18,7 +18,7 @@
|
|||
|
||||
#if !UCONFIG_NO_FORMATTING
|
||||
|
||||
#include "tznames.h"
|
||||
#include "unicode/tznames.h"
|
||||
#include "unicode/ures.h"
|
||||
#include "unicode/locid.h"
|
||||
#include "uhash.h"
|
||||
|
@ -168,6 +168,9 @@ public:
|
|||
|
||||
virtual ~TimeZoneNamesImpl();
|
||||
|
||||
virtual UBool operator==(const TimeZoneNames& other) const;
|
||||
virtual TimeZoneNames* clone() const;
|
||||
|
||||
StringEnumeration* getAvailableMetaZoneIDs(UErrorCode& status) const;
|
||||
StringEnumeration* getAvailableMetaZoneIDs(const UnicodeString& tzID, UErrorCode& status) const;
|
||||
|
||||
|
@ -179,7 +182,7 @@ public:
|
|||
|
||||
UnicodeString& getExemplarLocationName(const UnicodeString& tzID, UnicodeString& name) const;
|
||||
|
||||
TimeZoneNameMatchInfo* find(const UnicodeString& text, int32_t start, uint32_t types, UErrorCode& status) const;
|
||||
TimeZoneNames::MatchInfoCollection* find(const UnicodeString& text, int32_t start, uint32_t types, UErrorCode& status) const;
|
||||
|
||||
private:
|
||||
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
/*
|
||||
******************************************************************************
|
||||
* *
|
||||
* Copyright (C) 2001-2011, International Business Machines *
|
||||
* Copyright (C) 2001-2012, International Business Machines *
|
||||
* Corporation and others. All Rights Reserved. *
|
||||
* *
|
||||
******************************************************************************
|
||||
|
@ -33,7 +33,7 @@ typedef enum ECleanupI18NType {
|
|||
UCLN_I18N_HEBREW_CALENDAR,
|
||||
UCLN_I18N_ASTRO_CALENDAR,
|
||||
UCLN_I18N_CALENDAR,
|
||||
UCLN_I18N_TIMEZONEFORMAT,
|
||||
UCLN_I18N_TIMEZONEGENERICNAMES,
|
||||
UCLN_I18N_TIMEZONENAMES,
|
||||
UCLN_I18N_ZONEMETA,
|
||||
UCLN_I18N_TIMEZONE,
|
||||
|
|
|
@ -713,30 +713,6 @@ private:
|
|||
|
||||
Locale fZSFLocale; // Locale used for getting ZoneStringFormat
|
||||
|
||||
/**
|
||||
* String used for localized GMT. For example, "GMT"
|
||||
*/
|
||||
UnicodeString fGmtZero;
|
||||
|
||||
/**
|
||||
* Pattern string used for localized time zone GMT format. For example, "GMT{0}"
|
||||
*/
|
||||
UnicodeString fGmtFormat;
|
||||
|
||||
/**
|
||||
* Pattern strings used for formatting zone offset in a localized time zone GMT string.
|
||||
*/
|
||||
UnicodeString *fGmtHourFormats;
|
||||
int32_t fGmtHourFormatsCount;
|
||||
|
||||
enum GMTHourType {
|
||||
GMT_NEGATIVE_HMS = 0,
|
||||
GMT_NEGATIVE_HM,
|
||||
GMT_POSITIVE_HMS,
|
||||
GMT_POSITIVE_HM,
|
||||
GMT_HOUR_COUNT
|
||||
};
|
||||
|
||||
/**
|
||||
* Localized date-time pattern characters. For example: use 'u' as 'y'.
|
||||
*/
|
||||
|
|
|
@ -94,6 +94,7 @@ class TimeZoneFormat;
|
|||
* zzzz time zone (Text) Pacific Standard Time
|
||||
* Z time zone (RFC 822) (Number) -0800
|
||||
* ZZZZ time zone (RFC 822) (Text & Number) GMT-08:00
|
||||
* ZZZZZ time zone (ISO 8601) (Text & Number) -08:00 & Z
|
||||
* v time zone (generic) (Text) PT
|
||||
* vvvv time zone (generic) (Text) Pacific Time
|
||||
* V time zone (abreviation) (Text) PST
|
||||
|
@ -831,6 +832,31 @@ public:
|
|||
*/
|
||||
virtual int32_t getDefaultContext(UDateFormatContextType type, UErrorCode& status) const;
|
||||
|
||||
#ifndef U_HIDE_INTERNAL_API
|
||||
/**
|
||||
* Sets the TimeZoneFormat to be used by this date/time formatter.
|
||||
* The caller should not delete the TimeZoneFormat object after
|
||||
* it is adopted by this call.
|
||||
* @param timeZoneFormatToAdopt The TimeZoneFormat object to be adopted.
|
||||
* @internal ICU 49 technology preview
|
||||
*/
|
||||
virtual void adoptTimeZoneFormat(TimeZoneFormat* timeZoneFormatToAdopt);
|
||||
|
||||
/**
|
||||
* Sets the TimeZoneFormat to be used by this date/time formatter.
|
||||
* @param newTimeZoneFormat The TimeZoneFormat object to copy.
|
||||
* @internal ICU 49 technology preview
|
||||
*/
|
||||
virtual void setTimeZoneFormat(const TimeZoneFormat& newTimeZoneFormat);
|
||||
|
||||
/**
|
||||
* Gets the time zone format object associated with this date/time formatter.
|
||||
* @return the time zone format associated with this date/time formatter.
|
||||
* @internal ICU 49 technology preview
|
||||
*/
|
||||
virtual const TimeZoneFormat* getTimeZoneFormat(void) const;
|
||||
#endif /* U_HIDE_INTERNAL_API */
|
||||
|
||||
#ifndef U_HIDE_INTERNAL_API
|
||||
/**
|
||||
* This is for ICU internal use only. Please do not use.
|
||||
|
@ -1127,22 +1153,6 @@ private:
|
|||
*/
|
||||
int32_t skipUWhiteSpace(const UnicodeString& text, int32_t pos) const;
|
||||
|
||||
/**
|
||||
* Private methods for formatting/parsing GMT string
|
||||
*/
|
||||
void appendGMT(NumberFormat *currentNumberFormat,UnicodeString &appendTo, Calendar& cal, UErrorCode& status) const;
|
||||
void formatGMTDefault(NumberFormat *currentNumberFormat,UnicodeString &appendTo, int32_t offset) const;
|
||||
int32_t parseGMT(const UnicodeString &text, ParsePosition &pos) const;
|
||||
int32_t parseGMTDefault(const UnicodeString &text, ParsePosition &pos) const;
|
||||
UBool isDefaultGMTFormat() const;
|
||||
|
||||
void formatRFC822TZ(UnicodeString &appendTo, int32_t offset) const;
|
||||
|
||||
/**
|
||||
* Initialize MessageFormat instances used for GMT formatting/parsing
|
||||
*/
|
||||
void initGMTFormatters(UErrorCode &status);
|
||||
|
||||
/**
|
||||
* Initialize NumberFormat instances used for numbering system overrides.
|
||||
*/
|
||||
|
@ -1229,13 +1239,7 @@ private:
|
|||
*/
|
||||
/*transient*/ int32_t fDefaultCenturyStartYear;
|
||||
|
||||
enum ParsedTZType {
|
||||
TZTYPE_UNK,
|
||||
TZTYPE_STD,
|
||||
TZTYPE_DST
|
||||
};
|
||||
|
||||
ParsedTZType tztype; // here to avoid api change
|
||||
int32_t tztype; // here to avoid api change
|
||||
|
||||
typedef struct NSOverride {
|
||||
NumberFormat *nf;
|
||||
|
@ -1243,34 +1247,6 @@ private:
|
|||
NSOverride *next;
|
||||
} NSOverride;
|
||||
|
||||
/*
|
||||
* MessageFormat instances used for localized GMT format
|
||||
*/
|
||||
enum {
|
||||
kGMTNegativeHMS = 0,
|
||||
kGMTNegativeHM,
|
||||
kGMTPositiveHMS,
|
||||
kGMTPositiveHM,
|
||||
|
||||
kNumGMTFormatters
|
||||
};
|
||||
enum {
|
||||
kGMTNegativeHMSMinLenIdx = 0,
|
||||
kGMTPositiveHMSMinLenIdx,
|
||||
|
||||
kNumGMTFormatMinLengths
|
||||
};
|
||||
|
||||
MessageFormat **fGMTFormatters;
|
||||
// If a GMT hour format has a second field, we need to make sure
|
||||
// the length of input localized GMT string must match the expected
|
||||
// length. Otherwise, sub DateForamt handling offset format may
|
||||
// unexpectedly success parsing input GMT string without second field.
|
||||
// See #6880 about this issue.
|
||||
// TODO: SimpleDateFormat should provide an option to invalidate
|
||||
//
|
||||
int32_t fGMTFormatHmsMinLen[kNumGMTFormatMinLengths];
|
||||
|
||||
NumberFormat **fNumberFormatters;
|
||||
|
||||
NSOverride *fOverrideList;
|
||||
|
|
829
icu4c/source/i18n/unicode/tzfmt.h
Normal file
829
icu4c/source/i18n/unicode/tzfmt.h
Normal file
|
@ -0,0 +1,829 @@
|
|||
/*
|
||||
*******************************************************************************
|
||||
* Copyright (C) 2011-2012, International Business Machines Corporation and *
|
||||
* others. All Rights Reserved. *
|
||||
*******************************************************************************
|
||||
*/
|
||||
#ifndef __TZFMT_H
|
||||
#define __TZFMT_H
|
||||
|
||||
/**
|
||||
* \file
|
||||
* \brief C++ API: TimeZoneFormat
|
||||
*/
|
||||
|
||||
#include "unicode/utypes.h"
|
||||
|
||||
#if !UCONFIG_NO_FORMATTING
|
||||
#ifndef U_HIDE_INTERNAL_API
|
||||
|
||||
#include "unicode/format.h"
|
||||
#include "unicode/timezone.h"
|
||||
#include "unicode/tznames.h"
|
||||
|
||||
U_CDECL_BEGIN
|
||||
/**
|
||||
* Constants for time zone display format style used by format/parse APIs
|
||||
* in TimeZoneFormat.
|
||||
* @internal ICU 49 technology preview
|
||||
*/
|
||||
typedef enum UTimeZoneFormatStyle {
|
||||
/**
|
||||
* Generic location format, such as "United States Time (New York)", "Italy Time"
|
||||
* @internal ICU 49 technology preview
|
||||
*/
|
||||
UTZFMT_STYLE_GENERIC_LOCATION,
|
||||
/**
|
||||
* Generic long non-location format, such as "Eastern Time".
|
||||
* @internal ICU 49 technology preview
|
||||
*/
|
||||
UTZFMT_STYLE_GENERIC_LONG,
|
||||
/**
|
||||
* Generic short non-location format, such as "ET".
|
||||
* @internal ICU 49 technology preview
|
||||
*/
|
||||
UTZFMT_STYLE_GENERIC_SHORT,
|
||||
/**
|
||||
* Specific long format, such as "Eastern Standard Time".
|
||||
* @internal ICU 49 technology preview
|
||||
*/
|
||||
UTZFMT_STYLE_SPECIFIC_LONG,
|
||||
/**
|
||||
* Specific short format, such as "EST", "PDT".
|
||||
* @internal ICU 49 technology preview
|
||||
*/
|
||||
UTZFMT_STYLE_SPECIFIC_SHORT,
|
||||
/**
|
||||
* RFC822 format, such as "-0500"
|
||||
* @internal ICU 49 technology preview
|
||||
*/
|
||||
UTZFMT_STYLE_RFC822,
|
||||
/**
|
||||
* Localized GMT offset format, such as "GMT-05:00", "UTC+0100"
|
||||
* @internal ICU 49 technology preview
|
||||
*/
|
||||
UTZFMT_STYLE_LOCALIZED_GMT,
|
||||
/**
|
||||
* ISO 8601 format (extended), such as "-05:00", "Z"(UTC)
|
||||
* @internal ICU 49 technology preview
|
||||
*/
|
||||
UTZFMT_STYLE_ISO8601
|
||||
} UTimeZoneFormatStyle;
|
||||
|
||||
/**
|
||||
* Constants for GMT offset pattern types.
|
||||
* @internal ICU 49 technology preview
|
||||
*/
|
||||
typedef enum UTimeZoneFormatGMTOffsetPatternType {
|
||||
/**
|
||||
* Positive offset with hour and minute fields
|
||||
* @internal ICU 49 technology preview
|
||||
*/
|
||||
UTZFMT_PAT_POSITIVE_HM,
|
||||
/**
|
||||
* Positive offset with hour, minute and second fields
|
||||
* @internal ICU 49 technology preview
|
||||
*/
|
||||
UTZFMT_PAT_POSITIVE_HMS,
|
||||
/**
|
||||
* Negative offset with hour and minute fields
|
||||
* @internal ICU 49 technology preview
|
||||
*/
|
||||
UTZFMT_PAT_NEGATIVE_HM,
|
||||
/**
|
||||
* Negative offset with hour, minute and second fields
|
||||
* @internal ICU 49 technology preview
|
||||
*/
|
||||
UTZFMT_PAT_NEGATIVE_HMS
|
||||
} UTimeZoneFormatGMTOffsetPatternType;
|
||||
|
||||
/**
|
||||
* Constants for time types used by TimeZoneFormat APIs for
|
||||
* receiving time type (standard time, daylight time or unknown).
|
||||
* @internal ICU 49 technology preview
|
||||
*/
|
||||
typedef enum UTimeZoneFormatTimeType {
|
||||
/**
|
||||
* Unknown
|
||||
* @internal ICU 49 technology preview
|
||||
*/
|
||||
UTZFMT_TIME_TYPE_UNKNOWN,
|
||||
/**
|
||||
* Standard time
|
||||
* @internal ICU 49 technology preview
|
||||
*/
|
||||
UTZFMT_TIME_TYPE_STANDARD,
|
||||
/**
|
||||
* Daylight saving time
|
||||
* @internal ICU 49 technology preview
|
||||
*/
|
||||
UTZFMT_TIME_TYPE_DAYLIGHT
|
||||
} UTimeZoneFormatTimeType;
|
||||
|
||||
/**
|
||||
* Constants for parse option flags, used for specifying optional parse behavior.
|
||||
* @internal ICU 49 technology preview
|
||||
*/
|
||||
typedef enum UTimeZoneFormatParseOption {
|
||||
/**
|
||||
* No option.
|
||||
* @internal ICU 49 technology preview
|
||||
*/
|
||||
UTZFMT_PARSE_OPTION_NONE = 0x00,
|
||||
/**
|
||||
* When a time zone display name is not found within a set of display names
|
||||
* used for the specified style, look for the name from display names used
|
||||
* by other styles.
|
||||
* @internal ICU 49 technology preview
|
||||
*/
|
||||
UTZFMT_PARSE_OPTION_ALL_STYLES = 0x01
|
||||
} UTimeZoneFormatParseOption;
|
||||
|
||||
U_CDECL_END
|
||||
|
||||
typedef void *UMTX;
|
||||
|
||||
U_NAMESPACE_BEGIN
|
||||
|
||||
class TimeZoneGenericNames;
|
||||
class UVector;
|
||||
|
||||
/**
|
||||
* <code>TimeZoneFormat</code> supports time zone display name formatting and parsing.
|
||||
* An instance of TimeZoneFormat works as a subformatter of {@link SimpleDateFormat},
|
||||
* but you can also directly get a new instance of <code>TimeZoneFormat</code> and
|
||||
* formatting/parsing time zone display names.
|
||||
* <p>
|
||||
* ICU implements the time zone display names defined by <a href="http://www.unicode.org/reports/tr35/">UTS#35
|
||||
* Unicode Locale Data Markup Language (LDML)</a>. {@link TimeZoneNames} represents the
|
||||
* time zone display name data model and this class implements the algorithm for actual
|
||||
* formatting and parsing.
|
||||
*
|
||||
* @see SimpleDateFormat
|
||||
* @see TimeZoneNames
|
||||
* @internal ICU 49 technology preview
|
||||
*/
|
||||
class U_I18N_API TimeZoneFormat : public Format {
|
||||
public:
|
||||
/**
|
||||
* Copy constructor.
|
||||
* @internal ICU 49 technology preview
|
||||
*/
|
||||
TimeZoneFormat(const TimeZoneFormat& other);
|
||||
|
||||
/**
|
||||
* Destructor.
|
||||
* @internal ICU 49 technology preview
|
||||
*/
|
||||
virtual ~TimeZoneFormat();
|
||||
|
||||
/**
|
||||
* Assignment operator.
|
||||
* @internal ICU 49 technology preview
|
||||
*/
|
||||
TimeZoneFormat& operator=(const TimeZoneFormat& other);
|
||||
|
||||
/**
|
||||
* Return true if the given Format objects are semantically equal.
|
||||
* Objects of different subclasses are considered unequal.
|
||||
* @param other The object to be compared with.
|
||||
* @return Return TRUE if the given Format objects are semantically equal.
|
||||
* Objects of different subclasses are considered unequal.
|
||||
* @internal ICU 49 technology preview
|
||||
*/
|
||||
virtual UBool operator==(const Format& other) const;
|
||||
|
||||
/**
|
||||
* Clone this object polymorphically. The caller is responsible
|
||||
* for deleting the result when done.
|
||||
* @return A copy of the object
|
||||
* @internal ICU 49 technology preview
|
||||
*/
|
||||
virtual Format* clone() const;
|
||||
|
||||
/**
|
||||
* Creates an instance of <code>TimeZoneFormat</code> for the given locale.
|
||||
* @param locale The locale.
|
||||
* @param status Recevies the status.
|
||||
* @return An instance of <code>TimeZoneFormat</code> for the given locale,
|
||||
* owned by the caller.
|
||||
* @internal ICU 49 technology preview
|
||||
*/
|
||||
static TimeZoneFormat* U_EXPORT2 createInstance(const Locale& locale, UErrorCode& status);
|
||||
|
||||
/**
|
||||
* Returns the time zone display name data used by this instance.
|
||||
* @return The time zone display name data.
|
||||
* @internal ICU 49 technology preview
|
||||
*/
|
||||
const TimeZoneNames* getTimeZoneNames() const;
|
||||
|
||||
/**
|
||||
* Sets the time zone display name data to this format instnace.
|
||||
* The caller should not delete the TimeZoenNames object after it is adopted
|
||||
* by this call.
|
||||
* @param tznames TimeZoneNames object to be adopted.
|
||||
* @internal ICU 49 technology preview
|
||||
*/
|
||||
void adoptTimeZoneNames(TimeZoneNames *tznames);
|
||||
|
||||
/**
|
||||
* Sets the time zone display name data to this format instnace.
|
||||
* @param tznames TimeZoneNames object to be set.
|
||||
* @internal ICU 49 technology preview
|
||||
*/
|
||||
void setTimeZoneNames(const TimeZoneNames &tznames);
|
||||
|
||||
/**
|
||||
* Returns the localized GMT format pattern.
|
||||
* @param pattern Receives the localized GMT format pattern.
|
||||
* @return A reference to the result pattern.
|
||||
* @see #setGMTPattern
|
||||
* @internal ICU 49 technology preview
|
||||
*/
|
||||
UnicodeString& getGMTPattern(UnicodeString& pattern) const;
|
||||
|
||||
/**
|
||||
* Sets the localized GMT format pattern. The pattern must contain
|
||||
* a single argument {0}, for example "GMT {0}".
|
||||
* @param pattern The localized GMT format pattern to be used by this object.
|
||||
* @param status Recieves the status.
|
||||
* @see #getGMTPattern
|
||||
* @internal ICU 49 technology preview
|
||||
*/
|
||||
void setGMTPattern(const UnicodeString& pattern, UErrorCode& status);
|
||||
|
||||
/**
|
||||
* Returns the offset pattern used for localized GMT format.
|
||||
* @param type The offset pattern type enum.
|
||||
* @param pattern Receives the offset pattern.
|
||||
* @return A reference to the result pattern.
|
||||
* @see #setGMTOffsetPattern
|
||||
* @internal ICU 49 technology preview
|
||||
*/
|
||||
UnicodeString& getGMTOffsetPattern(UTimeZoneFormatGMTOffsetPatternType type, UnicodeString& pattern) const;
|
||||
|
||||
/**
|
||||
* Sets the offset pattern for the given offset type.
|
||||
* @param type The offset pattern type enum.
|
||||
* @param pattern The offset pattern used for localized GMT format for the type.
|
||||
* @param status Receives the status.
|
||||
* @see #getGMTOffsetPattern
|
||||
* @internal ICU 49 technology preview
|
||||
*/
|
||||
void setGMTOffsetPattern(UTimeZoneFormatGMTOffsetPatternType type, const UnicodeString& pattern, UErrorCode& status);
|
||||
|
||||
/**
|
||||
* Returns the decimal digit characters used for localized GMT format in a single string
|
||||
* containing from 0 to 9 in the ascending order.
|
||||
* @param digits Receives the decimal digits used for localized GMT format.
|
||||
* @see #setGMTOffsetDigits
|
||||
*/
|
||||
UnicodeString& getGMTOffsetDigits(UnicodeString& digits) const;
|
||||
|
||||
/**
|
||||
* Sets the decimal digit characters used for localized GMT format.
|
||||
* @param digits The decimal digits used for localized GMT format.
|
||||
* @param status Receives the status.
|
||||
* @see #getGMTOffsetDigits
|
||||
*/
|
||||
void setGMTOffsetDigits(const UnicodeString& digits, UErrorCode& status);
|
||||
|
||||
/**
|
||||
* Returns the localized GMT format string for GMT(UTC) itself (GMT offset is 0).
|
||||
* @param gmtZeroFormat Receives the localized GMT string string for GMT(UTC) itself.
|
||||
* @return A reference to the result GMT string.
|
||||
* @see #setGMTZeroFormat
|
||||
*/
|
||||
UnicodeString& getGMTZeroFormat(UnicodeString& gmtZeroFormat) const;
|
||||
|
||||
/**
|
||||
* Sets the localized GMT format string for GMT(UTC) itself (GMT offset is 0).
|
||||
* @param gmtZeroFormat The localized GMT format string for GMT(UTC).
|
||||
* @param status Receives the status.
|
||||
* @see #getGMTZeroFormat
|
||||
*/
|
||||
void setGMTZeroFormat(const UnicodeString& gmtZeroFormat, UErrorCode& status);
|
||||
|
||||
/**
|
||||
* Returns the bitwise flags of UTimeZoneFormatParseOption representing the default parse
|
||||
* options used by this object.
|
||||
* @return the default parse options.
|
||||
* @see ParseOption
|
||||
* @internal ICU 49 technology preview
|
||||
*/
|
||||
int32_t getDefaultParseOptions(void) const;
|
||||
|
||||
/**
|
||||
* Sets the default parse options.
|
||||
* <p><b>Note</b>: By default, an instance of <code>TimeZoneFormat</code>
|
||||
* created by {@link #createInstance} has no parse options set (UTZFMT_PARSE_OPTION_NONE).
|
||||
* To specify multipe options, use bitwise flags of UTimeZoneFormatParseOption.
|
||||
* @see #UTimeZoneFormatParseOption
|
||||
* @internal ICU 49 technology preview
|
||||
*/
|
||||
void setDefaultParseOptions(int32_t flags);
|
||||
|
||||
/**
|
||||
* Returns the RFC822 style time zone string for the given offset.
|
||||
* For example, "-0800".
|
||||
* @param offset The offset from GMT(UTC) in milliseconds.
|
||||
* @param result Recevies the RFC822 style GMT(UTC) offset format.
|
||||
* @return A reference to the result.
|
||||
* @see #parseOffsetRFC822
|
||||
* @internal ICU 49 technology preview
|
||||
*/
|
||||
UnicodeString& formatOffsetRFC822(int32_t offset, UnicodeString& result, UErrorCode& status) const;
|
||||
|
||||
/**
|
||||
* Returns the ISO 8601 style time zone string for the given offset.
|
||||
* For example, "-08:00" and "Z".
|
||||
* @param offset The offset from GMT(UTC) in milliseconds.
|
||||
* @param result Recevies the ISO 8601 style GMT(UTC) offset format.
|
||||
* @return A reference to the result.
|
||||
* @see #parseOffsetISO8601
|
||||
* @internal ICU 49 technology preview
|
||||
*/
|
||||
UnicodeString& formatOffsetISO8601(int32_t offset, UnicodeString& result, UErrorCode& status) const;
|
||||
|
||||
/**
|
||||
* Returns the localized GMT(UTC) offset format for the given offset.
|
||||
* The localized GMT offset is defined by;
|
||||
* <ul>
|
||||
* <li>GMT format pattern (e.g. "GMT {0}" - see {@link #getGMTPattern})
|
||||
* <li>Offset time pattern (e.g. "+HH:mm" - see {@link #getGMTOffsetPattern})
|
||||
* <li>Offset digits (e.g. "0123456789" - see {@link #getGMTOffsetDigits})
|
||||
* <li>GMT zero format (e.g. "GMT" - see {@link #getGMTZeroFormat})
|
||||
* </ul>
|
||||
* @param offset the offset from GMT(UTC) in milliseconds.
|
||||
* @param result Receives the localized GMT format string.
|
||||
* @return A reference to the result.
|
||||
* @see #parseOffsetLocalizedGMT
|
||||
* @internal ICU 49 technology preview
|
||||
*/
|
||||
UnicodeString& formatOffsetLocalizedGMT(int32_t offset, UnicodeString& result, UErrorCode& status) const;
|
||||
|
||||
/**
|
||||
* Returns the display name of the time zone at the given date for the style.
|
||||
* @param style The style (e.g. <code>UTZFMT_STYLE_GENERIC_LONG</code>, <code>UTZFMT_STYLE_LOCALIZED_GMT</code>...)
|
||||
* @param tz The time zone.
|
||||
* @param date The date.
|
||||
* @param name Receives the display name.
|
||||
* @param timeType the output argument for receiving the time type (standard/daylight/unknown)
|
||||
* used for the display name, or NULL if the information is not necessary.
|
||||
* @return A reference to the result
|
||||
* @see #UTimeZoneFormatStyle
|
||||
* @see #UTimeZoneFormatTimeType
|
||||
* @internal ICU 49 technology preview
|
||||
*/
|
||||
virtual UnicodeString& format(UTimeZoneFormatStyle style, const TimeZone& tz, UDate date,
|
||||
UnicodeString& name, UTimeZoneFormatTimeType* timeType = NULL) const;
|
||||
|
||||
/**
|
||||
* Returns offset from GMT(UTC) in milliseconds for the given RFC822
|
||||
* style time zone string. When the given string is not an RFC822 time zone
|
||||
* string, this method sets the current position as the error index
|
||||
* to <code>ParsePosition pos</code> and returns 0.
|
||||
* @param text The text contains RFC822 style time zone string (e.g. "-0800")
|
||||
* at the position.
|
||||
* @param pos The ParsePosition object.
|
||||
* @return The offset from GMT(UTC) in milliseconds for the given RFC822 style
|
||||
* time zone string.
|
||||
* @see #formatOffsetRFC822
|
||||
* @internal ICU 49 technology preview
|
||||
*/
|
||||
int32_t parseOffsetRFC822(const UnicodeString& text, ParsePosition& pos) const;
|
||||
|
||||
/**
|
||||
* Returns offset from GMT(UTC) in milliseconds for the given ISO 8601
|
||||
* style time zone string. When the given string is not an ISO 8601 time zone
|
||||
* string, this method sets the current position as the error index
|
||||
* to <code>ParsePosition pos</code> and returns 0.
|
||||
* @param text The text contains RFC822 style time zone string (e.g. "-08:00", "Z")
|
||||
* at the position.
|
||||
* @param pos The ParsePosition object.
|
||||
* @return The offset from GMT(UTC) in milliseconds for the given ISO 8601 style
|
||||
* time zone string.
|
||||
* @see #formatOffsetISO8601
|
||||
* @internal ICU 49 technology preview
|
||||
*/
|
||||
int32_t parseOffsetISO8601(const UnicodeString& text, ParsePosition& pos) const;
|
||||
|
||||
/**
|
||||
* Returns offset from GMT(UTC) in milliseconds for the given localized GMT
|
||||
* offset format string. When the given string cannot be parsed, this method
|
||||
* sets the current position as the error index to <code>ParsePosition pos</code>
|
||||
* and returns 0.
|
||||
* @param text The text contains a localized GMT offset string at the position.
|
||||
* @param pos The ParsePosition object.
|
||||
* @return The offset from GMT(UTC) in milliseconds for the given localized GMT
|
||||
* offset format string.
|
||||
* @see #formatOffsetLocalizedGMT
|
||||
* @internal ICU 49 technology preview
|
||||
*/
|
||||
int32_t parseOffsetLocalizedGMT(const UnicodeString& text, ParsePosition& pos) const;
|
||||
|
||||
/**
|
||||
* Returns a <code>TimeZone</code> by parsing the time zone string according to
|
||||
* the given parse position, the specified format style and parse options.
|
||||
*
|
||||
* @param text The text contains a time zone string at the position.
|
||||
* @param style The format style
|
||||
* @param pos The position.
|
||||
* @param parseOptions The parse options repesented by bitwise flags of UTimeZoneFormatParseOption.
|
||||
* @param timeType The output argument for receiving the time type (standard/daylight/unknown),
|
||||
* or NULL if the information is not necessary.
|
||||
* @return A <code>TimeZone</code>, or null if the input could not be parsed.
|
||||
* @see UTimeZoneFormatStyle
|
||||
* @see UTimeZoneFormatParseOption
|
||||
* @see UTimeZoneFormatTimeType
|
||||
* @internal ICU 49 technology preview
|
||||
*/
|
||||
virtual TimeZone* parse(UTimeZoneFormatStyle style, const UnicodeString& text, ParsePosition& pos,
|
||||
int32_t parseOptions, UTimeZoneFormatTimeType* timeType = NULL) const;
|
||||
|
||||
/**
|
||||
* Returns a <code>TimeZone</code> by parsing the time zone string according to
|
||||
* the given parse position, the specified format style and the default parse options.
|
||||
*
|
||||
* @param text The text contains a time zone string at the position.
|
||||
* @param style The format style
|
||||
* @param pos The position.
|
||||
* @param timeType The output argument for receiving the time type (standard/daylight/unknown),
|
||||
* or NULL if the information is not necessary.
|
||||
* @return A <code>TimeZone</code>, or null if the input could not be parsed.
|
||||
* @see UTimeZoneFormatStyle
|
||||
* @see UTimeZoneFormatParseOption
|
||||
* @see UTimeZoneFormatTimeType
|
||||
* @internal ICU 49 technology preview
|
||||
*/
|
||||
TimeZone* parse(UTimeZoneFormatStyle style, const UnicodeString& text, ParsePosition& pos,
|
||||
UTimeZoneFormatTimeType* timeType = NULL) const;
|
||||
|
||||
/* ----------------------------------------------
|
||||
* Format APIs
|
||||
* ---------------------------------------------- */
|
||||
|
||||
/**
|
||||
* Format an object to produce a time zone display string using localized GMT offset format.
|
||||
* This method handles Formattable objects with a <code>TimeZone</code>. If a the Formattable
|
||||
* object type is not a <code>TimeZone</code>, then it returns a failing UErrorCode.
|
||||
* @param obj The object to format. Must be a <code>TimeZone</code>.
|
||||
* @param appendTo Output parameter to receive result. Result is appended to existing contents.
|
||||
* @param pos On input: an alignment field, if desired. On output: the offsets of the alignment field.
|
||||
* @param status Output param filled with success/failure status.
|
||||
* @return Reference to 'appendTo' parameter.
|
||||
* @internal ICU 49 technology preview
|
||||
*/
|
||||
virtual UnicodeString& format(const Formattable& obj, UnicodeString& appendTo,
|
||||
FieldPosition& pos, UErrorCode& status) const;
|
||||
|
||||
/**
|
||||
* Parse a string to produce an object. This methods handles parsing of
|
||||
* time zone display strings into Formattable objects with <code>TimeZone</code>.
|
||||
* @param source The string to be parsed into an object.
|
||||
* @param result Formattable to be set to the parse result. If parse fails, return contents are undefined.
|
||||
* @param parse_pos The position to start parsing at. Upon return this param is set to the position after the
|
||||
* last character successfully parsed. If the source is not parsed successfully, this param
|
||||
* will remain unchanged.
|
||||
* @return A newly created Formattable* object, or NULL on failure. The caller owns this and should
|
||||
* delete it when done.
|
||||
* @internal ICU 49 technology preview
|
||||
*/
|
||||
virtual void parseObject(const UnicodeString& source, Formattable& result, ParsePosition& parse_pos) const;
|
||||
|
||||
/**
|
||||
* ICU "poor man's RTTI", returns a UClassID for this class.
|
||||
* @internal ICU 49 technology preview
|
||||
*/
|
||||
static UClassID U_EXPORT2 getStaticClassID(void);
|
||||
|
||||
/**
|
||||
* ICU "poor man's RTTI", returns a UClassID for the actual class.
|
||||
* @internal ICU 49 technology preview
|
||||
*/
|
||||
virtual UClassID getDynamicClassID() const;
|
||||
|
||||
protected:
|
||||
/**
|
||||
* Constructs a TimeZoneFormat object for the specified locale.
|
||||
* @param locale the locale
|
||||
* @param status receives the status.
|
||||
* @internal ICU 49 technology preview
|
||||
*/
|
||||
TimeZoneFormat(const Locale& locale, UErrorCode& status);
|
||||
|
||||
private:
|
||||
/* mutex */
|
||||
UMTX fLock;
|
||||
|
||||
/* Locale of this object */
|
||||
Locale fLocale;
|
||||
|
||||
/* Stores the region (could be implicit default) */
|
||||
char fTargetRegion[ULOC_COUNTRY_CAPACITY];
|
||||
|
||||
/* TimeZoneNames object used by this formatter */
|
||||
TimeZoneNames* fTimeZoneNames;
|
||||
|
||||
/* TimeZoneGenericNames object used by this formatter - lazily instantiated */
|
||||
TimeZoneGenericNames* fTimeZoneGenericNames;
|
||||
|
||||
/* Localized GMT format pattern - e.g. "GMT{0}" */
|
||||
UnicodeString fGMTPattern;
|
||||
|
||||
/* Array of offset patterns used by Localized GMT format - e.g. "+HH:mm" */
|
||||
UnicodeString fGMTOffsetPatterns[UTZFMT_PAT_NEGATIVE_HMS + 1];
|
||||
|
||||
/* Localized decimal digits used by Localized GMT format */
|
||||
UChar32 fGMTOffsetDigits[10];
|
||||
|
||||
/* Localized GMT zero format - e.g. "GMT" */
|
||||
UnicodeString fGMTZeroFormat;
|
||||
|
||||
/* Bit flags representing parse options */
|
||||
int32_t fDefParseOptionFlags;
|
||||
|
||||
/* Constant parts of GMT format pattern, populated from localized GMT format pattern*/
|
||||
UnicodeString fGMTPatternPrefix; /* Substring before {0} */
|
||||
UnicodeString fGMTPatternSuffix; /* Substring after {0} */
|
||||
|
||||
/* Compiled offset patterns generated from fGMTOffsetPatterns[] */
|
||||
UVector* fGMTOffsetPatternItems[UTZFMT_PAT_NEGATIVE_HMS + 1];
|
||||
|
||||
/**
|
||||
* Returns the time zone's specific format string.
|
||||
* @param tz the time zone
|
||||
* @param stdType the name type used for standard time
|
||||
* @param dstType the name type used for daylight time
|
||||
* @param date the date
|
||||
* @param name receives the time zone's specific format name string
|
||||
* @param timeType when null, actual time type is set
|
||||
* @return a reference to name.
|
||||
*/
|
||||
UnicodeString& formatSpecific(const TimeZone& tz, UTimeZoneNameType stdType, UTimeZoneNameType dstType,
|
||||
UDate date, UnicodeString& name, UTimeZoneFormatTimeType *timeType) const;
|
||||
|
||||
/**
|
||||
* Returns the time zone's generic format string.
|
||||
* @param tz the time zone
|
||||
* @param genType the generic name type
|
||||
* @param date the date
|
||||
* @param name receives the time zone's generic format name string
|
||||
* @return a reference to name.
|
||||
*/
|
||||
UnicodeString& formatGeneric(const TimeZone& tz, int32_t genType, UDate date, UnicodeString& name) const;
|
||||
|
||||
/**
|
||||
* Lazily create a TimeZoneGenericNames instance
|
||||
* @param status receives the status
|
||||
* @return the cached TimeZoneGenericNames.
|
||||
*/
|
||||
const TimeZoneGenericNames* getTimeZoneGenericNames(UErrorCode& status) const;
|
||||
|
||||
/**
|
||||
* Private enum specifying a combination of offset fields
|
||||
*/
|
||||
enum OffsetFields {
|
||||
FIELDS_H,
|
||||
FIELDS_HM,
|
||||
FIELDS_HMS
|
||||
};
|
||||
|
||||
/**
|
||||
* Parses the localized GMT pattern string and initialize
|
||||
* localized gmt pattern fields.
|
||||
* @param gmtPattern the localized GMT pattern string such as "GMT {0}"
|
||||
* @param status U_ILLEGAL_ARGUMENT_ERROR is set when the specified pattern does not
|
||||
* contain an argument "{0}".
|
||||
*/
|
||||
void initGMTPattern(const UnicodeString& gmtPattern, UErrorCode& status);
|
||||
|
||||
/**
|
||||
* Parse the GMT offset pattern into runtime optimized format.
|
||||
* @param pattern the offset pattern string
|
||||
* @param required the required set of fields, such as FIELDS_HM
|
||||
* @param status U_ILLEGAL_ARGUMENT is set when the specified pattern does not contain
|
||||
* pattern letters for the required fields.
|
||||
* @return A list of GMTOffsetField objects, or NULL on error.
|
||||
*/
|
||||
static UVector* parseOffsetPattern(const UnicodeString& pattern, OffsetFields required, UErrorCode& status);
|
||||
|
||||
/**
|
||||
* Appends second field to the offset pattern with hour/minute
|
||||
* Note: This code will be obsoleted once we add hour-minute-second pattern data in CLDR.
|
||||
* @param offsetHM the offset pattern including hour and minute fields
|
||||
* @param result the output offset pattern including hour, minute and second fields
|
||||
* @return a reference to result
|
||||
*/
|
||||
static UnicodeString& expandOffsetPattern(const UnicodeString& offsetHM, UnicodeString& result);
|
||||
|
||||
/**
|
||||
* Break input string into UChar32[]. Each array element represents
|
||||
* a code point. This method is used for parsing localized digit
|
||||
* characters and support characters in Unicode supplemental planes.
|
||||
* @param str the string
|
||||
* @param codeArray receives the result
|
||||
* @param capacity the capacity of codeArray
|
||||
* @return TRUE when the specified code array is fully filled with code points
|
||||
* (no under/overflow).
|
||||
*/
|
||||
static UBool toCodePoints(const UnicodeString& str, UChar32* codeArray, int32_t capacity);
|
||||
|
||||
/**
|
||||
* Returns offset from GMT(UTC) in milliseconds for the given ISO 8601 style
|
||||
* (extended format) time zone string. When the given string is not an ISO 8601 time
|
||||
* zone string, this method sets the current position as the error index
|
||||
* to <code>ParsePosition pos</code> and returns 0.
|
||||
* @param text the text contains ISO 8601 style time zone string (e.g. "-08:00", "Z")
|
||||
* at the position.
|
||||
* @param pos the position, non-negative error index will be set on failure.
|
||||
* @param extendedOnly TRUE if parsing the text as ISO 8601 extended offset format (e.g. "-08:00"),
|
||||
* or FALSE to evaluate the text as basic format.
|
||||
* @param hasDigitOffset receiving if the parsed zone string contains offset digits.
|
||||
* @return the offset from GMT(UTC) in milliseconds for the given ISO 8601 style
|
||||
* time zone string.
|
||||
*/
|
||||
int32_t parseOffsetISO8601(const UnicodeString& text, ParsePosition& pos, UBool extendedOnly,
|
||||
UBool* hasDigitOffset = NULL) const;
|
||||
|
||||
/**
|
||||
* Appends localized digits to the buffer.
|
||||
* This code assumes that the input number is 0 - 59
|
||||
* @param buf the target buffer
|
||||
* @param n the integer number
|
||||
* @param minDigits the minimum digits width
|
||||
*/
|
||||
void appendOffsetDigits(UnicodeString& buf, int32_t n, uint8_t minDigits) const;
|
||||
|
||||
/**
|
||||
* Returns offset from GMT(UTC) in milliseconds for the given localized GMT
|
||||
* offset format string. When the given string cannot be parsed, this method
|
||||
* sets the current position as the error index to <code>ParsePosition pos</code>
|
||||
* and returns 0.
|
||||
* @param text the text contains a localized GMT offset string at the position.
|
||||
* @param pos the position, non-negative error index will be set on failure.
|
||||
* @param hasDigitOffset receiving if the parsed zone string contains offset digits.
|
||||
* @return the offset from GMT(UTC) in milliseconds for the given localized GMT
|
||||
* offset format string.
|
||||
*/
|
||||
int32_t parseOffsetLocalizedGMT(const UnicodeString& text, ParsePosition& pos,
|
||||
UBool* hasDigitOffset) const;
|
||||
|
||||
/**
|
||||
* Parses localized GMT offset fields into offset.
|
||||
* @param text the input text
|
||||
* @param start the start index
|
||||
* @param minimumHourWidth true if the parser allows hour field width to be 1
|
||||
* @param parsedLen the parsed length, or 0 on failure.
|
||||
* @return the parsed offset in milliseconds.
|
||||
*/
|
||||
int32_t parseOffsetFields(const UnicodeString& text, int32_t start, UBool minimumHourWidth,
|
||||
int32_t& parsedLen) const;
|
||||
|
||||
/**
|
||||
* Parses abutting localized GMT offset fields (such as 0800) into offset.
|
||||
* @param text the input text
|
||||
* @param start the start index
|
||||
* @param parsedLen the parsed length, or 0 on failure
|
||||
* @return the parsed offset in milliseconds.
|
||||
*/
|
||||
int32_t parseAbuttingOffsetFields(const UnicodeString& text, int32_t start, int32_t& parsedLen) const;
|
||||
|
||||
/**
|
||||
* Parses the input text using the default format patterns (e.g. "UTC{0}").
|
||||
* @param text the input text
|
||||
* @param start the start index
|
||||
* @param parsedLen the parsed length, or 0 on failure
|
||||
* @return the parsed offset in milliseconds.
|
||||
*/
|
||||
int32_t parseOffsetDefaultLocalizedGMT(const UnicodeString& text, int start, int32_t& parsedLen) const;
|
||||
|
||||
/**
|
||||
* Parses the input GMT offset fields with the default offset pattern.
|
||||
* @param text the input text
|
||||
* @param start the start index
|
||||
* @param separator the separator character, e.g. ':'
|
||||
* @param parsedLen the parsed length, or 0 on failure.
|
||||
* @return the parsed offset in milliseconds.
|
||||
*/
|
||||
int32_t parseDefaultOffsetFields(const UnicodeString& text, int32_t start, UChar separator,
|
||||
int32_t& parsedLen) const;
|
||||
|
||||
/**
|
||||
* Reads an offset field value. This method will stop parsing when
|
||||
* 1) number of digits reaches <code>maxDigits</code>
|
||||
* 2) just before already parsed number exceeds <code>maxVal</code>
|
||||
*
|
||||
* @param text the text
|
||||
* @param start the start offset
|
||||
* @param minDigits the minimum number of required digits
|
||||
* @param maxDigits the maximum number of digits
|
||||
* @param minVal the minimum value
|
||||
* @param maxVal the maximum value
|
||||
* @param parsedLen the actual parsed length.
|
||||
* @return the integer value parsed
|
||||
*/
|
||||
int32_t parseOffsetFieldWithLocalizedDigits(const UnicodeString& text, int32_t start,
|
||||
uint8_t minDigits, uint8_t maxDigits, uint16_t minVal, uint16_t maxVal, int32_t& parsedLen) const;
|
||||
|
||||
/**
|
||||
* Reads a single decimal digit, either localized digits used by this object
|
||||
* or any Unicode numeric character.
|
||||
* @param text the text
|
||||
* @param start the start index
|
||||
* @param len the actual length read from the text
|
||||
* the start index is not a decimal number.
|
||||
* @return the integer value of the parsed digit, or -1 on failure.
|
||||
*/
|
||||
int32_t parseSingleLocalizedDigit(const UnicodeString& text, int32_t start, int32_t& len) const;
|
||||
|
||||
/**
|
||||
* Formats offset using ASCII digits. The input offset range must be
|
||||
* within +/-24 hours (exclusive).
|
||||
* @param offset The offset
|
||||
* @param sep The field separator character or 0 if not required
|
||||
* @param minFields The minimum fields
|
||||
* @param maxFields The maximum fields
|
||||
* @return The offset string
|
||||
*/
|
||||
static UnicodeString& formatOffsetWithAsciiDigits(int32_t offset, UChar sep,
|
||||
OffsetFields minFields, OffsetFields maxFields, UnicodeString& result);
|
||||
|
||||
/**
|
||||
* Parses offset represented by contiguous ASCII digits.
|
||||
* <p>
|
||||
* Note: This method expects the input position is already at the start of
|
||||
* ASCII digits and does not parse sign (+/-).
|
||||
* @param text The text contains a sequence of ASCII digits
|
||||
* @param pos The parse position
|
||||
* @param minFields The minimum Fields to be parsed
|
||||
* @param maxFields The maximum Fields to be parsed
|
||||
* @param fixedHourWidth true if hour field must be width of 2
|
||||
* @return Parsed offset, 0 or positive number.
|
||||
*/
|
||||
static int32_t parseAbuttingAsciiOffsetFields(const UnicodeString& text, ParsePosition& pos,
|
||||
OffsetFields minFields, OffsetFields maxFields, UBool fixedHourWidth);
|
||||
|
||||
/**
|
||||
* Parses offset represented by ASCII digits and separators.
|
||||
* <p>
|
||||
* Note: This method expects the input position is already at the start of
|
||||
* ASCII digits and does not parse sign (+/-).
|
||||
* @param text The text
|
||||
* @param pos The parse position
|
||||
* @param sep The separator character
|
||||
* @param minFields The minimum Fields to be parsed
|
||||
* @param maxFields The maximum Fields to be parsed
|
||||
* @param fixedHourWidth true if hour field must be width of 2
|
||||
* @return Parsed offset, 0 or positive number.
|
||||
*/
|
||||
static int32_t parseAsciiOffsetFields(const UnicodeString& text, ParsePosition& pos, UChar sep,
|
||||
OffsetFields minFields, OffsetFields maxFields, UBool fixedHourWidth);
|
||||
|
||||
/**
|
||||
* Unquotes the message format style pattern.
|
||||
* @param pattern the pattern
|
||||
* @param result receive the unquoted pattern.
|
||||
* @return A reference to result.
|
||||
*/
|
||||
static UnicodeString& unquote(const UnicodeString& pattern, UnicodeString& result);
|
||||
|
||||
/**
|
||||
* Initialize localized GMT format offset hour/min/sec patterns.
|
||||
* This method parses patterns into optimized run-time format.
|
||||
* @param status receives the status.
|
||||
*/
|
||||
void initGMTOffsetPatterns(UErrorCode& status);
|
||||
|
||||
/**
|
||||
* Creates an instance of TimeZone for the given offset
|
||||
* @param offset the offset
|
||||
* @return A TimeZone with the given offset
|
||||
*/
|
||||
TimeZone* createTimeZoneForOffset(int32_t offset) const;
|
||||
|
||||
/**
|
||||
* Returns the time type for the given name type
|
||||
* @param nameType the name type
|
||||
* @return the time type (unknown/standard/daylight)
|
||||
*/
|
||||
static UTimeZoneFormatTimeType getTimeType(UTimeZoneNameType nameType);
|
||||
|
||||
/*
|
||||
* Returns the time zone ID of a match at the specified index within
|
||||
* the MatchInfoCollection.
|
||||
* @param matches the collection of matches
|
||||
* @param idx the index withing matches
|
||||
* @param tzID receives the resolved time zone ID
|
||||
* @return a reference to tzID.
|
||||
*/
|
||||
UnicodeString& getTimeZoneID(const TimeZoneNames::MatchInfoCollection* matches, int32_t idx, UnicodeString& tzID) const;
|
||||
};
|
||||
|
||||
U_NAMESPACE_END
|
||||
|
||||
#endif /* U_HIDE_INTERNAL_API */
|
||||
#endif
|
||||
#endif
|
||||
|
378
icu4c/source/i18n/unicode/tznames.h
Normal file
378
icu4c/source/i18n/unicode/tznames.h
Normal file
|
@ -0,0 +1,378 @@
|
|||
/*
|
||||
*******************************************************************************
|
||||
* Copyright (C) 2011-2012, International Business Machines Corporation and *
|
||||
* others. All Rights Reserved. *
|
||||
*******************************************************************************
|
||||
*/
|
||||
#ifndef __TZNAMES_H
|
||||
#define __TZNAMES_H
|
||||
|
||||
/**
|
||||
* \file
|
||||
* \brief C++ API: TimeZoneNames
|
||||
*/
|
||||
#include "unicode/utypes.h"
|
||||
|
||||
#if !UCONFIG_NO_FORMATTING
|
||||
#ifndef U_HIDE_INTERNAL_API
|
||||
|
||||
#include "unicode/uloc.h"
|
||||
#include "unicode/unistr.h"
|
||||
|
||||
U_CDECL_BEGIN
|
||||
|
||||
/**
|
||||
* Constants for time zone display name types.
|
||||
* @internal ICU 49 technology preview
|
||||
*/
|
||||
typedef enum UTimeZoneNameType {
|
||||
/**
|
||||
* Unknown display name type.
|
||||
* @internal ICU 49 technology preview
|
||||
*/
|
||||
UTZNM_UNKNOWN = 0x00,
|
||||
/**
|
||||
* Long display name, such as "Eastern Time".
|
||||
* @internal ICU 49 technology preview
|
||||
*/
|
||||
UTZNM_LONG_GENERIC = 0x01,
|
||||
/**
|
||||
* Long display name for standard time, such as "Eastern Standard Time".
|
||||
* @internal ICU 49 technology preview
|
||||
*/
|
||||
UTZNM_LONG_STANDARD = 0x02,
|
||||
/**
|
||||
* Long display name for daylight saving time, such as "Eastern Daylight Time".
|
||||
* @internal ICU 49 technology preview
|
||||
*/
|
||||
UTZNM_LONG_DAYLIGHT = 0x04,
|
||||
/**
|
||||
* Short display name, such as "ET".
|
||||
* @internal ICU 49 technology preview
|
||||
*/
|
||||
UTZNM_SHORT_GENERIC = 0x08,
|
||||
/**
|
||||
* Short display name for standard time, such as "EST".
|
||||
* @internal ICU 49 technology preview
|
||||
*/
|
||||
UTZNM_SHORT_STANDARD = 0x10,
|
||||
/**
|
||||
* Short display name for daylight saving time, such as "EDT".
|
||||
* @internal ICU 49 technology preview
|
||||
*/
|
||||
UTZNM_SHORT_DAYLIGHT = 0x20
|
||||
} UTimeZoneNameType;
|
||||
|
||||
U_CDECL_END
|
||||
|
||||
U_NAMESPACE_BEGIN
|
||||
|
||||
class UVector;
|
||||
struct MatchInfo;
|
||||
|
||||
/**
|
||||
* <code>TimeZoneNames</code> is an abstract class representing the time zone display name data model defined
|
||||
* by <a href="http://www.unicode.org/reports/tr35/">UTS#35 Unicode Locale Data Markup Language (LDML)</a>.
|
||||
* The model defines meta zone, which is used for storing a set of display names. A meta zone can be shared
|
||||
* by multiple time zones. Also a time zone may have multiple meta zone historic mappings.
|
||||
* <p>
|
||||
* For example, people in the United States refer the zone used by the east part of North America as "Eastern Time".
|
||||
* The tz database contains multiple time zones "America/New_York", "America/Detroit", "America/Montreal" and some
|
||||
* others that belong to "Eastern Time". However, assigning different display names to these time zones does not make
|
||||
* much sense for most of people.
|
||||
* <p>
|
||||
* In <a href="http://cldr.unicode.org/">CLDR</a> (which uses LDML for representing locale data), the display name
|
||||
* "Eastern Time" is stored as long generic display name of a meta zone identified by the ID "America_Eastern".
|
||||
* Then, there is another table maintaining the historic mapping to meta zones for each time zone. The time zones in
|
||||
* the above example ("America/New_York", "America/Detroit"...) are mapped to the meta zone "America_Eastern".
|
||||
* <p>
|
||||
* Sometimes, a time zone is mapped to a different time zone in the past. For example, "America/Indiana/Knox"
|
||||
* had been moving "Eastern Time" and "Central Time" back and forth. Therefore, it is necessary that time zone
|
||||
* to meta zones mapping data are stored by date range.
|
||||
*
|
||||
* <p><b>Note:</b>
|
||||
* The methods in this class assume that time zone IDs are already canonicalized. For example, you may not get proper
|
||||
* result returned by a method with time zone ID "America/Indiana/Indianapolis", because it's not a canonical time zone
|
||||
* ID (the canonical time zone ID for the time zone is "America/Indianapolis". See
|
||||
* {@link TimeZone#getCanonicalID(const UnicodeString& id, UnicodeString& canonicalID, UErrorCode& status)} about ICU
|
||||
* canonical time zone IDs.
|
||||
*
|
||||
* <p>
|
||||
* In CLDR, most of time zone display names except location names are provided through meta zones. But a time zone may
|
||||
* have a specific name that is not shared with other time zones.
|
||||
*
|
||||
* For example, time zone "Europe/London" has English long name for standard time "Greenwich Mean Time", which is also
|
||||
* shared with other time zones. However, the long name for daylight saving time is "British Summer Time", which is only
|
||||
* used for "Europe/London".
|
||||
*
|
||||
* <p>
|
||||
* {@link #getTimeZoneDisplayName} is designed for accessing a name only used by a single time zone.
|
||||
* But is not necessarily mean that a subclass implementation use the same model with CLDR. A subclass implementation
|
||||
* may provide time zone names only through {@link #getTimeZoneDisplayName}, or only through {@link #getMetaZoneDisplayName},
|
||||
* or both.
|
||||
*
|
||||
* @internal ICU 49 technology preview
|
||||
*/
|
||||
class U_I18N_API TimeZoneNames : public UObject {
|
||||
public:
|
||||
/**
|
||||
* Destructor.
|
||||
* @internal ICU 49 technology preview
|
||||
*/
|
||||
virtual ~TimeZoneNames();
|
||||
|
||||
/**
|
||||
* Return true if the given TimeZoneNames objects are emantically equal.
|
||||
* @param other the object to be compared with.
|
||||
* @return Return TRUE if the given Format objects are semantically equal.
|
||||
* @internal ICU 49 technology preview
|
||||
*/
|
||||
virtual UBool operator==(const TimeZoneNames& other) const = 0;
|
||||
|
||||
/**
|
||||
* Return true if the given TimeZoneNames objects are not semantically
|
||||
* equal.
|
||||
* @param other the object to be compared with.
|
||||
* @return Return TRUE if the given Format objects are not semantically equal.
|
||||
* @internal ICU 49 technology preview
|
||||
*/
|
||||
UBool operator!=(const TimeZoneNames& other) const { return !operator==(other); }
|
||||
|
||||
/**
|
||||
* Clone this object polymorphically. The caller is responsible
|
||||
* for deleting the result when done.
|
||||
* @return A copy of the object
|
||||
* @internal ICU 49 technology preview
|
||||
*/
|
||||
virtual TimeZoneNames* clone() const = 0;
|
||||
|
||||
/**
|
||||
* Returns an instance of <code>TimeZoneDisplayNames</code> for the specified locale.
|
||||
*
|
||||
* @param locale The locale.
|
||||
* @param status Recevies the status.
|
||||
* @return An instance of <code>TimeZoneDisplayNames</code>
|
||||
* @internal ICU 49 technology preview
|
||||
*/
|
||||
static TimeZoneNames* U_EXPORT2 createInstance(const Locale& locale, UErrorCode& status);
|
||||
|
||||
/**
|
||||
* Returns an enumeration of all available meta zone IDs.
|
||||
* @param status Recevies the status.
|
||||
* @return an enumeration object, owned by the caller.
|
||||
* @internal ICU 49 technology preview
|
||||
*/
|
||||
virtual StringEnumeration* getAvailableMetaZoneIDs(UErrorCode& status) const = 0;
|
||||
|
||||
/**
|
||||
* Returns an enumeration of all available meta zone IDs used by the given time zone.
|
||||
* @param tzID The canoical tiem zone ID.
|
||||
* @param status Recevies the status.
|
||||
* @return an enumeration object, owned by the caller.
|
||||
* @internal ICU 49 technology preview
|
||||
*/
|
||||
virtual StringEnumeration* getAvailableMetaZoneIDs(const UnicodeString& tzID, UErrorCode& status) const = 0;
|
||||
|
||||
/**
|
||||
* Returns the meta zone ID for the given canonical time zone ID at the given date.
|
||||
* @param tzID The canonical time zone ID.
|
||||
* @param date The date.
|
||||
* @param mzID Receives the meta zone ID for the given time zone ID at the given date. If the time zone does not have a
|
||||
* corresponding meta zone at the given date or the implementation does not support meta zones, "bogus" state
|
||||
* is set.
|
||||
* @return A reference to the result.
|
||||
* @internal ICU 49 technology preview
|
||||
*/
|
||||
virtual UnicodeString& getMetaZoneID(const UnicodeString& tzID, UDate date, UnicodeString& mzID) const = 0;
|
||||
|
||||
/**
|
||||
* Returns the reference zone ID for the given meta zone ID for the region.
|
||||
* @param mzID The meta zone ID.
|
||||
* @param region The region.
|
||||
* @param tzID Receives the reference zone ID ("golden zone" in the LDML specification) for the given time zone ID for the
|
||||
* region. If the meta zone is unknown or the implementation does not support meta zones, "bogus" state
|
||||
* is set.
|
||||
* @return A reference to the result.
|
||||
* @internal ICU 49 technology preview
|
||||
*/
|
||||
virtual UnicodeString& getReferenceZoneID(const UnicodeString& mzID, const char* region, UnicodeString& tzID) const = 0;
|
||||
|
||||
/**
|
||||
* Returns the display name of the meta zone.
|
||||
* @param mzID The meta zone ID.
|
||||
* @param type The display name type. See {@link #UTimeZoneNameType}.
|
||||
* @param name Receives the display name of the meta zone. When this object does not have a localized display name for the given
|
||||
* meta zone with the specified type or the implementation does not provide any display names associated
|
||||
* with meta zones, "bogus" state is set.
|
||||
* @return A reference to the result.
|
||||
* @internal ICU 49 technology preview
|
||||
*/
|
||||
virtual UnicodeString& getMetaZoneDisplayName(const UnicodeString& mzID, UTimeZoneNameType type, UnicodeString& name) const = 0;
|
||||
|
||||
/**
|
||||
* Returns the display name of the time zone. Unlike {@link #getDisplayName},
|
||||
* this method does not get a name from a meta zone used by the time zone.
|
||||
* @param tzID The canonical time zone ID.
|
||||
* @param type The display name type. See {@link #UTimeZoneNameType}.
|
||||
* @param name Receives the display name for the time zone. When this object does not have a localized display name for the given
|
||||
* time zone with the specified type, "bogus" state is set.
|
||||
* @return A reference to the result.
|
||||
* @internal ICU 49 technology preview
|
||||
*/
|
||||
virtual UnicodeString& getTimeZoneDisplayName(const UnicodeString& tzID, UTimeZoneNameType type, UnicodeString& name) const = 0;
|
||||
|
||||
/**
|
||||
* Returns the exemplar location name for the given time zone. When this object does not have a localized location
|
||||
* name, the default implementation may still returns a programmatically generated name with the logic described
|
||||
* below.
|
||||
* <ol>
|
||||
* <li>Check if the ID contains "/". If not, return null.
|
||||
* <li>Check if the ID does not start with "Etc/" or "SystemV/". If it does, return null.
|
||||
* <li>Extract a substring after the last occurrence of "/".
|
||||
* <li>Replace "_" with " ".
|
||||
* </ol>
|
||||
* For example, "New York" is returned for the time zone ID "America/New_York" when this object does not have the
|
||||
* localized location name.
|
||||
*
|
||||
* @param tzID The canonical time zone ID
|
||||
* @param name Receives the exemplar location name for the given time zone, or "bogus" state is set when a localized
|
||||
* location name is not available and the fallback logic described above cannot extract location from the ID.
|
||||
* @return A reference to the result.
|
||||
* @internal ICU 49 technology preview
|
||||
*/
|
||||
virtual UnicodeString& getExemplarLocationName(const UnicodeString& tzID, UnicodeString& name) const;
|
||||
|
||||
/**
|
||||
* Returns the display name of the time zone at the given date.
|
||||
* <p>
|
||||
* <b>Note:</b> This method calls the subclass's {@link #getTimeZoneDisplayName} first. When the
|
||||
* result is bogus, this method calls {@link #getMetaZoneID} to get the meta zone ID mapped from the
|
||||
* time zone, then calls {@link #getMetaZoneDisplayName}.
|
||||
*
|
||||
* @param tzID The canonical time zone ID.
|
||||
* @param type The display name type. See {@link #UTimeZoneNameType}.
|
||||
* @param date The date.
|
||||
* @param name Receives the display name for the time zone at the given date. When this object does not have a localized display
|
||||
* name for the time zone with the specified type and date, "bogus" state is set.
|
||||
* @return A reference to the result.
|
||||
* @internal ICU 49 technology preview
|
||||
*/
|
||||
virtual UnicodeString& getDisplayName(const UnicodeString& tzID, UTimeZoneNameType type, UDate date, UnicodeString& name) const;
|
||||
|
||||
/**
|
||||
* <code>MatchInfoCollection</code> represents a collection of time zone name matches used by
|
||||
* {@link TimeZoneNames#find}.
|
||||
* @internal ICU 49 technology preview
|
||||
*/
|
||||
class U_I18N_API MatchInfoCollection : public UMemory {
|
||||
public:
|
||||
/**
|
||||
* Constructor.
|
||||
* @internal ICU 49 technology preview
|
||||
*/
|
||||
MatchInfoCollection();
|
||||
/**
|
||||
* Destructor.
|
||||
* @internal ICU 49 technology preview
|
||||
*/
|
||||
virtual ~MatchInfoCollection();
|
||||
|
||||
/**
|
||||
* Adds a zone match.
|
||||
* @param nameType The name type.
|
||||
* @param matchLength The match length.
|
||||
* @param tzID The time zone ID.
|
||||
* @param status Receives the status
|
||||
* @internal ICU 49 technology preview
|
||||
*/
|
||||
void addZone(UTimeZoneNameType nameType, int32_t matchLength,
|
||||
const UnicodeString& tzID, UErrorCode& status);
|
||||
|
||||
/**
|
||||
* Adds a meata zone match.
|
||||
* @param nameType The name type.
|
||||
* @param matchLength The match length.
|
||||
* @param mzID The metazone ID.
|
||||
* @param status Receives the status
|
||||
* @internal ICU 49 technology preview
|
||||
*/
|
||||
void addMetaZone(UTimeZoneNameType nameType, int32_t matchLength,
|
||||
const UnicodeString& mzID, UErrorCode& status);
|
||||
|
||||
/**
|
||||
* Returns the number of entries available in this object.
|
||||
* @return The number of entries.
|
||||
* @internal ICU 49 technology preview
|
||||
*/
|
||||
int32_t size() const;
|
||||
|
||||
/**
|
||||
* Returns the time zone name type of a match at the specified index.
|
||||
* @param idx The index
|
||||
* @return The time zone name type. If the specified idx is out of range,
|
||||
* it returns UTZNM_UNKNOWN.
|
||||
* @see UTimeZoneNameType
|
||||
* @internal ICU 49 technology preview
|
||||
*/
|
||||
UTimeZoneNameType getNameTypeAt(int32_t idx) const;
|
||||
|
||||
/**
|
||||
* Returns the match length of a match at the specified index.
|
||||
* @param idx The index
|
||||
* @param status Receives the status
|
||||
* @return The match length. If the specified idx is out of range,
|
||||
* it returns 0.
|
||||
* @internal ICU 49 technology preview
|
||||
*/
|
||||
int32_t getMatchLengthAt(int32_t idx) const;
|
||||
|
||||
/**
|
||||
* Gets the zone ID of a match at the specified index.
|
||||
* @param idx The index
|
||||
* @param tzID Receives the zone ID.
|
||||
* @return TRUE if the zone ID was set to tzID.
|
||||
* @internal ICU 49 technology preview
|
||||
*/
|
||||
UBool getTimeZoneIDAt(int32_t idx, UnicodeString& tzID) const;
|
||||
|
||||
/**
|
||||
* Gets the metazone ID of a match at the specified index.
|
||||
* @param idx The index
|
||||
* @param mzID Receives the metazone ID
|
||||
* @param status Receives the status.
|
||||
* @return TRUE if the meta zone ID was set to mzID.
|
||||
* @internal ICU 49 technology preview
|
||||
*/
|
||||
UBool getMetaZoneIDAt(int32_t idx, UnicodeString& mzID) const;
|
||||
|
||||
private:
|
||||
UVector* fMatches; // vector of MatchEntry
|
||||
|
||||
UVector* matches(UErrorCode& status);
|
||||
};
|
||||
|
||||
/**
|
||||
* Finds time zone name prefix matches for the input text at the
|
||||
* given offset and returns a collection of the matches.
|
||||
* @param text The text.
|
||||
* @param start The starting offset within the text.
|
||||
* @param types The set of name types represented by bitwise flags of UTimeZoneNameType enums,
|
||||
* or UTZNM_UNKNOWN for all name types.
|
||||
* @param status Receives the status.
|
||||
* @return A collection of matches (owned by the caller), or NULL if no matches are found.
|
||||
* @see UTimeZoneNameType
|
||||
* @see MatchInfoCollection
|
||||
* @internal ICU 49 technology preview
|
||||
*/
|
||||
virtual MatchInfoCollection* find(const UnicodeString& text, int32_t start, uint32_t types, UErrorCode& status) const = 0;
|
||||
|
||||
private:
|
||||
// No ICU "poor man's RTTI" for this class nor its subclasses.
|
||||
virtual UClassID getDynamicClassID() const;
|
||||
};
|
||||
|
||||
U_NAMESPACE_END
|
||||
|
||||
#endif /* U_HIDE_INTERNAL_API */
|
||||
#endif
|
||||
#endif
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
*******************************************************************************
|
||||
* Copyright (C) 2007-2011, International Business Machines Corporation and *
|
||||
* Copyright (C) 2007-2012, International Business Machines Corporation and *
|
||||
* others. All Rights Reserved. *
|
||||
*******************************************************************************
|
||||
*/
|
||||
|
@ -14,6 +14,7 @@
|
|||
#include "unicode/timezone.h"
|
||||
#include "unicode/ustring.h"
|
||||
#include "unicode/putil.h"
|
||||
#include "unicode/simpletz.h"
|
||||
|
||||
#include "umutex.h"
|
||||
#include "uvector.h"
|
||||
|
@ -132,6 +133,8 @@ static const UChar gDefaultFrom[] = {0x31, 0x39, 0x37, 0x30, 0x2D, 0x30, 0x31, 0
|
|||
static const UChar gDefaultTo[] = {0x39, 0x39, 0x39, 0x39, 0x2D, 0x31, 0x32, 0x2D, 0x33, 0x31,
|
||||
0x20, 0x32, 0x33, 0x3A, 0x35, 0x39, 0x00}; // "9999-12-31 23:59"
|
||||
|
||||
static const UChar gCustomTzPrefix[] = {0x47, 0x4D, 0x54, 0}; // "GMT"
|
||||
|
||||
#define ASCII_DIGIT(c) (((c)>=0x30 && (c)<=0x39) ? (c)-0x30 : -1)
|
||||
|
||||
/*
|
||||
|
@ -842,6 +845,54 @@ ZoneMeta::findTimeZoneID(const UnicodeString& tzid) {
|
|||
return TimeZone::findID(tzid);
|
||||
}
|
||||
|
||||
|
||||
TimeZone*
|
||||
ZoneMeta::createCustomTimeZone(int32_t offset) {
|
||||
UBool negative = FALSE;
|
||||
int32_t tmp = offset;
|
||||
if (offset < 0) {
|
||||
negative = TRUE;
|
||||
tmp = -offset;
|
||||
}
|
||||
int32_t hour, min, sec;
|
||||
|
||||
tmp /= 1000;
|
||||
sec = tmp % 60;
|
||||
tmp /= 60;
|
||||
min = tmp % 60;
|
||||
hour = tmp / 60;
|
||||
|
||||
UnicodeString zid;
|
||||
formatCustomID(hour, min, sec, negative, zid);
|
||||
return new SimpleTimeZone(offset, zid);
|
||||
}
|
||||
|
||||
UnicodeString&
|
||||
ZoneMeta::formatCustomID(uint8_t hour, uint8_t min, uint8_t sec, UBool negative, UnicodeString& id) {
|
||||
// Create normalized time zone ID - GMT[+|-]HH:mm[:ss]
|
||||
id.setTo(gCustomTzPrefix, -1);
|
||||
if (hour != 0 || min != 0) {
|
||||
if (negative) {
|
||||
id.append(0x2D); // '-'
|
||||
} else {
|
||||
id.append(0x2B); // '+'
|
||||
}
|
||||
// Always use US-ASCII digits
|
||||
id.append(0x30 + (hour%100)/10);
|
||||
id.append(0x30 + (hour%10));
|
||||
id.append(0x3A); // ':'
|
||||
id.append(0x30 + (min%100)/10);
|
||||
id.append(0x30 + (min%10));
|
||||
if (sec != 0) {
|
||||
id.append(0x3A); // ':'
|
||||
id.append(0x30 + (sec%100)/10);
|
||||
id.append(0x30 + (sec%10));
|
||||
}
|
||||
}
|
||||
return id;
|
||||
}
|
||||
|
||||
|
||||
U_NAMESPACE_END
|
||||
|
||||
#endif /* #if !UCONFIG_NO_FORMATTING */
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
*******************************************************************************
|
||||
* Copyright (C) 2007-2011, International Business Machines Corporation and *
|
||||
* Copyright (C) 2007-2012, International Business Machines Corporation and *
|
||||
* others. All Rights Reserved. *
|
||||
*******************************************************************************
|
||||
*/
|
||||
|
@ -87,10 +87,18 @@ public:
|
|||
*/
|
||||
static const UChar* U_EXPORT2 findMetaZoneID(const UnicodeString& mzid);
|
||||
|
||||
/**
|
||||
* Creates a custom zone for the offset
|
||||
* @param offset GMT offset in milliseconds
|
||||
* @return A custom TimeZone for the offset with normalized time zone id
|
||||
*/
|
||||
static TimeZone* createCustomTimeZone(int32_t offset);
|
||||
|
||||
private:
|
||||
ZoneMeta(); // Prevent construction.
|
||||
static UVector* createMetazoneMappings(const UnicodeString &tzid);
|
||||
static void initAvailableMetaZoneIDs();
|
||||
static UnicodeString& formatCustomID(uint8_t hour, uint8_t min, uint8_t sec, UBool negative, UnicodeString& id);
|
||||
};
|
||||
|
||||
U_NAMESPACE_END
|
||||
|
|
|
@ -2291,6 +2291,7 @@ void DateFormatTest::TestTimeZoneDisplayName()
|
|||
const char *fallbackTests[][6] = {
|
||||
{ "en", "America/Los_Angeles", "2004-01-15T00:00:00Z", "Z", "-0800", "-8:00" },
|
||||
{ "en", "America/Los_Angeles", "2004-01-15T00:00:00Z", "ZZZZ", "GMT-08:00", "-8:00" },
|
||||
{ "en", "America/Los_Angeles", "2004-01-15T00:00:00Z", "ZZZZZ", "-08:00", "-8:00" },
|
||||
{ "en", "America/Los_Angeles", "2004-01-15T00:00:00Z", "z", "PST", "America/Los_Angeles" },
|
||||
{ "en", "America/Los_Angeles", "2004-01-15T00:00:00Z", "V", "PST", "America/Los_Angeles" },
|
||||
{ "en", "America/Los_Angeles", "2004-01-15T00:00:00Z", "zzzz", "Pacific Standard Time", "America/Los_Angeles" },
|
||||
|
@ -3423,8 +3424,10 @@ void DateFormatTest::TestGMTParsing() {
|
|||
"HH:mm:ss zzzz", "10:20:30 UTC", "10:20:30 +0000", // standalone "UTC"
|
||||
"ZZZZ HH:mm:ss", "UT 10:20:30", "10:20:30 +0000",
|
||||
"V HH:mm:ss", "UT+0130 10:20:30", "10:20:30 +0130",
|
||||
"V HH:mm:ss", "UTC+0130 10:20:30", NULL, // UTC+0130 is not a supported pattern
|
||||
"V HH:mm:ss", "UTC+0130 10:20:30", "10:20:30 +0130",
|
||||
"HH mm Z ss", "10 20 GMT-1100 30", "10:20:30 -1100",
|
||||
"HH:mm:ssZZZZZ", "14:25:45Z", "14:25:45 +0000",
|
||||
"HH:mm:ssZZZZZ", "15:00:00-08:00", "15:00:00 -0800",
|
||||
};
|
||||
const int32_t DATA_len = sizeof(DATA)/sizeof(DATA[0]);
|
||||
expectParse(DATA, DATA_len, Locale("en"));
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
*******************************************************************************
|
||||
* Copyright (C) 2007-2011, International Business Machines Corporation and *
|
||||
* Copyright (C) 2007-2012, International Business Machines Corporation and *
|
||||
* others. All Rights Reserved. *
|
||||
*******************************************************************************
|
||||
*/
|
||||
|
@ -20,7 +20,7 @@
|
|||
#include "unicode/basictz.h"
|
||||
#include "cstring.h"
|
||||
|
||||
static const char* PATTERNS[] = {"z", "zzzz", "Z", "ZZZZ", "v", "vvvv", "V", "VVVV"};
|
||||
static const char* PATTERNS[] = {"z", "zzzz", "Z", "ZZZZ", "ZZZZZ", "v", "vvvv", "V", "VVVV"};
|
||||
static const int NUM_PATTERNS = sizeof(PATTERNS)/sizeof(const char*);
|
||||
|
||||
void
|
||||
|
@ -202,13 +202,18 @@ TimeZoneFormatTest::TestTimeZoneRoundTrip(void) {
|
|||
|
||||
} else {
|
||||
// Check if localized GMT format or RFC format is used.
|
||||
int32_t numDigits = 0;
|
||||
for (int n = 0; n < tzstr.length(); n++) {
|
||||
if (u_isdigit(tzstr.charAt(n))) {
|
||||
numDigits++;
|
||||
UBool isOffsetFormat = (*PATTERNS[patidx] == 'Z');
|
||||
if (!isOffsetFormat) {
|
||||
// Check if localized GMT format is used as a fallback of name styles
|
||||
int32_t numDigits = 0;
|
||||
for (int n = 0; n < tzstr.length(); n++) {
|
||||
if (u_isdigit(tzstr.charAt(n))) {
|
||||
numDigits++;
|
||||
}
|
||||
}
|
||||
isOffsetFormat = (numDigits >= 3);
|
||||
}
|
||||
if (tzstr == localGMTString || numDigits >= 3) {
|
||||
if (isOffsetFormat || tzstr == localGMTString) {
|
||||
// Localized GMT or RFC: total offset (raw + dst) must be preserved.
|
||||
int32_t inOffset = inRaw + inDst;
|
||||
int32_t outOffset = outRaw + outDst;
|
||||
|
@ -260,9 +265,9 @@ public:
|
|||
UBool REALLY_VERBOSE = FALSE;
|
||||
|
||||
// Whether each pattern is ambiguous at DST->STD local time overlap
|
||||
UBool AMBIGUOUS_DST_DECESSION[] = { FALSE, FALSE, FALSE, FALSE, TRUE, TRUE, FALSE, TRUE };
|
||||
UBool AMBIGUOUS_DST_DECESSION[] = { FALSE, FALSE, FALSE, FALSE, FALSE, TRUE, TRUE, FALSE, TRUE };
|
||||
// Whether each pattern is ambiguous at STD->STD/DST->DST local time overlap
|
||||
UBool AMBIGUOUS_NEGATIVE_SHIFT[] = { TRUE, TRUE, FALSE, FALSE, TRUE, TRUE, TRUE, TRUE };
|
||||
UBool AMBIGUOUS_NEGATIVE_SHIFT[] = { TRUE, TRUE, FALSE, FALSE, FALSE, TRUE, TRUE, TRUE, TRUE };
|
||||
|
||||
// Workaround for #6338
|
||||
//UnicodeString BASEPATTERN("yyyy-MM-dd'T'HH:mm:ss.SSS");
|
||||
|
|
Loading…
Add table
Reference in a new issue