* Copyright (c) 2010, Haiku, Inc.
* Distributed under the terms of the MIT license.
*
* Authors:
* Adrien Destugues <pulkomandy@pulkomandy.ath.cx>
* Oliver Tappe <zooey@hirschkaefer.de>
*/
#include <unicode/uversion.h>
#include <TimeZone.h>
#include <new>
#include <unicode/locid.h>
#include <unicode/timezone.h>
#include <ICUWrapper.h>
#include <Language.h>
U_NAMESPACE_USE
const char* BTimeZone::kNameOfGmtZone = "GMT";
static const BString skEmptyString;
static const uint32 skNameField = 1U << 0;
static const uint32 skDaylightSavingNameField = 1U << 1;
static const uint32 skShortNameField = 1U << 2;
static const uint32 skShortDaylightSavingNameField = 1U << 3;
static const uint32 skLongGenericNameField = 1U << 4;
static const uint32 skGenericLocationNameField = 1U << 5;
static const uint32 skShortCommonlyUsedNameField = 1U << 6;
static const uint32 skSupportsDaylightSavingField = 1U << 7;
static const uint32 skOffsetFromGMTField = 1U << 8;
BTimeZone::BTimeZone(const char* zoneID, const BLanguage* language)
:
fICUTimeZone(NULL),
fICULocale(NULL),
fInitStatus(B_NO_INIT),
fInitializedFields(0)
{
SetTo(zoneID, language);
}
BTimeZone::BTimeZone(const BTimeZone& other)
:
fICUTimeZone(other.fICUTimeZone == NULL
? NULL
: other.fICUTimeZone->clone()),
fICULocale(other.fICULocale == NULL
? NULL
: other.fICULocale->clone()),
fInitStatus(other.fInitStatus),
fInitializedFields(other.fInitializedFields),
fZoneID(other.fZoneID),
fName(other.fName),
fDaylightSavingName(other.fDaylightSavingName),
fShortName(other.fShortName),
fShortDaylightSavingName(other.fShortDaylightSavingName),
fOffsetFromGMT(other.fOffsetFromGMT),
fSupportsDaylightSaving(other.fSupportsDaylightSaving)
{
}
BTimeZone::~BTimeZone()
{
delete fICULocale;
delete fICUTimeZone;
}
BTimeZone& BTimeZone::operator=(const BTimeZone& source)
{
delete fICUTimeZone;
fICUTimeZone = source.fICUTimeZone == NULL
? NULL
: source.fICUTimeZone->clone();
fICULocale = source.fICULocale == NULL
? NULL
: source.fICULocale->clone();
fInitStatus = source.fInitStatus;
fInitializedFields = source.fInitializedFields;
fZoneID = source.fZoneID;
fName = source.fName;
fDaylightSavingName = source.fDaylightSavingName;
fShortName = source.fShortName;
fShortDaylightSavingName = source.fShortDaylightSavingName;
fOffsetFromGMT = source.fOffsetFromGMT;
fSupportsDaylightSaving = source.fSupportsDaylightSaving;
return *this;
}
const BString&
BTimeZone::ID() const
{
return fZoneID;
}
const BString&
BTimeZone::Name() const
{
if ((fInitializedFields & skNameField) == 0) {
UnicodeString unicodeString;
if (fICULocale != NULL) {
fICUTimeZone->getDisplayName(false, TimeZone::GENERIC_LOCATION,
*fICULocale, unicodeString);
} else {
fICUTimeZone->getDisplayName(false, TimeZone::GENERIC_LOCATION,
unicodeString);
}
BStringByteSink sink(&fName);
unicodeString.toUTF8(sink);
fInitializedFields |= skNameField;
}
return fName;
}
const BString&
BTimeZone::DaylightSavingName() const
{
if ((fInitializedFields & skDaylightSavingNameField) == 0) {
UnicodeString unicodeString;
if (fICULocale != NULL) {
fICUTimeZone->getDisplayName(true, TimeZone::GENERIC_LOCATION,
*fICULocale, unicodeString);
} else {
fICUTimeZone->getDisplayName(true, TimeZone::GENERIC_LOCATION,
unicodeString);
}
BStringByteSink sink(&fDaylightSavingName);
unicodeString.toUTF8(sink);
fInitializedFields |= skDaylightSavingNameField;
}
return fDaylightSavingName;
}
const BString&
BTimeZone::ShortName() const
{
if ((fInitializedFields & skShortNameField) == 0) {
UnicodeString unicodeString;
if (fICULocale != NULL) {
fICUTimeZone->getDisplayName(false, TimeZone::SHORT, *fICULocale,
unicodeString);
} else {
fICUTimeZone->getDisplayName(false, TimeZone::SHORT, unicodeString);
}
BStringByteSink sink(&fShortName);
unicodeString.toUTF8(sink);
fInitializedFields |= skShortNameField;
}
return fShortName;
}
const BString&
BTimeZone::ShortDaylightSavingName() const
{
if ((fInitializedFields & skShortDaylightSavingNameField) == 0) {
UnicodeString unicodeString;
if (fICULocale != NULL) {
fICUTimeZone->getDisplayName(true, TimeZone::SHORT, *fICULocale,
unicodeString);
} else {
fICUTimeZone->getDisplayName(true, TimeZone::SHORT, unicodeString);
}
BStringByteSink sink(&fShortDaylightSavingName);
unicodeString.toUTF8(sink);
fInitializedFields |= skShortDaylightSavingNameField;
}
return fShortDaylightSavingName;
}
int
BTimeZone::OffsetFromGMT() const
{
if ((fInitializedFields & skOffsetFromGMTField) == 0) {
int32_t rawOffset;
int32_t dstOffset;
UDate nowMillis = 1000 * (double)time(NULL);
UErrorCode error = U_ZERO_ERROR;
fICUTimeZone->getOffset(nowMillis, FALSE, rawOffset, dstOffset, error);
if (!U_SUCCESS(error))
fOffsetFromGMT = 0;
else {
fOffsetFromGMT = (rawOffset + dstOffset) / 1000;
}
fInitializedFields |= skOffsetFromGMTField;
}
return fOffsetFromGMT;
}
bool
BTimeZone::SupportsDaylightSaving() const
{
if ((fInitializedFields & skSupportsDaylightSavingField) == 0) {
fSupportsDaylightSaving = fICUTimeZone->useDaylightTime();
fInitializedFields |= skSupportsDaylightSavingField;
}
return fSupportsDaylightSaving;
}
status_t
BTimeZone::InitCheck() const
{
return fInitStatus;
}
status_t
BTimeZone::SetLanguage(const BLanguage* language)
{
return SetTo(fZoneID, language);
}
status_t
BTimeZone::SetTo(const char* zoneID, const BLanguage* language)
{
delete fICULocale;
fICULocale = NULL;
delete fICUTimeZone;
fInitializedFields = 0;
if (zoneID == NULL || zoneID[0] == '\0')
fICUTimeZone = TimeZone::createDefault();
else
fICUTimeZone = TimeZone::createTimeZone(zoneID);
if (fICUTimeZone == NULL) {
fInitStatus = B_NAME_NOT_FOUND;
return fInitStatus;
}
if (language != NULL) {
fICULocale = new Locale(language->Code());
if (fICULocale == NULL) {
fInitStatus = B_NO_MEMORY;
return fInitStatus;
}
}
UnicodeString unicodeString;
fICUTimeZone->getID(unicodeString);
BStringByteSink sink(&fZoneID);
unicodeString.toUTF8(sink);
fInitStatus = B_OK;
return fInitStatus;
}