2 * Copyright 2010-2014, Haiku, Inc. All Rights Reserved.
3 * Distributed under the terms of the MIT License.
6 * Oliver Tappe <zooey@hirschkaefer.de>
9 #include <unicode/uversion.h>
10 #include <TimeFormat.h>
12 #include <AutoDeleter.h>
15 #include <FormattingConventionsPrivate.h>
16 #include <LanguagePrivate.h>
19 #include <ICUWrapper.h>
21 #include <unicode/datefmt.h>
22 #include <unicode/smpdtfmt.h>
27 BTimeFormat::BTimeFormat()
33 BTimeFormat::BTimeFormat(const BLanguage
& language
,
34 const BFormattingConventions
& conventions
)
35 : BFormat(language
, conventions
)
40 BTimeFormat::BTimeFormat(const BTimeFormat
&other
)
46 BTimeFormat::~BTimeFormat()
52 BTimeFormat::SetTimeFormat(BTimeFormatStyle style
,
53 const BString
& format
)
55 fConventions
.SetExplicitTimeFormat(style
, format
);
59 // #pragma mark - Formatting
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
)
70 UnicodeString icuString
;
71 timeFormatter
->format((UDate
)time
* 1000, icuString
);
73 CheckedArrayByteSink
stringConverter(string
, maxSize
);
74 icuString
.toUTF8(stringConverter
);
76 if (stringConverter
.Overflowed())
79 return stringConverter
.NumberOfBytesWritten();
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
)
91 if (timeZone
!= NULL
) {
92 ObjectDeleter
<TimeZone
> icuTimeZone(
93 TimeZone::createTimeZone(timeZone
->ID().String()));
94 if (icuTimeZone
.Get() == NULL
)
96 timeFormatter
->setTimeZone(*icuTimeZone
.Get());
99 UnicodeString icuString
;
100 timeFormatter
->format((UDate
)time
* 1000, icuString
);
103 BStringByteSink
stringConverter(&string
);
104 icuString
.toUTF8(stringConverter
);
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
)
118 fieldPositions
= NULL
;
119 UErrorCode error
= U_ZERO_ERROR
;
120 icu::FieldPositionIterator positionIterator
;
121 UnicodeString icuString
;
122 timeFormatter
->format((UDate
)time
* 1000, icuString
, &positionIterator
,
125 if (error
!= U_ZERO_ERROR
)
128 icu::FieldPosition field
;
129 std::vector
<int> fieldPosStorage
;
131 while (positionIterator
.next(field
)) {
132 fieldPosStorage
.push_back(field
.getBeginIndex());
133 fieldPosStorage
.push_back(field
.getEndIndex());
137 fieldPositions
= (int*) malloc(fieldCount
* sizeof(int));
139 for (int i
= 0 ; i
< fieldCount
; i
++ )
140 fieldPositions
[i
] = fieldPosStorage
[i
];
143 BStringByteSink
stringConverter(&string
);
144 icuString
.toUTF8(stringConverter
);
151 BTimeFormat::GetTimeFields(BDateElement
*& fields
, int& fieldCount
,
152 BTimeFormatStyle style
) const
154 ObjectDeleter
<DateFormat
> timeFormatter(_CreateTimeFormatter(style
));
155 if (timeFormatter
.Get() == NULL
)
159 UErrorCode error
= U_ZERO_ERROR
;
160 icu::FieldPositionIterator positionIterator
;
161 UnicodeString icuString
;
163 timeFormatter
->format((UDate
)time(&now
) * 1000, icuString
,
164 &positionIterator
, error
);
166 if (error
!= U_ZERO_ERROR
)
169 icu::FieldPosition field
;
170 std::vector
<int> fieldPosStorage
;
172 while (positionIterator
.next(field
)) {
173 fieldPosStorage
.push_back(field
.getField());
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
;
187 case UDAT_MINUTE_FIELD
:
188 fields
[i
] = B_DATE_ELEMENT_MINUTE
;
190 case UDAT_SECOND_FIELD
:
191 fields
[i
] = B_DATE_ELEMENT_SECOND
;
193 case UDAT_AM_PM_FIELD
:
194 fields
[i
] = B_DATE_ELEMENT_AM_PM
;
197 fields
[i
] = B_DATE_ELEMENT_INVALID
;
207 BTimeFormat::Parse(BString source
, BTimeFormatStyle style
, BTime
& output
)
209 ObjectDeleter
<DateFormat
> timeFormatter(_CreateTimeFormatter(style
));
210 if (timeFormatter
.Get() == NULL
)
213 // If no timezone is specified in the time string, assume GMT
214 timeFormatter
->setTimeZone(*icu::TimeZone::getGMT());
217 UDate date
= timeFormatter
->parse(UnicodeString::fromUTF8(source
.String()),
220 output
.SetTime(0, 0, 0);
221 output
.AddMilliseconds(date
);
228 BTimeFormat::_CreateTimeFormatter(const BTimeFormatStyle style
) const
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
)
240 SimpleDateFormat
* timeFormatterImpl
241 = static_cast<SimpleDateFormat
*>(timeFormatter
);
244 fConventions
.GetTimeFormat(style
, format
);
246 UnicodeString
pattern(format
.String());
247 timeFormatterImpl
->applyPattern(pattern
);
249 return timeFormatter
;