diff --git a/include/date/tz.h b/include/date/tz.h index 49210683..a0d8ed44 100644 --- a/include/date/tz.h +++ b/include/date/tz.h @@ -47,8 +47,16 @@ # define USE_OS_TZDB 0 #endif +#ifndef USE_BINARY_TZDB +# define USE_BINARY_TZDB USE_OS_TZDB +#endif + +#if (!USE_BINARY_TZDB) && (USE_OS_TZDB) +# define error "If USE_OS_TZDB is used, then USE_BINARY_TZDB must also be used." +#endif + #ifndef HAS_REMOTE_API -# if USE_OS_TZDB == 0 +# if USE_BINARY_TZDB == 0 # ifdef _WIN32 # define HAS_REMOTE_API 0 # else @@ -64,8 +72,8 @@ # pragma clang diagnostic ignored "-Wconstant-logical-operand" #endif -static_assert(!(USE_OS_TZDB && HAS_REMOTE_API), - "USE_OS_TZDB and HAS_REMOTE_API can not be used together"); +static_assert(!(USE_BINARY_TZDB && HAS_REMOTE_API), + "USE_BINARY_TZDB and HAS_REMOTE_API can not be used together"); #ifdef __clang__ # pragma clang diagnostic pop @@ -82,9 +90,9 @@ static_assert(HAS_REMOTE_API == 0 ? AUTO_DOWNLOAD == 0 : true, # define USE_SHELL_API 1 #endif -#if USE_OS_TZDB +#if USE_OS_TZDB || USE_BINARY_TZDB # ifdef _WIN32 -# error "USE_OS_TZDB can not be used on Windows" +# error "USE_OS_TZDB and USE_BINARY_TZDB can not be used on Windows" # endif #endif @@ -764,13 +772,13 @@ operator!=(const zoned_time& x, namespace detail { -# if USE_OS_TZDB +# if USE_BINARY_TZDB struct transition; struct expanded_ttinfo; -# else // !USE_OS_TZDB +# else // !USE_BINARY_TZDB struct zonelet; class Rule; -# endif // !USE_OS_TZDB +# endif // !USE_BINARY_TZDB } #endif // !defined(_MSC_VER) || (_MSC_VER >= 1900) @@ -779,12 +787,12 @@ class time_zone { private: std::string name_; -#if USE_OS_TZDB +#if USE_BINARY_TZDB std::vector transitions_; std::vector ttinfos_; -#else // !USE_OS_TZDB +#else // !USE_BINARY_TZDB std::vector zonelets_; -#endif // !USE_OS_TZDB +#endif // !USE_BINARY_TZDB std::unique_ptr adjusted_; public: @@ -819,9 +827,9 @@ class time_zone friend bool operator< (const time_zone& x, const time_zone& y) NOEXCEPT; friend DATE_API std::ostream& operator<<(std::ostream& os, const time_zone& z); -#if !USE_OS_TZDB +#if !USE_BINARY_TZDB DATE_API void add(const std::string& s); -#endif // !USE_OS_TZDB +#endif // !USE_BINARY_TZDB private: DATE_API sys_info get_info_impl(sys_seconds tp) const; @@ -834,7 +842,7 @@ class time_zone sys_time::type> to_sys_impl(local_time tp, choose, std::true_type) const; -#if USE_OS_TZDB +#if USE_BINARY_TZDB DATE_API void init() const; DATE_API void init_impl(); DATE_API sys_info @@ -844,11 +852,11 @@ class time_zone DATE_API void load_data(std::istream& inf, std::int32_t tzh_leapcnt, std::int32_t tzh_timecnt, std::int32_t tzh_typecnt, std::int32_t tzh_charcnt); -#else // !USE_OS_TZDB +#else // !USE_BINARY_TZDB DATE_API sys_info get_info_impl(sys_seconds tp, int timezone) const; DATE_API void adjust_infos(const std::vector& rules); DATE_API void parse_info(std::istream& in); -#endif // !USE_OS_TZDB +#endif // !USE_BINARY_TZDB }; #if defined(_MSC_VER) && (_MSC_VER < 1900) @@ -958,7 +966,7 @@ time_zone::to_sys_impl(local_time tp, choose, std::true_type) const return sys_time{tp.time_since_epoch()} - i.first.offset; } -#if !USE_OS_TZDB +#if !USE_BINARY_TZDB class time_zone_link { @@ -984,7 +992,7 @@ inline bool operator> (const time_zone_link& x, const time_zone_link& y) {return inline bool operator<=(const time_zone_link& x, const time_zone_link& y) {return !(y < x);} inline bool operator>=(const time_zone_link& x, const time_zone_link& y) {return !(x < y);} -#endif // !USE_OS_TZDB +#endif // !USE_BINARY_TZDB class leap_second { @@ -992,7 +1000,7 @@ class leap_second sys_seconds date_; public: -#if USE_OS_TZDB +#if USE_BINARY_TZDB DATE_API explicit leap_second(const sys_seconds& s, detail::undocumented); #else DATE_API explicit leap_second(const std::string& s, detail::undocumented); @@ -1151,11 +1159,11 @@ struct tzdb { std::string version = "unknown"; std::vector zones; -#if !USE_OS_TZDB +#if !USE_BINARY_TZDB std::vector links; #endif std::vector leap_seconds; -#if !USE_OS_TZDB +#if !USE_BINARY_TZDB std::vector rules; #endif #ifdef _WIN32 @@ -1294,12 +1302,14 @@ tzdb_list::cend() const NOEXCEPT DATE_API tzdb_list& get_tzdb_list(); -#if !USE_OS_TZDB - +#if USE_BINARY_TZDB +# if !USE_OS_TZDB +DATE_API void set_tz_dir(const std::string& tz_dir); +# endif // !USE_OS_TZDB +#else // !USE_BINARY_TZDB DATE_API const tzdb& reload_tzdb(); DATE_API void set_install(const std::string& install); - -#endif // !USE_OS_TZDB +#endif // USE_BINARY_TZDB #if HAS_REMOTE_API diff --git a/include/date/tz_private.h b/include/date/tz_private.h index aec01d04..d9a9b137 100644 --- a/include/date/tz_private.h +++ b/include/date/tz_private.h @@ -40,7 +40,7 @@ namespace date namespace detail { -#if !USE_OS_TZDB +#if !USE_BINARY_TZDB enum class tz {utc, local, standard}; @@ -256,7 +256,7 @@ struct zonelet zonelet& operator=(const zonelet&) = delete; }; -#else // USE_OS_TZDB +#else // USE_BINARY_TZDB struct ttinfo { @@ -303,7 +303,7 @@ struct transition } }; -#endif // USE_OS_TZDB +#endif // USE_BINARY_TZDB } // namespace detail diff --git a/src/tz.cpp b/src/tz.cpp index 7cbdbcb9..54b8b223 100644 --- a/src/tz.cpp +++ b/src/tz.cpp @@ -92,7 +92,7 @@ # define TARGET_OS_SIMULATOR 0 #endif -#if USE_OS_TZDB +#if USE_BINARY_TZDB # include #endif #include @@ -105,7 +105,7 @@ #include #include #include -#if USE_OS_TZDB +#if USE_BINARY_TZDB # include #endif #include @@ -141,7 +141,7 @@ # endif // HAS_REMOTE_API #else // !_WIN32 # include -# if !USE_OS_TZDB && !defined(INSTALL) +# if !USE_BINARY_TZDB && !defined(INSTALL) # include # endif # include @@ -180,7 +180,7 @@ static CONSTDATA char folder_delimiter = '/'; # pragma GCC diagnostic ignored "-Wmissing-field-initializers" #endif // defined(__GNUC__) && __GNUC__ < 5 -#if !USE_OS_TZDB +#if !USE_BINARY_TZDB # ifdef _WIN32 # ifndef WINRT @@ -267,7 +267,7 @@ get_download_folder() # endif // !_WIN32 -#endif // !USE_OS_TZDB +#endif // !USE_BINARY_TZDB namespace date { @@ -277,7 +277,7 @@ namespace date using namespace detail; -#if !USE_OS_TZDB +#if !USE_BINARY_TZDB static std::string& @@ -326,7 +326,7 @@ get_download_gz_file(const std::string& version) } #endif // HAS_REMOTE_API -#endif // !USE_OS_TZDB +#endif // !USE_BINARY_TZDB // These can be used to reduce the range of the database to save memory CONSTDATA auto min_year = date::year::min(); @@ -335,13 +335,13 @@ CONSTDATA auto max_year = date::year::max(); CONSTDATA auto min_day = date::January/1; CONSTDATA auto max_day = date::December/31; -#if USE_OS_TZDB +#if USE_BINARY_TZDB CONSTCD14 const sys_seconds min_seconds = sys_days(min_year/min_day); -#endif // USE_OS_TZDB +#endif // USE_BINARY_TZDB -#ifndef _WIN32 +#if USE_OS_TZDB static std::string @@ -396,7 +396,33 @@ get_tz_dir() return tz_dir; } -#endif +#elif USE_BINARY_TZDB // !USE_OS_TZDB + +static +std::string& +access_tz_dir() +{ + static std::string tz_dir; + return tz_dir; +} + +void +set_tz_dir(const std::string& tz_dir) +{ + access_tz_dir() = tz_dir; +} + +static +const std::string& +get_tz_dir() +{ + static const std::string& tz_dir = access_tz_dir(); + if (tz_dir.empty()) + throw std::runtime_error("set_tz_dir() must set a directory path before calling get_tz_dir()."); + return tz_dir; +} + +#endif // USE_OS_TZDB // +-------------------+ // | End Configuration | @@ -491,7 +517,7 @@ parse_month(std::istream& in) return static_cast(++m); } -#if !USE_OS_TZDB +#if !USE_BINARY_TZDB #ifdef _WIN32 @@ -1718,11 +1744,11 @@ detail::zonelet::zonelet(const zonelet& i) #endif } -#endif // !USE_OS_TZDB +#endif // !USE_BINARY_TZDB // time_zone -#if USE_OS_TZDB +#if USE_BINARY_TZDB time_zone::time_zone(const std::string& s, detail::undocumented) : name_(s) @@ -2226,7 +2252,7 @@ leap_second::leap_second(const sys_seconds& s, detail::undocumented) { } -#else // !USE_OS_TZDB +#else // !USE_BINARY_TZDB time_zone::time_zone(const std::string& s, detail::undocumented) : adjusted_(new std::once_flag{}) @@ -2620,7 +2646,7 @@ operator<<(std::ostream& os, const time_zone& z) return os; } -#endif // !USE_OS_TZDB +#endif // !USE_BINARY_TZDB std::ostream& operator<<(std::ostream& os, const leap_second& x) @@ -2629,7 +2655,7 @@ operator<<(std::ostream& os, const leap_second& x) return os << x.date_ << " +"; } -#if USE_OS_TZDB +#if USE_BINARY_TZDB static std::string @@ -2793,7 +2819,7 @@ init_tzdb() return db; } -#else // !USE_OS_TZDB +#else // !USE_BINARY_TZDB // time_zone_link @@ -3569,7 +3595,7 @@ reload_tzdb() return get_tzdb_list().front(); } -#endif // !USE_OS_TZDB +#endif // !USE_BINARY_TZDB const tzdb& get_tzdb() @@ -3595,7 +3621,7 @@ tzdb::locate_zone(const std::string& tz_name) const }); if (zi == zones.end() || zi->name() != tz_name) { -#if !USE_OS_TZDB +#if !USE_BINARY_TZDB auto li = std::lower_bound(links.begin(), links.end(), tz_name, #if HAS_STRING_VIEW [](const time_zone_link& z, const std::string_view& nm) @@ -3615,7 +3641,7 @@ tzdb::locate_zone(const std::string& tz_name) const if (zi != zones.end() && zi->name() == li->target()) return &*zi; } -#endif // !USE_OS_TZDB +#endif // !USE_BINARY_TZDB throw std::runtime_error(std::string(tz_name) + " not found in timezone database"); } return &*zi; @@ -3631,7 +3657,7 @@ locate_zone(const std::string& tz_name) return get_tzdb().locate_zone(tz_name); } -#if USE_OS_TZDB +#if USE_BINARY_TZDB std::ostream& operator<<(std::ostream& os, const tzdb& db) @@ -3645,7 +3671,7 @@ operator<<(std::ostream& os, const tzdb& db) return os; } -#else // !USE_OS_TZDB +#else // !USE_BINARY_TZDB std::ostream& operator<<(std::ostream& os, const tzdb& db) @@ -3704,7 +3730,7 @@ operator<<(std::ostream& os, const tzdb& db) return os; } -#endif // !USE_OS_TZDB +#endif // !USE_BINARY_TZDB // ----------------------- @@ -3833,6 +3859,7 @@ tzdb::current_zone() const return locate_zone(extract_tz_name(rp)); } } +#if USE_OS_TZDB // On embedded systems e.g. buildroot with uclibc the timezone is linked // into /etc/TZ which is a symlink to path like this: // "/usr/share/zoneinfo/uclibc/America/Los_Angeles" @@ -3861,6 +3888,7 @@ tzdb::current_zone() const return locate_zone(result); } } +#endif // USE_OS_TZDB { // On some versions of some linux distro's (e.g. Ubuntu), // the current timezone might be in the first line of