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
27U_NAMESPACE_USE
28
29
30// maps our unit element to the corresponding ICU unit
31static const TimeUnit::UTimeUnitFields skUnitMap[] = {
32	TimeUnit::UTIMEUNIT_YEAR,
33	TimeUnit::UTIMEUNIT_MONTH,
34	TimeUnit::UTIMEUNIT_WEEK,
35	TimeUnit::UTIMEUNIT_DAY,
36	TimeUnit::UTIMEUNIT_HOUR,
37	TimeUnit::UTIMEUNIT_MINUTE,
38	TimeUnit::UTIMEUNIT_SECOND,
39};
40
41//maps our unit style to the corresponding ICU unit
42static const UTimeUnitFormatStyle kTimeUnitStyleToICU[] = {
43	UTMUTFMT_ABBREVIATED_STYLE,
44	UTMUTFMT_FULL_STYLE,
45};
46
47
48BTimeUnitFormat::BTimeUnitFormat(const time_unit_style style)
49	: Inherited()
50{
51	Locale icuLocale(fLanguage.Code());
52	UErrorCode icuStatus = U_ZERO_ERROR;
53	if (style != B_TIME_UNIT_ABBREVIATED && style != B_TIME_UNIT_FULL) {
54		fFormatter = NULL;
55		fInitStatus = B_BAD_VALUE;
56		return;
57	}
58
59	fFormatter = new TimeUnitFormat(icuLocale, kTimeUnitStyleToICU[style],
60		icuStatus);
61	if (fFormatter == NULL) {
62		fInitStatus = B_NO_MEMORY;
63		return;
64	}
65
66	if (!U_SUCCESS(icuStatus))
67		fInitStatus = B_ERROR;
68}
69
70
71BTimeUnitFormat::BTimeUnitFormat(const BLanguage& language,
72	const BFormattingConventions& conventions,
73	const time_unit_style style)
74	: Inherited(language, conventions)
75{
76	Locale icuLocale(fLanguage.Code());
77	UErrorCode icuStatus = U_ZERO_ERROR;
78	if (style != B_TIME_UNIT_ABBREVIATED && style != B_TIME_UNIT_FULL) {
79		fFormatter = NULL;
80		fInitStatus = B_BAD_VALUE;
81		return;
82	}
83
84	fFormatter = new TimeUnitFormat(icuLocale, kTimeUnitStyleToICU[style],
85		icuStatus);
86	if (fFormatter == NULL) {
87		fInitStatus = B_NO_MEMORY;
88		return;
89	}
90
91	if (!U_SUCCESS(icuStatus))
92		fInitStatus = B_ERROR;
93}
94
95
96BTimeUnitFormat::BTimeUnitFormat(const BTimeUnitFormat& other)
97	:
98	Inherited(other),
99	fFormatter(other.fFormatter != NULL
100		? new TimeUnitFormat(*other.fFormatter) : NULL)
101{
102	if (fFormatter == NULL && other.fFormatter != NULL)
103		fInitStatus = B_NO_MEMORY;
104}
105
106
107BTimeUnitFormat::~BTimeUnitFormat()
108{
109	delete fFormatter;
110}
111
112
113status_t
114BTimeUnitFormat::Format(BString& buffer, const int32 value,
115	const time_unit_element unit) const
116{
117	if (unit < 0 || unit > B_TIME_UNIT_LAST)
118		return B_BAD_VALUE;
119
120	if (fFormatter == NULL)
121		return B_NO_INIT;
122
123	UErrorCode icuStatus = U_ZERO_ERROR;
124	TimeUnitAmount* timeUnitAmount
125		= new TimeUnitAmount((double)value, skUnitMap[unit], icuStatus);
126	if (timeUnitAmount == NULL)
127		return B_NO_MEMORY;
128	if (!U_SUCCESS(icuStatus)) {
129		delete timeUnitAmount;
130		return B_ERROR;
131	}
132
133	Formattable formattable;
134	formattable.adoptObject(timeUnitAmount);
135	FieldPosition pos(FieldPosition::DONT_CARE);
136	UnicodeString unicodeResult;
137	fFormatter->format(formattable, unicodeResult, pos, icuStatus);
138	if (!U_SUCCESS(icuStatus))
139		return B_ERROR;
140
141	BStringByteSink byteSink(&buffer);
142	unicodeResult.toUTF8(byteSink);
143
144	return B_OK;
145}
146