BPicture: Fix archive constructor.
[haiku.git] / src / kits / locale / TimeFormat.cpp
blob55cc534299524d6b295c32ec23412cda95f5285c
1 /*
2 * Copyright 2010-2014, Haiku, Inc. All Rights Reserved.
3 * Distributed under the terms of the MIT License.
5 * Authors:
6 * Oliver Tappe <zooey@hirschkaefer.de>
7 */
9 #include <unicode/uversion.h>
10 #include <TimeFormat.h>
12 #include <AutoDeleter.h>
13 #include <Autolock.h>
14 #include <DateTime.h>
15 #include <FormattingConventionsPrivate.h>
16 #include <LanguagePrivate.h>
17 #include <TimeZone.h>
19 #include <ICUWrapper.h>
21 #include <unicode/datefmt.h>
22 #include <unicode/smpdtfmt.h>
24 #include <vector>
27 BTimeFormat::BTimeFormat()
28 : BFormat()
33 BTimeFormat::BTimeFormat(const BLanguage& language,
34 const BFormattingConventions& conventions)
35 : BFormat(language, conventions)
40 BTimeFormat::BTimeFormat(const BTimeFormat &other)
41 : BFormat(other)
46 BTimeFormat::~BTimeFormat()
51 void
52 BTimeFormat::SetTimeFormat(BTimeFormatStyle style,
53 const BString& format)
55 fConventions.SetExplicitTimeFormat(style, format);
59 // #pragma mark - Formatting
62 ssize_t
63 BTimeFormat::Format(char* string, size_t maxSize, time_t time,
64 BTimeFormatStyle style) const
66 ObjectDeleter<DateFormat> timeFormatter(_CreateTimeFormatter(style));
67 if (timeFormatter.Get() == NULL)
68 return B_NO_MEMORY;
70 UnicodeString icuString;
71 timeFormatter->format((UDate)time * 1000, icuString);
73 CheckedArrayByteSink stringConverter(string, maxSize);
74 icuString.toUTF8(stringConverter);
76 if (stringConverter.Overflowed())
77 return B_BAD_VALUE;
79 return stringConverter.NumberOfBytesWritten();
83 status_t
84 BTimeFormat::Format(BString& string, const time_t time,
85 const BTimeFormatStyle style, const BTimeZone* timeZone) const
87 ObjectDeleter<DateFormat> timeFormatter(_CreateTimeFormatter(style));
88 if (timeFormatter.Get() == NULL)
89 return B_NO_MEMORY;
91 if (timeZone != NULL) {
92 ObjectDeleter<TimeZone> icuTimeZone(
93 TimeZone::createTimeZone(timeZone->ID().String()));
94 if (icuTimeZone.Get() == NULL)
95 return B_NO_MEMORY;
96 timeFormatter->setTimeZone(*icuTimeZone.Get());
99 UnicodeString icuString;
100 timeFormatter->format((UDate)time * 1000, icuString);
102 string.Truncate(0);
103 BStringByteSink stringConverter(&string);
104 icuString.toUTF8(stringConverter);
106 return B_OK;
110 status_t
111 BTimeFormat::Format(BString& string, int*& fieldPositions, int& fieldCount,
112 time_t time, BTimeFormatStyle style) const
114 ObjectDeleter<DateFormat> timeFormatter(_CreateTimeFormatter(style));
115 if (timeFormatter.Get() == NULL)
116 return B_NO_MEMORY;
118 fieldPositions = NULL;
119 UErrorCode error = U_ZERO_ERROR;
120 icu::FieldPositionIterator positionIterator;
121 UnicodeString icuString;
122 timeFormatter->format((UDate)time * 1000, icuString, &positionIterator,
123 error);
125 if (error != U_ZERO_ERROR)
126 return B_BAD_VALUE;
128 icu::FieldPosition field;
129 std::vector<int> fieldPosStorage;
130 fieldCount = 0;
131 while (positionIterator.next(field)) {
132 fieldPosStorage.push_back(field.getBeginIndex());
133 fieldPosStorage.push_back(field.getEndIndex());
134 fieldCount += 2;
137 fieldPositions = (int*) malloc(fieldCount * sizeof(int));
139 for (int i = 0 ; i < fieldCount ; i++ )
140 fieldPositions[i] = fieldPosStorage[i];
142 string.Truncate(0);
143 BStringByteSink stringConverter(&string);
144 icuString.toUTF8(stringConverter);
146 return B_OK;
150 status_t
151 BTimeFormat::GetTimeFields(BDateElement*& fields, int& fieldCount,
152 BTimeFormatStyle style) const
154 ObjectDeleter<DateFormat> timeFormatter(_CreateTimeFormatter(style));
155 if (timeFormatter.Get() == NULL)
156 return B_NO_MEMORY;
158 fields = NULL;
159 UErrorCode error = U_ZERO_ERROR;
160 icu::FieldPositionIterator positionIterator;
161 UnicodeString icuString;
162 time_t now;
163 timeFormatter->format((UDate)time(&now) * 1000, icuString,
164 &positionIterator, error);
166 if (error != U_ZERO_ERROR)
167 return B_BAD_VALUE;
169 icu::FieldPosition field;
170 std::vector<int> fieldPosStorage;
171 fieldCount = 0;
172 while (positionIterator.next(field)) {
173 fieldPosStorage.push_back(field.getField());
174 fieldCount ++;
177 fields = (BDateElement*) malloc(fieldCount * sizeof(BDateElement));
179 for (int i = 0 ; i < fieldCount ; i++ ) {
180 switch (fieldPosStorage[i]) {
181 case UDAT_HOUR_OF_DAY1_FIELD:
182 case UDAT_HOUR_OF_DAY0_FIELD:
183 case UDAT_HOUR1_FIELD:
184 case UDAT_HOUR0_FIELD:
185 fields[i] = B_DATE_ELEMENT_HOUR;
186 break;
187 case UDAT_MINUTE_FIELD:
188 fields[i] = B_DATE_ELEMENT_MINUTE;
189 break;
190 case UDAT_SECOND_FIELD:
191 fields[i] = B_DATE_ELEMENT_SECOND;
192 break;
193 case UDAT_AM_PM_FIELD:
194 fields[i] = B_DATE_ELEMENT_AM_PM;
195 break;
196 default:
197 fields[i] = B_DATE_ELEMENT_INVALID;
198 break;
202 return B_OK;
206 status_t
207 BTimeFormat::Parse(BString source, BTimeFormatStyle style, BTime& output)
209 ObjectDeleter<DateFormat> timeFormatter(_CreateTimeFormatter(style));
210 if (timeFormatter.Get() == NULL)
211 return B_NO_MEMORY;
213 // If no timezone is specified in the time string, assume GMT
214 timeFormatter->setTimeZone(*icu::TimeZone::getGMT());
216 ParsePosition p(0);
217 UDate date = timeFormatter->parse(UnicodeString::fromUTF8(source.String()),
220 output.SetTime(0, 0, 0);
221 output.AddMilliseconds(date);
223 return B_OK;
227 DateFormat*
228 BTimeFormat::_CreateTimeFormatter(const BTimeFormatStyle style) const
230 Locale* icuLocale
231 = fConventions.UseStringsFromPreferredLanguage()
232 ? BLanguage::Private(&fLanguage).ICULocale()
233 : BFormattingConventions::Private(&fConventions).ICULocale();
235 icu::DateFormat* timeFormatter
236 = icu::DateFormat::createTimeInstance(DateFormat::kShort, *icuLocale);
237 if (timeFormatter == NULL)
238 return NULL;
240 SimpleDateFormat* timeFormatterImpl
241 = static_cast<SimpleDateFormat*>(timeFormatter);
243 BString format;
244 fConventions.GetTimeFormat(style, format);
246 UnicodeString pattern(format.String());
247 timeFormatterImpl->applyPattern(pattern);
249 return timeFormatter;