blob: 9cf79d7b4ac427982536bd8326cc736a35830cc4 [file] [log] [blame]
Jungshik Shin87232d82017-05-13 21:10:13 -07001// © 2016 and later: Unicode, Inc. and others.
Jungshik Shin5feb9ad2016-10-21 12:52:48 -07002// License & terms of use: http://www.unicode.org/copyright.html
jshin@chromium.org6f31ac32014-03-26 22:15:14 +00003/*
4********************************************************************************
Jungshik Shin70f82502016-01-29 00:32:36 -08005* Copyright (C) 2005-2015, International Business Machines
jshin@chromium.org6f31ac32014-03-26 22:15:14 +00006* Corporation and others. All Rights Reserved.
7********************************************************************************
8*
9* File WINTZ.CPP
10*
11********************************************************************************
12*/
13
14#include "unicode/utypes.h"
15
Jungshik Shinccad4472018-10-09 00:22:00 -070016#if U_PLATFORM_HAS_WIN32_API
jshin@chromium.org6f31ac32014-03-26 22:15:14 +000017
18#include "wintz.h"
19#include "cmemory.h"
20#include "cstring.h"
21
jshin@chromium.org6f31ac32014-03-26 22:15:14 +000022#include "unicode/ures.h"
Jungshik Shin (jungshik at google)0f8746a2015-01-08 15:46:45 -080023#include "unicode/ustring.h"
Jungshik Shinccad4472018-10-09 00:22:00 -070024#include "uresimp.h"
jshin@chromium.org6f31ac32014-03-26 22:15:14 +000025
Jungshik Shin87232d82017-05-13 21:10:13 -070026#ifndef WIN32_LEAN_AND_MEAN
jshin@chromium.org6f31ac32014-03-26 22:15:14 +000027# define WIN32_LEAN_AND_MEAN
Jungshik Shin87232d82017-05-13 21:10:13 -070028#endif
jshin@chromium.org6f31ac32014-03-26 22:15:14 +000029# define VC_EXTRALEAN
30# define NOUSER
31# define NOSERVICE
32# define NOIME
33# define NOMCX
34#include <windows.h>
35
Jungshik Shinccad4472018-10-09 00:22:00 -070036U_NAMESPACE_BEGIN
jshin@chromium.org6f31ac32014-03-26 22:15:14 +000037
Jungshik Shinccad4472018-10-09 00:22:00 -070038// The value of MAX_TIMEZONE_ID_LENGTH is 128, which is defined in DYNAMIC_TIME_ZONE_INFORMATION
39#define MAX_TIMEZONE_ID_LENGTH 128
jshin@chromium.org6f31ac32014-03-26 22:15:14 +000040
41/**
Jungshik Shinccad4472018-10-09 00:22:00 -070042* Main Windows time zone detection function.
43* Returns the Windows time zone converted to an ICU time zone as a heap-allocated buffer, or nullptr upon failure.
44* Note: We use the Win32 API GetDynamicTimeZoneInformation to get the current time zone info.
45* This API returns a non-localized time zone name, which we can then map to an ICU time zone name.
jshin@chromium.org6f31ac32014-03-26 22:15:14 +000046*/
jshin@chromium.org6f31ac32014-03-26 22:15:14 +000047U_CFUNC const char* U_EXPORT2
Jungshik Shinccad4472018-10-09 00:22:00 -070048uprv_detectWindowsTimeZone()
Jungshik Shin87232d82017-05-13 21:10:13 -070049{
jshin@chromium.org6f31ac32014-03-26 22:15:14 +000050 UErrorCode status = U_ZERO_ERROR;
Jungshik Shinccad4472018-10-09 00:22:00 -070051 char* icuid = nullptr;
52 char dynamicTZKeyName[MAX_TIMEZONE_ID_LENGTH];
53 char tmpid[MAX_TIMEZONE_ID_LENGTH];
jshin@chromium.org6f31ac32014-03-26 22:15:14 +000054 int32_t len;
Jungshik Shinccad4472018-10-09 00:22:00 -070055 int id = GEOID_NOT_AVAILABLE;
jshin@chromium.org6f31ac32014-03-26 22:15:14 +000056 int errorCode;
Jungshik Shinccad4472018-10-09 00:22:00 -070057 wchar_t ISOcodeW[3] = {}; /* 2 letter ISO code in UTF-16 */
58 char ISOcode[3] = {}; /* 2 letter ISO code in UTF-8 */
jshin@chromium.org6f31ac32014-03-26 22:15:14 +000059
Jungshik Shinccad4472018-10-09 00:22:00 -070060 DYNAMIC_TIME_ZONE_INFORMATION dynamicTZI;
61 uprv_memset(&dynamicTZI, 0, sizeof(dynamicTZI));
62 uprv_memset(dynamicTZKeyName, 0, sizeof(dynamicTZKeyName));
63 uprv_memset(tmpid, 0, sizeof(tmpid));
jshin@chromium.org6f31ac32014-03-26 22:15:14 +000064
Jungshik Shinccad4472018-10-09 00:22:00 -070065 /* Obtain TIME_ZONE_INFORMATION from the API and get the non-localized time zone name. */
66 if (TIME_ZONE_ID_INVALID == GetDynamicTimeZoneInformation(&dynamicTZI)) {
67 return nullptr;
68 }
jshin@chromium.org6f31ac32014-03-26 22:15:14 +000069
70 id = GetUserGeoID(GEOCLASS_NATION);
Jungshik Shin87232d82017-05-13 21:10:13 -070071 errorCode = GetGeoInfoW(id, GEO_ISO2, ISOcodeW, 3, 0);
jshin@chromium.org6f31ac32014-03-26 22:15:14 +000072
Jungshik Shinccad4472018-10-09 00:22:00 -070073 // convert from wchar_t* (UTF-16 on Windows) to char* (UTF-8).
74 u_strToUTF8(ISOcode, UPRV_LENGTHOF(ISOcode), nullptr,
75 reinterpret_cast<const UChar*>(ISOcodeW), UPRV_LENGTHOF(ISOcodeW), &status);
jshin@chromium.org6f31ac32014-03-26 22:15:14 +000076
Jungshik Shinccad4472018-10-09 00:22:00 -070077 LocalUResourceBundlePointer bundle(ures_openDirect(nullptr, "windowsZones", &status));
78 ures_getByKey(bundle.getAlias(), "mapTimezones", bundle.getAlias(), &status);
79
80 // convert from wchar_t* (UTF-16 on Windows) to char* (UTF-8).
81 u_strToUTF8(dynamicTZKeyName, UPRV_LENGTHOF(dynamicTZKeyName), nullptr,
82 reinterpret_cast<const UChar*>(dynamicTZI.TimeZoneKeyName), UPRV_LENGTHOF(dynamicTZI.TimeZoneKeyName), &status);
83
84 if (U_FAILURE(status)) {
85 return nullptr;
86 }
87
88 if (dynamicTZI.TimeZoneKeyName[0] != 0) {
89 UResourceBundle winTZ;
90 ures_initStackObject(&winTZ);
91 ures_getByKey(bundle.getAlias(), dynamicTZKeyName, &winTZ, &status);
92
93 if (U_SUCCESS(status)) {
94 const UChar* icuTZ = nullptr;
95 if (errorCode != 0) {
96 icuTZ = ures_getStringByKey(&winTZ, ISOcode, &len, &status);
jshin@chromium.org6f31ac32014-03-26 22:15:14 +000097 }
Jungshik Shinccad4472018-10-09 00:22:00 -070098 if (errorCode == 0 || icuTZ == nullptr) {
Jungshik Shin87232d82017-05-13 21:10:13 -070099 /* fallback to default "001" and reset status */
100 status = U_ZERO_ERROR;
Jungshik Shinccad4472018-10-09 00:22:00 -0700101 icuTZ = ures_getStringByKey(&winTZ, "001", &len, &status);
Jungshik Shin87232d82017-05-13 21:10:13 -0700102 }
103
Jungshik Shinccad4472018-10-09 00:22:00 -0700104 if (U_SUCCESS(status)) {
105 int index = 0;
106
107 while (!(*icuTZ == '\0' || *icuTZ == ' ')) {
108 // time zone IDs only contain ASCII invariant characters.
109 tmpid[index++] = (char)(*icuTZ++);
Jungshik Shin87232d82017-05-13 21:10:13 -0700110 }
Jungshik Shinccad4472018-10-09 00:22:00 -0700111 tmpid[index] = '\0';
Jungshik Shin87232d82017-05-13 21:10:13 -0700112 }
jshin@chromium.org6f31ac32014-03-26 22:15:14 +0000113 }
Jungshik Shinccad4472018-10-09 00:22:00 -0700114 ures_close(&winTZ);
Jungshik Shin (jungshik at google)0f8746a2015-01-08 15:46:45 -0800115 }
116
Jungshik Shinccad4472018-10-09 00:22:00 -0700117 // Copy the timezone ID to icuid to be returned.
118 if (tmpid[0] != 0) {
119 icuid = uprv_strdup(tmpid);
jshin@chromium.org6f31ac32014-03-26 22:15:14 +0000120 }
121
jshin@chromium.org6f31ac32014-03-26 22:15:14 +0000122 return icuid;
123}
124
Jungshik Shinccad4472018-10-09 00:22:00 -0700125U_NAMESPACE_END
126#endif /* U_PLATFORM_HAS_WIN32_API */