settings: Always report a valid time zone
Prevents needing to deduce the non-Switch setting in core. Instead, we deduce the meaning of this setting where the heresy is committed, in common. settings: Remove strftime usage GetTimeZoneString: Use standard features Also forces GMT on MinGW due to broken strftime.
This commit is contained in:
		| @@ -1,7 +1,15 @@ | |||||||
| // SPDX-FileCopyrightText: Copyright 2021 yuzu Emulator Project | // SPDX-FileCopyrightText: Copyright 2021 yuzu Emulator Project | ||||||
| // SPDX-License-Identifier: GPL-2.0-or-later | // SPDX-License-Identifier: GPL-2.0-or-later | ||||||
|  |  | ||||||
|  | #if __cpp_lib_chrono >= 201907L | ||||||
|  | #include <chrono> | ||||||
|  | #else | ||||||
|  | #include <ctime> | ||||||
|  | #include <limits> | ||||||
|  | #endif | ||||||
| #include <string_view> | #include <string_view> | ||||||
|  | #include <fmt/chrono.h> | ||||||
|  | #include <fmt/core.h> | ||||||
|  |  | ||||||
| #include "common/assert.h" | #include "common/assert.h" | ||||||
| #include "common/fs/path_util.h" | #include "common/fs/path_util.h" | ||||||
| @@ -15,7 +23,7 @@ static bool configuring_global = true; | |||||||
|  |  | ||||||
| std::string GetTimeZoneString() { | std::string GetTimeZoneString() { | ||||||
|     static constexpr std::array timezones{ |     static constexpr std::array timezones{ | ||||||
|         "auto",      "default",   "CET", "CST6CDT", "Cuba",    "EET",    "Egypt",     "Eire", |         "GMT",       "GMT",       "CET", "CST6CDT", "Cuba",    "EET",    "Egypt",     "Eire", | ||||||
|         "EST",       "EST5EDT",   "GB",  "GB-Eire", "GMT",     "GMT+0",  "GMT-0",     "GMT0", |         "EST",       "EST5EDT",   "GB",  "GB-Eire", "GMT",     "GMT+0",  "GMT-0",     "GMT0", | ||||||
|         "Greenwich", "Hongkong",  "HST", "Iceland", "Iran",    "Israel", "Jamaica",   "Japan", |         "Greenwich", "Hongkong",  "HST", "Iceland", "Iran",    "Israel", "Jamaica",   "Japan", | ||||||
|         "Kwajalein", "Libya",     "MET", "MST",     "MST7MDT", "Navajo", "NZ",        "NZ-CHAT", |         "Kwajalein", "Libya",     "MET", "MST",     "MST7MDT", "Navajo", "NZ",        "NZ-CHAT", | ||||||
| @@ -25,7 +33,73 @@ std::string GetTimeZoneString() { | |||||||
|  |  | ||||||
|     const auto time_zone_index = static_cast<std::size_t>(values.time_zone_index.GetValue()); |     const auto time_zone_index = static_cast<std::size_t>(values.time_zone_index.GetValue()); | ||||||
|     ASSERT(time_zone_index < timezones.size()); |     ASSERT(time_zone_index < timezones.size()); | ||||||
|     return timezones[time_zone_index]; |     std::string location_name; | ||||||
|  |     switch (time_zone_index) { | ||||||
|  |     case 0: { // Auto | ||||||
|  | #if __cpp_lib_chrono >= 201907L | ||||||
|  |         const struct std::chrono::tzdb& time_zone_data = std::chrono::get_tzdb(); | ||||||
|  |         const std::chrono::time_zone* current_zone = time_zone_data.current_zone(); | ||||||
|  |         std::string_view current_zone_name = current_zone->name(); | ||||||
|  |         location_name = current_zone_name; | ||||||
|  | #elif defined(MINGW) | ||||||
|  |         // MinGW has broken strftime -- https://sourceforge.net/p/mingw-w64/bugs/793/ | ||||||
|  |         // e.g. fmt::format("{:%z}") -- returns "Eastern Daylight Time" when it should be "-0400" | ||||||
|  |         location_name = timezones[0]; | ||||||
|  |         break; | ||||||
|  | #else | ||||||
|  |         static constexpr std::array offsets{ | ||||||
|  |             0,     0,     3600,   -21600, -19768, 7200,   7509,  -1521,  -18000, -18000, | ||||||
|  |             -75,   -75,   0,      0,      0,      0,      0,     27402,  -36000, -968, | ||||||
|  |             12344, 8454,  -18430, 33539,  40160,  3164,   3600,  -25200, -25200, -25196, | ||||||
|  |             41944, 44028, 5040,   -2205,  29143,  -28800, 29160, 30472,  24925,  6952, | ||||||
|  |             0,     0,     0,      9017,   0,      0, | ||||||
|  |         }; | ||||||
|  |  | ||||||
|  |         static constexpr std::array dst{ | ||||||
|  |             false, false, true,  true,  true,  true,  true,  true,  false, true,  true, true, | ||||||
|  |             false, false, false, false, false, true,  false, false, true,  true,  true, true, | ||||||
|  |             false, true,  true,  false, true,  true,  true,  true,  true,  true,  true, true, | ||||||
|  |             true,  true,  true,  true,  false, false, false, true,  true,  false, | ||||||
|  |         }; | ||||||
|  |  | ||||||
|  |         const auto now = std::time(nullptr); | ||||||
|  |         const struct std::tm& local = *std::localtime(&now); | ||||||
|  |         const std::string clock_offset_s = fmt::format("{:%z}", local); | ||||||
|  |         if (clock_offset_s.empty()) { | ||||||
|  |             location_name = timezones[0]; | ||||||
|  |             break; | ||||||
|  |         } | ||||||
|  |         const int hours_offset = std::stoi(clock_offset_s) / 100; | ||||||
|  |         const int minutes_offset = std::stoi(clock_offset_s) - hours_offset * 100; | ||||||
|  |         const int system_offset = | ||||||
|  |             hours_offset * 3600 + minutes_offset * 60 - (local.tm_isdst ? 3600 : 0); | ||||||
|  |  | ||||||
|  |         int min = std::numeric_limits<int>::max(); | ||||||
|  |         int min_index = -1; | ||||||
|  |         for (u32 i = 2; i < offsets.size(); i++) { | ||||||
|  |             // Skip if system is celebrating DST but considered time zone does not | ||||||
|  |             if (local.tm_isdst && !dst[i]) { | ||||||
|  |                 continue; | ||||||
|  |             } | ||||||
|  |  | ||||||
|  |             const auto offset = offsets[i]; | ||||||
|  |             const int difference = std::abs(std::abs(offset) - std::abs(system_offset)); | ||||||
|  |             if (difference < min) { | ||||||
|  |                 min = difference; | ||||||
|  |                 min_index = i; | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         location_name = timezones[min_index]; | ||||||
|  | #endif | ||||||
|  |         break; | ||||||
|  |     } | ||||||
|  |     default: | ||||||
|  |         location_name = timezones[time_zone_index]; | ||||||
|  |         break; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     return location_name; | ||||||
| } | } | ||||||
|  |  | ||||||
| void LogSettings() { | void LogSettings() { | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user