* Copyright 2010, Haiku, Inc. All Rights Reserved.
* Distributed under the terms of the MIT License.
*
* Authors:
* Oliver Tappe <zooey@hirschkaefer.de>
*/
#include <unicode/uversion.h>
#include <DurationFormat.h>
#include <new>
#include <unicode/gregocal.h>
#include <unicode/utypes.h>
#include <Locale.h>
#include <LocaleRoster.h>
#include <TimeZone.h>
#include <TimeZonePrivate.h>
U_NAMESPACE_USE
static const UCalendarDateFields skUnitMap[] = {
UCAL_YEAR,
UCAL_MONTH,
UCAL_WEEK_OF_MONTH,
UCAL_DAY_OF_WEEK,
UCAL_HOUR_OF_DAY,
UCAL_MINUTE,
UCAL_SECOND,
};
BDurationFormat::BDurationFormat(const BLanguage& language,
const BFormattingConventions& conventions,
const BString& separator, const time_unit_style style)
:
Inherited(language, conventions),
fSeparator(separator),
fTimeUnitFormat(language, conventions, style)
{
UErrorCode icuStatus = U_ZERO_ERROR;
fCalendar = new GregorianCalendar(icuStatus);
if (fCalendar == NULL) {
fInitStatus = B_NO_MEMORY;
return;
}
}
BDurationFormat::BDurationFormat(const BString& separator,
const time_unit_style style)
:
Inherited(),
fSeparator(separator),
fTimeUnitFormat(style)
{
UErrorCode icuStatus = U_ZERO_ERROR;
fCalendar = new GregorianCalendar(icuStatus);
if (fCalendar == NULL) {
fInitStatus = B_NO_MEMORY;
return;
}
}
BDurationFormat::BDurationFormat(const BDurationFormat& other)
:
Inherited(other),
fSeparator(other.fSeparator),
fTimeUnitFormat(other.fTimeUnitFormat),
fCalendar(other.fCalendar != NULL
? new GregorianCalendar(*other.fCalendar) : NULL)
{
if (fCalendar == NULL && other.fCalendar != NULL)
fInitStatus = B_NO_MEMORY;
}
BDurationFormat::~BDurationFormat()
{
delete fCalendar;
}
void
BDurationFormat::SetSeparator(const BString& separator)
{
fSeparator = separator;
}
status_t
BDurationFormat::SetTimeZone(const BTimeZone* timeZone)
{
if (fCalendar == NULL)
return B_NO_INIT;
BTimeZone::Private zonePrivate;
if (timeZone == NULL) {
BTimeZone defaultTimeZone;
status_t result
= BLocaleRoster::Default()->GetDefaultTimeZone(&defaultTimeZone);
if (result != B_OK)
return result;
zonePrivate.SetTo(&defaultTimeZone);
} else
zonePrivate.SetTo(timeZone);
TimeZone* icuTimeZone = zonePrivate.ICUTimeZone();
if (icuTimeZone != NULL)
fCalendar->setTimeZone(*icuTimeZone);
return B_OK;
}
status_t
BDurationFormat::Format(BString& buffer, const bigtime_t startValue,
const bigtime_t stopValue) const
{
UErrorCode icuStatus = U_ZERO_ERROR;
fCalendar->setTime((UDate)startValue / 1000, icuStatus);
if (!U_SUCCESS(icuStatus))
return B_ERROR;
UDate stop = (UDate)stopValue / 1000;
bool needSeparator = false;
for (int unit = 0; unit <= B_TIME_UNIT_LAST; ++unit) {
int delta
= fCalendar->fieldDifference(stop, skUnitMap[unit], icuStatus);
if (!U_SUCCESS(icuStatus))
return B_ERROR;
if (delta != 0) {
if (needSeparator)
buffer.Append(fSeparator);
else
needSeparator = true;
status_t status = fTimeUnitFormat.Format(buffer, delta,
(time_unit_element)unit);
if (status != B_OK)
return status;
}
}
return B_OK;
}