xref: /haiku/src/kits/locale/TimeUnitFormat.cpp (revision 9642f7705b27e5c270c15fa526d14e1848c2c27d)
1 /*
2  * Copyright 2010, Haiku, Inc. All Rights Reserved.
3  * Distributed under the terms of the MIT License.
4  *
5  * Authors:
6  * 		Adrien Destugues <pulkomandy@gmail.com>
7  *		Oliver Tappe <zooey@hirschkaefer.de>
8  */
9 
10 
11 #include <unicode/uversion.h>
12 #include <TimeUnitFormat.h>
13 
14 #include <new>
15 
16 #include <unicode/format.h>
17 #include <unicode/locid.h>
18 #include <unicode/tmutfmt.h>
19 #include <unicode/utypes.h>
20 #include <ICUWrapper.h>
21 
22 #include <Language.h>
23 #include <Locale.h>
24 #include <LocaleRoster.h>
25 
26 // maps our unit element to the corresponding ICU unit
27 static const TimeUnit::UTimeUnitFields skUnitMap[] = {
28 	TimeUnit::UTIMEUNIT_YEAR,
29 	TimeUnit::UTIMEUNIT_MONTH,
30 	TimeUnit::UTIMEUNIT_WEEK,
31 	TimeUnit::UTIMEUNIT_DAY,
32 	TimeUnit::UTIMEUNIT_HOUR,
33 	TimeUnit::UTIMEUNIT_MINUTE,
34 	TimeUnit::UTIMEUNIT_SECOND,
35 };
36 
37 //maps our unit style to the corresponding ICU unit
38 static const UTimeUnitFormatStyle kTimeUnitStyleToICU[] = {
39 	UTMUTFMT_ABBREVIATED_STYLE,
40 	UTMUTFMT_FULL_STYLE,
41 };
42 
43 
44 BTimeUnitFormat::BTimeUnitFormat(const time_unit_style style)
45 	: Inherited()
46 {
47 	Locale icuLocale(fLanguage.Code());
48 	UErrorCode icuStatus = U_ZERO_ERROR;
49 	if (style != B_TIME_UNIT_ABBREVIATED && style != B_TIME_UNIT_FULL) {
50 		fFormatter = NULL;
51 		fInitStatus = B_BAD_VALUE;
52 		return;
53 	}
54 
55 	fFormatter = new TimeUnitFormat(icuLocale, kTimeUnitStyleToICU[style],
56 		icuStatus);
57 	if (fFormatter == NULL) {
58 		fInitStatus = B_NO_MEMORY;
59 		return;
60 	}
61 
62 	if (!U_SUCCESS(icuStatus))
63 		fInitStatus = B_ERROR;
64 }
65 
66 
67 BTimeUnitFormat::BTimeUnitFormat(const BLanguage& language,
68 	const BFormattingConventions& conventions,
69 	const time_unit_style style)
70 	: Inherited(language, conventions)
71 {
72 	Locale icuLocale(fLanguage.Code());
73 	UErrorCode icuStatus = U_ZERO_ERROR;
74 	if (style != B_TIME_UNIT_ABBREVIATED && style != B_TIME_UNIT_FULL) {
75 		fFormatter = NULL;
76 		fInitStatus = B_BAD_VALUE;
77 		return;
78 	}
79 
80 	fFormatter = new TimeUnitFormat(icuLocale, kTimeUnitStyleToICU[style],
81 		icuStatus);
82 	if (fFormatter == NULL) {
83 		fInitStatus = B_NO_MEMORY;
84 		return;
85 	}
86 
87 	if (!U_SUCCESS(icuStatus))
88 		fInitStatus = B_ERROR;
89 }
90 
91 
92 BTimeUnitFormat::BTimeUnitFormat(const BTimeUnitFormat& other)
93 	:
94 	Inherited(other),
95 	fFormatter(other.fFormatter != NULL
96 		? new TimeUnitFormat(*other.fFormatter) : NULL)
97 {
98 	if (fFormatter == NULL && other.fFormatter != NULL)
99 		fInitStatus = B_NO_MEMORY;
100 }
101 
102 
103 BTimeUnitFormat::~BTimeUnitFormat()
104 {
105 	delete fFormatter;
106 }
107 
108 
109 status_t
110 BTimeUnitFormat::Format(BString& buffer, const int32 value,
111 	const time_unit_element unit) const
112 {
113 	if (unit < 0 || unit > B_TIME_UNIT_LAST)
114 		return B_BAD_VALUE;
115 
116 	if (fFormatter == NULL)
117 		return B_NO_INIT;
118 
119 	UErrorCode icuStatus = U_ZERO_ERROR;
120 	TimeUnitAmount* timeUnitAmount
121 		= new TimeUnitAmount((double)value, skUnitMap[unit], icuStatus);
122 	if (timeUnitAmount == NULL)
123 		return B_NO_MEMORY;
124 	if (!U_SUCCESS(icuStatus))
125 		return B_ERROR;
126 
127 	Formattable formattable;
128 	formattable.adoptObject(timeUnitAmount);
129 	FieldPosition pos(FieldPosition::DONT_CARE);
130 	UnicodeString unicodeResult;
131 	fFormatter->format(formattable, unicodeResult, pos, icuStatus);
132 	if (!U_SUCCESS(icuStatus))
133 		return B_ERROR;
134 
135 	BStringByteSink byteSink(&buffer);
136 	unicodeResult.toUTF8(byteSink);
137 
138 	return B_OK;
139 }
140