Skip to content

Commit

Permalink
Add API for parsing dates.
Browse files Browse the repository at this point in the history
  • Loading branch information
pulkomandy committed Oct 7, 2014
1 parent 090a0d7 commit 97d07c8
Show file tree
Hide file tree
Showing 4 changed files with 88 additions and 21 deletions.
7 changes: 5 additions & 2 deletions headers/os/locale/DateFormat.h
Expand Up @@ -71,11 +71,14 @@ class BDateFormat: public BFormat {
status_t GetStartOfWeek(BWeekday* weekday) const;
status_t GetMonthName(int month, BString& outName);

// TODO parsing
// parsing

status_t Parse(BString source, BDateFormatStyle style,
BDate& output);

private:
icu::DateFormat* _CreateDateFormatter(
const BString& format) const;
const BDateFormatStyle style) const;

};

Expand Down
57 changes: 38 additions & 19 deletions src/kits/locale/DateFormat.cpp
Expand Up @@ -72,9 +72,7 @@ BDateFormat::Format(char* string, const size_t maxSize, const time_t time,
if (!lock.IsLocked())
return B_ERROR;

BString format;
fConventions.GetDateFormat(style, format);
ObjectDeleter<DateFormat> dateFormatter(_CreateDateFormatter(format));
ObjectDeleter<DateFormat> dateFormatter(_CreateDateFormatter(style));
if (dateFormatter.Get() == NULL)
return B_NO_MEMORY;

Expand All @@ -99,9 +97,7 @@ BDateFormat::Format(BString& string, const time_t time,
if (!lock.IsLocked())
return B_ERROR;

BString format;
fConventions.GetDateFormat(style, format);
ObjectDeleter<DateFormat> dateFormatter(_CreateDateFormatter(format));
ObjectDeleter<DateFormat> dateFormatter(_CreateDateFormatter(style));
if (dateFormatter.Get() == NULL)
return B_NO_MEMORY;

Expand Down Expand Up @@ -135,9 +131,7 @@ BDateFormat::Format(BString& string, const BDate& time,
if (!lock.IsLocked())
return B_ERROR;

BString format;
fConventions.GetDateFormat(style, format);
ObjectDeleter<DateFormat> dateFormatter(_CreateDateFormatter(format));
ObjectDeleter<DateFormat> dateFormatter(_CreateDateFormatter(style));
if (dateFormatter.Get() == NULL)
return B_NO_MEMORY;

Expand Down Expand Up @@ -179,9 +173,7 @@ BDateFormat::Format(BString& string, int*& fieldPositions, int& fieldCount,
if (!lock.IsLocked())
return B_ERROR;

BString format;
fConventions.GetDateFormat(style, format);
ObjectDeleter<DateFormat> dateFormatter(_CreateDateFormatter(format));
ObjectDeleter<DateFormat> dateFormatter(_CreateDateFormatter(style));
if (dateFormatter.Get() == NULL)
return B_NO_MEMORY;

Expand Down Expand Up @@ -226,9 +218,7 @@ BDateFormat::GetFields(BDateElement*& fields, int& fieldCount,
if (!lock.IsLocked())
return B_ERROR;

BString format;
fConventions.GetDateFormat(style, format);
ObjectDeleter<DateFormat> dateFormatter(_CreateDateFormatter(format));
ObjectDeleter<DateFormat> dateFormatter(_CreateDateFormatter(style));
if (dateFormatter.Get() == NULL)
return B_NO_MEMORY;

Expand Down Expand Up @@ -332,9 +322,7 @@ BDateFormat::GetMonthName(int month, BString& outName)
if (!lock.IsLocked())
return B_ERROR;

BString pattern;
fConventions.GetDateFormat(B_LONG_DATE_FORMAT, pattern);
DateFormat* format = _CreateDateFormatter(pattern);
DateFormat* format = _CreateDateFormatter(B_LONG_DATE_FORMAT);

SimpleDateFormat* simpleFormat = dynamic_cast<SimpleDateFormat*>(format);
if (simpleFormat == NULL) {
Expand All @@ -360,8 +348,36 @@ BDateFormat::GetMonthName(int month, BString& outName)
}


status_t
BDateFormat::Parse(BString source, BDateFormatStyle style, BDate& output)
{
// FIXME currently this parses a date in any timezone (or the local one if
// none is specified) to a BDate in UTC. This may not be a good idea, we
// may want to parse to a "local" date instead. But BDate should be made
// timezone aware so things like BDate::Difference can work for dates in
// different timezones.
BAutolock lock(fLock);
if (!lock.IsLocked())
return B_ERROR;

ObjectDeleter<DateFormat> dateFormatter(_CreateDateFormatter(style));
if (dateFormatter.Get() == NULL)
return B_NO_MEMORY;


ParsePosition p(0);
UDate date = dateFormatter->parse(UnicodeString::fromUTF8(source.String()),
p);

output.SetDate(1970, 1, 1);
output.AddDays(date / U_MILLIS_PER_DAY + 0.5);

return B_OK;
}


DateFormat*
BDateFormat::_CreateDateFormatter(const BString& format) const
BDateFormat::_CreateDateFormatter(const BDateFormatStyle style) const
{
Locale* icuLocale
= fConventions.UseStringsFromPreferredLanguage()
Expand All @@ -376,6 +392,9 @@ BDateFormat::_CreateDateFormatter(const BString& format) const
SimpleDateFormat* dateFormatterImpl
= static_cast<SimpleDateFormat*>(dateFormatter);

BString format;
fConventions.GetDateFormat(style, format);

UnicodeString pattern(format.String());
dateFormatterImpl->applyPattern(pattern);

Expand Down
44 changes: 44 additions & 0 deletions src/tests/kits/locale/DateFormatTest.cpp
Expand Up @@ -143,6 +143,48 @@ 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();

return stream;
}


void
DateFormatTest::TestParseDate()
{
BLanguage language("en");
BFormattingConventions formatting("en_US");
BDateFormat format(&language, &formatting);
BDate date;
status_t result;

struct Test {
const char* input;
BDate output;
};

static const Test tests[] = {
{"01/01/1970", BDate(1970, 1, 1)},
{"05/07/1988", BDate(1988, 5, 7)},
{"07/31/2345", BDate(2345, 7, 31)},
{NULL}
};

for (int i = 0; tests[i].input != NULL; i++) {
NextSubTest();
result = format.Parse(tests[i].input, B_SHORT_DATE_FORMAT, date);

CPPUNIT_ASSERT_EQUAL(tests[i].output, date);
CPPUNIT_ASSERT_EQUAL(B_OK, result);
}
}


/*static*/ void
DateFormatTest::AddTests(BTestSuite& parent)
Expand All @@ -157,6 +199,8 @@ DateFormatTest::AddTests(BTestSuite& parent)
"DateFormatTest::TestFormatDate", &DateFormatTest::TestFormatDate));
suite.addTest(new CppUnit::TestCaller<DateFormatTest>(
"DateFormatTest::TestMonthNames", &DateFormatTest::TestMonthNames));
suite.addTest(new CppUnit::TestCaller<DateFormatTest>(
"DateFormatTest::TestParseDate", &DateFormatTest::TestParseDate));

parent.addTest("DateFormatTest", &suite);
}
1 change: 1 addition & 0 deletions src/tests/kits/locale/DateFormatTest.h
Expand Up @@ -19,6 +19,7 @@ class DateFormatTest: public BTestCase {
void TestFormat();
void TestFormatDate();
void TestMonthNames();
void TestParseDate();

static void AddTests(BTestSuite& suite);
};
Expand Down

0 comments on commit 97d07c8

Please sign in to comment.