xref: /haiku/src/kits/locale/DateTimeFormat.cpp (revision 824cb460ac8ac243f8d0dd3c88e3d482df104599)
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>
204a3a4742SAdrien Destugues #include <unicode/dtptngen.h>
21e3857211SAdrien Destugues #include <unicode/smpdtfmt.h>
22e3857211SAdrien Destugues 
23e3857211SAdrien Destugues 
244a3a4742SAdrien Destugues BDateTimeFormat::BDateTimeFormat(const BLanguage* const language,
254a3a4742SAdrien Destugues 		const BFormattingConventions* const conventions)
2638ac8defSOliver Tappe {
274a3a4742SAdrien Destugues 	if (conventions != NULL)
284a3a4742SAdrien Destugues 		fConventions = *conventions;
294a3a4742SAdrien Destugues 
304a3a4742SAdrien Destugues 	if (language != NULL)
314a3a4742SAdrien 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 
464a3a4742SAdrien Destugues void
474a3a4742SAdrien Destugues BDateTimeFormat::SetDateTimeFormat(BDateFormatStyle dateStyle,
484a3a4742SAdrien Destugues 	BTimeFormatStyle timeStyle, int32 elements) {
494a3a4742SAdrien Destugues 	UErrorCode error = U_ZERO_ERROR;
504a3a4742SAdrien Destugues 	DateTimePatternGenerator* generator
514a3a4742SAdrien Destugues 		= DateTimePatternGenerator::createInstance(error);
524a3a4742SAdrien Destugues 
534a3a4742SAdrien Destugues 	BString skeleton;
544a3a4742SAdrien Destugues 	if (elements & B_DATE_ELEMENT_YEAR)
554a3a4742SAdrien Destugues 		skeleton << "yyyy";
564a3a4742SAdrien Destugues 	if (elements & B_DATE_ELEMENT_MONTH)
574a3a4742SAdrien Destugues 		skeleton << "MM";
584a3a4742SAdrien Destugues 	if (elements & B_DATE_ELEMENT_WEEKDAY)
594a3a4742SAdrien Destugues 		skeleton << "eee";
604a3a4742SAdrien Destugues 	if (elements & B_DATE_ELEMENT_DAY)
614a3a4742SAdrien Destugues 		skeleton << "dd";
624a3a4742SAdrien Destugues 	if (elements & B_DATE_ELEMENT_AM_PM)
634a3a4742SAdrien Destugues 		skeleton << "a";
64*824cb460SAdrien Destugues 	if (elements & B_DATE_ELEMENT_HOUR) {
65*824cb460SAdrien Destugues 		if (fConventions.Use24HourClock())
66*824cb460SAdrien Destugues 			skeleton << "HH";
67*824cb460SAdrien Destugues 		else
68*824cb460SAdrien Destugues 			skeleton << "KK";
69*824cb460SAdrien Destugues 	}
704a3a4742SAdrien Destugues 	if (elements & B_DATE_ELEMENT_MINUTE)
714a3a4742SAdrien Destugues 		skeleton << "mm";
724a3a4742SAdrien Destugues 	if (elements & B_DATE_ELEMENT_SECOND)
734a3a4742SAdrien Destugues 		skeleton << "ss";
744a3a4742SAdrien Destugues 	if (elements & B_DATE_ELEMENT_TIMEZONE)
75892f3b8bSAdrien Destugues 		skeleton << "z";
764a3a4742SAdrien Destugues 
774a3a4742SAdrien Destugues 	UnicodeString pattern = generator->getBestPattern(
784a3a4742SAdrien Destugues 		UnicodeString::fromUTF8(skeleton.String()), error);
794a3a4742SAdrien Destugues 
804a3a4742SAdrien Destugues 	BString buffer;
814a3a4742SAdrien Destugues 	BStringByteSink stringConverter(&buffer);
824a3a4742SAdrien Destugues 	pattern.toUTF8(stringConverter);
834a3a4742SAdrien Destugues 	fConventions.SetExplicitDateTimeFormat(dateStyle, timeStyle, buffer);
844a3a4742SAdrien Destugues 
854a3a4742SAdrien Destugues 	delete generator;
864a3a4742SAdrien Destugues }
874a3a4742SAdrien Destugues 
884a3a4742SAdrien Destugues 
89e3857211SAdrien Destugues // #pragma mark - Formatting
90e3857211SAdrien Destugues 
91e3857211SAdrien Destugues 
92e3857211SAdrien Destugues ssize_t
93e3857211SAdrien Destugues BDateTimeFormat::Format(char* target, size_t maxSize, time_t time,
94e3857211SAdrien Destugues 	BDateFormatStyle dateStyle, BTimeFormatStyle timeStyle) const
9538ac8defSOliver Tappe {
96e3857211SAdrien Destugues 	BAutolock lock(fLock);
97e3857211SAdrien Destugues 	if (!lock.IsLocked())
9838ac8defSOliver Tappe 		return B_ERROR;
99e3857211SAdrien Destugues 
100e3857211SAdrien Destugues 	BString format;
1014a3a4742SAdrien Destugues 	fConventions.GetDateTimeFormat(dateStyle, timeStyle, format);
1024a3a4742SAdrien Destugues 	ObjectDeleter<DateFormat> dateFormatter(_CreateDateTimeFormatter(format));
103e3857211SAdrien Destugues 	if (dateFormatter.Get() == NULL)
104e3857211SAdrien Destugues 		return B_NO_MEMORY;
105e3857211SAdrien Destugues 
106e3857211SAdrien Destugues 	UnicodeString icuString;
107e3857211SAdrien Destugues 	dateFormatter->format((UDate)time * 1000, icuString);
108e3857211SAdrien Destugues 
109e3857211SAdrien Destugues 	CheckedArrayByteSink stringConverter(target, maxSize);
110e3857211SAdrien Destugues 	icuString.toUTF8(stringConverter);
111e3857211SAdrien Destugues 
112e3857211SAdrien Destugues 	if (stringConverter.Overflowed())
113e3857211SAdrien Destugues 		return B_BAD_VALUE;
114e3857211SAdrien Destugues 
115e3857211SAdrien Destugues 	return stringConverter.NumberOfBytesWritten();
116e3857211SAdrien Destugues }
117e3857211SAdrien Destugues 
118e3857211SAdrien Destugues 
119e3857211SAdrien Destugues status_t
120e3857211SAdrien Destugues BDateTimeFormat::Format(BString& target, const time_t time,
121e3857211SAdrien Destugues 	BDateFormatStyle dateStyle, BTimeFormatStyle timeStyle,
122e3857211SAdrien Destugues 	const BTimeZone* timeZone) const
123e3857211SAdrien Destugues {
124e3857211SAdrien Destugues 	BAutolock lock(fLock);
125e3857211SAdrien Destugues 	if (!lock.IsLocked())
126e3857211SAdrien Destugues 		return B_ERROR;
127e3857211SAdrien Destugues 
128e3857211SAdrien Destugues 	BString format;
1294a3a4742SAdrien Destugues 	fConventions.GetDateTimeFormat(dateStyle, timeStyle, format);
1304a3a4742SAdrien Destugues 	ObjectDeleter<DateFormat> dateFormatter(_CreateDateTimeFormatter(format));
131e3857211SAdrien Destugues 	if (dateFormatter.Get() == NULL)
132e3857211SAdrien Destugues 		return B_NO_MEMORY;
133e3857211SAdrien Destugues 
134e3857211SAdrien Destugues 	if (timeZone != NULL) {
135e3857211SAdrien Destugues 		ObjectDeleter<TimeZone> icuTimeZone(
136e3857211SAdrien Destugues 			TimeZone::createTimeZone(timeZone->ID().String()));
137e3857211SAdrien Destugues 		if (icuTimeZone.Get() == NULL)
138e3857211SAdrien Destugues 			return B_NO_MEMORY;
1394a3a4742SAdrien Destugues 		dateFormatter->setTimeZone(*icuTimeZone.Get());
140e3857211SAdrien Destugues 	}
141e3857211SAdrien Destugues 
142e3857211SAdrien Destugues 	UnicodeString icuString;
143e3857211SAdrien Destugues 	dateFormatter->format((UDate)time * 1000, icuString);
144e3857211SAdrien Destugues 
145e3857211SAdrien Destugues 	target.Truncate(0);
146e3857211SAdrien Destugues 	BStringByteSink stringConverter(&target);
147e3857211SAdrien Destugues 	icuString.toUTF8(stringConverter);
148e3857211SAdrien Destugues 
149e3857211SAdrien Destugues 	return B_OK;
150e3857211SAdrien Destugues }
151e3857211SAdrien Destugues 
152e3857211SAdrien Destugues 
153e3857211SAdrien Destugues DateFormat*
1544a3a4742SAdrien Destugues BDateTimeFormat::_CreateDateTimeFormatter(const BString& format) const
155e3857211SAdrien Destugues {
156e3857211SAdrien Destugues 	Locale* icuLocale
157e3857211SAdrien Destugues 		= fConventions.UseStringsFromPreferredLanguage()
158e3857211SAdrien Destugues 			? BLanguage::Private(&fLanguage).ICULocale()
159e3857211SAdrien Destugues 			: BFormattingConventions::Private(&fConventions).ICULocale();
160e3857211SAdrien Destugues 
1614a3a4742SAdrien Destugues 	icu::DateFormat* dateFormatter = icu::DateFormat::createDateTimeInstance(
1624a3a4742SAdrien Destugues 		DateFormat::kDefault, DateFormat::kDefault, *icuLocale);
163e3857211SAdrien Destugues 	if (dateFormatter == NULL)
164e3857211SAdrien Destugues 		return NULL;
165e3857211SAdrien Destugues 
166e3857211SAdrien Destugues 	SimpleDateFormat* dateFormatterImpl
167e3857211SAdrien Destugues 		= static_cast<SimpleDateFormat*>(dateFormatter);
168e3857211SAdrien Destugues 
169e3857211SAdrien Destugues 	UnicodeString pattern(format.String());
170e3857211SAdrien Destugues 	dateFormatterImpl->applyPattern(pattern);
171e3857211SAdrien Destugues 
172e3857211SAdrien Destugues 	return dateFormatter;
173e3857211SAdrien Destugues }
174