Add API for parsing dates.
This commit is contained in:
@@ -71,11 +71,14 @@ public:
|
||||
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;
|
||||
|
||||
};
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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) {
|
||||
@@ -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()
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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)
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -19,6 +19,7 @@ public:
|
||||
void TestFormat();
|
||||
void TestFormatDate();
|
||||
void TestMonthNames();
|
||||
void TestParseDate();
|
||||
|
||||
static void AddTests(BTestSuite& suite);
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user