summaryrefslogtreecommitdiff
path: root/src/common/time_zone.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/common/time_zone.cpp')
-rw-r--r--src/common/time_zone.cpp43
1 files changed, 16 insertions, 27 deletions
diff --git a/src/common/time_zone.cpp b/src/common/time_zone.cpp
index d8d7896c6..a25f8b040 100644
--- a/src/common/time_zone.cpp
+++ b/src/common/time_zone.cpp
@@ -33,32 +33,27 @@ std::string GetDefaultTimeZone() {
33 return "GMT"; 33 return "GMT";
34} 34}
35 35
36static std::string GetOsTimeZoneOffset() { 36// Results are not comparable to seconds since Epoch
37 const std::time_t t{std::time(nullptr)}; 37static std::time_t TmSpecToSeconds(const struct std::tm& spec) {
38 const std::tm tm{*std::localtime(&t)}; 38 std::time_t cumulative = spec.tm_year;
39 39 cumulative = cumulative * 365 + spec.tm_yday; // Years to days
40 return fmt::format("{:%z}", tm); 40 cumulative = cumulative * 24 + spec.tm_hour; // Days to hours
41} 41 cumulative = cumulative * 60 + spec.tm_min; // Hours to minutes
42 42 cumulative = cumulative * 60 + spec.tm_sec; // Minutes to seconds
43static int ConvertOsTimeZoneOffsetToInt(const std::string& timezone) { 43 return cumulative;
44 try {
45 return std::stoi(timezone);
46 } catch (const std::invalid_argument&) {
47 LOG_CRITICAL(Common, "invalid_argument with {}!", timezone);
48 return 0;
49 } catch (const std::out_of_range&) {
50 LOG_CRITICAL(Common, "out_of_range with {}!", timezone);
51 return 0;
52 }
53} 44}
54 45
55std::chrono::seconds GetCurrentOffsetSeconds() { 46std::chrono::seconds GetCurrentOffsetSeconds() {
56 const int offset{ConvertOsTimeZoneOffsetToInt(GetOsTimeZoneOffset())}; 47 const std::time_t t{std::time(nullptr)};
48 const std::tm local{*std::localtime(&t)};
49 const std::tm gmt{*std::gmtime(&t)};
57 50
58 int seconds{(offset / 100) * 60 * 60}; // Convert hour component to seconds 51 // gmt_seconds is a different offset than time(nullptr)
59 seconds += (offset % 100) * 60; // Convert minute component to seconds 52 const auto gmt_seconds = TmSpecToSeconds(gmt);
53 const auto local_seconds = TmSpecToSeconds(local);
54 const auto seconds_offset = gmt_seconds - local_seconds;
60 55
61 return std::chrono::seconds{seconds}; 56 return std::chrono::seconds{seconds_offset};
62} 57}
63 58
64// Key is [Hours * 100 + Minutes], multiplied by 100 if DST 59// Key is [Hours * 100 + Minutes], multiplied by 100 if DST
@@ -71,11 +66,6 @@ const static std::map<s64, const char*> off_timezones = {
71}; 66};
72 67
73std::string FindSystemTimeZone() { 68std::string FindSystemTimeZone() {
74#if defined(MINGW)
75 // MinGW has broken strftime -- https://sourceforge.net/p/mingw-w64/bugs/793/
76 // e.g. fmt::format("{:%z}") -- returns "Eastern Daylight Time" when it should be "-0400"
77 return timezones[0];
78#else
79 const s64 seconds = static_cast<s64>(GetCurrentOffsetSeconds().count()); 69 const s64 seconds = static_cast<s64>(GetCurrentOffsetSeconds().count());
80 70
81 const s64 minutes = seconds / 60; 71 const s64 minutes = seconds / 60;
@@ -97,7 +87,6 @@ std::string FindSystemTimeZone() {
97 } 87 }
98 } 88 }
99 return fmt::format("Etc/GMT{:s}{:d}", hours > 0 ? "-" : "+", std::abs(hours)); 89 return fmt::format("Etc/GMT{:s}{:d}", hours > 0 ? "-" : "+", std::abs(hours));
100#endif
101} 90}
102 91
103} // namespace Common::TimeZone 92} // namespace Common::TimeZone