diff options
| author | Carl Hetherington <cth@carlh.net> | 2025-01-07 20:46:02 +0100 |
|---|---|---|
| committer | Carl Hetherington <cth@carlh.net> | 2025-01-09 20:56:26 +0100 |
| commit | 32ac98a4b6f53f06cfe26687d338dfa5125ec20d (patch) | |
| tree | 30ac889b9ee4112549ff801df5de00b8c5f254b4 | |
| parent | 2dc531378af4cc050a3c0a3d22aa8b2c30b11471 (diff) | |
Add rfc_2822_date().
| -rw-r--r-- | src/lib/util.cc | 19 | ||||
| -rw-r--r-- | src/lib/util.h | 1 | ||||
| -rw-r--r-- | test/util_test.cc | 60 |
3 files changed, 79 insertions, 1 deletions
diff --git a/src/lib/util.cc b/src/lib/util.cc index 14839d80d..5b0c25cda 100644 --- a/src/lib/util.cc +++ b/src/lib/util.cc @@ -78,8 +78,10 @@ LIBDCP_ENABLE_WARNINGS #include <unicode/unistr.h> #include <unicode/translit.h> #include <unicode/brkiter.h> +#include <fmt/chrono.h> #include <fmt/format.h> #include <boost/algorithm/string.hpp> +#include <boost/date_time/c_local_time_adjustor.hpp> #include <boost/range/algorithm/replace_if.hpp> #include <boost/thread.hpp> #include <boost/filesystem.hpp> @@ -1207,3 +1209,20 @@ join_strings(vector<string> const& in, string const& separator) }); } + +string +rfc_2822_date(time_t time) +{ + auto const utc_now = boost::posix_time::second_clock::universal_time (); + auto const local_now = boost::date_time::c_local_adjustor<boost::posix_time::ptime>::utc_to_local (utc_now); + auto const offset = local_now - utc_now; + + auto const hours = int(abs(offset.hours())); + + auto tm = localtime(&time); + + /* I tried using %z in the time formatter but it gave results like "Pacific Standard Time" instead +0800 on Windows */ + return fmt::format("{:%a, %d %b %Y %H:%M:%S} {}{:02d}{:02d}", *tm, offset.hours() >= 0 ? "+" : "-", hours, int(offset.minutes())); +} + + diff --git a/src/lib/util.h b/src/lib/util.h index eaa705f5e..e70d6f90f 100644 --- a/src/lib/util.h +++ b/src/lib/util.h @@ -102,6 +102,7 @@ extern void capture_ffmpeg_logs(); extern void setup_grok_library_path(); #endif extern std::string join_strings(std::vector<std::string> const& in, std::string const& separator = " "); +extern std::string rfc_2822_date(time_t time); template <class T> diff --git a/test/util_test.cc b/test/util_test.cc index afcc4cfc9..f50a1620e 100644 --- a/test/util_test.cc +++ b/test/util_test.cc @@ -30,8 +30,11 @@ #include "lib/exceptions.h" #include "test.h" #include <dcp/certificate_chain.h> -#include <boost/test/unit_test.hpp> +#include <fmt/format.h> #include <boost/bind/bind.hpp> +#include <boost/date_time/c_local_time_adjustor.hpp> +#include <boost/test/unit_test.hpp> + using std::list; @@ -166,3 +169,58 @@ BOOST_AUTO_TEST_CASE(screen_names_to_string_test) BOOST_CHECK_EQUAL(screen_names_to_string({"Sheila", "Fred", "Jim", "1"}), "1, Fred, Jim, Sheila"); } + +BOOST_AUTO_TEST_CASE(rfc_2822_date_test) +{ +#ifdef DCPOMATIC_WINDOWS + auto result = setlocale(LC_TIME, "German"); +#endif +#ifdef DCPOMATIC_OSX + auto result = setlocale(LC_TIME, "de_DE"); +#endif +#ifdef DCPOMATIC_LINUX + auto result = setlocale(LC_TIME, "de_DE.UTF8"); +#endif + BOOST_REQUIRE(result); + + auto const utc_now = boost::posix_time::second_clock::universal_time (); + auto const local_now = boost::date_time::c_local_adjustor<boost::posix_time::ptime>::utc_to_local (utc_now); + auto const offset = local_now - utc_now; + + auto const hours = int(abs(offset.hours())); + auto const tz = fmt::format("{}{:02d}{:02d}", offset.hours() >= 0 ? "+" : "-", hours, int(offset.minutes())); + + int constexpr day = 24 * 60 * 60; + + /* This won't pass when running in all time zones, but it's really the overall format (and in particular + * the use of English for day and month names) that we want to check. + */ + + auto check_allowing_dst = [hours, tz](int day_index, string format) { + auto test = rfc_2822_date(day_index * day); + BOOST_CHECK( + test == fmt::format(format, hours, tz) || + test == fmt::format(format, hours + 1, tz) + ); + }; + + check_allowing_dst(0, "Thu, 01 Jan 1970 {:02d}:00:00 {}"); + check_allowing_dst(1, "Fri, 02 Jan 1970 {:02d}:00:00 {}"); + check_allowing_dst(2, "Sat, 03 Jan 1970 {:02d}:00:00 {}"); + check_allowing_dst(3, "Sun, 04 Jan 1970 {:02d}:00:00 {}"); + check_allowing_dst(4, "Mon, 05 Jan 1970 {:02d}:00:00 {}"); + check_allowing_dst(5, "Tue, 06 Jan 1970 {:02d}:00:00 {}"); + check_allowing_dst(6, "Wed, 07 Jan 1970 {:02d}:00:00 {}"); + check_allowing_dst(39, "Mon, 09 Feb 1970 {:02d}:00:00 {}"); + check_allowing_dst(89, "Tue, 31 Mar 1970 {:02d}:00:00 {}"); + check_allowing_dst(109, "Mon, 20 Apr 1970 {:02d}:00:00 {}"); + check_allowing_dst(134, "Fri, 15 May 1970 {:02d}:00:00 {}"); + check_allowing_dst(158, "Mon, 08 Jun 1970 {:02d}:00:00 {}"); + check_allowing_dst(182, "Thu, 02 Jul 1970 {:02d}:00:00 {}"); + check_allowing_dst(221, "Mon, 10 Aug 1970 {:02d}:00:00 {}"); + check_allowing_dst(247, "Sat, 05 Sep 1970 {:02d}:00:00 {}"); + check_allowing_dst(300, "Wed, 28 Oct 1970 {:02d}:00:00 {}"); + check_allowing_dst(314, "Wed, 11 Nov 1970 {:02d}:00:00 {}"); + check_allowing_dst(363, "Wed, 30 Dec 1970 {:02d}:00:00 {}"); +} + |
