/*********************************************************************** * GetTimeZoneInformationForYear (KERNEL32.@) */ BOOL WINAPI GetTimeZoneInformationForYear( USHORT wYear, PDYNAMIC_TIME_ZONE_INFORMATION pdtzi, LPTIME_ZONE_INFORMATION ptzi ) { DYNAMIC_TIME_ZONE_INFORMATION local_dtzi, result; if (!pdtzi) { if (GetDynamicTimeZoneInformation(&local_dtzi) == TIME_ZONE_ID_INVALID) return FALSE; pdtzi = &local_dtzi; } if (!TIME_GetSpecificTimeZoneInfo(pdtzi->TimeZoneKeyName, wYear, !pdtzi->DynamicDaylightTimeDisabled, &result)) return FALSE; memcpy(ptzi, &result, sizeof(*ptzi)); return TRUE; }
/*********************************************************************** * TIMEZONE_InitRegistry * * Update registry contents on startup if the user timezone has changed. * This simulates the action of the Windows control panel. */ void TIMEZONE_InitRegistry(void) { static const WCHAR szTimezoneInformation[] = { 'M','a','c','h','i','n','e','\\','S','y','s','t','e','m','\\', 'C','u','r','r','e','n','t','C','o','n','t','r','o','l','S','e','t','\\', 'C','o','n','t','r','o','l','\\', 'T','i','m','e','Z','o','n','e','I','n','f','o','r','m','a','t','i','o','n','\0' }; WCHAR standardnameW[] = {'S','t','a','n','d','a','r','d','N','a','m','e','\0'}; WCHAR timezonekeynameW[] = {'T','i','m','e','Z','o','n','e','K','e','y','N','a','m','e','\0'}; DYNAMIC_TIME_ZONE_INFORMATION tzinfo; UNICODE_STRING keyName; OBJECT_ATTRIBUTES attr; HANDLE hkey; DWORD tzid; tzid = GetDynamicTimeZoneInformation(&tzinfo); if (tzid == TIME_ZONE_ID_INVALID) { ERR("fail to get timezone information.\n"); return; } RtlInitUnicodeString(&keyName, szTimezoneInformation); InitializeObjectAttributes(&attr, &keyName, 0, 0, NULL); if (NtCreateKey(&hkey, KEY_ALL_ACCESS, &attr, 0, NULL, 0, NULL) != STATUS_SUCCESS) { ERR("fail to create timezone information key.\n"); return; } RtlInitUnicodeString(&keyName, standardnameW); NtSetValueKey(hkey, &keyName, 0, REG_SZ, tzinfo.StandardName, (strlenW(tzinfo.StandardName) + 1) * sizeof(WCHAR)); RtlInitUnicodeString(&keyName, timezonekeynameW); NtSetValueKey(hkey, &keyName, 0, REG_SZ, tzinfo.TimeZoneKeyName, (strlenW(tzinfo.TimeZoneKeyName) + 1) * sizeof(WCHAR)); NtClose( hkey ); }
Timezone::Timezone() : _offset(0),_dstOffset(3600000) { #if defined(_WIN32) /// GET LOCAL INFOS _tzset(); //// LOAD default values //////////////////////// DYNAMIC_TIME_ZONE_INFORMATION timezoneInfo; DWORD result = GetDynamicTimeZoneInformation(&timezoneInfo); _offset=(-(Int32)timezoneInfo.Bias*60000); if (result != TIME_ZONE_ID_UNKNOWN) _dstOffset = (-(Int32)timezoneInfo.DaylightBias*60000); _dstOffset += _offset; fillDefaultTransitionRule(timezoneInfo.DaylightDate,_offset,_dstOffset,true,_StartDST); fillDefaultTransitionRule(timezoneInfo.StandardDate,_offset,_dstOffset,false,_EndDST); int size(sizeof(timezoneInfo.TimeZoneKeyName)); _name.resize(size); if ((size = WideCharToMultiByte(CP_ACP, 0, timezoneInfo.TimeZoneKeyName, -1, (char*)_name.data(), _name.size(), NULL, NULL)) > 0) { _name.resize(size-1); static const map<string, const char*> WindowToTZID ({ { "AUS Central Standard Time", "Australia/Darwin" }, { "AUS Eastern Standard Time", "Australia/Sydney" }, { "Afghanistan Standard Time", "Asia/Kabul" }, { "Alaskan Standard Time", "America/Anchorage" }, { "Arab Standard Time", "Asia/Riyadh" }, { "Arabian Standard Time", "Asia/Dubai" }, { "Arabic Standard Time", "Asia/Baghdad" }, { "Argentina Standard Time", "America/Buenos_Aires" }, { "Atlantic Standard Time", "America/Halifax" }, { "Azerbaijan Standard Time", "Asia/Baku" }, { "Azores Standard Time", "Atlantic/Azores" }, { "Bahia Standard Time", "America/Bahia" }, { "Bangladesh Standard Time", "Asia/Dhaka" }, { "Canada Central Standard Time", "America/Regina" }, { "Cape Verde Standard Time", "Atlantic/Cape_Verde" }, { "Caucasus Standard Time", "Asia/Yerevan" }, { "Cen. Australia Standard Time", "Australia/Adelaide" }, { "Central America Standard Time", "America/Guatemala" }, { "Central Asia Standard Time", "Asia/Almaty" }, { "Central Brazilian Standard Time", "America/Cuiaba" }, { "Central Europe Standard Time", "Europe/Budapest" }, { "Central European Standard Time", "Europe/Warsaw" }, { "Central Pacific Standard Time", "Pacific/Guadalcanal" }, { "Central Standard Time", "America/Chicago" }, { "China Standard Time", "Asia/Shanghai" }, { "Dateline Standard Time", "Etc/GMT+12" }, { "E. Africa Standard Time", "Africa/Nairobi" }, { "E. Australia Standard Time", "Australia/Brisbane" }, { "E. Europe Standard Time", "Asia/Nicosia" }, { "E. South America Standard Time", "America/Sao_Paulo" }, { "Eastern Standard Time", "America/New_York" }, { "Egypt Standard Time", "Africa/Cairo" }, { "Ekaterinburg Standard Time", "Asia/Yekaterinburg" }, { "FLE Standard Time", "Europe/Kiev" }, { "Fiji Standard Time", "Pacific/Fiji" }, { "GMT Standard Time", "Europe/London" }, { "GTB Standard Time", "Europe/Bucharest" }, { "Georgian Standard Time", "Asia/Tbilisi" }, { "Greenland Standard Time", "America/Godthab" }, { "Greenwich Standard Time", "Atlantic/Reykjavik" }, { "Hawaiian Standard Time", "Pacific/Honolulu" }, { "India Standard Time", "Asia/Calcutta" }, { "Iran Standard Time", "Asia/Tehran" }, { "Israel Standard Time", "Asia/Jerusalem" }, { "Jordan Standard Time", "Asia/Amman" }, { "Kaliningrad Standard Time", "Europe/Kaliningrad" }, { "Korea Standard Time", "Asia/Seoul" }, { "Libya Standard Time", "Africa/Tripoli" }, { "Magadan Standard Time", "Asia/Magadan" }, { "Mauritius Standard Time", "Indian/Mauritius" }, { "Mauritius Standard Time", "Indian/Reunion" }, { "Middle East Standard Time", "Asia/Beirut" }, { "Montevideo Standard Time", "America/Montevideo" }, { "Morocco Standard Time", "Africa/Casablanca" }, { "Mountain Standard Time", "America/Denver" }, { "Myanmar Standard Time", "Asia/Rangoon" }, { "N. Central Asia Standard Time", "Asia/Novosibirsk" }, { "Namibia Standard Time", "Africa/Windhoek" }, { "Nepal Standard Time", "Asia/Katmandu" }, { "New Zealand Standard Time", "Pacific/Auckland" }, { "Newfoundland Standard Time", "America/St_Johns" }, { "North Asia East Standard Time", "Asia/Irkutsk" }, { "North Asia Standard Time", "Asia/Krasnoyarsk" }, { "Pacific SA Standard Time", "America/Santiago" }, { "Pacific Standard Time", "America/Los_Angeles" }, { "Pakistan Standard Time", "Asia/Karachi" }, { "Paraguay Standard Time", "America/Asuncion" }, { "Romance Standard Time", "Europe/Paris" }, { "Russian Standard Time", "Europe/Moscow" }, { "SA Eastern Standard Time", "America/Cayenne" }, { "SA Pacific Standard Time", "America/Bogota" }, { "SA Western Standard Time", "America/La_Paz" }, { "SE Asia Standard Time", "Asia/Bangkok" }, { "Samoa Standard Time", "Pacific/Apia" }, { "Singapore Standard Time", "Asia/Singapore" }, { "South Africa Standard Time", "Africa/Johannesburg" }, { "Sri Lanka Standard Time", "Asia/Colombo" }, { "Syria Standard Time", "Asia/Damascus" }, { "Taipei Standard Time", "Asia/Taipei" }, { "Tasmania Standard Time", "Australia/Hobart" }, { "Tokyo Standard Time", "Asia/Tokyo" }, { "Tonga Standard Time", "Pacific/Tongatapu" }, { "Turkey Standard Time", "Europe/Istanbul" }, { "US Eastern Standard Time", "America/Indianapolis" }, { "US Mountain Standard Time", "America/Phoenix" }, { "UTC", "Etc/GMT" }, { "UTC+12", "Etc/GMT-12" }, { "UTC-02", "Etc/GMT+2" }, { "UTC-11", "Etc/GMT+11" }, { "Ulaanbaatar Standard Time", "Asia/Ulaanbaatar" }, { "Venezuela Standard Time", "America/Caracas" }, { "Vladivostok Standard Time", "Asia/Vladivostok" }, { "W. Australia Standard Time", "Australia/Perth" }, { "W. Central Africa Standard Time", "Africa/Lagos" }, { "W. Europe Standard Time", "Europe/Berlin" }, { "West Asia Standard Time", "Asia/Tashkent" }, { "West Pacific Standard Time", "Pacific/Port_Moresby" }, { "Yakutsk Standard Time", "Asia/Yakutsk" }, }); auto& it = WindowToTZID.find(_name); if (it != WindowToTZID.end()) _name.assign(it->second); } else _name.clear(); #else tzset(); #if defined(_OS_BSD) // timezone not available on BSD std::time_t now = std::time(NULL); struct std::tm t; gmtime_r(&now, &t); _offset = now - std::mktime(&t); #else _offset = (-(Int32)timezone*1000); #endif _name.assign(tzname[0]); _dstOffset += _offset; #endif if (_name.empty()) return; // no more TZ information available //// LOAD TZ database //////////////////////// string path; if(Util::Environment().getString("TZDIR",path)) { FileSystem::MakeDirectory(path).append(_name); if(readTZDatabase(path)) return; } #if !defined(_WIN32) path.assign("/usr/lib/zoneinfo/").append(_name); if(readTZDatabase(path)) return; path.assign("/usr/share/zoneinfo/").append(_name); if(readTZDatabase(path)) return; #endif if (FileSystem::GetCurrent(path)) { path.append("zoneinfo/").append(_name); if(readTZDatabase(path)) return; } if (FileSystem::GetCurrentApplication(path)) { FileSystem::GetParent(path).append("zoneinfo/").append(_name); if(readTZDatabase(path)) return; } #if !defined(_WIN32) path.assign("/etc/localtime"); readTZDatabase(path); #endif }