From 26b0a53d1249e607a1b0be57c7f3ad33a9d3f36f Mon Sep 17 00:00:00 2001 From: Adrien Destugues Date: Thu, 9 Oct 2014 13:35:23 +0200 Subject: [PATCH] Add parsing support to BTimeFormat. --- headers/os/locale/TimeFormat.h | 21 ++-- src/kits/locale/TimeFormat.cpp | 119 +++++++++-------------- src/tests/kits/locale/DateFormatTest.cpp | 58 +++++++++-- src/tests/kits/locale/DateFormatTest.h | 1 + 4 files changed, 111 insertions(+), 88 deletions(-) diff --git a/headers/os/locale/TimeFormat.h b/headers/os/locale/TimeFormat.h index 563a1da7fb..89d460de94 100644 --- a/headers/os/locale/TimeFormat.h +++ b/headers/os/locale/TimeFormat.h @@ -5,11 +5,16 @@ #ifndef _B_TIME_FORMAT_H_ #define _B_TIME_FORMAT_H_ + #include class BString; +namespace BPrivate { + class BTime; +} + class BTimeFormat : public BFormat { public: @@ -20,18 +25,16 @@ public: BTimeFormat(const BTimeFormat &other); virtual ~BTimeFormat(); + void SetTimeFormat(BTimeFormatStyle style, + const BString& format); + // formatting ssize_t Format(char* string, size_t maxSize, time_t time, BTimeFormatStyle style) const; - ssize_t Format(char* string, size_t maxSize, - time_t time, BString format) const; status_t Format(BString& string, const time_t time, const BTimeFormatStyle style, const BTimeZone* timeZone = NULL) const; - status_t Format(BString& string, const time_t time, - const BString format, - const BTimeZone* timeZone) const; status_t Format(BString& string, int*& fieldPositions, int& fieldCount, time_t time, BTimeFormatStyle style) const; @@ -40,10 +43,14 @@ public: int& fieldCount, BTimeFormatStyle style ) const; - // TODO parsing + // parsing + + status_t Parse(BString source, BTimeFormatStyle style, + BPrivate::BTime& output); + private: icu::DateFormat* _CreateTimeFormatter( - const BString& format) const; + const BTimeFormatStyle style) const; }; diff --git a/src/kits/locale/TimeFormat.cpp b/src/kits/locale/TimeFormat.cpp index 2f7301c929..633f47bb95 100644 --- a/src/kits/locale/TimeFormat.cpp +++ b/src/kits/locale/TimeFormat.cpp @@ -10,6 +10,7 @@ #include #include +#include #include #include #include @@ -44,6 +45,14 @@ BTimeFormat::~BTimeFormat() } +void +BTimeFormat::SetTimeFormat(BTimeFormatStyle style, + const BString& format) +{ + fConventions.SetExplicitTimeFormat(style, format); +} + + // #pragma mark - Formatting @@ -55,37 +64,7 @@ BTimeFormat::Format(char* string, size_t maxSize, time_t time, if (!lock.IsLocked()) return B_ERROR; - BString format; - fConventions.GetTimeFormat(style, format); - ObjectDeleter timeFormatter(_CreateTimeFormatter(format)); - if (timeFormatter.Get() == NULL) - 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(); -} - - -ssize_t -BTimeFormat::Format(char* string, size_t maxSize, time_t time, - BString format) const -{ - BAutolock lock(fLock); - if (!lock.IsLocked()) - return B_ERROR; - - if (format == NULL || format.CountChars() <= 0) - return B_BAD_VALUE; - - ObjectDeleter timeFormatter(_CreateTimeFormatter(format)); + ObjectDeleter timeFormatter(_CreateTimeFormatter(style)); if (timeFormatter.Get() == NULL) return B_NO_MEMORY; @@ -110,43 +89,7 @@ BTimeFormat::Format(BString& string, const time_t time, if (!lock.IsLocked()) return B_ERROR; - BString format; - fConventions.GetTimeFormat(style, format); - ObjectDeleter timeFormatter(_CreateTimeFormatter(format)); - if (timeFormatter.Get() == NULL) - return B_NO_MEMORY; - - if (timeZone != NULL) { - ObjectDeleter icuTimeZone( - TimeZone::createTimeZone(timeZone->ID().String())); - if (icuTimeZone.Get() == NULL) - 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, const time_t time, - const BString format, const BTimeZone* timeZone) const -{ - BAutolock lock(fLock); - if (!lock.IsLocked()) - return B_ERROR; - - if (format == NULL || format.CountChars() <= 0) - return B_BAD_VALUE; - - ObjectDeleter timeFormatter(_CreateTimeFormatter(format)); + ObjectDeleter timeFormatter(_CreateTimeFormatter(style)); if (timeFormatter.Get() == NULL) return B_NO_MEMORY; @@ -177,9 +120,7 @@ BTimeFormat::Format(BString& string, int*& fieldPositions, int& fieldCount, if (!lock.IsLocked()) return B_ERROR; - BString format; - fConventions.GetTimeFormat(style, format); - ObjectDeleter timeFormatter(_CreateTimeFormatter(format)); + ObjectDeleter timeFormatter(_CreateTimeFormatter(style)); if (timeFormatter.Get() == NULL) return B_NO_MEMORY; @@ -223,9 +164,7 @@ BTimeFormat::GetTimeFields(BDateElement*& fields, int& fieldCount, if (!lock.IsLocked()) return B_ERROR; - BString format; - fConventions.GetTimeFormat(style, format); - ObjectDeleter timeFormatter(_CreateTimeFormatter(format)); + ObjectDeleter timeFormatter(_CreateTimeFormatter(style)); if (timeFormatter.Get() == NULL) return B_NO_MEMORY; @@ -277,8 +216,35 @@ BTimeFormat::GetTimeFields(BDateElement*& fields, int& fieldCount, } +status_t +BTimeFormat::Parse(BString source, BTimeFormatStyle style, BTime& output) +{ + BAutolock lock(fLock); + if (!lock.IsLocked()) + return B_ERROR; + + ObjectDeleter timeFormatter(_CreateTimeFormatter(style)); + if (timeFormatter.Get() == NULL) + 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); + + printf("T %f\n", date); + + output.SetTime(0, 0, 0); + output.AddMilliseconds(date); + + return B_OK; +} + + DateFormat* -BTimeFormat::_CreateTimeFormatter(const BString& format) const +BTimeFormat::_CreateTimeFormatter(const BTimeFormatStyle style) const { Locale* icuLocale = fConventions.UseStringsFromPreferredLanguage() @@ -293,6 +259,9 @@ BTimeFormat::_CreateTimeFormatter(const BString& format) const SimpleDateFormat* timeFormatterImpl = static_cast(timeFormatter); + BString format; + fConventions.GetTimeFormat(style, format); + UnicodeString pattern(format.String()); timeFormatterImpl->applyPattern(pattern); diff --git a/src/tests/kits/locale/DateFormatTest.cpp b/src/tests/kits/locale/DateFormatTest.cpp index 733282dd9e..4c248949be 100644 --- a/src/tests/kits/locale/DateFormatTest.cpp +++ b/src/tests/kits/locale/DateFormatTest.cpp @@ -162,15 +162,28 @@ DateFormatTest::TestMonthNames() CPPUNIT_ASSERT_EQUAL(B_OK, result); } + std::ostream& operator<<(std::ostream& stream, const BDate& date) { - stream << date.Year(); - stream << '-'; - stream << date.Month(); - stream << '-'; - stream << date.Day(); + stream << date.Year(); + stream << '-'; + stream << date.Month(); + stream << '-'; + stream << date.Day(); - return stream; + return stream; +} + + +std::ostream& operator<<(std::ostream& stream, const BTime& date) +{ + stream << date.Hour(); + stream << ':'; + stream << date.Minute(); + stream << ':'; + stream << date.Second(); + + return stream; } @@ -205,6 +218,37 @@ DateFormatTest::TestParseDate() } +void +DateFormatTest::TestParseTime() +{ + BLanguage language("fr"); + BFormattingConventions formatting("fr_FR"); + BTimeFormat format(&language, &formatting); + BTime date; + status_t result; + + struct Test { + const char* input; + BTime output; + }; + + static const Test tests[] = { + {"03:25", BTime(3, 25, 0)}, + {"16:18", BTime(16, 18, 0)}, + {"23:59", BTime(23, 59, 0)}, + {NULL} + }; + + for (int i = 0; tests[i].input != NULL; i++) { + NextSubTest(); + result = format.Parse(tests[i].input, B_SHORT_TIME_FORMAT, date); + + CPPUNIT_ASSERT_EQUAL(tests[i].output, date); + CPPUNIT_ASSERT_EQUAL(B_OK, result); + } +} + + /*static*/ void DateFormatTest::AddTests(BTestSuite& parent) { @@ -220,6 +264,8 @@ DateFormatTest::AddTests(BTestSuite& parent) "DateFormatTest::TestMonthNames", &DateFormatTest::TestMonthNames)); suite.addTest(new CppUnit::TestCaller( "DateFormatTest::TestParseDate", &DateFormatTest::TestParseDate)); + suite.addTest(new CppUnit::TestCaller( + "DateFormatTest::TestParseTime", &DateFormatTest::TestParseTime)); parent.addTest("DateFormatTest", &suite); } diff --git a/src/tests/kits/locale/DateFormatTest.h b/src/tests/kits/locale/DateFormatTest.h index f886e69bde..9c99ff68eb 100644 --- a/src/tests/kits/locale/DateFormatTest.h +++ b/src/tests/kits/locale/DateFormatTest.h @@ -20,6 +20,7 @@ public: void TestFormatDate(); void TestMonthNames(); void TestParseDate(); + void TestParseTime(); static void AddTests(BTestSuite& suite); };