2022-01-08 02:09:44 +00:00
|
|
|
#pragma once
|
|
|
|
|
2023-11-10 14:57:26 +00:00
|
|
|
#include <chrono>
|
2022-01-08 02:09:44 +00:00
|
|
|
|
2023-01-17 01:30:06 +00:00
|
|
|
#if HAVE_CHRONO_TIMEZONES
|
|
|
|
#include <format>
|
2023-11-10 14:57:26 +00:00
|
|
|
#else
|
|
|
|
#include <date/tz.h>
|
|
|
|
#include <fmt/format.h>
|
2023-01-17 01:30:06 +00:00
|
|
|
|
2023-11-10 14:57:26 +00:00
|
|
|
#include <regex>
|
|
|
|
#endif
|
2023-01-17 01:30:06 +00:00
|
|
|
|
2023-11-10 14:57:26 +00:00
|
|
|
// Date
|
|
|
|
namespace date {
|
|
|
|
#if HAVE_CHRONO_TIMEZONES
|
2023-01-17 01:30:06 +00:00
|
|
|
using namespace std::chrono;
|
2023-11-10 14:57:26 +00:00
|
|
|
using namespace std;
|
|
|
|
#else
|
2023-01-17 01:30:06 +00:00
|
|
|
|
2023-11-10 14:57:26 +00:00
|
|
|
using system_clock = std::chrono::system_clock;
|
|
|
|
using seconds = std::chrono::seconds;
|
2023-01-17 01:30:06 +00:00
|
|
|
|
2023-11-10 14:57:26 +00:00
|
|
|
template <typename T>
|
|
|
|
inline auto format(const char* spec, const T& arg) {
|
|
|
|
return date::format(std::regex_replace(spec, std::regex("\\{:L|\\}"), ""), arg);
|
2023-01-17 01:30:06 +00:00
|
|
|
}
|
|
|
|
|
2023-11-10 14:57:26 +00:00
|
|
|
template <typename T>
|
|
|
|
inline auto format(const std::locale& loc, const char* spec, const T& arg) {
|
|
|
|
return date::format(loc, std::regex_replace(spec, std::regex("\\{:L|\\}"), ""), arg);
|
2023-01-17 01:30:06 +00:00
|
|
|
}
|
|
|
|
|
2023-11-10 14:57:26 +00:00
|
|
|
constexpr decltype(auto) operator""d(unsigned long long d) noexcept {
|
|
|
|
return date::operator""_d(d); // very verbose, but it works
|
|
|
|
}
|
|
|
|
#endif
|
2023-01-17 01:30:06 +00:00
|
|
|
} // namespace date
|
|
|
|
|
2023-11-10 14:57:26 +00:00
|
|
|
// Format
|
|
|
|
namespace waybar::util::date::format {
|
|
|
|
#if HAVE_CHRONO_TIMEZONES
|
|
|
|
using namespace std;
|
2023-01-17 01:30:06 +00:00
|
|
|
#else
|
2023-11-10 14:57:26 +00:00
|
|
|
using namespace fmt;
|
2023-01-17 01:30:06 +00:00
|
|
|
#endif
|
2023-11-10 14:57:26 +00:00
|
|
|
} // namespace waybar::util::date::format
|
2023-01-17 01:30:06 +00:00
|
|
|
|
2023-11-10 14:57:26 +00:00
|
|
|
#if not HAVE_CHRONO_TIMEZONES
|
2023-01-17 00:48:30 +00:00
|
|
|
template <typename Duration, typename TimeZonePtr>
|
|
|
|
struct fmt::formatter<date::zoned_time<Duration, TimeZonePtr>> {
|
2022-01-08 06:25:15 +00:00
|
|
|
std::string_view specs;
|
|
|
|
|
|
|
|
template <typename ParseContext>
|
|
|
|
constexpr auto parse(ParseContext& ctx) -> decltype(ctx.begin()) {
|
|
|
|
auto it = ctx.begin();
|
|
|
|
if (it != ctx.end() && *it == ':') {
|
|
|
|
++it;
|
|
|
|
}
|
|
|
|
auto end = it;
|
|
|
|
while (end != ctx.end() && *end != '}') {
|
|
|
|
++end;
|
|
|
|
}
|
|
|
|
if (end != it) {
|
|
|
|
specs = {it, std::string_view::size_type(end - it)};
|
|
|
|
}
|
|
|
|
return end;
|
|
|
|
}
|
|
|
|
|
2022-01-08 02:09:44 +00:00
|
|
|
template <typename FormatContext>
|
2023-01-17 00:48:30 +00:00
|
|
|
auto format(const date::zoned_time<Duration, TimeZonePtr>& ztime, FormatContext& ctx) {
|
|
|
|
if (ctx.locale()) {
|
|
|
|
const auto loc = ctx.locale().template get<std::locale>();
|
|
|
|
return fmt::format_to(ctx.out(), "{}", date::format(loc, fmt::to_string(specs), ztime));
|
|
|
|
}
|
|
|
|
return fmt::format_to(ctx.out(), "{}", date::format(fmt::to_string(specs), ztime));
|
2022-01-08 02:09:44 +00:00
|
|
|
}
|
|
|
|
};
|
2023-11-10 14:57:26 +00:00
|
|
|
#endif
|
|
|
|
|
|
|
|
using namespace date;
|