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-License-Identifier: GPL-2.0-or-later | ||||
|  | ||||
| #if __cpp_lib_chrono >= 201907L | ||||
| #include <chrono> | ||||
| #else | ||||
| #include <ctime> | ||||
| #include <limits> | ||||
| #endif | ||||
| #include <string_view> | ||||
| #include <fmt/chrono.h> | ||||
| #include <fmt/core.h> | ||||
|  | ||||
| #include "common/assert.h" | ||||
| #include "common/fs/path_util.h" | ||||
| @@ -15,7 +23,7 @@ static bool configuring_global = true; | ||||
|  | ||||
| std::string GetTimeZoneString() { | ||||
|     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", | ||||
|         "Greenwich", "Hongkong",  "HST", "Iceland", "Iran",    "Israel", "Jamaica",   "Japan", | ||||
|         "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()); | ||||
|     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() { | ||||
|   | ||||
		Reference in New Issue
	
	Block a user