Add parsing support to BTimeFormat.
This commit is contained in:
parent
640158e2e7
commit
26b0a53d12
@ -5,11 +5,16 @@
|
||||
#ifndef _B_TIME_FORMAT_H_
|
||||
#define _B_TIME_FORMAT_H_
|
||||
|
||||
|
||||
#include <DateTimeFormat.h>
|
||||
|
||||
|
||||
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;
|
||||
};
|
||||
|
||||
|
||||
|
@ -10,6 +10,7 @@
|
||||
|
||||
#include <AutoDeleter.h>
|
||||
#include <Autolock.h>
|
||||
#include <DateTime.h>
|
||||
#include <FormattingConventionsPrivate.h>
|
||||
#include <LanguagePrivate.h>
|
||||
#include <TimeZone.h>
|
||||
@ -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<DateFormat> 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<DateFormat> timeFormatter(_CreateTimeFormatter(format));
|
||||
ObjectDeleter<DateFormat> 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<DateFormat> timeFormatter(_CreateTimeFormatter(format));
|
||||
if (timeFormatter.Get() == NULL)
|
||||
return B_NO_MEMORY;
|
||||
|
||||
if (timeZone != NULL) {
|
||||
ObjectDeleter<TimeZone> 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<DateFormat> timeFormatter(_CreateTimeFormatter(format));
|
||||
ObjectDeleter<DateFormat> 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<DateFormat> timeFormatter(_CreateTimeFormatter(format));
|
||||
ObjectDeleter<DateFormat> 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<DateFormat> timeFormatter(_CreateTimeFormatter(format));
|
||||
ObjectDeleter<DateFormat> 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<DateFormat> 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<SimpleDateFormat*>(timeFormatter);
|
||||
|
||||
BString format;
|
||||
fConventions.GetTimeFormat(style, format);
|
||||
|
||||
UnicodeString pattern(format.String());
|
||||
timeFormatterImpl->applyPattern(pattern);
|
||||
|
||||
|
@ -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>(
|
||||
"DateFormatTest::TestParseDate", &DateFormatTest::TestParseDate));
|
||||
suite.addTest(new CppUnit::TestCaller<DateFormatTest>(
|
||||
"DateFormatTest::TestParseTime", &DateFormatTest::TestParseTime));
|
||||
|
||||
parent.addTest("DateFormatTest", &suite);
|
||||
}
|
||||
|
@ -20,6 +20,7 @@ public:
|
||||
void TestFormatDate();
|
||||
void TestMonthNames();
|
||||
void TestParseDate();
|
||||
void TestParseTime();
|
||||
|
||||
static void AddTests(BTestSuite& suite);
|
||||
};
|
||||
|
Loading…
x
Reference in New Issue
Block a user