diff --git a/src/common/CMakeLists.txt b/src/common/CMakeLists.txt index 95f09e5d6..35c1e6d01 100644 --- a/src/common/CMakeLists.txt +++ b/src/common/CMakeLists.txt @@ -56,6 +56,7 @@ add_library(common small_string.h string_util.cpp string_util.h + time_helpers.h thirdparty/SmallVector.cpp thirdparty/SmallVector.h thirdparty/aes.cpp diff --git a/src/common/common.vcxproj b/src/common/common.vcxproj index 6b53194bb..004a6d0e2 100644 --- a/src/common/common.vcxproj +++ b/src/common/common.vcxproj @@ -23,6 +23,7 @@ + @@ -105,6 +106,9 @@ + + + diff --git a/src/common/common.vcxproj.filters b/src/common/common.vcxproj.filters index 4318f4452..4933ef382 100644 --- a/src/common/common.vcxproj.filters +++ b/src/common/common.vcxproj.filters @@ -57,6 +57,7 @@ thirdparty + @@ -112,4 +113,7 @@ thirdparty + + + \ No newline at end of file diff --git a/src/common/time_helpers.h b/src/common/time_helpers.h new file mode 100644 index 000000000..025d91976 --- /dev/null +++ b/src/common/time_helpers.h @@ -0,0 +1,21 @@ +// SPDX-FileCopyrightText: 2019-2024 Connor McLaughlin +// SPDX-License-Identifier: CC-BY-NC-ND-4.0 + +#pragma once + +#include + +namespace Common { + +inline std::tm LocalTime(std::time_t tvalue) +{ + std::tm ttime; +#ifdef _MSC_VER + localtime_s(&ttime, &tvalue); +#else + localtime_r(&tvalue, &ttime); +#endif + return ttime; +} + +} // namespace Common diff --git a/src/core/game_list.cpp b/src/core/game_list.cpp index 8a4dbe465..48900e80a 100644 --- a/src/core/game_list.cpp +++ b/src/core/game_list.cpp @@ -27,6 +27,7 @@ #include "common/progress_callback.h" #include "common/string_util.h" #include "common/thirdparty/SmallVector.h" +#include "common/time_helpers.h" #include "common/timer.h" #include "fmt/format.h" @@ -1592,17 +1593,8 @@ std::string GameList::FormatTimestamp(std::time_t timestamp) } else { - struct tm ctime = {}; - struct tm ttime = {}; - const std::time_t ctimestamp = std::time(nullptr); -#ifdef _MSC_VER - localtime_s(&ctime, &ctimestamp); - localtime_s(&ttime, ×tamp); -#else - localtime_r(&ctimestamp, &ctime); - localtime_r(×tamp, &ttime); -#endif - + const std::tm ctime = Common::LocalTime(std::time(nullptr)); + const std::tm ttime = Common::LocalTime(timestamp); if (ctime.tm_year == ttime.tm_year && ctime.tm_yday == ttime.tm_yday) { ret = TRANSLATE_STR("GameList", "Today"); diff --git a/src/core/imgui_overlays.cpp b/src/core/imgui_overlays.cpp index d08fbd4fe..d58b6a46d 100644 --- a/src/core/imgui_overlays.cpp +++ b/src/core/imgui_overlays.cpp @@ -34,6 +34,7 @@ #include "common/path.h" #include "common/string_util.h" #include "common/thirdparty/SmallVector.h" +#include "common/time_helpers.h" #include "common/timer.h" #include "IconsEmoji.h" @@ -44,7 +45,6 @@ #include #include -#include #include #include #include @@ -1157,7 +1157,8 @@ void SaveStateSelectorUI::InitializeListEntry(ListEntry* li, ExtendedSaveStateIn if (global) li->game_details = fmt::format(TRANSLATE_FS("SaveStateSelectorUI", "{} ({})"), ssi->title, ssi->serial); - li->summary = fmt::format(TRANSLATE_FS("SaveStateSelectorUI", DATE_TIME_FORMAT), fmt::localtime(ssi->timestamp)); + li->summary = fmt::format(TRANSLATE_FS("SaveStateSelectorUI", DATE_TIME_FORMAT), + Common::LocalTime(static_cast(ssi->timestamp))); li->filename = Path::GetFileName(path); li->slot = slot; li->global = global; @@ -1440,7 +1441,7 @@ void SaveStateSelectorUI::ShowSlotOSDMessage() FILESYSTEM_STAT_DATA sd; std::string date; if (!path.empty() && FileSystem::StatFile(path.c_str(), &sd)) - date = fmt::format(TRANSLATE_FS("SaveStateSelectorUI", DATE_TIME_FORMAT), fmt::localtime(sd.ModificationTime)); + date = fmt::format(TRANSLATE_FS("SaveStateSelectorUI", DATE_TIME_FORMAT), Common::LocalTime(sd.ModificationTime)); else date = TRANSLATE_STR("SaveStateSelectorUI", "no save yet"); diff --git a/src/core/system.cpp b/src/core/system.cpp index 8cd7d43bb..c6858bfa8 100644 --- a/src/core/system.cpp +++ b/src/core/system.cpp @@ -67,6 +67,7 @@ #include "common/ryml_helpers.h" #include "common/string_util.h" #include "common/task_queue.h" +#include "common/time_helpers.h" #include "common/timer.h" #include "IconsEmoji.h" @@ -80,6 +81,7 @@ #include "xxhash.h" #include +#include #include #include #include @@ -351,7 +353,7 @@ static StateVars s_state; static TinyString GetTimestampStringForFileName() { - return TinyString::from_format("{:%Y-%m-%d-%H-%M-%S}", fmt::localtime(std::time(nullptr))); + return TinyString::from_format("{:%Y-%m-%d-%H-%M-%S}", Common::LocalTime(std::time(nullptr))); } bool System::PerformEarlyHardwareChecks(Error* error) diff --git a/src/duckstation-mini/mini_host.cpp b/src/duckstation-mini/mini_host.cpp index 400081188..f7ec22ec7 100644 --- a/src/duckstation-mini/mini_host.cpp +++ b/src/duckstation-mini/mini_host.cpp @@ -37,6 +37,7 @@ #include "common/path.h" #include "common/string_util.h" #include "common/threading.h" +#include "common/time_helpers.h" #include "IconsEmoji.h" #include "fmt/format.h" @@ -1415,15 +1416,8 @@ std::string Host::FormatNumber(NumberFormatType type, s64 value) DefaultCaseIsUnreachable(); } - struct tm ttime = {}; - const std::time_t tvalue = static_cast(value); -#ifdef _MSC_VER - localtime_s(&ttime, &tvalue); -#else - localtime_r(&tvalue, &ttime); -#endif - char buf[128]; + const std::tm ttime = Common::LocalTime(static_cast(value)); std::strftime(buf, std::size(buf), format, &ttime); ret.assign(buf); } diff --git a/src/duckstation-regtest/regtest_host.cpp b/src/duckstation-regtest/regtest_host.cpp index 314c29107..a1f6aeb73 100644 --- a/src/duckstation-regtest/regtest_host.cpp +++ b/src/duckstation-regtest/regtest_host.cpp @@ -34,6 +34,7 @@ #include "common/sha256_digest.h" #include "common/string_util.h" #include "common/threading.h" +#include "common/time_helpers.h" #include "common/timer.h" #include "fmt/format.h" @@ -604,15 +605,8 @@ std::string Host::FormatNumber(NumberFormatType type, s64 value) DefaultCaseIsUnreachable(); } - struct tm ttime = {}; - const std::time_t tvalue = static_cast(value); -#ifdef _MSC_VER - localtime_s(&ttime, &tvalue); -#else - localtime_r(&tvalue, &ttime); -#endif - char buf[128]; + const std::tm ttime = Common::LocalTime(static_cast(value)); std::strftime(buf, std::size(buf), format, &ttime); ret.assign(buf); } diff --git a/src/util/iso_reader.cpp b/src/util/iso_reader.cpp index c33db3b26..8750bdd1f 100644 --- a/src/util/iso_reader.cpp +++ b/src/util/iso_reader.cpp @@ -10,6 +10,7 @@ #include "common/file_system.h" #include "common/progress_callback.h" #include "common/string_util.h" +#include "common/time_helpers.h" #include "fmt/format.h" @@ -572,14 +573,8 @@ std::string IsoReader::ISODirectoryEntryDateTime::GetFormattedTime() const const s32 uts_offset = static_cast(gmt_offset) * 3600; const time_t uts = std::mktime(&utime) + uts_offset; - struct tm ltime; -#ifdef _MSC_VER - localtime_s(<ime, &uts); -#else - localtime_r(&uts, <ime); -#endif - char buf[128]; + const std::tm ltime = Common::LocalTime(uts); const size_t len = std::strftime(buf, std::size(buf), "%c", <ime); return std::string(buf, len); }