Add API for parsing dates.
This commit is contained in:
@@ -71,11 +71,14 @@ public:
|
|||||||
status_t GetStartOfWeek(BWeekday* weekday) const;
|
status_t GetStartOfWeek(BWeekday* weekday) const;
|
||||||
status_t GetMonthName(int month, BString& outName);
|
status_t GetMonthName(int month, BString& outName);
|
||||||
|
|
||||||
// TODO parsing
|
// parsing
|
||||||
|
|
||||||
|
status_t Parse(BString source, BDateFormatStyle style,
|
||||||
|
BDate& output);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
icu::DateFormat* _CreateDateFormatter(
|
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())
|
if (!lock.IsLocked())
|
||||||
return B_ERROR;
|
return B_ERROR;
|
||||||
|
|
||||||
BString format;
|
ObjectDeleter<DateFormat> dateFormatter(_CreateDateFormatter(style));
|
||||||
fConventions.GetDateFormat(style, format);
|
|
||||||
ObjectDeleter<DateFormat> dateFormatter(_CreateDateFormatter(format));
|
|
||||||
if (dateFormatter.Get() == NULL)
|
if (dateFormatter.Get() == NULL)
|
||||||
return B_NO_MEMORY;
|
return B_NO_MEMORY;
|
||||||
|
|
||||||
@@ -99,9 +97,7 @@ BDateFormat::Format(BString& string, const time_t time,
|
|||||||
if (!lock.IsLocked())
|
if (!lock.IsLocked())
|
||||||
return B_ERROR;
|
return B_ERROR;
|
||||||
|
|
||||||
BString format;
|
ObjectDeleter<DateFormat> dateFormatter(_CreateDateFormatter(style));
|
||||||
fConventions.GetDateFormat(style, format);
|
|
||||||
ObjectDeleter<DateFormat> dateFormatter(_CreateDateFormatter(format));
|
|
||||||
if (dateFormatter.Get() == NULL)
|
if (dateFormatter.Get() == NULL)
|
||||||
return B_NO_MEMORY;
|
return B_NO_MEMORY;
|
||||||
|
|
||||||
@@ -135,9 +131,7 @@ BDateFormat::Format(BString& string, const BDate& time,
|
|||||||
if (!lock.IsLocked())
|
if (!lock.IsLocked())
|
||||||
return B_ERROR;
|
return B_ERROR;
|
||||||
|
|
||||||
BString format;
|
ObjectDeleter<DateFormat> dateFormatter(_CreateDateFormatter(style));
|
||||||
fConventions.GetDateFormat(style, format);
|
|
||||||
ObjectDeleter<DateFormat> dateFormatter(_CreateDateFormatter(format));
|
|
||||||
if (dateFormatter.Get() == NULL)
|
if (dateFormatter.Get() == NULL)
|
||||||
return B_NO_MEMORY;
|
return B_NO_MEMORY;
|
||||||
|
|
||||||
@@ -179,9 +173,7 @@ BDateFormat::Format(BString& string, int*& fieldPositions, int& fieldCount,
|
|||||||
if (!lock.IsLocked())
|
if (!lock.IsLocked())
|
||||||
return B_ERROR;
|
return B_ERROR;
|
||||||
|
|
||||||
BString format;
|
ObjectDeleter<DateFormat> dateFormatter(_CreateDateFormatter(style));
|
||||||
fConventions.GetDateFormat(style, format);
|
|
||||||
ObjectDeleter<DateFormat> dateFormatter(_CreateDateFormatter(format));
|
|
||||||
if (dateFormatter.Get() == NULL)
|
if (dateFormatter.Get() == NULL)
|
||||||
return B_NO_MEMORY;
|
return B_NO_MEMORY;
|
||||||
|
|
||||||
@@ -226,9 +218,7 @@ BDateFormat::GetFields(BDateElement*& fields, int& fieldCount,
|
|||||||
if (!lock.IsLocked())
|
if (!lock.IsLocked())
|
||||||
return B_ERROR;
|
return B_ERROR;
|
||||||
|
|
||||||
BString format;
|
ObjectDeleter<DateFormat> dateFormatter(_CreateDateFormatter(style));
|
||||||
fConventions.GetDateFormat(style, format);
|
|
||||||
ObjectDeleter<DateFormat> dateFormatter(_CreateDateFormatter(format));
|
|
||||||
if (dateFormatter.Get() == NULL)
|
if (dateFormatter.Get() == NULL)
|
||||||
return B_NO_MEMORY;
|
return B_NO_MEMORY;
|
||||||
|
|
||||||
@@ -332,9 +322,7 @@ BDateFormat::GetMonthName(int month, BString& outName)
|
|||||||
if (!lock.IsLocked())
|
if (!lock.IsLocked())
|
||||||
return B_ERROR;
|
return B_ERROR;
|
||||||
|
|
||||||
BString pattern;
|
DateFormat* format = _CreateDateFormatter(B_LONG_DATE_FORMAT);
|
||||||
fConventions.GetDateFormat(B_LONG_DATE_FORMAT, pattern);
|
|
||||||
DateFormat* format = _CreateDateFormatter(pattern);
|
|
||||||
|
|
||||||
SimpleDateFormat* simpleFormat = dynamic_cast<SimpleDateFormat*>(format);
|
SimpleDateFormat* simpleFormat = dynamic_cast<SimpleDateFormat*>(format);
|
||||||
if (simpleFormat == NULL) {
|
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*
|
DateFormat*
|
||||||
BDateFormat::_CreateDateFormatter(const BString& format) const
|
BDateFormat::_CreateDateFormatter(const BDateFormatStyle style) const
|
||||||
{
|
{
|
||||||
Locale* icuLocale
|
Locale* icuLocale
|
||||||
= fConventions.UseStringsFromPreferredLanguage()
|
= fConventions.UseStringsFromPreferredLanguage()
|
||||||
@@ -376,6 +392,9 @@ BDateFormat::_CreateDateFormatter(const BString& format) const
|
|||||||
SimpleDateFormat* dateFormatterImpl
|
SimpleDateFormat* dateFormatterImpl
|
||||||
= static_cast<SimpleDateFormat*>(dateFormatter);
|
= static_cast<SimpleDateFormat*>(dateFormatter);
|
||||||
|
|
||||||
|
BString format;
|
||||||
|
fConventions.GetDateFormat(style, format);
|
||||||
|
|
||||||
UnicodeString pattern(format.String());
|
UnicodeString pattern(format.String());
|
||||||
dateFormatterImpl->applyPattern(pattern);
|
dateFormatterImpl->applyPattern(pattern);
|
||||||
|
|
||||||
|
|||||||
@@ -143,6 +143,48 @@ DateFormatTest::TestMonthNames()
|
|||||||
CPPUNIT_ASSERT_EQUAL(B_OK, result);
|
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
|
/*static*/ void
|
||||||
DateFormatTest::AddTests(BTestSuite& parent)
|
DateFormatTest::AddTests(BTestSuite& parent)
|
||||||
@@ -157,6 +199,8 @@ DateFormatTest::AddTests(BTestSuite& parent)
|
|||||||
"DateFormatTest::TestFormatDate", &DateFormatTest::TestFormatDate));
|
"DateFormatTest::TestFormatDate", &DateFormatTest::TestFormatDate));
|
||||||
suite.addTest(new CppUnit::TestCaller<DateFormatTest>(
|
suite.addTest(new CppUnit::TestCaller<DateFormatTest>(
|
||||||
"DateFormatTest::TestMonthNames", &DateFormatTest::TestMonthNames));
|
"DateFormatTest::TestMonthNames", &DateFormatTest::TestMonthNames));
|
||||||
|
suite.addTest(new CppUnit::TestCaller<DateFormatTest>(
|
||||||
|
"DateFormatTest::TestParseDate", &DateFormatTest::TestParseDate));
|
||||||
|
|
||||||
parent.addTest("DateFormatTest", &suite);
|
parent.addTest("DateFormatTest", &suite);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -19,6 +19,7 @@ public:
|
|||||||
void TestFormat();
|
void TestFormat();
|
||||||
void TestFormatDate();
|
void TestFormatDate();
|
||||||
void TestMonthNames();
|
void TestMonthNames();
|
||||||
|
void TestParseDate();
|
||||||
|
|
||||||
static void AddTests(BTestSuite& suite);
|
static void AddTests(BTestSuite& suite);
|
||||||
};
|
};
|
||||||
|
|||||||
Reference in New Issue
Block a user