xref: /haiku/src/kits/locale/DateTimeFormat.cpp (revision 779ab335dd81d47f9aa7ef06822de37c8fec1c6e)
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 
973de5837SJérôme Duval #include <unicode/uversion.h>
1038ac8defSOliver Tappe #include <DateTimeFormat.h>
1138ac8defSOliver Tappe 
12e3857211SAdrien Destugues #include <AutoDeleter.h>
13e3857211SAdrien Destugues #include <Autolock.h>
14e3857211SAdrien Destugues #include <FormattingConventionsPrivate.h>
15e3857211SAdrien Destugues #include <LanguagePrivate.h>
16e3857211SAdrien Destugues #include <TimeZone.h>
1738ac8defSOliver Tappe 
18e3857211SAdrien Destugues #include <ICUWrapper.h>
19e3857211SAdrien Destugues 
20e3857211SAdrien Destugues #include <unicode/datefmt.h>
214a3a4742SAdrien Destugues #include <unicode/dtptngen.h>
22e3857211SAdrien Destugues #include <unicode/smpdtfmt.h>
23e3857211SAdrien Destugues 
24e3857211SAdrien Destugues 
251bad1ff3SAdrien Destugues U_NAMESPACE_USE
261bad1ff3SAdrien Destugues 
271bad1ff3SAdrien Destugues 
BDateTimeFormat(const BLocale * locale)285d5ec05bSAdrien Destugues BDateTimeFormat::BDateTimeFormat(const BLocale* locale)
295d5ec05bSAdrien Destugues 	: BFormat(locale)
3038ac8defSOliver Tappe {
315d5ec05bSAdrien Destugues }
324a3a4742SAdrien Destugues 
335d5ec05bSAdrien Destugues 
BDateTimeFormat(const BLanguage & language,const BFormattingConventions & conventions)345d5ec05bSAdrien Destugues BDateTimeFormat::BDateTimeFormat(const BLanguage& language,
355d5ec05bSAdrien Destugues 	const BFormattingConventions& conventions)
365d5ec05bSAdrien Destugues 	: BFormat(language, conventions)
375d5ec05bSAdrien Destugues {
3838ac8defSOliver Tappe }
3938ac8defSOliver Tappe 
40f3dd81abSOliver Tappe 
BDateTimeFormat(const BDateTimeFormat & other)4138ac8defSOliver Tappe BDateTimeFormat::BDateTimeFormat(const BDateTimeFormat &other)
4238ac8defSOliver Tappe 	: BFormat(other)
4338ac8defSOliver Tappe {
4438ac8defSOliver Tappe }
4538ac8defSOliver Tappe 
46f3dd81abSOliver Tappe 
~BDateTimeFormat()4738ac8defSOliver Tappe BDateTimeFormat::~BDateTimeFormat()
4838ac8defSOliver Tappe {
4938ac8defSOliver Tappe }
5038ac8defSOliver Tappe 
51f3dd81abSOliver Tappe 
524a3a4742SAdrien Destugues void
SetDateTimeFormat(BDateFormatStyle dateStyle,BTimeFormatStyle timeStyle,int32 elements)534a3a4742SAdrien Destugues BDateTimeFormat::SetDateTimeFormat(BDateFormatStyle dateStyle,
544a3a4742SAdrien Destugues 	BTimeFormatStyle timeStyle, int32 elements) {
554a3a4742SAdrien Destugues 	UErrorCode error = U_ZERO_ERROR;
564a3a4742SAdrien Destugues 	DateTimePatternGenerator* generator
57bb2a5b4dSAdrien Destugues 		= DateTimePatternGenerator::createInstance(
58bb2a5b4dSAdrien Destugues 			*BLanguage::Private(&fLanguage).ICULocale(), error);
594a3a4742SAdrien Destugues 
604a3a4742SAdrien Destugues 	BString skeleton;
614a3a4742SAdrien Destugues 	if (elements & B_DATE_ELEMENT_YEAR)
624a3a4742SAdrien Destugues 		skeleton << "yyyy";
634a3a4742SAdrien Destugues 	if (elements & B_DATE_ELEMENT_MONTH)
644a3a4742SAdrien Destugues 		skeleton << "MM";
654a3a4742SAdrien Destugues 	if (elements & B_DATE_ELEMENT_WEEKDAY)
664a3a4742SAdrien Destugues 		skeleton << "eee";
674a3a4742SAdrien Destugues 	if (elements & B_DATE_ELEMENT_DAY)
684a3a4742SAdrien Destugues 		skeleton << "dd";
694a3a4742SAdrien Destugues 	if (elements & B_DATE_ELEMENT_AM_PM)
704a3a4742SAdrien Destugues 		skeleton << "a";
71824cb460SAdrien Destugues 	if (elements & B_DATE_ELEMENT_HOUR) {
72824cb460SAdrien Destugues 		if (fConventions.Use24HourClock())
73bb2a5b4dSAdrien Destugues 			skeleton << "k";
74824cb460SAdrien Destugues 		else
75bb2a5b4dSAdrien Destugues 			skeleton << "K";
76824cb460SAdrien Destugues 	}
774a3a4742SAdrien Destugues 	if (elements & B_DATE_ELEMENT_MINUTE)
784a3a4742SAdrien Destugues 		skeleton << "mm";
794a3a4742SAdrien Destugues 	if (elements & B_DATE_ELEMENT_SECOND)
804a3a4742SAdrien Destugues 		skeleton << "ss";
814a3a4742SAdrien Destugues 	if (elements & B_DATE_ELEMENT_TIMEZONE)
82892f3b8bSAdrien Destugues 		skeleton << "z";
834a3a4742SAdrien Destugues 
844a3a4742SAdrien Destugues 	UnicodeString pattern = generator->getBestPattern(
854a3a4742SAdrien Destugues 		UnicodeString::fromUTF8(skeleton.String()), error);
864a3a4742SAdrien Destugues 
874a3a4742SAdrien Destugues 	BString buffer;
884a3a4742SAdrien Destugues 	BStringByteSink stringConverter(&buffer);
894a3a4742SAdrien Destugues 	pattern.toUTF8(stringConverter);
90bb2a5b4dSAdrien Destugues 
914a3a4742SAdrien Destugues 	fConventions.SetExplicitDateTimeFormat(dateStyle, timeStyle, buffer);
924a3a4742SAdrien Destugues 
934a3a4742SAdrien Destugues 	delete generator;
944a3a4742SAdrien Destugues }
954a3a4742SAdrien Destugues 
964a3a4742SAdrien Destugues 
97e3857211SAdrien Destugues // #pragma mark - Formatting
98e3857211SAdrien Destugues 
99e3857211SAdrien Destugues 
100e3857211SAdrien Destugues ssize_t
Format(char * target,size_t maxSize,time_t time,BDateFormatStyle dateStyle,BTimeFormatStyle timeStyle) const101e3857211SAdrien Destugues BDateTimeFormat::Format(char* target, size_t maxSize, time_t time,
102e3857211SAdrien Destugues 	BDateFormatStyle dateStyle, BTimeFormatStyle timeStyle) const
10338ac8defSOliver Tappe {
104e3857211SAdrien Destugues 	BString format;
1054a3a4742SAdrien Destugues 	fConventions.GetDateTimeFormat(dateStyle, timeStyle, format);
1064a3a4742SAdrien Destugues 	ObjectDeleter<DateFormat> dateFormatter(_CreateDateTimeFormatter(format));
107*779ab335SX512 	if (!dateFormatter.IsSet())
108e3857211SAdrien Destugues 		return B_NO_MEMORY;
109e3857211SAdrien Destugues 
110e3857211SAdrien Destugues 	UnicodeString icuString;
111e3857211SAdrien Destugues 	dateFormatter->format((UDate)time * 1000, icuString);
112e3857211SAdrien Destugues 
113e3857211SAdrien Destugues 	CheckedArrayByteSink stringConverter(target, maxSize);
114e3857211SAdrien Destugues 	icuString.toUTF8(stringConverter);
115e3857211SAdrien Destugues 
116e3857211SAdrien Destugues 	if (stringConverter.Overflowed())
117e3857211SAdrien Destugues 		return B_BAD_VALUE;
118e3857211SAdrien Destugues 
119e3857211SAdrien Destugues 	return stringConverter.NumberOfBytesWritten();
120e3857211SAdrien Destugues }
121e3857211SAdrien Destugues 
122e3857211SAdrien Destugues 
123e3857211SAdrien Destugues status_t
Format(BString & target,const time_t time,BDateFormatStyle dateStyle,BTimeFormatStyle timeStyle,const BTimeZone * timeZone) const124e3857211SAdrien Destugues BDateTimeFormat::Format(BString& target, const time_t time,
125e3857211SAdrien Destugues 	BDateFormatStyle dateStyle, BTimeFormatStyle timeStyle,
126e3857211SAdrien Destugues 	const BTimeZone* timeZone) const
127e3857211SAdrien Destugues {
128e3857211SAdrien Destugues 	BString format;
1294a3a4742SAdrien Destugues 	fConventions.GetDateTimeFormat(dateStyle, timeStyle, format);
1304a3a4742SAdrien Destugues 	ObjectDeleter<DateFormat> dateFormatter(_CreateDateTimeFormatter(format));
131*779ab335SX512 	if (!dateFormatter.IsSet())
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()));
137*779ab335SX512 		if (!icuTimeZone.IsSet())
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*
_CreateDateTimeFormatter(const BString & format) const1544a3a4742SAdrien 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