icu4c/source/extra/uconv/uconv.vcxproj.filters -text
icu4c/source/i18n/i18n.vcxproj -text
icu4c/source/i18n/i18n.vcxproj.filters -text
+icu4c/source/i18n/timeperiod.cpp -text
+icu4c/source/i18n/unicode/timeperiod.h -text
icu4c/source/i18n/unicode/uregion.h -text
icu4c/source/i18n/uregion.cpp -text
icu4c/source/io/io.vcxproj -text
/*
*******************************************************************************
*
-* Copyright (C) 2012, International Business Machines
+* Copyright (C) 2013, International Business Machines
* Corporation and others. All Rights Reserved.
*
*******************************************************************************
static UMutex listFormatterMutex = U_MUTEX_INITIALIZER;
static UChar FIRST_PARAMETER[] = { 0x7b, 0x30, 0x7d }; // "{0}"
static UChar SECOND_PARAMETER[] = { 0x7b, 0x31, 0x7d }; // "{0}"
+static const char *STANDARD_STYLE = "standard";
U_CDECL_BEGIN
static UBool U_CALLCONV uprv_listformatter_cleanup() {
U_CDECL_END
-static ListFormatData* loadListFormatData(const Locale& locale, UErrorCode& errorCode);
+static ListFormatData* loadListFormatData(const Locale& locale, const char* style, UErrorCode& errorCode);
static void getStringByKey(const UResourceBundle* rb, const char* key, UnicodeString& result, UErrorCode& errorCode);
+ListFormatter::ListFormatter(const ListFormatter& other) : data(other.data) {
+}
+
+ListFormatter& ListFormatter::operator=(const ListFormatter& other) {
+ data = other.data;
+ return *this;
+}
+
void ListFormatter::initializeHash(UErrorCode& errorCode) {
if (U_FAILURE(errorCode)) {
return;
}
const ListFormatData* ListFormatter::getListFormatData(
- const Locale& locale, UErrorCode& errorCode) {
+ const Locale& locale, const char *style, UErrorCode& errorCode) {
if (U_FAILURE(errorCode)) {
return NULL;
}
- UnicodeString key(locale.getName(), -1, US_INV);
+ CharString keyBuffer(locale.getName(), errorCode);
+ keyBuffer.append(':', errorCode).append(style, errorCode);
+ UnicodeString key(keyBuffer.data(), -1, US_INV);
ListFormatData* result = NULL;
{
Mutex m(&listFormatterMutex);
if (result != NULL) {
return result;
}
- result = loadListFormatData(locale, errorCode);
+ result = loadListFormatData(locale, style, errorCode);
if (U_FAILURE(errorCode)) {
return NULL;
}
return result;
}
-static ListFormatData* loadListFormatData(const Locale& locale, UErrorCode& errorCode) {
+static ListFormatData* loadListFormatData(
+ const Locale& locale, const char * style, UErrorCode& errorCode) {
UResourceBundle* rb = ures_open(NULL, locale.getName(), &errorCode);
if (U_FAILURE(errorCode)) {
ures_close(rb);
return NULL;
}
rb = ures_getByKeyWithFallback(rb, "listPattern", rb, &errorCode);
- rb = ures_getByKeyWithFallback(rb, "standard", rb, &errorCode);
+ rb = ures_getByKeyWithFallback(rb, style, rb, &errorCode);
+
+ // TODO(Travis Keep): This is a hack until fallbacks can be added for
+ // listPattern/duration and listPattern/duration-narrow in CLDR.
+ if (errorCode == U_MISSING_RESOURCE_ERROR) {
+ errorCode = U_ZERO_ERROR;
+ rb = ures_getByKeyWithFallback(rb, "standard", rb, &errorCode);
+ }
if (U_FAILURE(errorCode)) {
ures_close(rb);
return NULL;
}
ListFormatter* ListFormatter::createInstance(const Locale& locale, UErrorCode& errorCode) {
+ return createInstance(locale, STANDARD_STYLE, errorCode);
+}
+
+ListFormatter* ListFormatter::createInstance(const Locale& locale, const char *style, UErrorCode& errorCode) {
Locale tempLocale = locale;
- const ListFormatData* listFormatData = getListFormatData(tempLocale, errorCode);
+ const ListFormatData* listFormatData = getListFormatData(tempLocale, style, errorCode);
if (U_FAILURE(errorCode)) {
return NULL;
}
- ListFormatter* p = new ListFormatter(*listFormatData);
+ ListFormatter* p = new ListFormatter(listFormatData);
if (p == NULL) {
errorCode = U_MEMORY_ALLOCATION_ERROR;
return NULL;
return p;
}
-ListFormatter::ListFormatter(const ListFormatData& listFormatterData) : data(listFormatterData) {
+
+ListFormatter::ListFormatter(const ListFormatData* listFormatterData) : data(listFormatterData) {
}
ListFormatter::~ListFormatter() {}
if (U_FAILURE(errorCode)) {
return appendTo;
}
+ if (data == NULL) {
+ errorCode = U_INVALID_STATE_ERROR;
+ return appendTo;
+ }
if (nItems > 0) {
UnicodeString newString = items[0];
if (nItems == 2) {
- addNewString(data.twoPattern, newString, items[1], errorCode);
+ addNewString(data->twoPattern, newString, items[1], errorCode);
} else if (nItems > 2) {
- addNewString(data.startPattern, newString, items[1], errorCode);
+ addNewString(data->startPattern, newString, items[1], errorCode);
int32_t i;
for (i = 2; i < nItems - 1; ++i) {
- addNewString(data.middlePattern, newString, items[i], errorCode);
+ addNewString(data->middlePattern, newString, items[i], errorCode);
}
- addNewString(data.endPattern, newString, items[nItems - 1], errorCode);
+ addNewString(data->endPattern, newString, items[nItems - 1], errorCode);
}
if (U_SUCCESS(errorCode)) {
appendTo += newString;
class U_COMMON_API ListFormatter : public UObject{
public:
+
+ /**
+ * Copy constructor.
+ * @draft ICU 52
+ */
+ ListFormatter(const ListFormatter&);
+
+ /**
+ * Assignment operator.
+ * @draft ICU 52
+ */
+ ListFormatter& operator=(const ListFormatter& other);
+
/**
* Creates a ListFormatter appropriate for the default locale.
*
* @param errorCode ICU error code, set if no data available for default locale.
* @return Pointer to a ListFormatter object for the default locale,
* created from internal data derived from CLDR data.
+ * @deprecated
* @draft ICU 50
*/
static ListFormatter* createInstance(UErrorCode& errorCode);
* @param errorCode ICU error code, set if no data available for the given locale.
* @return A ListFormatter object created from internal data derived from
* CLDR data.
+ * @deprecated
* @draft ICU 50
*/
static ListFormatter* createInstance(const Locale& locale, UErrorCode& errorCode);
+ /**
+ * Creates a ListFormatter appropriate for a locale and style.
+ *
+ * @param locale The locale.
+ * @param style the style, either "standard", "duration", or "duration-short"
+ * @param errorCode ICU error code, set if no data available for the given locale.
+ * @return A ListFormatter object created from internal data derived from
+ * CLDR data.
+ * @internal
+ */
+ static ListFormatter* createInstance(const Locale& locale, const char* style, UErrorCode& errorCode);
/**
* Destructor.
/**
* @internal constructor made public for testing.
*/
- ListFormatter(const ListFormatData& listFormatterData);
+ ListFormatter(const ListFormatData* listFormatterData);
private:
static void initializeHash(UErrorCode& errorCode);
- static const ListFormatData* getListFormatData(const Locale& locale, UErrorCode& errorCode);
+ static const ListFormatData* getListFormatData(const Locale& locale, const char *style, UErrorCode& errorCode);
ListFormatter();
- ListFormatter(const ListFormatter&);
-
- ListFormatter& operator = (const ListFormatter&);
void addNewString(const UnicodeString& pattern, UnicodeString& originalString,
const UnicodeString& newString, UErrorCode& errorCode) const;
- const ListFormatData& data;
+ const ListFormatData* data;
};
U_NAMESPACE_END
uspoof.o uspoof_impl.o uspoof_build.o uspoof_conf.o uspoof_wsconf.o decfmtst.o smpdtfst.o \
ztrans.o zrule.o vzone.o fphdlimp.o fpositer.o locdspnm.o \
decNumber.o decContext.o alphaindex.o tznames.o tznames_impl.o tzgnames.o \
-tzfmt.o compactdecimalformat.o gender.o region.o uregion.o scriptset.o identifier_info.o
+tzfmt.o compactdecimalformat.o gender.o region.o scriptset.o identifier_info.o \
+tzfmt.o compactdecimalformat.o gender.o region.o uregion.o scriptset.o \
+identifier_info.o timeperiod.o
## Header files to install
HEADERS = $(srcdir)/unicode/*.h
<ClCompile Include="smpdtfmt.cpp" />\r
<ClCompile Include="smpdtfst.cpp" />\r
<ClCompile Include="taiwncal.cpp" />\r
+ <ClCompile Include="timeperiod.cpp" />\r
<ClCompile Include="timezone.cpp" />\r
<ClCompile Include="tmunit.cpp" />\r
<ClCompile Include="tmutamt.cpp" />\r
</CustomBuild>\r
<ClInclude Include="smpdtfst.h" />\r
<ClInclude Include="taiwncal.h" />\r
+ <CustomBuild Include="unicode\timeperiod.h">\r
+ <Command Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">copy "%(FullPath)" ..\..\include\unicode\r
+</Command>\r
+ <Outputs Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">..\..\include\unicode\%(Filename)%(Extension);%(Outputs)</Outputs>\r
+ <Command Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">copy "%(FullPath)" ..\..\include\unicode\r
+</Command>\r
+ <Outputs Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">..\..\include\unicode\%(Filename)%(Extension);%(Outputs)</Outputs>\r
+ <Command Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">copy "%(FullPath)" ..\..\include\unicode\r
+</Command>\r
+ <Outputs Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">..\..\include\unicode\%(Filename)%(Extension);%(Outputs)</Outputs>\r
+ <Command Condition="'$(Configuration)|$(Platform)'=='Release|x64'">copy "%(FullPath)" ..\..\include\unicode\r
+</Command>\r
+ <Outputs Condition="'$(Configuration)|$(Platform)'=='Release|x64'">..\..\include\unicode\%(Filename)%(Extension);%(Outputs)</Outputs>\r
+ </CustomBuild>\r
<CustomBuild Include="unicode\timezone.h">\r
<Command Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">copy "%(FullPath)" ..\..\include\unicode\r
</Command>\r
<ClCompile Include="taiwncal.cpp">\r
<Filter>formatting</Filter>\r
</ClCompile>\r
+ <ClCompile Include="timeperiod.cpp">\r
+ <Filter>formatting</Filter>\r
+ </ClCompile>\r
<ClCompile Include="timezone.cpp">\r
<Filter>formatting</Filter>\r
</ClCompile>\r
<CustomBuild Include="unicode\smpdtfmt.h">\r
<Filter>formatting</Filter>\r
</CustomBuild>\r
+ <CustomBuild Include="unicode\timeperiod.h">\r
+ <Filter>formatting</Filter>\r
+ </CustomBuild>\r
<CustomBuild Include="unicode\timezone.h">\r
<Filter>formatting</Filter>\r
</CustomBuild>\r
--- /dev/null
+/*
+ *******************************************************************************
+ * Copyright (C) 2013-2013, Google, International Business Machines Corporation
+ * and others. All Rights Reserved.
+ *******************************************************************************
+ */
+
+#include <math.h>
+#include "unicode/timeperiod.h"
+#include "putilimp.h"
+
+#if !UCONFIG_NO_FORMATTING
+
+U_NAMESPACE_BEGIN
+
+TimePeriod::TimePeriod(const TimePeriod& other) : fLength(other.fLength) {
+ for (int32_t i = 0; i < sizeof(fFields) / sizeof(fFields[0]); ++i) {
+ if (other.fFields[i] == NULL) {
+ fFields[i] = NULL;
+ } else {
+ fFields[i] = (TimeUnitAmount *) other.fFields[i]->clone();
+ }
+ }
+}
+
+
+TimePeriod::TimePeriod(
+ const TimeUnitAmount * const *timeUnitAmounts,
+ int32_t length,
+ UErrorCode& status) : fLength(0) {
+ int32_t fieldCount = sizeof(fFields) / sizeof(fFields[0]);
+ for (int32_t i = 0; i < fieldCount; ++i) {
+ fFields[i] = NULL;
+ }
+ if (U_FAILURE(status)) {
+ return;
+ }
+ for (int32_t i = 0; i < length; ++i) {
+ const TimeUnitAmount *tua = timeUnitAmounts[i];
+ int32_t idx = tua->getTimeUnitField();
+ if (fFields[idx] != NULL) {
+ status = U_ILLEGAL_ARGUMENT_ERROR;
+ return;
+ }
+ fFields[idx] = (TimeUnitAmount *) tua->clone();
+ ++fLength;
+ }
+ validate(status);
+ if (U_FAILURE(status)) {
+ return;
+ }
+}
+
+void TimePeriod::validate(UErrorCode& status) const {
+ if (U_FAILURE(status)) {
+ return;
+ }
+ if (fLength == 0) {
+ status = U_ILLEGAL_ARGUMENT_ERROR;
+ return;
+ }
+ int32_t fieldCount = sizeof(fFields) / sizeof(fFields[0]);
+ UBool fractionalFieldEncountered = FALSE;
+ for (int32_t i = 0; i < fieldCount; ++i) {
+ if (fFields[i] == NULL) {
+ continue;
+ }
+ if (fractionalFieldEncountered) {
+ status = U_ILLEGAL_ARGUMENT_ERROR;
+ return;
+ }
+ UErrorCode doubleStatus = U_ZERO_ERROR;
+ double value = fFields[i]->getNumber().getDouble(doubleStatus);
+ if (value != uprv_floor(value)) {
+ fractionalFieldEncountered = TRUE;
+ }
+ }
+}
+
+TimePeriod::~TimePeriod() {
+ int32_t fieldCount = sizeof(fFields) / sizeof(fFields[0]);
+ for (int32_t i = 0; i < fieldCount; ++i) {
+ delete fFields[i];
+ }
+}
+
+UBool TimePeriod::operator==(const TimePeriod& other) const {
+ // If same object, they are equal
+ if (this == &other) {
+ return TRUE;
+ }
+ int32_t fieldCount = sizeof(fFields) / sizeof(fFields[0]);
+ for (int32_t i = 0; i < fieldCount; ++i) {
+ if (fFields[i] == other.fFields[i]) {
+ continue;
+ }
+ // One is NULL, the other isn't.
+ if (fFields[i] == NULL || other.fFields[i] == NULL) {
+ return FALSE;
+ }
+ if (*fFields[i] != *other.fFields[i]) {
+ return FALSE;
+ }
+ }
+ return TRUE;
+}
+
+UBool TimePeriod::operator!=(const TimePeriod& other) const {
+ return !(*this == other);
+}
+
+const TimeUnitAmount *TimePeriod::getAmount(
+ TimeUnit::UTimeUnitFields field) const {
+ return fFields[field];
+}
+
+U_NAMESPACE_END
+
+#endif
#include "cstring.h"
#include "hash.h"
#include "uresimp.h"
+#include "unicode/datefmt.h"
+#include "unicode/listformatter.h"
#include "unicode/msgfmt.h"
+#include "unicode/smpdtfmt.h"
+#include "unicode/timeperiod.h"
+#include "unicode/udat.h"
#include "uassert.h"
#define LEFT_CURLY_BRACKET ((UChar)0x007B)
static const UChar PLURAL_COUNT_ONE[] = {LOW_O, LOW_N, LOW_E, 0};
static const UChar PLURAL_COUNT_TWO[] = {LOW_T, LOW_W, LOW_O, 0};
+static const TimeUnit::UTimeUnitFields FIELDS_BY_DURATION[] = {
+ TimeUnit::UTIMEUNIT_YEAR,
+ TimeUnit::UTIMEUNIT_MONTH,
+ TimeUnit::UTIMEUNIT_WEEK,
+ TimeUnit::UTIMEUNIT_DAY,
+ TimeUnit::UTIMEUNIT_HOUR,
+ TimeUnit::UTIMEUNIT_MINUTE,
+ TimeUnit::UTIMEUNIT_SECOND,
+ TimeUnit::UTIMEUNIT_FIELD_COUNT};
+
+static void cloneDateFormat(DateFormat *&, const DateFormat *);
+static double getAmountOrZero(const TimePeriod& timePeriod, TimeUnit::UTimeUnitFields field);
TimeUnitFormat::TimeUnitFormat(UErrorCode& status)
: fNumberFormat(NULL),
- fPluralRules(NULL) {
+ fPluralRules(NULL),
+ fListFormatter(NULL),
+ fHourMinute(NULL),
+ fHourMinuteSecond(NULL),
+ fMinuteSecond(NULL) {
create(Locale::getDefault(), UTMUTFMT_FULL_STYLE, status);
}
TimeUnitFormat::TimeUnitFormat(const Locale& locale, UErrorCode& status)
: fNumberFormat(NULL),
- fPluralRules(NULL) {
+ fPluralRules(NULL),
+ fListFormatter(NULL),
+ fHourMinute(NULL),
+ fHourMinuteSecond(NULL),
+ fMinuteSecond(NULL) {
create(locale, UTMUTFMT_FULL_STYLE, status);
}
TimeUnitFormat::TimeUnitFormat(const Locale& locale, UTimeUnitFormatStyle style, UErrorCode& status)
: fNumberFormat(NULL),
- fPluralRules(NULL) {
+ fPluralRules(NULL),
+ fListFormatter(NULL),
+ fHourMinute(NULL),
+ fHourMinuteSecond(NULL),
+ fMinuteSecond(NULL) {
create(locale, style, status);
}
: MeasureFormat(other),
fNumberFormat(NULL),
fPluralRules(NULL),
- fStyle(UTMUTFMT_FULL_STYLE)
-{
+ fListFormatter(NULL),
+ fHourMinute(NULL),
+ fHourMinuteSecond(NULL),
+ fMinuteSecond(NULL),
+ fStyle(UTMUTFMT_FULL_STYLE) {
for (TimeUnit::UTimeUnitFields i = TimeUnit::UTIMEUNIT_YEAR;
i < TimeUnit::UTIMEUNIT_FIELD_COUNT;
i = (TimeUnit::UTimeUnitFields)(i+1)) {
}
delete fPluralRules;
fPluralRules = NULL;
+ delete fListFormatter;
+ fListFormatter = NULL;
+ delete fHourMinute;
+ fHourMinute = NULL;
+ delete fHourMinuteSecond;
+ fHourMinuteSecond = NULL;
+ delete fMinuteSecond;
+ fMinuteSecond = NULL;
}
} else {
fNumberFormat = NULL;
}
+ delete fListFormatter;
+ if (other.fListFormatter) {
+ fListFormatter = new ListFormatter(*other.fListFormatter);
+ } else {
+ fListFormatter = NULL;
+ }
+ cloneDateFormat(fHourMinute, other.fHourMinute);
+ cloneDateFormat(fHourMinuteSecond, other.fHourMinuteSecond);
+ cloneDateFormat(fMinuteSecond, other.fMinuteSecond);
+
fLocale = other.fLocale;
for (TimeUnit::UTimeUnitFields i = TimeUnit::UTIMEUNIT_YEAR;
i < TimeUnit::UTIMEUNIT_FIELD_COUNT;
count.extract(0, count.length(), result, "UTF-8");
std::cout << "number: " << number << "; format plural count: " << result << "\n";
#endif
- MessageFormat* pattern = ((MessageFormat**)countToPattern->get(count))[fStyle];
+ UTimeUnitFormatStyle effectiveStyle = (fStyle == UTMUTFMT_NUMERIC_STYLE) ?
+ UTMUTFMT_ABBREVIATED_STYLE : fStyle;
+ MessageFormat* pattern = ((MessageFormat**)countToPattern->get(count))[effectiveStyle];
Formattable formattable[1];
formattable[0].setDouble(number);
return pattern->format(formattable, 1, toAppendTo, pos, status);
}
+ const TimePeriod* period = dynamic_cast<const TimePeriod*>(formatObj);
+ if (period != NULL) {
+ return formatTimePeriod(*period, toAppendTo, status);
+ }
}
status = U_ILLEGAL_ARGUMENT_ERROR;
return toAppendTo;
MessageFormat** patterns = (MessageFormat**)valueTok.pointer;
for (UTimeUnitFormatStyle style = UTMUTFMT_FULL_STYLE; style < UTMUTFMT_FORMAT_STYLE_COUNT;
style = (UTimeUnitFormatStyle)(style + 1)) {
+ // We don't support parsing of numeric styles, so skip it.
+ if (style == UTMUTFMT_NUMERIC_STYLE) {
+ continue;
+ }
MessageFormat* pattern = patterns[style];
pos.setErrorIndex(-1);
pos.setIndex(oldPos);
}
}
+UnicodeString&
+TimeUnitFormat::formatTimePeriod(
+ const TimePeriod& timePeriod, UnicodeString& toAppendTo, UErrorCode& status) const {
+ if (U_FAILURE(status)) {
+ return toAppendTo;
+ }
+ if (fStyle == UTMUTFMT_NUMERIC_STYLE && formatTimePeriodAsNumeric(timePeriod, toAppendTo, status)) {
+ return toAppendTo;
+ }
+ UnicodeString *items = new UnicodeString[timePeriod.length()];
+ if (items == NULL) {
+ status = U_MEMORY_ALLOCATION_ERROR;
+ return toAppendTo;
+ }
+ int32_t idx = 0;
+ for (int32_t fieldIndex = 0; FIELDS_BY_DURATION[fieldIndex] != TimeUnit::UTIMEUNIT_FIELD_COUNT; ++fieldIndex) {
+ const TimeUnitAmount *amount = timePeriod.getAmount(FIELDS_BY_DURATION[fieldIndex]);
+ if (amount == NULL) {
+ continue;
+ }
+ TimeUnitAmount *timeUnitAmountCopy = new TimeUnitAmount(*amount);
+ if (timeUnitAmountCopy == NULL) {
+ status = U_MEMORY_ALLOCATION_ERROR;
+ delete [] items;
+ return toAppendTo;
+ }
+ format(Formattable(timeUnitAmountCopy), items[idx], status);
+ if (U_FAILURE(status)) {
+ delete [] items;
+ return toAppendTo;
+ }
+ ++idx;
+ }
+ UnicodeString& result = fListFormatter->format(items, timePeriod.length(), toAppendTo, status);
+ delete [] items;
+ return result;
+}
+
+UBool
+TimeUnitFormat::formatTimePeriodAsNumeric(
+ const TimePeriod& timePeriod, UnicodeString& toAppendTo, UErrorCode& status) const {
+ if (U_FAILURE(status)) {
+ return TRUE;
+ }
+ TimeUnit::UTimeUnitFields biggestUnit = TimeUnit::UTIMEUNIT_FIELD_COUNT;
+ TimeUnit::UTimeUnitFields smallestUnit = TimeUnit::UTIMEUNIT_FIELD_COUNT;
+ const TimeUnitAmount *smallestAmount = NULL;
+ for (int32_t fieldIndex = 0; FIELDS_BY_DURATION[fieldIndex] != TimeUnit::UTIMEUNIT_FIELD_COUNT; ++fieldIndex) {
+ const TimeUnitAmount *amount = timePeriod.getAmount(FIELDS_BY_DURATION[fieldIndex]);
+ if (amount == NULL) {
+ continue;
+ }
+ if (biggestUnit == TimeUnit::UTIMEUNIT_FIELD_COUNT) {
+ biggestUnit = FIELDS_BY_DURATION[fieldIndex];
+ }
+ smallestUnit = FIELDS_BY_DURATION[fieldIndex];
+ smallestAmount = amount;
+ }
+ U_ASSERT(biggestUnit != TimeUnit::UTIMEUNIT_FIELD_COUNT);
+ U_ASSERT(smallestUnit != TimeUnit::UTIMEUNIT_FIELD_COUNT);
+ U_ASSERT(smallestAmount != NULL);
+
+ double millis = ((getAmountOrZero(timePeriod, TimeUnit::UTIMEUNIT_HOUR) * 60.0
+ + getAmountOrZero(timePeriod, TimeUnit::UTIMEUNIT_MINUTE)) * 60.0
+ + getAmountOrZero(timePeriod, TimeUnit::UTIMEUNIT_SECOND)) * 1000.0;
+ if (biggestUnit == TimeUnit::UTIMEUNIT_HOUR && smallestUnit == TimeUnit::UTIMEUNIT_SECOND) {
+ numericFormat(millis, *fHourMinuteSecond, UDAT_SECOND_FIELD, smallestAmount->getNumber(), toAppendTo, status);
+ return TRUE;
+ }
+ if (biggestUnit == TimeUnit::UTIMEUNIT_MINUTE && smallestUnit == TimeUnit::UTIMEUNIT_SECOND) {
+ numericFormat(millis, *fMinuteSecond, UDAT_SECOND_FIELD, smallestAmount->getNumber(), toAppendTo, status);
+ return TRUE;
+ }
+ if (biggestUnit == TimeUnit::UTIMEUNIT_HOUR && smallestUnit == TimeUnit::UTIMEUNIT_MINUTE) {
+ numericFormat(millis, *fHourMinute, UDAT_MINUTE_FIELD, smallestAmount->getNumber(), toAppendTo, status);
+ return TRUE;
+ }
+ return FALSE;
+}
+
+void
+TimeUnitFormat::numericFormat(
+ double date,
+ const DateFormat &dateFormat,
+ int32_t smallestField,
+ const Formattable& smallestAmount,
+ UnicodeString& toAppendTo,
+ UErrorCode& status) const {
+ if (U_FAILURE(status)) {
+ return;
+ }
+ UnicodeString smallestAmountFormatted;
+ fNumberFormat->format(smallestAmount, smallestAmountFormatted, status);
+ if (U_FAILURE(status)) {
+ return;
+ }
+ FieldPositionIterator fpi;
+ int32_t prevLength = toAppendTo.length();
+ dateFormat.format(Formattable(date, Formattable::kIsDate), toAppendTo, &fpi, status);
+ if (U_FAILURE(status)) {
+ return;
+ }
+ FieldPosition fp;
+ UBool substituted = FALSE;
+ while (fpi.next(fp)) {
+ if (fp.getField() == smallestField) {
+ toAppendTo.replace(
+ prevLength + fp.getBeginIndex(),
+ fp.getEndIndex() - fp.getBeginIndex(),
+ smallestAmountFormatted);
+ substituted = TRUE;
+ break;
+ }
+ }
+ U_ASSERT(substituted);
+}
void
TimeUnitFormat::create(const Locale& locale, UTimeUnitFormatStyle style, UErrorCode& status) {
if (U_FAILURE(status)) {
return;
}
- if (style < UTMUTFMT_FULL_STYLE || style > UTMUTFMT_ABBREVIATED_STYLE) {
+ if (style < UTMUTFMT_FULL_STYLE || style >= UTMUTFMT_FORMAT_STYLE_COUNT) {
status = U_ILLEGAL_ARGUMENT_ERROR;
return;
}
}
delete fPluralRules;
fPluralRules = PluralRules::forLocale(fLocale, err);
+ delete fListFormatter;
+ if (fStyle == UTMUTFMT_FULL_STYLE) {
+ fListFormatter = ListFormatter::createInstance(fLocale, "duration", err);
+ } else {
+ fListFormatter = ListFormatter::createInstance(fLocale, "duration-short", err);
+ }
+ delete fHourMinute;
+ fHourMinute = loadNumericDurationFormat("hm", err);
+ delete fHourMinuteSecond;
+ fHourMinuteSecond = loadNumericDurationFormat("hms", err);
+ delete fMinuteSecond;
+ fMinuteSecond = loadNumericDurationFormat("ms", err);
for (TimeUnit::UTimeUnitFields i = TimeUnit::UTIMEUNIT_YEAR;
i < TimeUnit::UTIMEUNIT_FIELD_COUNT;
i = (TimeUnit::UTimeUnitFields)(i+1)) {
}
}
+DateFormat *
+TimeUnitFormat::loadNumericDurationFormat(const char *pattern, UErrorCode& status) const {
+ if (U_FAILURE(status)) {
+ return NULL;
+ }
+ UResourceBundle *rb, *unitsRes;
+ rb = ures_open(NULL, fLocale.getName(), &status);
+ if (U_FAILURE(status)) {
+ return NULL;
+ }
+ CharString path("durationUnits", status);
+ path.append('/', status).append(pattern, status);
-
+ int32_t fullPatternSize;
+ const UChar *fullPatternChars = ures_getStringByKeyWithFallback(rb, path.data(), &fullPatternSize, &status);
+ if (U_FAILURE(status)) {
+ ures_close(rb);
+ return NULL;
+ }
+ UnicodeString fullPattern(FALSE, fullPatternChars, fullPatternSize);
+ fullPattern.findAndReplace(UnicodeString("h"), UnicodeString("H"));
+ DateFormat *result = new SimpleDateFormat(fullPattern, status);
+ if (result == NULL) {
+ status = U_MEMORY_ALLOCATION_ERROR;
+ ures_close(rb);
+ return NULL;
+ }
+ if (U_FAILURE(status)) {
+ delete result;
+ return NULL;
+ }
+ result->setTimeZone(*TimeZone::getGMT());
+ return result;
+}
void
TimeUnitFormat::readFromCurrentLocale(UTimeUnitFormatStyle style, const char* key,
}
}
+void cloneDateFormat(DateFormat *&dest, const DateFormat *src) {
+ delete dest;
+ if (src) {
+ dest = (DateFormat *) src->clone();
+ } else {
+ dest = NULL;
+ }
+}
+
+double getAmountOrZero(const TimePeriod& timePeriod, TimeUnit::UTimeUnitFields field) {
+ const TimeUnitAmount *amount = timePeriod.getAmount(field);
+ if (amount == NULL) {
+ return 0.0;
+ }
+ UErrorCode status = U_ZERO_ERROR;
+ return amount->getNumber().getDouble(status);
+}
+
+
U_NAMESPACE_END
#endif
--- /dev/null
+/*
+ *******************************************************************************
+ * Copyright (C) 2013-2013, Google, International Business Machines Corporation
+ * and others. All Rights Reserved.
+ *******************************************************************************
+ */
+
+#ifndef __TIMEPERIOD_H__
+#define __TIMEPERIOD_H__
+
+// TODO:
+// 1. Add size() method and test.
+// 2. testEquals() -> testTimePeriodEquals()
+
+#include "unicode/utypes.h"
+
+/**
+ * \file
+ * \brief C++ API: Format and parse duration in single time unit
+ */
+
+
+#if !UCONFIG_NO_FORMATTING
+
+#include "unicode/tmunit.h"
+#include "unicode/tmutamt.h"
+
+U_NAMESPACE_BEGIN
+
+class U_I18N_API TimePeriod: public UObject {
+public:
+ // copy constructor.
+ TimePeriod(const TimePeriod& other);
+
+ /**
+ * Constructor.
+ * @param timeUnitAmounts an array of TimeUnitAmounts pointers. TimePeriod copies the
+ * data in this array. The caller is responsible for freeing the TimeUnitAmount objects
+ * and the array.
+ * @param length the number of timeUnitAmount pointers in timeUnitAmounts array.
+ * @param status error returned here if timeUnitAmounts is empty;
+ * timeUnitAmounts has duplicate time units; or any timeUnitAmount except the
+ * smallest has a non-integer value.
+ * @draft ICU 52
+ */
+ TimePeriod(
+ const TimeUnitAmount * const *timeUnitAmounts, int32_t length, UErrorCode& status);
+
+ /**
+ * Destructor
+ * @draft ICU 52
+ */
+ virtual ~TimePeriod();
+
+ /**
+ * Returns true if the given TimePeriod objects are semantically equal.
+ * For two TimePeriod objects to be equal, they must contain the same
+ * units, and the amount for each unit much be equal. For example,
+ * 5 hours, 37 minutes == 37 minutes, 5 hours,
+ * but 0 days, 5 hours != 5 hours.
+ * @param that the TimePeriod to compare with.
+ * @return true if the given TimePeriod objects are semantically equal.
+ * @draft ICU 52
+ */
+ UBool operator==(const TimePeriod& that) const;
+
+ /**
+ * Returns true if the given TimePeriod objects are semantically
+ * unequal.
+ * @param that the TimePeriod to compare with.
+ * @return true if the given TimePeriod objects are semantically
+ * unequal.
+ * @draft ICU 52
+ */
+ UBool operator!=(const TimePeriod& that) const;
+
+ /**
+ * Gets a specific field out of a time period.
+ * @param field is the field to fetch
+ * @return The desired field or NULL if it does not exist.
+ */
+ const TimeUnitAmount* getAmount(TimeUnit::UTimeUnitFields field) const;
+
+ /**
+ * Returns the number of time units in this object.
+ * @draft ICU 52
+ */
+ inline int32_t length() const {
+ return fLength;
+ }
+
+private:
+ int32_t fLength;
+ TimeUnitAmount *fFields[TimeUnit::UTIMEUNIT_FIELD_COUNT];
+
+ // Clients use forAmount and never use ctor directly.
+ TimePeriod() {
+ }
+
+ /**
+ * No assignment operator needed because class is immutable.
+ */
+ TimePeriod& operator=(const TimePeriod& other);
+
+ void validate(UErrorCode& status) const;
+};
+
+U_NAMESPACE_END
+
+#endif /* #if !UCONFIG_NO_FORMATTING */
+
+#endif // __TMUTFMT_H__
+//eof
/*
*******************************************************************************
- * Copyright (C) 2008-2012, Google, International Business Machines Corporation
+ * Copyright (C) 2008-2013, Google, International Business Machines Corporation
* and others. All Rights Reserved.
*******************************************************************************
*/
UTMUTFMT_FULL_STYLE,
/** @stable ICU 4.8 */
UTMUTFMT_ABBREVIATED_STYLE,
+ /** @draft ICU 52 */
+ UTMUTFMT_NUMERIC_STYLE,
/** @stable ICU 4.8 */
UTMUTFMT_FORMAT_STYLE_COUNT
};
U_NAMESPACE_BEGIN
+class DateFormat;
class Hashtable;
class UVector;
+class TimePeriod;
+class ListFormatter;
/**
* Format or parse a TimeUnitAmount, using plural rules for the units where available.
Formattable& result,
ParsePosition& pos) const;
+ /**
+ * Format a time period.
+ * @param timePeriod the time period to format.
+ * @param toAppendTo where the formatted string is stored.
+ * @param status any error is stored here
+ * @return a reference to toAppendto
+ * @draft ICU 52
+ */
+ UnicodeString& formatTimePeriod(const TimePeriod &timePeriod,
+ UnicodeString& toAppendTo,
+ UErrorCode& status) const;
+
/**
* Return the class ID for this class. This is useful only for comparing to
* a return value from getDynamicClassID(). For example:
Locale fLocale;
Hashtable* fTimeUnitToCountToPatterns[TimeUnit::UTIMEUNIT_FIELD_COUNT];
PluralRules* fPluralRules;
+ ListFormatter *fListFormatter;
+ DateFormat *fHourMinute;
+ DateFormat *fHourMinuteSecond;
+ DateFormat *fMinuteSecond;
UTimeUnitFormatStyle fStyle;
+ UBool formatTimePeriodAsNumeric(
+ const TimePeriod& timePeriod, UnicodeString& toAppendTo, UErrorCode& status) const;
+
void create(const Locale& locale, UTimeUnitFormatStyle style, UErrorCode& status);
// it might actually be simpler to make them Decimal Formats later.
// get time unit name, such as "year", from time unit field enum, such as
// UTIMEUNIT_YEAR.
static const char* getTimeUnitName(TimeUnit::UTimeUnitFields field, UErrorCode& status);
+
+ void numericFormat(
+ double date,
+ const DateFormat &dateFormat,
+ int32_t smallestField,
+ const Formattable& smallestAmount,
+ UnicodeString& toAppendto,
+ UErrorCode& status) const;
+
+ DateFormat *loadNumericDurationFormat(
+ const char *pattern,
+ UErrorCode& status) const;
+
};
ListFormatData data("{1} after {0}", "{1} after the first {0}",
"{1} after {0}", "{1} in the last after {0}");
- ListFormatter formatter(data);
+ ListFormatter formatter(&data);
UnicodeString input1[] = {one};
CheckFormatting(&formatter, input1, 1, results[0]);
/********************************************************************
- * Copyright (c) 2008-2012, International Business Machines Corporation and
+ * Copyright (c) 2008-2013, International Business Machines Corporation and
* others. All Rights Reserved.
********************************************************************/
#include "unicode/tmutamt.h"
#include "unicode/tmutfmt.h"
#include "tufmtts.h"
+#include "unicode/timeperiod.h"
#include "unicode/ustring.h"
//TODO: put as compilation flag
#include <iostream>
#endif
+struct TimePeriodResult {
+ TimePeriod timePeriod;
+ const char* result;
+};
+
+class TimeUnitAmountSubClass : public TimeUnitAmount {
+ public:
+ TimeUnitAmountSubClass(double amount, TimeUnit::UTimeUnitFields timeUnitField, int ex, UErrorCode &status) : TimeUnitAmount(amount, timeUnitField, status), extra(ex) { }
+
+ TimeUnitAmountSubClass(const TimeUnitAmountSubClass &that)
+ : TimeUnitAmount(that), extra(that.extra) { }
+
+ TimeUnitAmountSubClass &operator=(const TimeUnitAmountSubClass &that) {
+ TimeUnitAmount::operator=(that);
+ extra = that.extra;
+ return *this;
+ }
+
+ virtual UObject* clone() const {
+ return new TimeUnitAmountSubClass(*this);
+ }
+
+ virtual ~TimeUnitAmountSubClass() { }
+ int extra;
+};
+
+static TimePeriod create1m59_9996s(UErrorCode &status);
+static TimePeriod create19m(UErrorCode &status);
+static TimePeriod create19m28s(UErrorCode &status);
+static TimePeriod create19m29s(UErrorCode &status);
+static TimePeriod create1h23_5s(UErrorCode &status);
+static TimePeriod create1h23s(UErrorCode &status);
+static TimePeriod create1h23_5m(UErrorCode &status);
+static TimePeriod create1h0m23s(UErrorCode &status);
+static TimePeriod create5h17m(UErrorCode &status);
+static TimePeriod create2y5M3w4d(UErrorCode &status);
+static TimePeriod create0h0m17s(UErrorCode &status);
+static TimePeriod create6h56_92m(UErrorCode &status);
+
void TimeUnitTest::runIndexedTest( int32_t index, UBool exec, const char* &name, char* /*par*/ ) {
if (exec) logln("TestSuite TimeUnitTest");
switch (index) {
TESTCASE(1, testAPI);
TESTCASE(2, testGreekWithFallback);
TESTCASE(3, testGreekWithSanitization);
+ TESTCASE(4, testFormatPeriodEn);
+ TESTCASE(5, testTimePeriodForAmounts);
+ TESTCASE(6, testTimeUnitAmountSubClass);
+ TESTCASE(7, testTimePeriodEquals);
+ TESTCASE(8, testTimePeriodLength);
default: name = ""; break;
}
}
delete timeUnitFormat;
}
+void TimeUnitTest::testFormatPeriodEn() {
+ UErrorCode status = U_ZERO_ERROR;
+
+ TimePeriodResult fullResults[] = {
+ {create1m59_9996s(status), "1 minute, 59.9996 seconds"},
+ {create19m(status), "19 minutes"},
+ {create1h23_5s(status), "1 hour, 23.5 seconds"},
+ {create1h23_5m(status), "1 hour, 23.5 minutes"},
+ {create1h0m23s(status), "1 hour, 0 minutes, 23 seconds"},
+ {create2y5M3w4d(status), "2 years, 5 months, 3 weeks, 4 days"}};
+
+ TimePeriodResult abbrevResults[] = {
+ {create1m59_9996s(status), "1 min, 59.9996 secs"},
+ {create19m(status), "19 mins"},
+ {create1h23_5s(status), "1 hr, 23.5 secs"},
+ {create1h23_5m(status), "1 hr, 23.5 mins"},
+ {create1h0m23s(status), "1 hr, 0 mins, 23 secs"},
+ {create2y5M3w4d(status), "2 yrs, 5 mths, 3 wks, 4 days"}};
+
+ TimePeriodResult numericResults[] = {
+ {create1m59_9996s(status), "1:59.9996"},
+ {create19m(status), "19 mins"},
+ {create1h23_5s(status), "1:00:23.5"},
+ {create1h0m23s(status), "1:00:23"},
+ {create5h17m(status), "5:17"},
+ {create19m28s(status), "19:28"},
+ {create2y5M3w4d(status), "2 yrs, 5 mths, 3 wks, 4 days"},
+ {create0h0m17s(status), "0:00:17"},
+ {create6h56_92m(status), "6:56.92"}};
+
+ if (U_FAILURE(status)) {
+ dataerrln("Unable to create time periods - %s", u_errorName(status));
+ return;
+ }
+
+ LocalPointer<NumberFormat> nf(NumberFormat::createInstance(Locale::getEnglish(), status));
+ if (U_FAILURE(status)) {
+ dataerrln("Unable to create NumberFormat object - %s", u_errorName(status));
+ return;
+ }
+ nf->setMaximumFractionDigits(4);
+ {
+ TimeUnitFormat tuf(Locale::getEnglish(), UTMUTFMT_FULL_STYLE, status);
+ tuf.setNumberFormat(*nf, status);
+ if (U_FAILURE(status)) {
+ dataerrln("Unable to create TimeUnitFormat object - %s", u_errorName(status));
+ return;
+ }
+ verifyFormatTimePeriod(
+ tuf,
+ fullResults,
+ sizeof(fullResults) / sizeof(TimePeriodResult));
+ }
+ {
+ TimeUnitFormat tuf(Locale::getEnglish(), UTMUTFMT_ABBREVIATED_STYLE, status);
+ tuf.setNumberFormat(*nf, status);
+ if (U_FAILURE(status)) {
+ dataerrln("Unable to create TimeUnitFormat object - %s", u_errorName(status));
+ return;
+ }
+ verifyFormatTimePeriod(
+ tuf,
+ abbrevResults,
+ sizeof(abbrevResults) / sizeof(TimePeriodResult));
+ }
+ {
+ TimeUnitFormat tuf(Locale::getEnglish(), UTMUTFMT_NUMERIC_STYLE, status);
+ tuf.setNumberFormat(*nf, status);
+ if (U_FAILURE(status)) {
+ dataerrln("Unable to create TimeUnitFormat object - %s", u_errorName(status));
+ return;
+ }
+ verifyFormatTimePeriod(
+ tuf,
+ numericResults,
+ sizeof(numericResults) / sizeof(TimePeriodResult));
+ }
+}
+
+void TimeUnitTest::testTimePeriodLength() {
+ UErrorCode status = U_ZERO_ERROR;
+ int32_t actual = create1h23_5m(status).length();
+ if (U_FAILURE(status)) {
+ dataerrln("Unable to create time period object - %s", u_errorName(status));
+ return;
+ }
+ if (actual != 2) {
+ errln("Expected 2, got %d", actual);
+ }
+}
+
+void TimeUnitTest::testTimePeriodForAmounts() {
+ UErrorCode status = U_ZERO_ERROR;
+ TimeUnitAmount _5h(5.0, TimeUnit::UTIMEUNIT_HOUR, status);
+ TimeUnitAmount _3_5h(3.5, TimeUnit::UTIMEUNIT_HOUR, status);
+ TimeUnitAmount _3h(3.0, TimeUnit::UTIMEUNIT_HOUR, status);
+ TimeUnitAmount _5m(5.0, TimeUnit::UTIMEUNIT_MINUTE, status);
+ if (U_FAILURE(status)) {
+ dataerrln("Unable to alocate time unit amounts - %s", u_errorName(status));
+ return;
+ }
+ {
+ UErrorCode status = U_ZERO_ERROR;
+ TimeUnitAmount *amounts[] = {&_3h, &_5h};
+ int32_t len = sizeof(amounts) / sizeof(TimeUnitAmount*);
+ TimePeriod(amounts, len, status);
+ if (status != U_ILLEGAL_ARGUMENT_ERROR) {
+ errln("Expected U_ILLEGAL_ARGUMENT_ERROR for 3h + 5h, got %s", u_errorName(status));
+ }
+ }
+ {
+ UErrorCode status = U_ZERO_ERROR;
+ TimePeriod(NULL, 0, status);
+ if (status != U_ILLEGAL_ARGUMENT_ERROR) {
+ errln("Expected U_ILLEGAL_ARGUMENT_ERROR for empty time period, got %s", u_errorName(status));
+ }
+ }
+ {
+ UErrorCode status = U_ZERO_ERROR;
+ TimeUnitAmount *amounts[] = {&_3_5h, &_5m};
+ int32_t len = sizeof(amounts) / sizeof(TimeUnitAmount*);
+ TimePeriod(amounts, len, status);
+ if (status != U_ILLEGAL_ARGUMENT_ERROR) {
+ errln("Expected U_ILLEGAL_ARGUMENT_ERROR for 3.5h + 5m, got %s", u_errorName(status));
+ }
+ }
+}
+
+void TimeUnitTest::testTimePeriodEquals() {
+ UErrorCode status = U_ZERO_ERROR;
+
+ TimePeriod _1h23s = create1h23s(status);
+
+ // Same variable
+ verifyEquals(_1h23s, _1h23s);
+
+ // Different variables same value
+ verifyEquals(_1h23s, TimePeriod(_1h23s));
+
+ // Different fields
+ verifyNotEqual(_1h23s, create1h0m23s(status));
+
+ // Same fields different values
+ verifyNotEqual(create19m28s(status), create19m29s(status));
+
+ if (U_FAILURE(status)) {
+ errln("Failure creating TimePeriods, got %s", u_errorName(status));
+ }
+}
+
+void TimeUnitTest::testTimeUnitAmountSubClass() {
+ UErrorCode status = U_ZERO_ERROR;
+ TimeUnitAmountSubClass _6h(6.0, TimeUnit::UTIMEUNIT_HOUR, 1, status);
+ TimeUnitAmountSubClass _5m(5.0, TimeUnit::UTIMEUNIT_MINUTE, 2, status);
+ if (U_FAILURE(status)) {
+ dataerrln("Unable to alocate time unit amounts - %s", u_errorName(status));
+ return;
+ }
+ {
+ UErrorCode status = U_ZERO_ERROR;
+ TimeUnitAmount *amounts[] = {&_6h, &_5m};
+ int32_t len = sizeof(amounts) / sizeof(TimeUnitAmount*);
+ TimePeriod period(amounts, len, status);
+ if (2 != ((const TimeUnitAmountSubClass *) period.getAmount(TimeUnit::UTIMEUNIT_MINUTE))->extra) {
+ errln("Expected polymorphic behavior.");
+ }
+ }
+}
+
+void TimeUnitTest::verifyFormatTimePeriod(
+ const TimeUnitFormat& tuf,
+ const TimePeriodResult* timePeriodResults,
+ int32_t numResults) {
+ for (int32_t i = 0; i < numResults; i++) {
+ UnicodeString expected(timePeriodResults[i].result, -1, US_INV);
+ expected = expected.unescape();
+ UErrorCode status = U_ZERO_ERROR;
+ Formattable formattable(new TimePeriod(timePeriodResults[i].timePeriod));
+ UnicodeString actual;
+ FieldPosition pos(0);
+ tuf.format(formattable, actual, pos, status);
+ if (U_FAILURE(status)) {
+ dataerrln("Unable to format time period - %s", u_errorName(status));
+ return;
+ }
+ if (actual != expected) {
+ errln(UnicodeString("Fail: Expected: ") + expected
+ + UnicodeString(" Got: ") + actual);
+ }
+ }
+}
+
+void TimeUnitTest::verifyEquals(const TimePeriod& lhs, const TimePeriod& rhs) {
+ if (lhs != rhs) {
+ errln("Expected equal.");
+ return;
+ }
+ if (!(lhs == rhs)) {
+ errln("Expected not not equal.");
+ }
+}
+
+void TimeUnitTest::verifyNotEqual(const TimePeriod& lhs, const TimePeriod& rhs) {
+ if (lhs == rhs) {
+ errln("Expected not equal.");
+ return;
+ }
+ if (!(lhs != rhs)) {
+ errln("Expected not not not equal.");
+ }
+}
+
+static TimePeriod create1m59_9996s(UErrorCode &status) {
+ TimeUnitAmount minutes(1.0, TimeUnit::UTIMEUNIT_MINUTE, status);
+ TimeUnitAmount seconds(59.9996, TimeUnit::UTIMEUNIT_SECOND, status);
+ TimeUnitAmount *amounts[] = {&minutes, &seconds};
+ int32_t len = sizeof(amounts) / sizeof(TimeUnitAmount*);
+ return TimePeriod(amounts, len, status);
+}
+
+static TimePeriod create19m(UErrorCode &status) {
+ TimeUnitAmount minutes(19.0, TimeUnit::UTIMEUNIT_MINUTE, status);
+ TimeUnitAmount *amounts[] = {&minutes};
+ int32_t len = sizeof(amounts) / sizeof(TimeUnitAmount*);
+ return TimePeriod(amounts, len, status);
+}
+
+static TimePeriod create19m28s(UErrorCode &status) {
+ TimeUnitAmount minutes(19.0, TimeUnit::UTIMEUNIT_MINUTE, status);
+ TimeUnitAmount seconds(28.0, TimeUnit::UTIMEUNIT_SECOND, status);
+ TimeUnitAmount *amounts[] = {&minutes, &seconds};
+ int32_t len = sizeof(amounts) / sizeof(TimeUnitAmount*);
+ return TimePeriod(amounts, len, status);
+}
+
+static TimePeriod create19m29s(UErrorCode &status) {
+ TimeUnitAmount minutes(19.0, TimeUnit::UTIMEUNIT_MINUTE, status);
+ TimeUnitAmount seconds(29.0, TimeUnit::UTIMEUNIT_SECOND, status);
+ TimeUnitAmount *amounts[] = {&minutes, &seconds};
+ int32_t len = sizeof(amounts) / sizeof(TimeUnitAmount*);
+ return TimePeriod(amounts, len, status);
+}
+
+static TimePeriod create1h23_5s(UErrorCode &status) {
+ TimeUnitAmount hours(1.0, TimeUnit::UTIMEUNIT_HOUR, status);
+ TimeUnitAmount seconds(23.5, TimeUnit::UTIMEUNIT_SECOND, status);
+ TimeUnitAmount *amounts[] = {&hours, &seconds};
+ int32_t len = sizeof(amounts) / sizeof(TimeUnitAmount*);
+ return TimePeriod(amounts, len, status);
+}
+
+static TimePeriod create1h23_5m(UErrorCode &status) {
+ TimeUnitAmount hours(1.0, TimeUnit::UTIMEUNIT_HOUR, status);
+ TimeUnitAmount seconds(23.5, TimeUnit::UTIMEUNIT_MINUTE, status);
+ TimeUnitAmount *amounts[] = {&hours, &seconds};
+ int32_t len = sizeof(amounts) / sizeof(TimeUnitAmount*);
+ return TimePeriod(amounts, len, status);
+}
+
+static TimePeriod create1h0m23s(UErrorCode &status) {
+ TimeUnitAmount hours(1.0, TimeUnit::UTIMEUNIT_HOUR, status);
+ TimeUnitAmount minutes(0.0, TimeUnit::UTIMEUNIT_MINUTE, status);
+ TimeUnitAmount seconds(23.0, TimeUnit::UTIMEUNIT_SECOND, status);
+ TimeUnitAmount *amounts[] = {&hours, &minutes, &seconds};
+ int32_t len = sizeof(amounts) / sizeof(TimeUnitAmount*);
+ return TimePeriod(amounts, len, status);
+}
+
+static TimePeriod create1h23s(UErrorCode &status) {
+ TimeUnitAmount hours(1.0, TimeUnit::UTIMEUNIT_HOUR, status);
+ TimeUnitAmount seconds(23.0, TimeUnit::UTIMEUNIT_SECOND, status);
+ TimeUnitAmount *amounts[] = {&hours, &seconds};
+ int32_t len = sizeof(amounts) / sizeof(TimeUnitAmount*);
+ return TimePeriod(amounts, len, status);
+}
+
+static TimePeriod create5h17m(UErrorCode &status) {
+ TimeUnitAmount hours(5.0, TimeUnit::UTIMEUNIT_HOUR, status);
+ TimeUnitAmount minutes(17.0, TimeUnit::UTIMEUNIT_MINUTE, status);
+ TimeUnitAmount *amounts[] = {&hours, &minutes};
+ int32_t len = sizeof(amounts) / sizeof(TimeUnitAmount*);
+ return TimePeriod(amounts, len, status);
+}
+
+static TimePeriod create2y5M3w4d(UErrorCode &status) {
+ TimeUnitAmount years(2.0, TimeUnit::UTIMEUNIT_YEAR, status);
+ TimeUnitAmount months(5.0, TimeUnit::UTIMEUNIT_MONTH, status);
+ TimeUnitAmount weeks(3.0, TimeUnit::UTIMEUNIT_WEEK, status);
+ TimeUnitAmount days(4.0, TimeUnit::UTIMEUNIT_DAY, status);
+ TimeUnitAmount *amounts[] = {&years, &months, &weeks, &days};
+ int32_t len = sizeof(amounts) / sizeof(TimeUnitAmount*);
+ return TimePeriod(amounts, len, status);
+}
+
+static TimePeriod create0h0m17s(UErrorCode &status) {
+ TimeUnitAmount hours(0.0, TimeUnit::UTIMEUNIT_HOUR, status);
+ TimeUnitAmount minutes(0.0, TimeUnit::UTIMEUNIT_MINUTE, status);
+ TimeUnitAmount seconds(17.0, TimeUnit::UTIMEUNIT_SECOND, status);
+ TimeUnitAmount *amounts[] = {&hours, &minutes, &seconds};
+ int32_t len = sizeof(amounts) / sizeof(TimeUnitAmount*);
+ return TimePeriod(amounts, len, status);
+}
+
+static TimePeriod create6h56_92m(UErrorCode &status) {
+ TimeUnitAmount hours(6.0, TimeUnit::UTIMEUNIT_HOUR, status);
+ TimeUnitAmount minutes(56.92, TimeUnit::UTIMEUNIT_MINUTE, status);
+ TimeUnitAmount *amounts[] = {&hours, &minutes};
+ int32_t len = sizeof(amounts) / sizeof(TimeUnitAmount*);
+ return TimePeriod(amounts, len, status);
+}
#endif
/********************************************************************
* COPYRIGHT:
- * Copyright (c) 2008-2012, International Business Machines Corporation
+ * Copyright (c) 2008-2013, International Business Machines Corporation
* and others. All Rights Reserved.
********************************************************************/
#include "unicode/locid.h"
#include "intltest.h"
+U_NAMESPACE_BEGIN
+class TimeUnitFormat;
+class TimePeriod;
+U_NAMESPACE_END
+struct TimePeriodResult;
+
/**
* Test basic functionality of various API functions
**/
* As of CLDR shiped in ICU4.8, Greek is one such language.
*/
void testGreekWithSanitization();
+
+ void testFormatPeriodEn();
+
+ void testTimePeriodLength();
+
+ void testTimePeriodEquals();
+
+ void testTimePeriodForAmounts();
+
+ void testTimeUnitAmountSubClass();
+
+ void verifyEquals(const TimePeriod&, const TimePeriod&);
+
+ void verifyNotEqual(const TimePeriod&, const TimePeriod&);
+
+ void verifyFormatTimePeriod(
+ const TimeUnitFormat& tuf,
+ const TimePeriodResult* timePeriodResults,
+ int32_t numResults);
+
+
};
#endif /* #if !UCONFIG_NO_FORMATTING */