forked from conan-io/conan-center-index
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[date] Hotfix date#611 to v3.0.0 and v2.4.1
* Add patches for v3.0.0 and v2.4.1 that hotfix the changes present in HowardHinnant/date#611 on to these older versions. This will allow all versions of date currently on CCI to utilise the tz package as a data source for the timezone database. Some additional modification of the build system was required in these patches to ensure a consistent interface across versions. Only the minimal changes necessary to introduce desired features were made, preserving deficiencies associated with older versions of date.
- Loading branch information
1 parent
6a8e364
commit 7a12d26
Showing
3 changed files
with
725 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
359 changes: 359 additions & 0 deletions
359
recipes/date/all/patches/load-tzdb-from-envvar-and-windows-binary-db-support-2.4.1.patch
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,359 @@ | ||
From 7505317a4b5397f70e9007c871a73245a4f60417 Mon Sep 17 00:00:00 2001 | ||
From: John McCann Cunniff Jr <[email protected]> | ||
Date: Tue, 20 Oct 2020 12:54:56 -0400 | ||
Subject: [PATCH] ADD windows support for USE_SYSTEM_TZ_DB | ||
|
||
--- | ||
CMakeLists.txt | 23 ++++--- | ||
include/date/tz.h | 3 - | ||
src/tz.cpp | 170 ++++++++++++++++++++++++++++++++++++---------- | ||
3 files changed, 149 insertions(+), 47 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/include/date/tz.h b/include/date/tz.h | ||
index 9840e7b..53f4a56 100644 | ||
--- a/include/date/tz.h | ||
+++ b/include/date/tz.h | ||
@@ -83,9 +83,6 @@ static_assert(HAS_REMOTE_API == 0 ? AUTO_DOWNLOAD == 0 : true, | ||
#endif | ||
|
||
#if USE_OS_TZDB | ||
-# ifdef _WIN32 | ||
-# error "USE_OS_TZDB can not be used on Windows" | ||
-# endif | ||
# ifndef MISSING_LEAP_SECONDS | ||
# ifdef __APPLE__ | ||
# define MISSING_LEAP_SECONDS 1 | ||
diff --git a/src/tz.cpp b/src/tz.cpp | ||
index f4a819b..0cde872 100644 | ||
--- a/src/tz.cpp | ||
+++ b/src/tz.cpp | ||
@@ -81,6 +81,10 @@ | ||
# endif // __MINGW32__ | ||
|
||
# include <windows.h> | ||
+# include <regex> | ||
+# 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" | ||
@@ -92,7 +96,12 @@ | ||
#endif | ||
|
||
#if USE_OS_TZDB | ||
-# include <dirent.h> | ||
+# if !WIN32 | ||
+# include <dirent.h> | ||
+# else | ||
+# include <windef.h> | ||
+# include <fstream> | ||
+# endif | ||
#endif | ||
#include <algorithm> | ||
#include <cctype> | ||
@@ -276,6 +285,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; | ||
} | ||
|
||
@@ -318,7 +335,6 @@ CONSTCD14 const sys_seconds min_seconds = sys_days(min_year/min_day); | ||
|
||
#endif // USE_OS_TZDB | ||
|
||
-#ifndef _WIN32 | ||
|
||
static | ||
std::string | ||
@@ -330,6 +346,16 @@ discover_tz_dir() | ||
CONSTDATA auto tz_dir_default = "/usr/share/zoneinfo"; | ||
CONSTDATA auto tz_dir_buildroot = "/usr/share/zoneinfo/uclibc"; | ||
|
||
+ { | ||
+ // TZDIR is from the posix naming | ||
+ // https://man7.org/linux/man-pages/man3/tzset.3.html | ||
+ 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; | ||
@@ -369,7 +395,6 @@ get_tz_dir() | ||
return tz_dir; | ||
} | ||
|
||
-#endif | ||
|
||
// +-------------------+ | ||
// | End Configuration | | ||
@@ -443,7 +468,31 @@ get_tzdb_list() | ||
return tz_db; | ||
} | ||
|
||
-#if !USE_OS_TZDB | ||
+static | ||
+std::string | ||
+parse3(std::istream& in) | ||
+{ | ||
+ std::string r(3, ' '); | ||
+ ws(in); | ||
+ r[0] = static_cast<char>(in.get()); | ||
+ r[1] = static_cast<char>(in.get()); | ||
+ r[2] = static_cast<char>(in.get()); | ||
+ return r; | ||
+} | ||
+ | ||
+static | ||
+unsigned | ||
+parse_month(std::istream& in) | ||
+{ | ||
+ CONSTDATA char*const month_names[] = | ||
+ {"Jan", "Feb", "Mar", "Apr", "May", "Jun", | ||
+ "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"}; | ||
+ auto s = parse3(in); | ||
+ auto m = std::find(std::begin(month_names), std::end(month_names), s) - month_names; | ||
+ if (m >= std::end(month_names) - std::begin(month_names)) | ||
+ throw std::runtime_error("oops: bad month name: " + s); | ||
+ return static_cast<unsigned>(++m); | ||
+} | ||
|
||
#ifdef _WIN32 | ||
|
||
@@ -655,19 +704,9 @@ load_timezone_mappings_from_xml_file(const std::string& input_path) | ||
|
||
#endif // _WIN32 | ||
|
||
-// Parsing helpers | ||
|
||
-static | ||
-std::string | ||
-parse3(std::istream& in) | ||
-{ | ||
- std::string r(3, ' '); | ||
- ws(in); | ||
- r[0] = static_cast<char>(in.get()); | ||
- r[1] = static_cast<char>(in.get()); | ||
- r[2] = static_cast<char>(in.get()); | ||
- return r; | ||
-} | ||
+#if !USE_OS_TZDB | ||
+// Parsing helpers | ||
|
||
static | ||
unsigned | ||
@@ -682,20 +721,6 @@ parse_dow(std::istream& in) | ||
return static_cast<unsigned>(dow); | ||
} | ||
|
||
-static | ||
-unsigned | ||
-parse_month(std::istream& in) | ||
-{ | ||
- CONSTDATA char*const month_names[] = | ||
- {"Jan", "Feb", "Mar", "Apr", "May", "Jun", | ||
- "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"}; | ||
- auto s = parse3(in); | ||
- auto m = std::find(std::begin(month_names), std::end(month_names), s) - month_names; | ||
- if (m >= std::end(month_names) - std::begin(month_names)) | ||
- throw std::runtime_error("oops: bad month name: " + s); | ||
- return static_cast<unsigned>(++m); | ||
-} | ||
- | ||
static | ||
std::chrono::seconds | ||
parse_unsigned_time(std::istream& in) | ||
@@ -1710,9 +1735,15 @@ time_zone::time_zone(const std::string& s, detail::undocumented) | ||
|
||
enum class endian | ||
{ | ||
- native = __BYTE_ORDER__, | ||
+#ifdef _WIN32 | ||
+ little = 0, | ||
+ big = 1, | ||
+ native = little | ||
+#else | ||
little = __ORDER_LITTLE_ENDIAN__, | ||
- big = __ORDER_BIG_ENDIAN__ | ||
+ big = __ORDER_BIG_ENDIAN__, | ||
+ native = __BYTE_ORDER__ | ||
+#endif | ||
}; | ||
|
||
static | ||
@@ -2018,8 +2049,10 @@ time_zone::init_impl() | ||
{ | ||
using namespace std; | ||
using namespace std::chrono; | ||
- auto name = get_tz_dir() + ('/' + name_); | ||
- std::ifstream inf(name); | ||
+ auto name = get_tz_dir() + (folder_delimiter + name_); | ||
+ // Some platforms will open the inf stream in text mode. Specify binary | ||
+ // to avoid confusion. | ||
+ std::ifstream inf(name, std::ios::in | std::ios::binary); | ||
if (!inf.is_open()) | ||
throw std::runtime_error{"Unable to open " + name}; | ||
inf.exceptions(std::ios::failbit | std::ios::badbit); | ||
@@ -2630,8 +2663,10 @@ init_tzdb() | ||
//Iterate through folders | ||
std::queue<std::string> subfolders; | ||
subfolders.emplace(get_tz_dir()); | ||
- struct dirent* d; | ||
+ | ||
struct stat s; | ||
+#if !WIN32 // !WIN32 | ||
+ struct dirent* d; | ||
while (!subfolders.empty()) | ||
{ | ||
auto dirname = std::move(subfolders.front()); | ||
@@ -2648,8 +2683,11 @@ init_tzdb() | ||
strcmp(d->d_name, "iso3166.tab") == 0 || | ||
strcmp(d->d_name, "right") == 0 || | ||
strcmp(d->d_name, "+VERSION") == 0 || | ||
+ strcmp(d->d_name, "version") == 0 || | ||
strcmp(d->d_name, "zone.tab") == 0 || | ||
strcmp(d->d_name, "zone1970.tab") == 0 || | ||
+ strcmp(d->d_name, "tzdata.zi") == 0 || | ||
+ strcmp(d->d_name, "leapseconds") == 0 || | ||
strcmp(d->d_name, "leap-seconds.list") == 0 ) | ||
continue; | ||
auto subname = dirname + folder_delimiter + d->d_name; | ||
@@ -2671,6 +2709,56 @@ init_tzdb() | ||
} | ||
closedir(dir); | ||
} | ||
+#else // WIN32 | ||
+ // POSIX dirent is not availible in Visual C++ | ||
+ // Use Windows file API instead | ||
+ WIN32_FIND_DATA hFindData; | ||
+ while (!subfolders.empty()) | ||
+ { | ||
+ auto dirname = std::move(subfolders.front()); | ||
+ subfolders.pop(); | ||
+ HANDLE hFind = FindFirstFile((dirname + "\\\\*").c_str(), &hFindData); | ||
+ if (hFind == INVALID_HANDLE_VALUE) | ||
+ { | ||
+ continue; | ||
+ } | ||
+ | ||
+ do | ||
+ { | ||
+ // Ignore these files: | ||
+ if (hFindData.cFileName[0] == '.' || // curdir, prevdir, hidden | ||
+ memcmp(hFindData.cFileName, "posix", 5) == 0 || // starts with posix | ||
+ strcmp(hFindData.cFileName, "Factory") == 0 || | ||
+ strcmp(hFindData.cFileName, "iso3166.tab") == 0 || | ||
+ strcmp(hFindData.cFileName, "right") == 0 || | ||
+ strcmp(hFindData.cFileName, "+VERSION") == 0 || | ||
+ strcmp(hFindData.cFileName, "zone.tab") == 0 || | ||
+ strcmp(hFindData.cFileName, "zone1970.tab") == 0 || | ||
+ strcmp(hFindData.cFileName, "tzdata.zi") == 0 || | ||
+ strcmp(hFindData.cFileName, "leapseconds") == 0 || | ||
+ strcmp(hFindData.cFileName, "leap-seconds.list") == 0 ) | ||
+ { | ||
+ continue; | ||
+ } | ||
+ auto subname = dirname + folder_delimiter + hFindData.cFileName; | ||
+ if(stat(subname.c_str(), &s) == 0) | ||
+ { | ||
+ if(S_ISDIR(s.st_mode)) | ||
+ { | ||
+ subfolders.push(subname); | ||
+ } | ||
+ else | ||
+ { | ||
+ std::string zone = subname.substr(get_tz_dir().size()+1); | ||
+ db->zones.emplace_back(zone, | ||
+ detail::undocumented{}); | ||
+ } | ||
+ } | ||
+ } | ||
+ while (FindNextFile(hFind, &hFindData )); | ||
+ FindClose(hFind); | ||
+ } | ||
+#endif // WIN32 | ||
db->zones.shrink_to_fit(); | ||
std::sort(db->zones.begin(), db->zones.end()); | ||
# if !MISSING_LEAP_SECONDS | ||
@@ -3528,7 +3616,17 @@ locate_zone(std::string_view tz_name) | ||
locate_zone(const std::string& tz_name) | ||
#endif | ||
{ | ||
- return get_tzdb().locate_zone(tz_name); | ||
+ return get_tzdb().locate_zone( | ||
+#if WIN32 && USE_OS_TZDB | ||
+ // When USE_OS_TZDB=ON, the tz_name needs to be a valid path. | ||
+ // For timezone labeling consistency in Windows, switch "/" to "\". | ||
+ // This will allow for tz_name to have consistent naming regardless of | ||
+ // if USE_OS_TZDB is ON. | ||
+ std::regex_replace(tz_name, std::regex("\\/"), "\\") | ||
+#else | ||
+ tz_name | ||
+#endif | ||
+ ); | ||
} | ||
|
||
#if USE_OS_TZDB | ||
-- | ||
2.24.3 (Apple Git-128) | ||
|
Oops, something went wrong.