xref: /haiku/src/kits/locale/DateTimeFormat.cpp (revision 4a3a4742241f0843867e76cbc49694b9e4146b2f)
138ac8defSOliver Tappe /*
2e3857211SAdrien Destugues  * Copyright 2010-2014, Haiku, Inc. All Rights Reserved.
338ac8defSOliver Tappe  * Distributed under the terms of the MIT License.
438ac8defSOliver Tappe  *
538ac8defSOliver Tappe  * Authors:
638ac8defSOliver Tappe  *		Oliver Tappe <zooey@hirschkaefer.de>
738ac8defSOliver Tappe  */
838ac8defSOliver Tappe 
938ac8defSOliver Tappe #include <DateTimeFormat.h>
1038ac8defSOliver Tappe 
11e3857211SAdrien Destugues #include <AutoDeleter.h>
12e3857211SAdrien Destugues #include <Autolock.h>
13e3857211SAdrien Destugues #include <FormattingConventionsPrivate.h>
14e3857211SAdrien Destugues #include <LanguagePrivate.h>
15e3857211SAdrien Destugues #include <TimeZone.h>
1638ac8defSOliver Tappe 
17e3857211SAdrien Destugues #include <ICUWrapper.h>
18e3857211SAdrien Destugues 
19e3857211SAdrien Destugues #include <unicode/datefmt.h>
20*4a3a4742SAdrien Destugues #include <unicode/dtptngen.h>
21e3857211SAdrien Destugues #include <unicode/smpdtfmt.h>
22e3857211SAdrien Destugues 
23e3857211SAdrien Destugues 
24*4a3a4742SAdrien Destugues BDateTimeFormat::BDateTimeFormat(const BLanguage* const language,
25*4a3a4742SAdrien Destugues 		const BFormattingConventions* const conventions)
2638ac8defSOliver Tappe {
27*4a3a4742SAdrien Destugues 	if (conventions != NULL)
28*4a3a4742SAdrien Destugues 		fConventions = *conventions;
29*4a3a4742SAdrien Destugues 
30*4a3a4742SAdrien Destugues 	if (language != NULL)
31*4a3a4742SAdrien Destugues 		fLanguage = *language;
3238ac8defSOliver Tappe }
3338ac8defSOliver Tappe 
34f3dd81abSOliver Tappe 
3538ac8defSOliver Tappe BDateTimeFormat::BDateTimeFormat(const BDateTimeFormat &other)
3638ac8defSOliver Tappe 	: BFormat(other)
3738ac8defSOliver Tappe {
3838ac8defSOliver Tappe }
3938ac8defSOliver Tappe 
40f3dd81abSOliver Tappe 
4138ac8defSOliver Tappe BDateTimeFormat::~BDateTimeFormat()
4238ac8defSOliver Tappe {
4338ac8defSOliver Tappe }
4438ac8defSOliver Tappe 
45f3dd81abSOliver Tappe 
46*4a3a4742SAdrien Destugues void
47*4a3a4742SAdrien Destugues BDateTimeFormat::SetDateTimeFormat(BDateFormatStyle dateStyle,
48*4a3a4742SAdrien Destugues 	BTimeFormatStyle timeStyle, int32 elements) {
49*4a3a4742SAdrien Destugues 	UErrorCode error = U_ZERO_ERROR;
50*4a3a4742SAdrien Destugues 	DateTimePatternGenerator* generator
51*4a3a4742SAdrien Destugues 		= DateTimePatternGenerator::createInstance(error);
52*4a3a4742SAdrien Destugues 
53*4a3a4742SAdrien Destugues 	BString skeleton;
54*4a3a4742SAdrien Destugues 	if (elements & B_DATE_ELEMENT_YEAR)
55*4a3a4742SAdrien Destugues 		skeleton << "yyyy";
56*4a3a4742SAdrien Destugues 	if (elements & B_DATE_ELEMENT_MONTH)
57*4a3a4742SAdrien Destugues 		skeleton << "MM";
58*4a3a4742SAdrien Destugues 	if (elements & B_DATE_ELEMENT_WEEKDAY)
59*4a3a4742SAdrien Destugues 		skeleton << "eee";
60*4a3a4742SAdrien Destugues 	if (elements & B_DATE_ELEMENT_DAY)
61*4a3a4742SAdrien Destugues 		skeleton << "dd";
62*4a3a4742SAdrien Destugues 	if (elements & B_DATE_ELEMENT_AM_PM)
63*4a3a4742SAdrien Destugues 		skeleton << "a";
64*4a3a4742SAdrien Destugues 	if (elements & B_DATE_ELEMENT_HOUR)
65*4a3a4742SAdrien Destugues 		skeleton << "jj";
66*4a3a4742SAdrien Destugues 	if (elements & B_DATE_ELEMENT_MINUTE)
67*4a3a4742SAdrien Destugues 		skeleton << "mm";
68*4a3a4742SAdrien Destugues 	if (elements & B_DATE_ELEMENT_SECOND)
69*4a3a4742SAdrien Destugues 		skeleton << "ss";
70*4a3a4742SAdrien Destugues 	if (elements & B_DATE_ELEMENT_TIMEZONE)
71*4a3a4742SAdrien Destugues 		skeleton << "V";
72*4a3a4742SAdrien Destugues 
73*4a3a4742SAdrien Destugues 	UnicodeString pattern = generator->getBestPattern(
74*4a3a4742SAdrien Destugues 		UnicodeString::fromUTF8(skeleton.String()), error);
75*4a3a4742SAdrien Destugues 
76*4a3a4742SAdrien Destugues 	BString buffer;
77*4a3a4742SAdrien Destugues 	BStringByteSink stringConverter(&buffer);
78*4a3a4742SAdrien Destugues 	pattern.toUTF8(stringConverter);
79*4a3a4742SAdrien Destugues 	fConventions.SetExplicitDateTimeFormat(dateStyle, timeStyle, buffer);
80*4a3a4742SAdrien Destugues 
81*4a3a4742SAdrien Destugues 	delete generator;
82*4a3a4742SAdrien Destugues }
83*4a3a4742SAdrien Destugues 
84*4a3a4742SAdrien Destugues 
85e3857211SAdrien Destugues // #pragma mark - Formatting
86e3857211SAdrien Destugues 
87e3857211SAdrien Destugues 
88e3857211SAdrien Destugues ssize_t
89e3857211SAdrien Destugues BDateTimeFormat::Format(char* target, size_t maxSize, time_t time,
90e3857211SAdrien Destugues 	BDateFormatStyle dateStyle, BTimeFormatStyle timeStyle) const
9138ac8defSOliver Tappe {
92e3857211SAdrien Destugues 	BAutolock lock(fLock);
93e3857211SAdrien Destugues 	if (!lock.IsLocked())
9438ac8defSOliver Tappe 		return B_ERROR;
95e3857211SAdrien Destugues 
96e3857211SAdrien Destugues 	BString format;
97*4a3a4742SAdrien Destugues 	fConventions.GetDateTimeFormat(dateStyle, timeStyle, format);
98*4a3a4742SAdrien Destugues 	ObjectDeleter<DateFormat> dateFormatter(_CreateDateTimeFormatter(format));
99e3857211SAdrien Destugues 	if (dateFormatter.Get() == NULL)
100e3857211SAdrien Destugues 		return B_NO_MEMORY;
101e3857211SAdrien Destugues 
102e3857211SAdrien Destugues 	UnicodeString icuString;
103e3857211SAdrien Destugues 	dateFormatter->format((UDate)time * 1000, icuString);
104e3857211SAdrien Destugues 
105e3857211SAdrien Destugues 	CheckedArrayByteSink stringConverter(target, maxSize);
106e3857211SAdrien Destugues 	icuString.toUTF8(stringConverter);
107e3857211SAdrien Destugues 
108e3857211SAdrien Destugues 	if (stringConverter.Overflowed())
109e3857211SAdrien Destugues 		return B_BAD_VALUE;
110e3857211SAdrien Destugues 
111e3857211SAdrien Destugues 	return stringConverter.NumberOfBytesWritten();
112e3857211SAdrien Destugues }
113e3857211SAdrien Destugues 
114e3857211SAdrien Destugues 
115e3857211SAdrien Destugues status_t
116e3857211SAdrien Destugues BDateTimeFormat::Format(BString& target, const time_t time,
117e3857211SAdrien Destugues 	BDateFormatStyle dateStyle, BTimeFormatStyle timeStyle,
118e3857211SAdrien Destugues 	const BTimeZone* timeZone) const
119e3857211SAdrien Destugues {
120e3857211SAdrien Destugues 	BAutolock lock(fLock);
121e3857211SAdrien Destugues 	if (!lock.IsLocked())
122e3857211SAdrien Destugues 		return B_ERROR;
123e3857211SAdrien Destugues 
124e3857211SAdrien Destugues 	BString format;
125*4a3a4742SAdrien Destugues 	fConventions.GetDateTimeFormat(dateStyle, timeStyle, format);
126*4a3a4742SAdrien Destugues 	ObjectDeleter<DateFormat> dateFormatter(_CreateDateTimeFormatter(format));
127e3857211SAdrien Destugues 	if (dateFormatter.Get() == NULL)
128e3857211SAdrien Destugues 		return B_NO_MEMORY;
129e3857211SAdrien Destugues 
130e3857211SAdrien Destugues 	if (timeZone != NULL) {
131e3857211SAdrien Destugues 		ObjectDeleter<TimeZone> icuTimeZone(
132e3857211SAdrien Destugues 			TimeZone::createTimeZone(timeZone->ID().String()));
133e3857211SAdrien Destugues 		if (icuTimeZone.Get() == NULL)
134e3857211SAdrien Destugues 			return B_NO_MEMORY;
135*4a3a4742SAdrien Destugues 		dateFormatter->setTimeZone(*icuTimeZone.Get());
136e3857211SAdrien Destugues 	}
137e3857211SAdrien Destugues 
138e3857211SAdrien Destugues 	UnicodeString icuString;
139e3857211SAdrien Destugues 	dateFormatter->format((UDate)time * 1000, icuString);
140e3857211SAdrien Destugues 
141e3857211SAdrien Destugues 	target.Truncate(0);
142e3857211SAdrien Destugues 	BStringByteSink stringConverter(&target);
143e3857211SAdrien Destugues 	icuString.toUTF8(stringConverter);
144e3857211SAdrien Destugues 
145e3857211SAdrien Destugues 	return B_OK;
146e3857211SAdrien Destugues }
147e3857211SAdrien Destugues 
148e3857211SAdrien Destugues 
149e3857211SAdrien Destugues DateFormat*
150*4a3a4742SAdrien Destugues BDateTimeFormat::_CreateDateTimeFormatter(const BString& format) const
151e3857211SAdrien Destugues {
152e3857211SAdrien Destugues 	Locale* icuLocale
153e3857211SAdrien Destugues 		= fConventions.UseStringsFromPreferredLanguage()
154e3857211SAdrien Destugues 			? BLanguage::Private(&fLanguage).ICULocale()
155e3857211SAdrien Destugues 			: BFormattingConventions::Private(&fConventions).ICULocale();
156e3857211SAdrien Destugues 
157*4a3a4742SAdrien Destugues 	icu::DateFormat* dateFormatter = icu::DateFormat::createDateTimeInstance(
158*4a3a4742SAdrien Destugues 		DateFormat::kDefault, DateFormat::kDefault, *icuLocale);
159e3857211SAdrien Destugues 	if (dateFormatter == NULL)
160e3857211SAdrien Destugues 		return NULL;
161e3857211SAdrien Destugues 
162e3857211SAdrien Destugues 	SimpleDateFormat* dateFormatterImpl
163e3857211SAdrien Destugues 		= static_cast<SimpleDateFormat*>(dateFormatter);
164e3857211SAdrien Destugues 
165e3857211SAdrien Destugues 	UnicodeString pattern(format.String());
166e3857211SAdrien Destugues 	dateFormatterImpl->applyPattern(pattern);
167e3857211SAdrien Destugues 
168e3857211SAdrien Destugues 	return dateFormatter;
169e3857211SAdrien Destugues }
170