diff --git a/recipes/date/all/conandata.yml b/recipes/date/all/conandata.yml index bed2d768a8963..2d1fd7013f259 100644 --- a/recipes/date/all/conandata.yml +++ b/recipes/date/all/conandata.yml @@ -13,10 +13,18 @@ patches: - patch_file: "patches/cmake-3.0.1.patch" patch_description: "Disable string view to workaround clang 5 not having it" patch_type: "portability" + - patch_file: "patches/load-tzdb-from-envvar-3.0.x.patch" + patch_description: "Allow TZDB to be loaded from the TZDATA environment variable" + patch_type: "portability" + patch_source: "https://github.com/HowardHinnant/date/pull/807" "3.0.0": - patch_file: "patches/cmake-3.0.0.patch" patch_description: "Disable string view to workaround clang 5 not having it" patch_type: "portability" + - patch_file: "patches/load-tzdb-from-envvar-3.0.x.patch" + patch_description: "Allow TZDB to be loaded from the TZDATA environment variable" + patch_type: "portability" + patch_source: "https://github.com/HowardHinnant/date/pull/807" "2.4.1": - patch_file: "patches/0001-fix-uwp.patch" patch_description: "Fix Universal Windows Platform (UWP) unhandled exception support. See https://github.com/microsoft/vcpkg/pull/8151#issuecomment-531175393." @@ -27,3 +35,7 @@ patches: - patch_file: "patches/string_view.patch" patch_description: "Disable string view to workaround clang 5 not having it" patch_type: "portability" + - patch_file: "patches/load-tzdb-from-envvar-2.4.1.patch" + patch_description: "Allow TZDB to be loaded from the TZDATA environment variable" + patch_type: "portability" + patch_source: "https://github.com/HowardHinnant/date/pull/807" diff --git a/recipes/date/all/conanfile.py b/recipes/date/all/conanfile.py index 315ca73f8ae1f..357f5ded4065a 100644 --- a/recipes/date/all/conanfile.py +++ b/recipes/date/all/conanfile.py @@ -3,6 +3,7 @@ from conan.tools.cmake import CMake, CMakeToolchain, CMakeDeps, cmake_layout from conan.tools.files import get, rmdir, apply_conandata_patches, export_conandata_patches, copy from conan.tools.scm import Version +from conan.errors import ConanInvalidConfiguration import os @@ -22,7 +23,9 @@ class DateConan(ConanFile): "shared": [True, False], "fPIC": [True, False], "header_only": [True, False], - "use_system_tz_db": [True, False], + "use_system_tz_db": [True, False, "deprecated"], + "with_tzdb": [False, "system", "download", "manual", "tz"], + "with_db_format": ["source", "binary"], "use_tz_db_in_dot": [True, False], } default_options = { @@ -30,6 +33,8 @@ class DateConan(ConanFile): "fPIC": True, "header_only": False, "use_system_tz_db": False, + "with_tzdb": "tz", + "with_db_format": "source", "use_tz_db_in_dot": False, } @@ -53,8 +58,10 @@ def layout(self): cmake_layout(self, src_folder="src") def requirements(self): - if not self.options.header_only and not self.options.use_system_tz_db: + if not self.options.header_only and not self.options.use_system_tz_db and self.options.with_tzdb == "download": self.requires("libcurl/[>=7.78 <9]") + if self.options.with_tzdb == "tz": + self.requires("tz/2023c", options={"with_binary_db": self.options.with_db_format == "binary"}) def package_id(self): if self.info.options.header_only: @@ -63,6 +70,14 @@ def package_id(self): def validate(self): if self.settings.compiler.get_safe("cppstd"): check_min_cppstd(self, 11) + if self.options.with_tzdb != "download" and self.options.use_tz_db_in_dot: + raise ConanInvalidConfiguration("'use_tz_db_in_dot=True' is only valid when 'with_tzdb=\"download\"'") + if self.options.use_system_tz_db and (self.options.with_tzdb not in [False, "system"]): + raise ConanInvalidConfiguration("'use_system_tz_db' is deprecated. You must set 'with_tzdb=system'") + if (self.options.use_system_tz_db or self.options.with_tzdb == "system") and not self.options.with_db_format == "binary": + raise ConanInvalidConfiguration("date only supports using the operating system database in a binary format. You must set 'with_db_format=binary'") + if self.settings.os == "Windows" and self.options.with_db_format == "binary": + raise ConanInvalidConfiguration("date does not currently support parsing the binary tzdb on Windows. An attempt has been made to introduce this in https://github.com/HowardHinnant/date/pull/611, so if this is functionality you would like please feel free to adapt this to a conan patch.") def source(self): get(self, **self.conan_data["sources"][self.version], strip_root=True) @@ -70,9 +85,10 @@ def source(self): def generate(self): tc = CMakeToolchain(self) tc.variables["ENABLE_DATE_TESTING"] = False - tc.variables["USE_SYSTEM_TZ_DB"] = self.options.use_system_tz_db + tc.variables["USE_SYSTEM_TZ_DB"] = (self.options.use_system_tz_db or self.options.with_tzdb in ["system", "tz"]) and self.options.with_db_format == "binary" tc.variables["USE_TZ_DB_IN_DOT"] = self.options.use_tz_db_in_dot tc.variables["BUILD_TZ_LIB"] = not self.options.header_only + tc.variables["MANUAL_TZ_DB"] = self.options.with_tzdb in ["manual", "tz"] and not self.options.with_db_format == "binary" # workaround for clang 5 not having string_view if Version(self.version) >= "3.0.0" and self.settings.compiler == "clang" \ and Version(self.settings.compiler.version) <= "5.0": @@ -123,10 +139,10 @@ def package_info(self): self.cpp_info.components["date-tz"].system_libs.append("pthread") self.cpp_info.components["date-tz"].system_libs.append("m") - if not self.options.use_system_tz_db: + if self.options.with_tzdb == "download": self.cpp_info.components["date-tz"].requires.append("libcurl::libcurl") - if self.options.use_system_tz_db and not self.settings.os == "Windows": + if (self.options.use_system_tz_db or self.options.with_tzdb in ["system", "tz"]) and self.options.with_db_format == "binary": use_os_tzdb = 1 else: use_os_tzdb = 0 diff --git a/recipes/date/all/patches/load-tzdb-from-envvar-2.4.1.patch b/recipes/date/all/patches/load-tzdb-from-envvar-2.4.1.patch new file mode 100644 index 0000000000000..d35040f1078ee --- /dev/null +++ b/recipes/date/all/patches/load-tzdb-from-envvar-2.4.1.patch @@ -0,0 +1,117 @@ +From 73ed8608827b3256e4f97415c9e2014fd31da2be Mon Sep 17 00:00:00 2001 +From: Samuel Dowling +Date: Sat, 13 Jan 2024 19:57:49 +1030 +Subject: [PATCH] Add ability to specify timezone database location via + environment variable + +This adds the ability for a user to populate the TZDATA environment +variable to specify the location in which to look for the timezone +database, which allows for a runtime query of this location. Without +this, date currently only supports compile time determination of the +database location. + +This facilitates the ability to: +* Use a timezone database provided by a package manager +* Keep the timezone database up to date without re-compilation +* Be flexible about where the timezone database is stored + +Closes #788 +--- + CMakeLists.txt | 23 +++++++++++++++-------- + src/tz.cpp | 19 +++++++++++++++++++ + 2 files changed, 34 insertions(+), 8 deletions(-) + +diff --git a/CMakeLists.txt b/CMakeLists.txt +index 7bc93df..ac989c8 100644 +--- a/CMakeLists.txt ++++ b/CMakeLists.txt +@@ -23,6 +23,7 @@ function( print_option OPT ) + endfunction( ) + + print_option( USE_SYSTEM_TZ_DB ) ++print_option( MANUAL_TZ_DB ) + print_option( USE_TZ_DB_IN_DOT ) + print_option( BUILD_SHARED_LIBS ) + print_option( ENABLE_DATE_TESTING ) +@@ -45,20 +46,26 @@ set( HEADER_FILES + + add_library( tz ${HEADER_FILES} ${SOURCE_FOLDER}/tz.cpp ) + +-if( USE_SYSTEM_TZ_DB ) ++if( USE_SYSTEM_TZ_DB OR MANUAL_TZ_DB ) + target_compile_definitions( tz PRIVATE -DUSE_AUTOLOAD=0 ) + target_compile_definitions( tz PRIVATE -DHAS_REMOTE_API=0 ) +- # cannot set USE_OS_TZDB to 1 on Windows +- if( NOT WIN32 ) +- target_compile_definitions( tz PUBLIC -DUSE_OS_TZDB=1 ) +- endif( ) + else( ) + target_compile_definitions( tz PRIVATE -DUSE_AUTOLOAD=1 ) + target_compile_definitions( tz PRIVATE -DHAS_REMOTE_API=1 ) +- target_compile_definitions( tz PUBLIC -DUSE_OS_TZDB=0 ) +- find_package( CURL REQUIRED ) ++endif( ) ++ ++if ( USE_SYSTEM_TZ_DB AND NOT MANUAL_TZ_DB ) ++ target_compile_definitions( tz PRIVATE -DINSTALL=. ) ++ target_compile_definitions( tz PUBLIC -DUSE_OS_TZDB=1 ) ++else( ) ++ target_compile_definitions( tz PUBLIC USE_OS_TZDB=0 ) ++endif( ) ++ ++if( NOT USE_SYSTEM_TZ_DB AND NOT MANUAL_TZ_DB ) ++ find_package( CURL REQUIRED ) ++ include_directories( SYSTEM ${CURL_INCLUDE_DIRS} ) + set( OPTIONAL_LIBRARIES CURL::libcurl ) +-endif() ++endif( ) + + if( BUILD_SHARED_LIBS ) + target_compile_definitions( tz PRIVATE -DDATE_BUILD_DLL=1 ) +diff --git a/src/tz.cpp b/src/tz.cpp +index f4a819b..fd7cd9f 100644 +--- a/src/tz.cpp ++++ b/src/tz.cpp +@@ -81,6 +81,9 @@ + # endif // __MINGW32__ + + # include ++# if !defined(S_ISDIR) && defined(S_IFMT) && defined(_S_IFDIR) ++# define S_ISDIR(m) (((m) & S_IFMT) == _S_IFDIR) ++# endif + #endif // _WIN32 + + #include "date/tz_private.h" +@@ -276,6 +279,14 @@ access_install() + #undef STRINGIZE + #endif // !INSTALL + ++ { ++ static char* tz_local_env = getenv("TZDATA"); ++ if (tz_local_env != nullptr) { ++ static std::string tz_local_env_s = tz_local_env; ++ return tz_local_env_s; ++ } ++ } ++ + return install; + } + +@@ -330,6 +341,14 @@ discover_tz_dir() + CONSTDATA auto tz_dir_default = "/usr/share/zoneinfo"; + CONSTDATA auto tz_dir_buildroot = "/usr/share/zoneinfo/uclibc"; + ++ { ++ static char* tz_local_env = getenv("TZDATA"); ++ if (tz_local_env != nullptr) { ++ static std::string tz_local_env_s = tz_local_env; ++ return tz_local_env_s; ++ } ++ } ++ + // Check special path which is valid for buildroot with uclibc builds + if(stat(tz_dir_buildroot, &sb) == 0 && S_ISDIR(sb.st_mode)) + return tz_dir_buildroot; +-- +2.43.0.windows.1 + diff --git a/recipes/date/all/patches/load-tzdb-from-envvar-3.0.x.patch b/recipes/date/all/patches/load-tzdb-from-envvar-3.0.x.patch new file mode 100644 index 0000000000000..5e2d16697032e --- /dev/null +++ b/recipes/date/all/patches/load-tzdb-from-envvar-3.0.x.patch @@ -0,0 +1,69 @@ +From 8b2cceb71f65f6aa6bdb3ffa63a63400214d5f1b Mon Sep 17 00:00:00 2001 +From: Samuel Dowling +Date: Sat, 13 Jan 2024 19:57:49 +1030 +Subject: [PATCH] Add ability to specify timezone database location via + environment variable + +This adds the ability for a user to populate the TZDATA environment +variable to specify the location in which to look for the timezone +database, which allows for a runtime query of this location. Without +this, date currently only supports compile time determination of the +database location. + +This facilitates the ability to: +* Use a timezone database provided by a package manager +* Keep the timezone database up to date without re-compilation +* Be flexible about where the timezone database is stored + +Closes #788 +--- + src/tz.cpp | 19 +++++++++++++++++++ + 1 file changed, 19 insertions(+) + +diff --git a/src/tz.cpp b/src/tz.cpp +index 26babbd..6d010b8 100644 +--- a/src/tz.cpp ++++ b/src/tz.cpp +@@ -81,6 +81,9 @@ + # endif // __MINGW32__ + + # include ++# if !defined(S_ISDIR) && defined(S_IFMT) && defined(_S_IFDIR) ++# define S_ISDIR(m) (((m) & S_IFMT) == _S_IFDIR) ++# endif + #endif // _WIN32 + + #include "date/tz_private.h" +@@ -299,6 +302,14 @@ access_install() + #undef STRINGIZE + #endif // !INSTALL + ++ { ++ static char* tz_local_env = getenv("TZDATA"); ++ if (tz_local_env != nullptr) { ++ static std::string tz_local_env_s = tz_local_env; ++ return tz_local_env_s; ++ } ++ } ++ + return install; + } + +@@ -353,6 +364,14 @@ discover_tz_dir() + CONSTDATA auto tz_dir_default = "/usr/share/zoneinfo"; + CONSTDATA auto tz_dir_buildroot = "/usr/share/zoneinfo/uclibc"; + ++ { ++ static char* tz_local_env = getenv("TZDATA"); ++ if (tz_local_env != nullptr) { ++ static std::string tz_local_env_s = tz_local_env; ++ return tz_local_env_s; ++ } ++ } ++ + // Check special path which is valid for buildroot with uclibc builds + if(stat(tz_dir_buildroot, &sb) == 0 && S_ISDIR(sb.st_mode)) + return tz_dir_buildroot; +-- +2.43.0.windows.1 + diff --git a/recipes/date/all/test_package/test_package.cpp b/recipes/date/all/test_package/test_package.cpp index 8dcac9f656989..87f4c68e8cf7f 100644 --- a/recipes/date/all/test_package/test_package.cpp +++ b/recipes/date/all/test_package/test_package.cpp @@ -15,8 +15,7 @@ class ZoneOffset { auto to_local(date::sys_time tp) const -> date::local_time::type> { using namespace date; - using namespace std::chrono; - using LT = local_time::type>; + using LT = local_time::type>; return LT{(tp + _offset).time_since_epoch()}; } @@ -24,8 +23,7 @@ class ZoneOffset { auto to_sys(date::local_time tp) const -> date::sys_time::type> { using namespace date; - using namespace std::chrono; - using ST = sys_time::type>; + using ST = sys_time::type>; return ST{(tp - _offset).time_since_epoch()}; } @@ -34,7 +32,6 @@ class ZoneOffset { }; int main() { - using namespace std::chrono; using namespace date; auto date1 = 2015_y/March/22; @@ -44,8 +41,8 @@ int main() { auto date3 = 22_d/March/2015; std::cout << date3 << '\n'; - ZoneOffset p3_45{hours{3} + minutes{45}}; - zoned_time zt{&p3_45, floor(system_clock::now())}; + ZoneOffset p3_45{std::chrono::hours{3} + std::chrono::minutes{45}}; + zoned_time zt{&p3_45, floor(std::chrono::system_clock::now())}; std::cout << zt.get_sys_time() << " (sys time)\n"; std::cout << zt.get_local_time() << " (local time)\n";