/* * Copyright 2010-2014, Haiku, Inc. All Rights Reserved. * Distributed under the terms of the MIT License. * * Authors: * Oliver Tappe */ #include #include #include #include #include #include #include #include #include #include #include #include U_NAMESPACE_USE BTimeFormat::BTimeFormat() : BFormat() { } BTimeFormat::BTimeFormat(const BLanguage& language, const BFormattingConventions& conventions) : BFormat(language, conventions) { } BTimeFormat::BTimeFormat(const BTimeFormat &other) : BFormat(other) { } BTimeFormat::~BTimeFormat() { } void BTimeFormat::SetTimeFormat(BTimeFormatStyle style, const BString& format) { fConventions.SetExplicitTimeFormat(style, format); } // #pragma mark - Formatting ssize_t BTimeFormat::Format(char* string, size_t maxSize, time_t time, BTimeFormatStyle style) const { ObjectDeleter timeFormatter(_CreateTimeFormatter(style)); if (!timeFormatter.IsSet()) return B_NO_MEMORY; UnicodeString icuString; timeFormatter->format((UDate)time * 1000, icuString); CheckedArrayByteSink stringConverter(string, maxSize); icuString.toUTF8(stringConverter); if (stringConverter.Overflowed()) return B_BAD_VALUE; return stringConverter.NumberOfBytesWritten(); } status_t BTimeFormat::Format(BString& string, const time_t time, const BTimeFormatStyle style, const BTimeZone* timeZone) const { ObjectDeleter timeFormatter(_CreateTimeFormatter(style)); if (!timeFormatter.IsSet()) return B_NO_MEMORY; if (timeZone != NULL) { ObjectDeleter icuTimeZone( TimeZone::createTimeZone(timeZone->ID().String())); if (!icuTimeZone.IsSet()) return B_NO_MEMORY; timeFormatter->setTimeZone(*icuTimeZone.Get()); } UnicodeString icuString; timeFormatter->format((UDate)time * 1000, icuString); string.Truncate(0); BStringByteSink stringConverter(&string); icuString.toUTF8(stringConverter); return B_OK; } status_t BTimeFormat::Format(BString& string, int*& fieldPositions, int& fieldCount, time_t time, BTimeFormatStyle style) const { ObjectDeleter timeFormatter(_CreateTimeFormatter(style)); if (!timeFormatter.IsSet()) return B_NO_MEMORY; fieldPositions = NULL; UErrorCode error = U_ZERO_ERROR; icu::FieldPositionIterator positionIterator; UnicodeString icuString; timeFormatter->format((UDate)time * 1000, icuString, &positionIterator, error); if (error != U_ZERO_ERROR) return B_BAD_VALUE; icu::FieldPosition field; std::vector fieldPosStorage; fieldCount = 0; while (positionIterator.next(field)) { fieldPosStorage.push_back(field.getBeginIndex()); fieldPosStorage.push_back(field.getEndIndex()); fieldCount += 2; } fieldPositions = (int*) malloc(fieldCount * sizeof(int)); for (int i = 0 ; i < fieldCount ; i++ ) fieldPositions[i] = fieldPosStorage[i]; string.Truncate(0); BStringByteSink stringConverter(&string); icuString.toUTF8(stringConverter); return B_OK; } status_t BTimeFormat::GetTimeFields(BDateElement*& fields, int& fieldCount, BTimeFormatStyle style) const { ObjectDeleter timeFormatter(_CreateTimeFormatter(style)); if (!timeFormatter.IsSet()) return B_NO_MEMORY; fields = NULL; UErrorCode error = U_ZERO_ERROR; icu::FieldPositionIterator positionIterator; UnicodeString icuString; time_t now; timeFormatter->format((UDate)time(&now) * 1000, icuString, &positionIterator, error); if (error != U_ZERO_ERROR) return B_BAD_VALUE; icu::FieldPosition field; std::vector fieldPosStorage; fieldCount = 0; while (positionIterator.next(field)) { fieldPosStorage.push_back(field.getField()); fieldCount ++; } fields = (BDateElement*) malloc(fieldCount * sizeof(BDateElement)); for (int i = 0 ; i < fieldCount ; i++ ) { switch (fieldPosStorage[i]) { case UDAT_HOUR_OF_DAY1_FIELD: case UDAT_HOUR_OF_DAY0_FIELD: case UDAT_HOUR1_FIELD: case UDAT_HOUR0_FIELD: fields[i] = B_DATE_ELEMENT_HOUR; break; case UDAT_MINUTE_FIELD: fields[i] = B_DATE_ELEMENT_MINUTE; break; case UDAT_SECOND_FIELD: fields[i] = B_DATE_ELEMENT_SECOND; break; case UDAT_AM_PM_FIELD: fields[i] = B_DATE_ELEMENT_AM_PM; break; default: fields[i] = B_DATE_ELEMENT_INVALID; break; } } return B_OK; } status_t BTimeFormat::Parse(BString source, BTimeFormatStyle style, BTime& output) { ObjectDeleter timeFormatter(_CreateTimeFormatter(style)); if (!timeFormatter.IsSet()) return B_NO_MEMORY; // If no timezone is specified in the time string, assume GMT timeFormatter->setTimeZone(*icu::TimeZone::getGMT()); ParsePosition p(0); UDate date = timeFormatter->parse(UnicodeString::fromUTF8(source.String()), p); output.SetTime(0, 0, 0); output.AddMilliseconds(date); return B_OK; } DateFormat* BTimeFormat::_CreateTimeFormatter(const BTimeFormatStyle style) const { Locale* icuLocale = fConventions.UseStringsFromPreferredLanguage() ? BLanguage::Private(&fLanguage).ICULocale() : BFormattingConventions::Private(&fConventions).ICULocale(); icu::DateFormat* timeFormatter = icu::DateFormat::createTimeInstance(DateFormat::kShort, *icuLocale); if (timeFormatter == NULL) return NULL; SimpleDateFormat* timeFormatterImpl = static_cast(timeFormatter); BString format; fConventions.GetTimeFormat(style, format); UnicodeString pattern(format.String()); timeFormatterImpl->applyPattern(pattern); return timeFormatter; }