* @brief Get a string representing the current time. * * @return The string. */
| 3830 | * @return The string. |
| 3831 | */ |
| 3832 | std::string get_time() |
| 3833 | { |
| 3834 | #ifdef __cpp_lib_format |
| 3835 | // Things are much easier with C++20 `std::format`. |
| 3836 | return std::format("{:%Y-%m-%d_%H.%M.%S}", std::chrono::time_point_cast<std::chrono::seconds>(std::chrono::system_clock::now())); |
| 3837 | #else |
| 3838 | std::string time_string = "YYYY-MM-DD_HH.MM.SS"; |
| 3839 | std::tm local_tm = {}; |
| 3840 | const std::time_t epoch = std::time(nullptr); |
| 3841 | #if defined(_MSC_VER) && !defined(__cpp_lib_modules) |
| 3842 | // If MSVC is detected, use `localtime_s()` to avoid warning C4996. (This doesn't work if we used `import std`, so we check that to be on the safe side, although in that case `std::format` should be available anyway). |
| 3843 | if (localtime_s(&local_tm, &epoch) != 0) |
| 3844 | time_string = ""; |
| 3845 | #elif defined(__linux__) || defined(__APPLE__) |
| 3846 | // On Linux or macOS, use `localtime_r()` to avoid clang-tidy warning `concurrency-mt-unsafe`. |
| 3847 | if (localtime_r(&epoch, &local_tm) == nullptr) |
| 3848 | time_string = ""; |
| 3849 | #else |
| 3850 | local_tm = *std::localtime(&epoch); // NOLINT(concurrency-mt-unsafe) |
| 3851 | #endif |
| 3852 | if (!time_string.empty()) |
| 3853 | { |
| 3854 | const std::size_t bytes = std::strftime(time_string.data(), time_string.length() + 1, "%Y-%m-%d_%H.%M.%S", &local_tm); |
| 3855 | if (bytes != time_string.length()) |
| 3856 | time_string = ""; |
| 3857 | } |
| 3858 | return time_string; |
| 3859 | #endif |
| 3860 | } |
| 3861 | |
| 3862 | /** |
| 3863 | * @brief A class to parse command line arguments. All arguments are simple on/off flags. |