#include "unicode/utypes.h"
#if U_PLATFORM_USES_ONLY_WIN32_API && !UCONFIG_NO_FORMATTING
#include "wintzimpl.h"
#include "unicode/unistr.h"
#include "unicode/timezone.h"
#include "unicode/basictz.h"
#include "putilimp.h"
#include "uassert.h"
#include "cmemory.h"
#ifndef WIN32_LEAN_AND_MEAN
#define WIN32_LEAN_AND_MEAN
#endif
#define VC_EXTRALEAN
#define NOUSER
#define NOSERVICE
#define NOIME
#define NOMCX
#include <windows.h>
U_NAMESPACE_USE
static UBool getSystemTimeInformation(TimeZone *tz, SYSTEMTIME &daylightDate, SYSTEMTIME &standardDate, int32_t &bias, int32_t &daylightBias, int32_t &standardBias) {
UErrorCode status = U_ZERO_ERROR;
UBool result = true;
BasicTimeZone *btz = (BasicTimeZone*)tz;
InitialTimeZoneRule *initial = nullptr;
AnnualTimeZoneRule *std = nullptr, *dst = nullptr;
btz->getSimpleRulesNear(uprv_getUTCtime(), initial, std, dst, status);
if (U_SUCCESS(status)) {
if (std == nullptr || dst == nullptr) {
bias = -1 * (initial->getRawOffset()/60000);
standardBias = 0;
daylightBias = 0;
standardDate.wYear = standardDate.wMonth = standardDate.wDayOfWeek = standardDate.wDay =
standardDate.wHour = standardDate.wMinute = standardDate.wSecond = standardDate.wMilliseconds = 0;
daylightDate.wYear = daylightDate.wMonth = daylightDate.wDayOfWeek = daylightDate.wDay =
daylightDate.wHour = daylightDate.wMinute = daylightDate.wSecond = daylightDate.wMilliseconds = 0;
} else {
U_ASSERT(std->getRule()->getDateRuleType() == DateTimeRule::DOW);
U_ASSERT(dst->getRule()->getDateRuleType() == DateTimeRule::DOW);
bias = -1 * (std->getRawOffset()/60000);
standardBias = 0;
daylightBias = -1 * (dst->getDSTSavings()/60000);
int32_t hour, min, sec, mil;
standardDate.wYear = 0;
standardDate.wMonth = static_cast<WORD>(std->getRule()->getRuleMonth()) + 1;
standardDate.wDay = static_cast<WORD>(std->getRule()->getRuleWeekInMonth());
if (standardDate.wDay < 0) {
standardDate.wDay = 5;
}
standardDate.wDayOfWeek = static_cast<WORD>(std->getRule()->getRuleDayOfWeek()) - 1;
mil = std->getRule()->getRuleMillisInDay();
hour = mil/3600000;
mil %= 3600000;
min = mil/60000;
mil %= 60000;
sec = mil/1000;
mil %= 1000;
standardDate.wHour = static_cast<WORD>(hour);
standardDate.wMinute = static_cast<WORD>(min);
standardDate.wSecond = static_cast<WORD>(sec);
standardDate.wMilliseconds = static_cast<WORD>(mil);
daylightDate.wYear = 0;
daylightDate.wMonth = static_cast<WORD>(dst->getRule()->getRuleMonth()) + 1;
daylightDate.wDay = static_cast<WORD>(dst->getRule()->getRuleWeekInMonth());
if (daylightDate.wDay < 0) {
daylightDate.wDay = 5;
}
daylightDate.wDayOfWeek = static_cast<WORD>(dst->getRule()->getRuleDayOfWeek()) - 1;
mil = dst->getRule()->getRuleMillisInDay();
hour = mil/3600000;
mil %= 3600000;
min = mil/60000;
mil %= 60000;
sec = mil/1000;
mil %= 1000;
daylightDate.wHour = static_cast<WORD>(hour);
daylightDate.wMinute = static_cast<WORD>(min);
daylightDate.wSecond = static_cast<WORD>(sec);
daylightDate.wMilliseconds = static_cast<WORD>(mil);
}
} else {
result = false;
}
delete initial;
delete std;
delete dst;
return result;
}
static UBool getWindowsTimeZoneInfo(TIME_ZONE_INFORMATION *zoneInfo, const char16_t *icuid, int32_t length) {
UBool result = false;
UnicodeString id = UnicodeString(icuid, length);
TimeZone *tz = TimeZone::createTimeZone(id);
if (tz != nullptr) {
int32_t bias;
int32_t daylightBias;
int32_t standardBias;
SYSTEMTIME daylightDate;
SYSTEMTIME standardDate;
if (getSystemTimeInformation(tz, daylightDate, standardDate, bias, daylightBias, standardBias)) {
uprv_memset(zoneInfo, 0, sizeof(TIME_ZONE_INFORMATION));
zoneInfo->Bias = bias;
zoneInfo->DaylightBias = daylightBias;
zoneInfo->StandardBias = standardBias;
zoneInfo->DaylightDate = daylightDate;
zoneInfo->StandardDate = standardDate;
result = true;
}
}
return result;
}
U_CAPI UBool U_EXPORT2
uprv_getWindowsTimeZoneInfo(TIME_ZONE_INFORMATION *zoneInfo, const char16_t *icuid, int32_t length)
{
if (getWindowsTimeZoneInfo(zoneInfo, icuid, length)) {
return true;
} else {
return false;
}
}
#endif