forked from HowardHinnant/date
Compare commits
35 Commits
v3.0.0
...
esp-idf-re
Author | SHA1 | Date | |
---|---|---|---|
1658637448 | |||
4bbbffdf4c | |||
8ec7f3a36d | |||
b1a75847d5 | |||
49d78d1837 | |||
a32ff4f07e | |||
3be6b76d70 | |||
bf79dd5a81 | |||
26fc2bd372 | |||
97246a638a | |||
432bab81f9 | |||
215cacff56 | |||
3cbfa4318f | |||
115dd428cf | |||
7848566815 | |||
393b52f21b | |||
0b72599bd4 | |||
ba99134b8a | |||
5e18488899 | |||
313189b0a8 | |||
057b441ceb | |||
d7a0bf1fa7 | |||
8140d979cd | |||
7990eae740 | |||
1ec2ea0295 | |||
658a3b9495 | |||
e7969c32e8 | |||
569b2d6785 | |||
abe3ada04f | |||
9537addfc4 | |||
6952fb50a6 | |||
fe2f9c7eac | |||
a6243ce56f | |||
a55f1a103b | |||
d544e5af25 |
269
CMakeLists.txt
269
CMakeLists.txt
@ -1,248 +1,23 @@
|
||||
#[===================================================================[
|
||||
date library by Howard Hinnant
|
||||
if(DEFINED IDF_TARGET)
|
||||
idf_component_register(INCLUDE_DIRS include)
|
||||
set_property(TARGET ${COMPONENT_LIB} PROPERTY CXX_STANDARD 23)
|
||||
target_compile_definitions(${COMPONENT_TARGET} INTERFACE HAS_UNCAUGHT_EXCEPTIONS=1)
|
||||
else()
|
||||
add_library(date
|
||||
include/date/chrono_io.h
|
||||
include/date/date.h
|
||||
include/date/ios.h
|
||||
include/date/islamic.h
|
||||
include/date/iso_week.h
|
||||
include/date/julian.h
|
||||
include/date/ptz.h
|
||||
include/date/solar_hijri.h
|
||||
include/date/tz.h
|
||||
include/date/tz_private.h
|
||||
src/tz.cpp
|
||||
)
|
||||
|
||||
CMake projects that wish to use this library should consider
|
||||
something like the following :
|
||||
|
||||
include( FetchContent )
|
||||
FetchContent_Declare( date_src
|
||||
GIT_REPOSITORY https://github.com/HowardHinnant/date.git
|
||||
GIT_TAG 2.4.2 # adjust tag/branch/commit as needed
|
||||
)
|
||||
FetchContent_MakeAvailable(date_src)
|
||||
...
|
||||
target_link_libraries (my_target PRIVATE date::date)
|
||||
|
||||
#]===================================================================]
|
||||
|
||||
cmake_minimum_required( VERSION 3.7 )
|
||||
|
||||
project( date VERSION 2.4.1 )
|
||||
|
||||
include( GNUInstallDirs )
|
||||
|
||||
get_directory_property( has_parent PARENT_DIRECTORY )
|
||||
|
||||
# Override by setting on CMake command line.
|
||||
set( CMAKE_CXX_STANDARD 17 CACHE STRING "The C++ standard whose features are requested." )
|
||||
|
||||
option( USE_SYSTEM_TZ_DB "Use the operating system's timezone database" OFF )
|
||||
option( MANUAL_TZ_DB "User will set TZ DB manually by invoking set_install in their code" OFF )
|
||||
option( USE_TZ_DB_IN_DOT "Save the timezone database in the current folder" OFF )
|
||||
option( BUILD_SHARED_LIBS "Build a shared version of library" OFF )
|
||||
option( ENABLE_DATE_TESTING "Enable unit tests" OFF )
|
||||
option( DISABLE_STRING_VIEW "Disable string view" OFF )
|
||||
option( COMPILE_WITH_C_LOCALE "define ONLY_C_LOCALE=1" OFF )
|
||||
option( BUILD_TZ_LIB "build/install of TZ library" OFF )
|
||||
|
||||
if( ENABLE_DATE_TESTING AND NOT BUILD_TZ_LIB )
|
||||
message(WARNING "Testing requested, bug BUILD_TZ_LIB not ON - forcing the latter")
|
||||
set (BUILD_TZ_LIB ON CACHE BOOL "required for testing" FORCE)
|
||||
endif( )
|
||||
|
||||
function( print_option OPT )
|
||||
if ( NOT DEFINED PRINT_OPTION_CURR_${OPT} OR ( NOT PRINT_OPTION_CURR_${OPT} STREQUAL ${OPT} ) )
|
||||
set( PRINT_OPTION_CURR_${OPT} ${${OPT}} CACHE BOOL "" )
|
||||
mark_as_advanced(PRINT_OPTION_CURR_${OPT})
|
||||
message( "# date: ${OPT} ${${OPT}}" )
|
||||
endif( )
|
||||
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 )
|
||||
print_option( DISABLE_STRING_VIEW )
|
||||
|
||||
#[===================================================================[
|
||||
date (header only) library
|
||||
#]===================================================================]
|
||||
add_library( date INTERFACE )
|
||||
add_library( date::date ALIAS date )
|
||||
target_include_directories( date INTERFACE
|
||||
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>
|
||||
$<INSTALL_INTERFACE:include> )
|
||||
# adding header sources just helps IDEs
|
||||
target_sources( date INTERFACE
|
||||
$<BUILD_INTERFACE:${CMAKE_CURRENT_LIST_DIR}/include>$<INSTALL_INTERFACE:include>/date/date.h
|
||||
# the rest of these are not currently part of the public interface of the library:
|
||||
$<BUILD_INTERFACE:${CMAKE_CURRENT_LIST_DIR}/include/date/solar_hijri.h>
|
||||
$<BUILD_INTERFACE:${CMAKE_CURRENT_LIST_DIR}/include/date/islamic.h>
|
||||
$<BUILD_INTERFACE:${CMAKE_CURRENT_LIST_DIR}/include/date/iso_week.h>
|
||||
$<BUILD_INTERFACE:${CMAKE_CURRENT_LIST_DIR}/include/date/julian.h>
|
||||
)
|
||||
if (CMAKE_VERSION VERSION_GREATER_EQUAL 3.15)
|
||||
# public headers will get installed:
|
||||
set_target_properties( date PROPERTIES PUBLIC_HEADER include/date/date.h )
|
||||
endif ()
|
||||
target_compile_definitions( date INTERFACE
|
||||
#To workaround libstdc++ issue https://github.com/HowardHinnant/date/issues/388
|
||||
ONLY_C_LOCALE=$<IF:$<BOOL:${COMPILE_WITH_C_LOCALE}>,1,0>
|
||||
$<$<BOOL:${DISABLE_STRING_VIEW}>:HAS_STRING_VIEW=0> )
|
||||
|
||||
#[===================================================================[
|
||||
tz (compiled) library
|
||||
#]===================================================================]
|
||||
if( BUILD_TZ_LIB )
|
||||
add_library( date-tz )
|
||||
target_sources( date-tz
|
||||
PUBLIC
|
||||
$<BUILD_INTERFACE:${CMAKE_CURRENT_LIST_DIR}/include>$<INSTALL_INTERFACE:include>/date/tz.h
|
||||
$<$<BOOL:${IOS}>:$<BUILD_INTERFACE:${CMAKE_CURRENT_LIST_DIR}/include>$<INSTALL_INTERFACE:include>/date/ios.h>
|
||||
PRIVATE
|
||||
include/date/tz_private.h
|
||||
$<$<BOOL:${IOS}>:src/ios.mm>
|
||||
src/tz.cpp )
|
||||
add_library( date::tz ALIAS date-tz )
|
||||
target_link_libraries( date-tz PUBLIC date )
|
||||
target_include_directories( date-tz PUBLIC
|
||||
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>
|
||||
$<INSTALL_INTERFACE:include> )
|
||||
target_compile_definitions( date-tz
|
||||
PRIVATE
|
||||
AUTO_DOWNLOAD=$<IF:$<OR:$<BOOL:${USE_SYSTEM_TZ_DB}>,$<BOOL:${MANUAL_TZ_DB}>>,0,1>
|
||||
HAS_REMOTE_API=$<IF:$<OR:$<BOOL:${USE_SYSTEM_TZ_DB}>,$<BOOL:${MANUAL_TZ_DB}>>,0,1>
|
||||
$<$<AND:$<BOOL:${WIN32}>,$<BOOL:${BUILD_SHARED_LIBS}>>:DATE_BUILD_DLL=1>
|
||||
$<$<BOOL:${USE_TZ_DB_IN_DOT}>:INSTALL=.>
|
||||
PUBLIC
|
||||
USE_OS_TZDB=$<IF:$<AND:$<BOOL:${USE_SYSTEM_TZ_DB}>,$<NOT:$<BOOL:${WIN32}>>,$<NOT:$<BOOL:${MANUAL_TZ_DB}>>>,1,0>
|
||||
INTERFACE
|
||||
$<$<AND:$<BOOL:${WIN32}>,$<BOOL:${BUILD_SHARED_LIBS}>>:DATE_USE_DLL=1> )
|
||||
set(TZ_HEADERS include/date/tz.h)
|
||||
if( IOS )
|
||||
list(APPEND TZ_HEADERS include/date/ios.h)
|
||||
endif( )
|
||||
set_target_properties( date-tz PROPERTIES
|
||||
POSITION_INDEPENDENT_CODE ON
|
||||
PUBLIC_HEADER "${TZ_HEADERS}"
|
||||
VERSION "${PROJECT_VERSION}"
|
||||
SOVERSION "${PROJECT_VERSION}" )
|
||||
if( NOT MSVC )
|
||||
find_package( Threads )
|
||||
target_link_libraries( date-tz PUBLIC Threads::Threads )
|
||||
endif( )
|
||||
if( NOT USE_SYSTEM_TZ_DB AND NOT MANUAL_TZ_DB )
|
||||
find_package( CURL REQUIRED )
|
||||
target_include_directories( date-tz SYSTEM PRIVATE ${CURL_INCLUDE_DIRS} )
|
||||
target_link_libraries( date-tz PRIVATE ${CURL_LIBRARIES} )
|
||||
endif( )
|
||||
endif( )
|
||||
|
||||
#[===================================================================[
|
||||
installation
|
||||
#]===================================================================]
|
||||
set( version_config "${CMAKE_CURRENT_BINARY_DIR}/dateConfigVersion.cmake" )
|
||||
|
||||
include( CMakePackageConfigHelpers )
|
||||
write_basic_package_version_file( "${version_config}"
|
||||
VERSION ${PROJECT_VERSION}
|
||||
COMPATIBILITY SameMajorVersion )
|
||||
|
||||
install( TARGETS date
|
||||
EXPORT dateConfig
|
||||
PUBLIC_HEADER DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/date )
|
||||
export( TARGETS date NAMESPACE date:: FILE dateTargets.cmake )
|
||||
if (CMAKE_VERSION VERSION_LESS 3.15)
|
||||
install(
|
||||
FILES include/date/date.h
|
||||
DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/date )
|
||||
endif ()
|
||||
|
||||
if( BUILD_TZ_LIB )
|
||||
install( TARGETS date-tz
|
||||
EXPORT dateConfig
|
||||
PUBLIC_HEADER DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/date
|
||||
ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}
|
||||
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
|
||||
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} ) # This is for Windows
|
||||
export( TARGETS date-tz NAMESPACE date:: APPEND FILE dateTargets.cmake )
|
||||
endif( )
|
||||
|
||||
if( WIN32 AND NOT CYGWIN)
|
||||
set( CONFIG_LOC CMake )
|
||||
else( )
|
||||
set( CONFIG_LOC "${CMAKE_INSTALL_LIBDIR}/cmake/date" )
|
||||
endif( )
|
||||
install( EXPORT dateConfig
|
||||
FILE dateTargets.cmake
|
||||
NAMESPACE date::
|
||||
DESTINATION ${CONFIG_LOC} )
|
||||
install (
|
||||
FILES cmake/dateConfig.cmake "${version_config}"
|
||||
DESTINATION ${CONFIG_LOC})
|
||||
|
||||
#[===================================================================[
|
||||
testing
|
||||
#]===================================================================]
|
||||
if( ENABLE_DATE_TESTING )
|
||||
enable_testing( )
|
||||
|
||||
add_custom_target( testit COMMAND ${CMAKE_CTEST_COMMAND} )
|
||||
add_dependencies( testit date-tz )
|
||||
|
||||
function( add_pass_tests TEST_GLOB TEST_PREFIX )
|
||||
file( GLOB_RECURSE FILENAMES ${TEST_GLOB} )
|
||||
|
||||
foreach( TEST_FILE ${FILENAMES} )
|
||||
get_filename_component( TEST_NAME ${TEST_FILE} NAME_WE )
|
||||
get_filename_component( TEST_EXT ${TEST_FILE} EXT )
|
||||
if( NOT ${TEST_EXT} STREQUAL ".fail.cpp" )
|
||||
set( PREFIX "${TEST_PREFIX}_pass_${TEST_NAME}" )
|
||||
set( BIN_NAME ${PREFIX}_bin )
|
||||
set( TST_NAME ${PREFIX}_test )
|
||||
add_executable( ${BIN_NAME} EXCLUDE_FROM_ALL ${TEST_FILE} )
|
||||
add_test( ${TST_NAME} ${BIN_NAME} )
|
||||
target_link_libraries( ${BIN_NAME} date-tz )
|
||||
# HACK: because the test files don't use FQ includes:
|
||||
target_include_directories( ${BIN_NAME} PRIVATE include/date )
|
||||
add_dependencies( testit ${BIN_NAME} )
|
||||
endif( )
|
||||
endforeach( )
|
||||
endfunction( )
|
||||
|
||||
function( add_fail_tests TEST_GLOB TEST_PREFIX )
|
||||
file( GLOB_RECURSE FILENAMES ${TEST_GLOB} )
|
||||
|
||||
foreach( TEST_FILE ${FILENAMES} )
|
||||
get_filename_component( TEST_NAME ${TEST_FILE} NAME_WE )
|
||||
get_filename_component( TEST_EXT ${TEST_FILE} EXT )
|
||||
|
||||
set( TEST_TYPE "_fail" )
|
||||
|
||||
set( PREFIX "${TEST_PREFIX}_fail_${TEST_NAME}" )
|
||||
set( BIN_NAME ${PREFIX}_bin )
|
||||
set( TST_NAME ${PREFIX}_test )
|
||||
|
||||
set( TEST_BIN_NAME ${CMAKE_BINARY_DIR}/${BIN_NAME} )
|
||||
add_custom_target( ${BIN_NAME}
|
||||
COMMAND
|
||||
${PROJECT_SOURCE_DIR}/compile_fail.sh
|
||||
${TEST_BIN_NAME}
|
||||
${CMAKE_CXX_COMPILER}
|
||||
-std=c++14
|
||||
-L${CMAKE_BINARY_DIR}/
|
||||
-ltz
|
||||
-I${PROJECT_SOURCE_DIR}/include
|
||||
-I${PROJECT_SOURCE_DIR}/include/date
|
||||
-o ${BIN_NAME}
|
||||
${TEST_FILE}
|
||||
WORKING_DIRECTORY ${CMAKE_BINARY_DIR}
|
||||
COMMENT ${TST_NAME} )
|
||||
add_test( ${TST_NAME} "${PROJECT_SOURCE_DIR}/test_fail.sh" ${CMAKE_BINARY_DIR}/${BIN_NAME} WORKING_DIRECTORY "${PROJECT_SOURCE_DIR}/" )
|
||||
#set_tests_properties( ${TST_NAME} PROPERTIES WILL_FAIL TRUE)
|
||||
add_dependencies( testit ${BIN_NAME} )
|
||||
endforeach( )
|
||||
endfunction( )
|
||||
|
||||
file( GLOB children RELATIVE "${PROJECT_SOURCE_DIR}/test" "${PROJECT_SOURCE_DIR}/test/*" )
|
||||
foreach( child ${children} )
|
||||
if( IS_DIRECTORY "${PROJECT_SOURCE_DIR}/test/${child}" )
|
||||
set( CUR_FOLDER "${PROJECT_SOURCE_DIR}/test/${child}" )
|
||||
add_pass_tests( "${CUR_FOLDER}/*.cpp" ${child} )
|
||||
if( NOT WIN32 )
|
||||
add_fail_tests( "${CUR_FOLDER}/*.fail.cpp" ${child} )
|
||||
endif( )
|
||||
endif( )
|
||||
endforeach( )
|
||||
endif( )
|
||||
target_include_directories(date PUBLIC
|
||||
include/
|
||||
)
|
||||
endif()
|
||||
|
13
README.md
13
README.md
@ -5,7 +5,7 @@
|
||||
|
||||
---
|
||||
|
||||
**[Try it out on wandbox!](https://wandbox.org/permlink/L8MwjzSSC3fXXrMd)**
|
||||
**[Try it out on wandbox!](https://wandbox.org/permlink/oyXjibyF680HHoyS)**
|
||||
|
||||
## Summary
|
||||
|
||||
@ -43,6 +43,14 @@ Slightly modified versions of `"date.h"` and `"tz.h"` were voted into the C++20
|
||||
|
||||
## Build & Test
|
||||
|
||||
The recommended way to use any of these libraries besides `"tz.h"` is to just include it. These are header-only libraries (except `"tz.h"`).
|
||||
|
||||
To use `"tz.h"`, there is a single source file (`src/tz.cpp`) that needs to be compiled. Here are the recommended directions: https://howardhinnant.github.io/date/tz.html#Installation.
|
||||
|
||||
One can run tests by cd'ing into the `test` subdirectory and running `testit`. There are known failures on all platforms except for macOS. And even on macOS if C++11 is used. If any of these failures present problems for you, there exist workarounds.
|
||||
|
||||
Additionally there is unsupported support for [vcpkg](https://github.com/Microsoft/vcpkg) and [CMake](https://cmake.org/). I don't personally use or maintain these systems as for me they cause more problems than they solve (for this small project). If you would like to contribute to these build systems please feel free to file a PR.
|
||||
|
||||
You can download and install Date using the [vcpkg](https://github.com/Microsoft/vcpkg) dependency manager:
|
||||
|
||||
git clone https://github.com/Microsoft/vcpkg.git
|
||||
@ -69,5 +77,8 @@ cmake --build . --target testit # Consider '-- -j4' for multithreading
|
||||
* https://routinghub.com
|
||||
* https://github.com/valhalla
|
||||
* https://github.com/siodb/siodb
|
||||
* https://github.com/KomodoPlatform/atomicDEX-Pro
|
||||
* https://github.com/Kotlin/kotlinx-datetime
|
||||
* https://github.com/royalbee/jewish_date
|
||||
|
||||
If you would like your project (or product) on this list, just let me know.
|
||||
|
@ -1,8 +1,8 @@
|
||||
include( CMakeFindDependencyMacro )
|
||||
include( "${CMAKE_CURRENT_LIST_DIR}/dateTargets.cmake" )
|
||||
if( NOT MSVC AND TARGET date::tz )
|
||||
if( NOT MSVC AND TARGET date::date-tz )
|
||||
find_dependency( Threads REQUIRED)
|
||||
get_target_property( _tzill date::tz INTERFACE_LINK_LIBRARIES )
|
||||
get_target_property( _tzill date::date-tz INTERFACE_LINK_LIBRARIES )
|
||||
if( _tzill AND "${_tzill}" MATCHES "libcurl" )
|
||||
find_dependency( CURL )
|
||||
endif( )
|
||||
|
@ -45,9 +45,7 @@
|
||||
#include <cctype>
|
||||
#include <chrono>
|
||||
#include <climits>
|
||||
#if !(__cplusplus >= 201402)
|
||||
# include <cmath>
|
||||
#endif
|
||||
#include <cmath>
|
||||
#include <cstddef>
|
||||
#include <cstdint>
|
||||
#include <cstdlib>
|
||||
@ -1166,7 +1164,11 @@ private:
|
||||
static const std::intmax_t d1 = R1::den / gcd_d1_d2;
|
||||
static const std::intmax_t n2 = R2::num / gcd_n1_n2;
|
||||
static const std::intmax_t d2 = R2::den / gcd_d1_d2;
|
||||
#ifdef __cpp_constexpr
|
||||
static const std::intmax_t max = std::numeric_limits<std::intmax_t>::max();
|
||||
#else
|
||||
static const std::intmax_t max = LLONG_MAX;
|
||||
#endif
|
||||
|
||||
template <std::intmax_t Xp, std::intmax_t Yp, bool overflow>
|
||||
struct mul // overflow == false
|
||||
@ -1354,6 +1356,47 @@ using std::chrono::abs;
|
||||
|
||||
#endif // HAS_CHRONO_ROUNDING
|
||||
|
||||
namespace detail
|
||||
{
|
||||
|
||||
template <class To, class Rep, class Period>
|
||||
CONSTCD14
|
||||
inline
|
||||
typename std::enable_if
|
||||
<
|
||||
!std::chrono::treat_as_floating_point<typename To::rep>::value,
|
||||
To
|
||||
>::type
|
||||
round_i(const std::chrono::duration<Rep, Period>& d)
|
||||
{
|
||||
return round<To>(d);
|
||||
}
|
||||
|
||||
template <class To, class Rep, class Period>
|
||||
CONSTCD14
|
||||
inline
|
||||
typename std::enable_if
|
||||
<
|
||||
std::chrono::treat_as_floating_point<typename To::rep>::value,
|
||||
To
|
||||
>::type
|
||||
round_i(const std::chrono::duration<Rep, Period>& d)
|
||||
{
|
||||
return d;
|
||||
}
|
||||
|
||||
template <class To, class Clock, class FromDuration>
|
||||
CONSTCD11
|
||||
inline
|
||||
std::chrono::time_point<Clock, To>
|
||||
round_i(const std::chrono::time_point<Clock, FromDuration>& tp)
|
||||
{
|
||||
using std::chrono::time_point;
|
||||
return time_point<Clock, To>{round_i<To>(tp.time_since_epoch())};
|
||||
}
|
||||
|
||||
} // detail
|
||||
|
||||
// trunc towards zero
|
||||
template <class To, class Clock, class FromDuration>
|
||||
CONSTCD11
|
||||
@ -3681,11 +3724,12 @@ struct undocumented {explicit undocumented() = default;};
|
||||
// Example: width<4>::value == 2
|
||||
// Example: width<10>::value == 1
|
||||
// Example: width<1000>::value == 3
|
||||
template <std::uint64_t n, std::uint64_t d = 10, unsigned w = 0,
|
||||
bool should_continue = !(n < 2) && d != 0 && (w < 19)>
|
||||
template <std::uint64_t n, std::uint64_t d, unsigned w = 0,
|
||||
bool should_continue = n%d != 0 && (w < 19)>
|
||||
struct width
|
||||
{
|
||||
static CONSTDATA unsigned value = 1 + width<n, d%n*10, w+1>::value;
|
||||
static_assert(d > 0, "width called with zero denominator");
|
||||
static CONSTDATA unsigned value = 1 + width<n%d*10, d, w+1>::value;
|
||||
};
|
||||
|
||||
template <std::uint64_t n, std::uint64_t d, unsigned w>
|
||||
@ -3714,9 +3758,10 @@ class decimal_format_seconds
|
||||
{
|
||||
using CT = typename std::common_type<Duration, std::chrono::seconds>::type;
|
||||
using rep = typename CT::rep;
|
||||
static unsigned CONSTDATA trial_width =
|
||||
detail::width<CT::period::num, CT::period::den>::value;
|
||||
public:
|
||||
static unsigned constexpr width = detail::width<CT::period::den>::value < 19 ?
|
||||
detail::width<CT::period::den>::value : 6u;
|
||||
static unsigned CONSTDATA width = trial_width < 19 ? trial_width : 6u;
|
||||
using precision = std::chrono::duration<rep,
|
||||
std::ratio<1, static_pow10<width>::value>>;
|
||||
|
||||
@ -6122,9 +6167,16 @@ long double
|
||||
read_long_double(std::basic_istream<CharT, Traits>& is, unsigned m = 1, unsigned M = 10)
|
||||
{
|
||||
unsigned count = 0;
|
||||
unsigned fcount = 0;
|
||||
unsigned long long i = 0;
|
||||
unsigned long long f = 0;
|
||||
bool parsing_fraction = false;
|
||||
#if ONLY_C_LOCALE
|
||||
typename Traits::int_type decimal_point = '.';
|
||||
#else
|
||||
auto decimal_point = Traits::to_int_type(
|
||||
std::use_facet<std::numpunct<CharT>>(is.getloc()).decimal_point());
|
||||
std::string buf;
|
||||
#endif
|
||||
while (true)
|
||||
{
|
||||
auto ic = is.peek();
|
||||
@ -6132,18 +6184,25 @@ read_long_double(std::basic_istream<CharT, Traits>& is, unsigned m = 1, unsigned
|
||||
break;
|
||||
if (Traits::eq_int_type(ic, decimal_point))
|
||||
{
|
||||
buf += '.';
|
||||
decimal_point = Traits::eof();
|
||||
is.get();
|
||||
parsing_fraction = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
auto c = static_cast<char>(Traits::to_char_type(ic));
|
||||
if (!('0' <= c && c <= '9'))
|
||||
break;
|
||||
buf += c;
|
||||
(void)is.get();
|
||||
if (!parsing_fraction)
|
||||
{
|
||||
i = 10*i + static_cast<unsigned>(c - '0');
|
||||
}
|
||||
else
|
||||
{
|
||||
f = 10*f + static_cast<unsigned>(c - '0');
|
||||
++fcount;
|
||||
}
|
||||
}
|
||||
(void)is.get();
|
||||
if (++count == M)
|
||||
break;
|
||||
}
|
||||
@ -6152,7 +6211,7 @@ read_long_double(std::basic_istream<CharT, Traits>& is, unsigned m = 1, unsigned
|
||||
is.setstate(std::ios::failbit);
|
||||
return 0;
|
||||
}
|
||||
return std::stold(buf);
|
||||
return i + f/std::pow(10.L, fcount);
|
||||
}
|
||||
|
||||
struct rs
|
||||
@ -6309,6 +6368,7 @@ from_stream(std::basic_istream<CharT, Traits>& is, const CharT* fmt,
|
||||
using std::chrono::seconds;
|
||||
using std::chrono::minutes;
|
||||
using std::chrono::hours;
|
||||
using detail::round_i;
|
||||
typename std::basic_istream<CharT, Traits>::sentry ok{is, true};
|
||||
if (ok)
|
||||
{
|
||||
@ -6324,7 +6384,7 @@ from_stream(std::basic_istream<CharT, Traits>& is, const CharT* fmt,
|
||||
auto modified = CharT{};
|
||||
auto width = -1;
|
||||
|
||||
CONSTDATA int not_a_year = numeric_limits<int>::min();
|
||||
CONSTDATA int not_a_year = numeric_limits<short>::min();
|
||||
CONSTDATA int not_a_2digit_year = 100;
|
||||
CONSTDATA int not_a_century = not_a_year / 100;
|
||||
CONSTDATA int not_a_month = 0;
|
||||
@ -6522,7 +6582,7 @@ from_stream(std::basic_istream<CharT, Traits>& is, const CharT* fmt,
|
||||
CharT{':'}, rld{S, 1, w});
|
||||
checked_set(H, tH, not_a_hour, is);
|
||||
checked_set(M, tM, not_a_minute, is);
|
||||
checked_set(s, round<Duration>(duration<long double>{S}),
|
||||
checked_set(s, round_i<Duration>(duration<long double>{S}),
|
||||
not_a_second, is);
|
||||
ws(is);
|
||||
int tY = not_a_year;
|
||||
@ -6602,7 +6662,7 @@ from_stream(std::basic_istream<CharT, Traits>& is, const CharT* fmt,
|
||||
CharT{':'}, rld{S, 1, w});
|
||||
checked_set(H, tH, not_a_hour, is);
|
||||
checked_set(M, tM, not_a_minute, is);
|
||||
checked_set(s, round<Duration>(duration<long double>{S}),
|
||||
checked_set(s, round_i<Duration>(duration<long double>{S}),
|
||||
not_a_second, is);
|
||||
#endif
|
||||
}
|
||||
@ -6918,7 +6978,7 @@ from_stream(std::basic_istream<CharT, Traits>& is, const CharT* fmt,
|
||||
#else
|
||||
auto nm = detail::ampm_names();
|
||||
auto i = detail::scan_keyword(is, nm.first, nm.second) - nm.first;
|
||||
tp = i;
|
||||
tp = static_cast<decltype(tp)>(i);
|
||||
#endif
|
||||
checked_set(p, tp, not_a_ampm, is);
|
||||
}
|
||||
@ -6959,7 +7019,7 @@ from_stream(std::basic_istream<CharT, Traits>& is, const CharT* fmt,
|
||||
CharT{':'}, rld{S, 1, w});
|
||||
checked_set(I, tI, not_a_hour_12_value, is);
|
||||
checked_set(M, tM, not_a_minute, is);
|
||||
checked_set(s, round<Duration>(duration<long double>{S}),
|
||||
checked_set(s, round_i<Duration>(duration<long double>{S}),
|
||||
not_a_second, is);
|
||||
ws(is);
|
||||
auto nm = detail::ampm_names();
|
||||
@ -7010,7 +7070,7 @@ from_stream(std::basic_istream<CharT, Traits>& is, const CharT* fmt,
|
||||
CONSTDATA auto w = Duration::period::den == 1 ? 2 : 3 + dfs::width;
|
||||
long double S;
|
||||
read(is, rld{S, 1, width == -1 ? w : static_cast<unsigned>(width)});
|
||||
checked_set(s, round<Duration>(duration<long double>{S}),
|
||||
checked_set(s, round_i<Duration>(duration<long double>{S}),
|
||||
not_a_second, is);
|
||||
}
|
||||
#if !ONLY_C_LOCALE
|
||||
@ -7047,7 +7107,7 @@ from_stream(std::basic_istream<CharT, Traits>& is, const CharT* fmt,
|
||||
CharT{':'}, rld{S, 1, w});
|
||||
checked_set(H, tH, not_a_hour, is);
|
||||
checked_set(M, tM, not_a_minute, is);
|
||||
checked_set(s, round<Duration>(duration<long double>{S}),
|
||||
checked_set(s, round_i<Duration>(duration<long double>{S}),
|
||||
not_a_second, is);
|
||||
}
|
||||
else
|
||||
@ -7750,6 +7810,7 @@ from_stream(std::basic_istream<CharT, Traits>& is, const CharT* fmt,
|
||||
std::chrono::minutes* offset = nullptr)
|
||||
{
|
||||
using CT = typename std::common_type<Duration, std::chrono::seconds>::type;
|
||||
using detail::round_i;
|
||||
std::chrono::minutes offset_local{};
|
||||
auto offptr = offset ? offset : &offset_local;
|
||||
fields<CT> fds{};
|
||||
@ -7758,7 +7819,7 @@ from_stream(std::basic_istream<CharT, Traits>& is, const CharT* fmt,
|
||||
if (!fds.ymd.ok() || !fds.tod.in_conventional_range())
|
||||
is.setstate(std::ios::failbit);
|
||||
if (!is.fail())
|
||||
tp = round<Duration>(sys_days(fds.ymd) - *offptr + fds.tod.to_duration());
|
||||
tp = round_i<Duration>(sys_days(fds.ymd) - *offptr + fds.tod.to_duration());
|
||||
return is;
|
||||
}
|
||||
|
||||
@ -7769,13 +7830,14 @@ from_stream(std::basic_istream<CharT, Traits>& is, const CharT* fmt,
|
||||
std::chrono::minutes* offset = nullptr)
|
||||
{
|
||||
using CT = typename std::common_type<Duration, std::chrono::seconds>::type;
|
||||
using detail::round_i;
|
||||
fields<CT> fds{};
|
||||
fds.has_tod = true;
|
||||
from_stream(is, fmt, fds, abbrev, offset);
|
||||
if (!fds.ymd.ok() || !fds.tod.in_conventional_range())
|
||||
is.setstate(std::ios::failbit);
|
||||
if (!is.fail())
|
||||
tp = round<Duration>(local_seconds{local_days(fds.ymd)} + fds.tod.to_duration());
|
||||
tp = round_i<Duration>(local_seconds{local_days(fds.ymd)} + fds.tod.to_duration());
|
||||
return is;
|
||||
}
|
||||
|
||||
|
@ -1655,9 +1655,12 @@ inline
|
||||
bool
|
||||
month_day::ok() const NOEXCEPT
|
||||
{
|
||||
CONSTDATA julian::day d[] =
|
||||
{31_d, 29_d, 31_d, 30_d, 31_d, 30_d, 31_d, 31_d, 30_d, 31_d, 30_d, 31_d};
|
||||
return m_.ok() && 1_d <= d_ && d_ <= d[static_cast<unsigned>(m_)-1];
|
||||
CONSTDATA julian::day d[] = {
|
||||
julian::day(31), julian::day(29), julian::day(31), julian::day(30),
|
||||
julian::day(31), julian::day(30), julian::day(31), julian::day(31),
|
||||
julian::day(30), julian::day(31), julian::day(30), julian::day(31)
|
||||
};
|
||||
return m_.ok() && julian::day(1) <= d_ && d_ <= d[static_cast<unsigned>(m_)-1];
|
||||
}
|
||||
|
||||
CONSTCD11
|
||||
@ -1946,9 +1949,12 @@ inline
|
||||
day
|
||||
year_month_day_last::day() const NOEXCEPT
|
||||
{
|
||||
CONSTDATA julian::day d[] =
|
||||
{31_d, 28_d, 31_d, 30_d, 31_d, 30_d, 31_d, 31_d, 30_d, 31_d, 30_d, 31_d};
|
||||
return month() != feb || !y_.is_leap() ? d[static_cast<unsigned>(month())-1] : 29_d;
|
||||
CONSTDATA julian::day d[] = {
|
||||
julian::day(31), julian::day(28), julian::day(31), julian::day(30),
|
||||
julian::day(31), julian::day(30), julian::day(31), julian::day(31),
|
||||
julian::day(30), julian::day(31), julian::day(30), julian::day(31)
|
||||
};
|
||||
return month() != feb || !y_.is_leap() ? d[static_cast<unsigned>(month())-1] : julian::day(29);
|
||||
}
|
||||
|
||||
CONSTCD14
|
||||
@ -2190,7 +2196,7 @@ year_month_day::ok() const NOEXCEPT
|
||||
{
|
||||
if (!(y_.ok() && m_.ok()))
|
||||
return false;
|
||||
return 1_d <= d_ && d_ <= (y_/m_/last).day();
|
||||
return julian::day(1) <= d_ && d_ <= (y_/m_/last).day();
|
||||
}
|
||||
|
||||
CONSTCD11
|
||||
|
@ -36,6 +36,9 @@
|
||||
// Posix::time_zone tz{"EST5EDT,M3.2.0,M11.1.0"};
|
||||
// zoned_time<system_clock::duration, Posix::time_zone> zt{tz, system_clock::now()};
|
||||
//
|
||||
// If the rule set is missing (everything starting with ','), then the rule is that the
|
||||
// alternate offset is never enabled.
|
||||
//
|
||||
// Note, Posix-style time zones are not recommended for all of the reasons described here:
|
||||
// https://stackoverflow.com/tags/timezone/info
|
||||
//
|
||||
@ -70,7 +73,8 @@ unsigned read_date(const string_t& s, unsigned i, rule& r);
|
||||
unsigned read_name(const string_t& s, unsigned i, std::string& name);
|
||||
unsigned read_signed_time(const string_t& s, unsigned i, std::chrono::seconds& t);
|
||||
unsigned read_unsigned_time(const string_t& s, unsigned i, std::chrono::seconds& t);
|
||||
unsigned read_unsigned(const string_t& s, unsigned i, unsigned limit, unsigned& u);
|
||||
unsigned read_unsigned(const string_t& s, unsigned i, unsigned limit, unsigned& u,
|
||||
const string_t& message = string_t{});
|
||||
|
||||
class rule
|
||||
{
|
||||
@ -584,7 +588,7 @@ throw_invalid(const string_t& s, unsigned i, const string_t& message)
|
||||
std::string(s) + '\n' +
|
||||
"\x1b[1;32m" +
|
||||
std::string(i, '~') + '^' +
|
||||
std::string(s.size()-i-1, '~') +
|
||||
std::string(i < s.size() ? s.size()-i-1 : 0, '~') +
|
||||
"\x1b[0m");
|
||||
}
|
||||
|
||||
@ -600,7 +604,7 @@ read_date(const string_t& s, unsigned i, rule& r)
|
||||
{
|
||||
++i;
|
||||
unsigned n;
|
||||
i = read_unsigned(s, i, 3, n);
|
||||
i = read_unsigned(s, i, 3, n, "Expected to find the Julian day [1, 365]");
|
||||
r.mode_ = rule::J;
|
||||
r.n_ = n;
|
||||
}
|
||||
@ -608,17 +612,17 @@ read_date(const string_t& s, unsigned i, rule& r)
|
||||
{
|
||||
++i;
|
||||
unsigned m;
|
||||
i = read_unsigned(s, i, 2, m);
|
||||
i = read_unsigned(s, i, 2, m, "Expected to find month [1, 12]");
|
||||
if (i == s.size() || s[i] != '.')
|
||||
throw_invalid(s, i, "Expected '.' after month");
|
||||
++i;
|
||||
unsigned n;
|
||||
i = read_unsigned(s, i, 1, n);
|
||||
i = read_unsigned(s, i, 1, n, "Expected to find week number [1, 5]");
|
||||
if (i == s.size() || s[i] != '.')
|
||||
throw_invalid(s, i, "Expected '.' after weekday index");
|
||||
++i;
|
||||
unsigned wd;
|
||||
i = read_unsigned(s, i, 1, wd);
|
||||
i = read_unsigned(s, i, 1, wd, "Expected to find day of week [0, 6]");
|
||||
r.mode_ = rule::M;
|
||||
r.m_ = month{m};
|
||||
r.wd_ = weekday{wd};
|
||||
@ -708,17 +712,17 @@ read_unsigned_time(const string_t& s, unsigned i, std::chrono::seconds& t)
|
||||
if (i == s.size())
|
||||
throw_invalid(s, i, "Expected to read unsigned time, but found end of string");
|
||||
unsigned x;
|
||||
i = read_unsigned(s, i, 2, x);
|
||||
i = read_unsigned(s, i, 2, x, "Expected to find hours [0, 24]");
|
||||
t = hours{x};
|
||||
if (i != s.size() && s[i] == ':')
|
||||
{
|
||||
++i;
|
||||
i = read_unsigned(s, i, 2, x);
|
||||
i = read_unsigned(s, i, 2, x, "Expected to find minutes [0, 59]");
|
||||
t += minutes{x};
|
||||
if (i != s.size() && s[i] == ':')
|
||||
{
|
||||
++i;
|
||||
i = read_unsigned(s, i, 2, x);
|
||||
i = read_unsigned(s, i, 2, x, "Expected to find seconds [0, 59]");
|
||||
t += seconds{x};
|
||||
}
|
||||
}
|
||||
@ -727,10 +731,11 @@ read_unsigned_time(const string_t& s, unsigned i, std::chrono::seconds& t)
|
||||
|
||||
inline
|
||||
unsigned
|
||||
read_unsigned(const string_t& s, unsigned i, unsigned limit, unsigned& u)
|
||||
read_unsigned(const string_t& s, unsigned i, unsigned limit, unsigned& u,
|
||||
const string_t& message)
|
||||
{
|
||||
if (i == s.size() || !std::isdigit(s[i]))
|
||||
throw_invalid(s, i, "Expected to find a decimal digit");
|
||||
throw_invalid(s, i, message);
|
||||
u = static_cast<unsigned>(s[i] - '0');
|
||||
unsigned count = 1;
|
||||
for (++i; count < limit && i != s.size() && std::isdigit(s[i]); ++i, ++count)
|
||||
|
@ -1707,9 +1707,13 @@ inline
|
||||
bool
|
||||
month_day::ok() const NOEXCEPT
|
||||
{
|
||||
CONSTDATA solar_hijri::day d[] =
|
||||
{31_d, 31_d, 31_d, 31_d, 31_d, 31_d, 30_d, 30_d, 30_d, 30_d, 30_d, 30_d};
|
||||
return m_.ok() && 1_d <= d_ && d_ <= d[static_cast<unsigned>(m_)-1];
|
||||
CONSTDATA solar_hijri::day d[] = {
|
||||
solar_hijri::day(31), solar_hijri::day(31), solar_hijri::day(31),
|
||||
solar_hijri::day(31), solar_hijri::day(31), solar_hijri::day(31),
|
||||
solar_hijri::day(30), solar_hijri::day(30), solar_hijri::day(30),
|
||||
solar_hijri::day(30), solar_hijri::day(30), solar_hijri::day(30)
|
||||
};
|
||||
return m_.ok() && solar_hijri::day(1) <= d_ && d_ <= d[static_cast<unsigned>(m_)-1];
|
||||
}
|
||||
|
||||
CONSTCD11
|
||||
@ -1998,10 +2002,14 @@ inline
|
||||
day
|
||||
year_month_day_last::day() const NOEXCEPT
|
||||
{
|
||||
CONSTDATA solar_hijri::day d[] =
|
||||
{31_d, 31_d, 31_d, 31_d, 31_d, 31_d, 30_d, 30_d, 30_d, 30_d, 30_d, 29_d};
|
||||
CONSTDATA solar_hijri::day d[] = {
|
||||
solar_hijri::day(31), solar_hijri::day(31), solar_hijri::day(31),
|
||||
solar_hijri::day(31), solar_hijri::day(31), solar_hijri::day(31),
|
||||
solar_hijri::day(30), solar_hijri::day(30), solar_hijri::day(30),
|
||||
solar_hijri::day(30), solar_hijri::day(30), solar_hijri::day(29)
|
||||
};
|
||||
return month() != esf || !y_.is_leap() ?
|
||||
d[static_cast<unsigned>(month())-1] : 30_d;
|
||||
d[static_cast<unsigned>(month()) - 1] : solar_hijri::day(30);
|
||||
}
|
||||
|
||||
CONSTCD14
|
||||
@ -2260,7 +2268,7 @@ year_month_day::ok() const NOEXCEPT
|
||||
{
|
||||
if (!(y_.ok() && m_.ok()))
|
||||
return false;
|
||||
return 1_d <= d_ && d_ <= (y_/m_/last).day();
|
||||
return solar_hijri::day(1) <= d_ && d_ <= (y_/m_/last).day();
|
||||
}
|
||||
|
||||
CONSTCD11
|
||||
|
@ -86,15 +86,6 @@ static_assert(HAS_REMOTE_API == 0 ? AUTO_DOWNLOAD == 0 : true,
|
||||
# ifdef _WIN32
|
||||
# error "USE_OS_TZDB can not be used on Windows"
|
||||
# endif
|
||||
# ifndef MISSING_LEAP_SECONDS
|
||||
# ifdef __APPLE__
|
||||
# define MISSING_LEAP_SECONDS 1
|
||||
# else
|
||||
# define MISSING_LEAP_SECONDS 0
|
||||
# endif
|
||||
# endif
|
||||
#else
|
||||
# define MISSING_LEAP_SECONDS 0
|
||||
#endif
|
||||
|
||||
#ifndef HAS_DEDUCTION_GUIDES
|
||||
@ -703,6 +694,11 @@ public:
|
||||
|
||||
private:
|
||||
template <class D, class T> friend class zoned_time;
|
||||
|
||||
template <class TimeZonePtr2>
|
||||
static
|
||||
TimeZonePtr2&&
|
||||
check(TimeZonePtr2&& p);
|
||||
};
|
||||
|
||||
using zoned_seconds = zoned_time<std::chrono::seconds>;
|
||||
@ -990,8 +986,6 @@ inline bool operator>=(const time_zone_link& x, const time_zone_link& y) {return
|
||||
|
||||
#endif // !USE_OS_TZDB
|
||||
|
||||
#if !MISSING_LEAP_SECONDS
|
||||
|
||||
class leap_second
|
||||
{
|
||||
private:
|
||||
@ -1115,8 +1109,6 @@ operator>=(const sys_time<Duration>& x, const leap_second& y)
|
||||
|
||||
using leap = leap_second;
|
||||
|
||||
#endif // !MISSING_LEAP_SECONDS
|
||||
|
||||
#ifdef _WIN32
|
||||
|
||||
namespace detail
|
||||
@ -1162,9 +1154,7 @@ struct tzdb
|
||||
#if !USE_OS_TZDB
|
||||
std::vector<time_zone_link> links;
|
||||
#endif
|
||||
#if !MISSING_LEAP_SECONDS
|
||||
std::vector<leap_second> leap_seconds;
|
||||
#endif
|
||||
#if !USE_OS_TZDB
|
||||
std::vector<detail::Rule> rules;
|
||||
#endif
|
||||
@ -1221,31 +1211,31 @@ class tzdb_list
|
||||
public:
|
||||
~tzdb_list();
|
||||
tzdb_list() = default;
|
||||
tzdb_list(tzdb_list&& x) noexcept;
|
||||
tzdb_list(tzdb_list&& x) NOEXCEPT;
|
||||
|
||||
const tzdb& front() const noexcept {return *head_;}
|
||||
tzdb& front() noexcept {return *head_;}
|
||||
const tzdb& front() const NOEXCEPT {return *head_;}
|
||||
tzdb& front() NOEXCEPT {return *head_;}
|
||||
|
||||
class const_iterator;
|
||||
|
||||
const_iterator begin() const noexcept;
|
||||
const_iterator end() const noexcept;
|
||||
const_iterator begin() const NOEXCEPT;
|
||||
const_iterator end() const NOEXCEPT;
|
||||
|
||||
const_iterator cbegin() const noexcept;
|
||||
const_iterator cend() const noexcept;
|
||||
const_iterator cbegin() const NOEXCEPT;
|
||||
const_iterator cend() const NOEXCEPT;
|
||||
|
||||
const_iterator erase_after(const_iterator p) noexcept;
|
||||
const_iterator erase_after(const_iterator p) NOEXCEPT;
|
||||
|
||||
struct undocumented_helper;
|
||||
private:
|
||||
void push_front(tzdb* tzdb) noexcept;
|
||||
void push_front(tzdb* tzdb) NOEXCEPT;
|
||||
};
|
||||
|
||||
class tzdb_list::const_iterator
|
||||
{
|
||||
tzdb* p_ = nullptr;
|
||||
|
||||
explicit const_iterator(tzdb* p) noexcept : p_{p} {}
|
||||
explicit const_iterator(tzdb* p) NOEXCEPT : p_{p} {}
|
||||
public:
|
||||
const_iterator() = default;
|
||||
|
||||
@ -1255,20 +1245,20 @@ public:
|
||||
using pointer = const value_type*;
|
||||
using difference_type = std::ptrdiff_t;
|
||||
|
||||
reference operator*() const noexcept {return *p_;}
|
||||
pointer operator->() const noexcept {return p_;}
|
||||
reference operator*() const NOEXCEPT {return *p_;}
|
||||
pointer operator->() const NOEXCEPT {return p_;}
|
||||
|
||||
const_iterator& operator++() noexcept {p_ = p_->next; return *this;}
|
||||
const_iterator operator++(int) noexcept {auto t = *this; ++(*this); return t;}
|
||||
const_iterator& operator++() NOEXCEPT {p_ = p_->next; return *this;}
|
||||
const_iterator operator++(int) NOEXCEPT {auto t = *this; ++(*this); return t;}
|
||||
|
||||
friend
|
||||
bool
|
||||
operator==(const const_iterator& x, const const_iterator& y) noexcept
|
||||
operator==(const const_iterator& x, const const_iterator& y) NOEXCEPT
|
||||
{return x.p_ == y.p_;}
|
||||
|
||||
friend
|
||||
bool
|
||||
operator!=(const const_iterator& x, const const_iterator& y) noexcept
|
||||
operator!=(const const_iterator& x, const const_iterator& y) NOEXCEPT
|
||||
{return !(x == y);}
|
||||
|
||||
friend class tzdb_list;
|
||||
@ -1276,28 +1266,28 @@ public:
|
||||
|
||||
inline
|
||||
tzdb_list::const_iterator
|
||||
tzdb_list::begin() const noexcept
|
||||
tzdb_list::begin() const NOEXCEPT
|
||||
{
|
||||
return const_iterator{head_};
|
||||
}
|
||||
|
||||
inline
|
||||
tzdb_list::const_iterator
|
||||
tzdb_list::end() const noexcept
|
||||
tzdb_list::end() const NOEXCEPT
|
||||
{
|
||||
return const_iterator{nullptr};
|
||||
}
|
||||
|
||||
inline
|
||||
tzdb_list::const_iterator
|
||||
tzdb_list::cbegin() const noexcept
|
||||
tzdb_list::cbegin() const NOEXCEPT
|
||||
{
|
||||
return begin();
|
||||
}
|
||||
|
||||
inline
|
||||
tzdb_list::const_iterator
|
||||
tzdb_list::cend() const noexcept
|
||||
tzdb_list::cend() const NOEXCEPT
|
||||
{
|
||||
return end();
|
||||
}
|
||||
@ -1328,7 +1318,7 @@ namespace detail
|
||||
template <class T>
|
||||
inline
|
||||
T*
|
||||
to_raw_pointer(T* p) noexcept
|
||||
to_raw_pointer(T* p) NOEXCEPT
|
||||
{
|
||||
return p;
|
||||
}
|
||||
@ -1336,7 +1326,7 @@ to_raw_pointer(T* p) noexcept
|
||||
template <class Pointer>
|
||||
inline
|
||||
auto
|
||||
to_raw_pointer(Pointer p) noexcept
|
||||
to_raw_pointer(Pointer p) NOEXCEPT
|
||||
-> decltype(detail::to_raw_pointer(p.operator->()))
|
||||
{
|
||||
return detail::to_raw_pointer(p.operator->());
|
||||
@ -1344,13 +1334,25 @@ to_raw_pointer(Pointer p) noexcept
|
||||
|
||||
} // namespace detail
|
||||
|
||||
template <class Duration, class TimeZonePtr>
|
||||
template <class TimeZonePtr2>
|
||||
inline
|
||||
TimeZonePtr2&&
|
||||
zoned_time<Duration, TimeZonePtr>::check(TimeZonePtr2&& p)
|
||||
{
|
||||
if (detail::to_raw_pointer(p) == nullptr)
|
||||
throw std::runtime_error(
|
||||
"zoned_time constructed with a time zone pointer == nullptr");
|
||||
return std::forward<TimeZonePtr2>(p);
|
||||
}
|
||||
|
||||
template <class Duration, class TimeZonePtr>
|
||||
#if !defined(_MSC_VER) || (_MSC_VER > 1916)
|
||||
template <class T, class>
|
||||
#endif
|
||||
inline
|
||||
zoned_time<Duration, TimeZonePtr>::zoned_time()
|
||||
: zone_(zoned_traits<TimeZonePtr>::default_zone())
|
||||
: zone_(check(zoned_traits<TimeZonePtr>::default_zone()))
|
||||
{}
|
||||
|
||||
template <class Duration, class TimeZonePtr>
|
||||
@ -1359,15 +1361,15 @@ template <class T, class>
|
||||
#endif
|
||||
inline
|
||||
zoned_time<Duration, TimeZonePtr>::zoned_time(const sys_time<Duration>& st)
|
||||
: zone_(zoned_traits<TimeZonePtr>::default_zone())
|
||||
: zone_(check(zoned_traits<TimeZonePtr>::default_zone()))
|
||||
, tp_(st)
|
||||
{}
|
||||
|
||||
template <class Duration, class TimeZonePtr>
|
||||
inline
|
||||
zoned_time<Duration, TimeZonePtr>::zoned_time(TimeZonePtr z)
|
||||
: zone_(std::move(z))
|
||||
{assert(detail::to_raw_pointer(zone_) != nullptr);}
|
||||
: zone_(check(std::move(z)))
|
||||
{}
|
||||
|
||||
#if HAS_STRING_VIEW
|
||||
|
||||
@ -1402,7 +1404,7 @@ zoned_time<Duration, TimeZonePtr>::zoned_time(const zoned_time<Duration2, TimeZo
|
||||
template <class Duration, class TimeZonePtr>
|
||||
inline
|
||||
zoned_time<Duration, TimeZonePtr>::zoned_time(TimeZonePtr z, const sys_time<Duration>& st)
|
||||
: zone_(std::move(z))
|
||||
: zone_(check(std::move(z)))
|
||||
, tp_(st)
|
||||
{}
|
||||
|
||||
@ -1412,7 +1414,7 @@ template <class T, class>
|
||||
#endif
|
||||
inline
|
||||
zoned_time<Duration, TimeZonePtr>::zoned_time(TimeZonePtr z, const local_time<Duration>& t)
|
||||
: zone_(std::move(z))
|
||||
: zone_(check(std::move(z)))
|
||||
, tp_(zone_->to_sys(t))
|
||||
{}
|
||||
|
||||
@ -1423,7 +1425,7 @@ template <class T, class>
|
||||
inline
|
||||
zoned_time<Duration, TimeZonePtr>::zoned_time(TimeZonePtr z, const local_time<Duration>& t,
|
||||
choose c)
|
||||
: zone_(std::move(z))
|
||||
: zone_(check(std::move(z)))
|
||||
, tp_(zone_->to_sys(t, c))
|
||||
{}
|
||||
|
||||
@ -1432,7 +1434,7 @@ template <class Duration2, class TimeZonePtr2, class>
|
||||
inline
|
||||
zoned_time<Duration, TimeZonePtr>::zoned_time(TimeZonePtr z,
|
||||
const zoned_time<Duration2, TimeZonePtr2>& zt)
|
||||
: zone_(std::move(z))
|
||||
: zone_(check(std::move(z)))
|
||||
, tp_(zt.tp_)
|
||||
{}
|
||||
|
||||
@ -1847,8 +1849,6 @@ operator<<(std::basic_ostream<CharT, Traits>& os, const zoned_time<Duration, Tim
|
||||
return to_stream(os, fmt, t);
|
||||
}
|
||||
|
||||
#if !MISSING_LEAP_SECONDS
|
||||
|
||||
class utc_clock
|
||||
{
|
||||
public:
|
||||
@ -2787,8 +2787,6 @@ to_gps_time(const tai_time<Duration>& t)
|
||||
return gps_clock::from_utc(tai_clock::to_utc(t));
|
||||
}
|
||||
|
||||
#endif // !MISSING_LEAP_SECONDS
|
||||
|
||||
} // namespace date
|
||||
|
||||
#endif // TZ_H
|
||||
|
@ -95,9 +95,9 @@ private:
|
||||
U& operator=(const pair& x);
|
||||
} u;
|
||||
|
||||
std::chrono::hours h_{};
|
||||
std::chrono::minutes m_{};
|
||||
std::chrono::seconds s_{};
|
||||
std::chrono::hours h_{0};
|
||||
std::chrono::minutes m_{0};
|
||||
std::chrono::seconds s_{0};
|
||||
tz zone_{tz::local};
|
||||
|
||||
public:
|
||||
@ -245,7 +245,7 @@ struct zonelet
|
||||
sys_seconds until_utc_;
|
||||
local_seconds until_std_;
|
||||
local_seconds until_loc_;
|
||||
std::chrono::minutes initial_save_{};
|
||||
std::chrono::minutes initial_save_{0};
|
||||
std::string initial_abbrev_;
|
||||
std::pair<const Rule*, date::year> first_rule_{nullptr, date::year::min()};
|
||||
std::pair<const Rule*, date::year> last_rule_{nullptr, date::year::max()};
|
||||
|
11
library.json
Normal file
11
library.json
Normal file
@ -0,0 +1,11 @@
|
||||
{
|
||||
"name": "date",
|
||||
"version": "1.0.0",
|
||||
"build": {
|
||||
"includeDir": "include",
|
||||
"srcFilter":
|
||||
[
|
||||
"+<->"
|
||||
]
|
||||
}
|
||||
}
|
224
src/tz.cpp
224
src/tz.cpp
@ -141,7 +141,7 @@
|
||||
# endif // HAS_REMOTE_API
|
||||
#else // !_WIN32
|
||||
# include <unistd.h>
|
||||
# if !USE_OS_TZDB
|
||||
# if !USE_OS_TZDB && !defined(INSTALL)
|
||||
# include <wordexp.h>
|
||||
# endif
|
||||
# include <limits.h>
|
||||
@ -420,20 +420,20 @@ tzdb_list::~tzdb_list()
|
||||
}
|
||||
}
|
||||
|
||||
tzdb_list::tzdb_list(tzdb_list&& x) noexcept
|
||||
tzdb_list::tzdb_list(tzdb_list&& x) NOEXCEPT
|
||||
: head_{x.head_.exchange(nullptr)}
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
tzdb_list::push_front(tzdb* tzdb) noexcept
|
||||
tzdb_list::push_front(tzdb* tzdb) NOEXCEPT
|
||||
{
|
||||
tzdb->next = head_;
|
||||
head_ = tzdb;
|
||||
}
|
||||
|
||||
tzdb_list::const_iterator
|
||||
tzdb_list::erase_after(const_iterator p) noexcept
|
||||
tzdb_list::erase_after(const_iterator p) NOEXCEPT
|
||||
{
|
||||
auto t = p.p_->next;
|
||||
p.p_->next = p.p_->next->next;
|
||||
@ -443,7 +443,7 @@ tzdb_list::erase_after(const_iterator p) noexcept
|
||||
|
||||
struct tzdb_list::undocumented_helper
|
||||
{
|
||||
static void push_front(tzdb_list& db_list, tzdb* tzdb) noexcept
|
||||
static void push_front(tzdb_list& db_list, tzdb* tzdb) NOEXCEPT
|
||||
{
|
||||
db_list.push_front(tzdb);
|
||||
}
|
||||
@ -465,6 +465,32 @@ get_tzdb_list()
|
||||
return tz_db;
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
#if !USE_OS_TZDB
|
||||
|
||||
#ifdef _WIN32
|
||||
@ -679,18 +705,6 @@ load_timezone_mappings_from_xml_file(const std::string& input_path)
|
||||
|
||||
// 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;
|
||||
}
|
||||
|
||||
static
|
||||
unsigned
|
||||
parse_dow(std::istream& in)
|
||||
@ -704,20 +718,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)
|
||||
@ -2125,14 +2125,25 @@ time_zone::load_sys_info(std::vector<detail::transition>::const_iterator i) cons
|
||||
{
|
||||
using namespace std::chrono;
|
||||
assert(!transitions_.empty());
|
||||
assert(i != transitions_.begin());
|
||||
sys_info r;
|
||||
r.begin = i[-1].timepoint;
|
||||
r.end = i != transitions_.end() ? i->timepoint :
|
||||
sys_seconds(sys_days(year::max()/max_day));
|
||||
r.offset = i[-1].info->offset;
|
||||
r.save = i[-1].info->is_dst ? minutes{1} : minutes{0};
|
||||
r.abbrev = i[-1].info->abbrev;
|
||||
if (i != transitions_.begin())
|
||||
{
|
||||
r.begin = i[-1].timepoint;
|
||||
r.end = i != transitions_.end() ? i->timepoint :
|
||||
sys_seconds(sys_days(year::max()/max_day));
|
||||
r.offset = i[-1].info->offset;
|
||||
r.save = i[-1].info->is_dst ? minutes{1} : minutes{0};
|
||||
r.abbrev = i[-1].info->abbrev;
|
||||
}
|
||||
else
|
||||
{
|
||||
r.begin = sys_days(year::min()/min_day);
|
||||
r.end = i+1 != transitions_.end() ? i[1].timepoint :
|
||||
sys_seconds(sys_days(year::max()/max_day));
|
||||
r.offset = i[0].info->offset;
|
||||
r.save = i[0].info->is_dst ? minutes{1} : minutes{0};
|
||||
r.abbrev = i[0].info->abbrev;
|
||||
}
|
||||
return r;
|
||||
}
|
||||
|
||||
@ -2167,7 +2178,7 @@ time_zone::get_info_impl(local_seconds tp) const
|
||||
{
|
||||
i.second = load_sys_info(--tr);
|
||||
tps = sys_seconds{(tp - i.second.offset).time_since_epoch()};
|
||||
if (tps < i.second.end)
|
||||
if (tps < i.second.end && i.first.end != i.second.end)
|
||||
{
|
||||
i.result = local_info::ambiguous;
|
||||
std::swap(i.first, i.second);
|
||||
@ -2210,15 +2221,11 @@ operator<<(std::ostream& os, const time_zone& z)
|
||||
return os;
|
||||
}
|
||||
|
||||
#if !MISSING_LEAP_SECONDS
|
||||
|
||||
leap_second::leap_second(const sys_seconds& s, detail::undocumented)
|
||||
: date_(s)
|
||||
{
|
||||
}
|
||||
|
||||
#endif // !MISSING_LEAP_SECONDS
|
||||
|
||||
#else // !USE_OS_TZDB
|
||||
|
||||
time_zone::time_zone(const std::string& s, detail::undocumented)
|
||||
@ -2615,8 +2622,6 @@ operator<<(std::ostream& os, const time_zone& z)
|
||||
|
||||
#endif // !USE_OS_TZDB
|
||||
|
||||
#if !MISSING_LEAP_SECONDS
|
||||
|
||||
std::ostream&
|
||||
operator<<(std::ostream& os, const leap_second& x)
|
||||
{
|
||||
@ -2624,11 +2629,8 @@ operator<<(std::ostream& os, const leap_second& x)
|
||||
return os << x.date_ << " +";
|
||||
}
|
||||
|
||||
#endif // !MISSING_LEAP_SECONDS
|
||||
|
||||
#if USE_OS_TZDB
|
||||
|
||||
# ifdef __APPLE__
|
||||
static
|
||||
std::string
|
||||
get_version()
|
||||
@ -2637,12 +2639,99 @@ get_version()
|
||||
auto path = get_tz_dir() + string("/+VERSION");
|
||||
ifstream in{path};
|
||||
string version;
|
||||
in >> version;
|
||||
if (in.fail())
|
||||
throw std::runtime_error("Unable to get Timezone database version from " + path);
|
||||
return version;
|
||||
if (in)
|
||||
{
|
||||
in >> version;
|
||||
return version;
|
||||
}
|
||||
in.clear();
|
||||
in.open(get_tz_dir() + std::string(1, folder_delimiter) + "version");
|
||||
if (in)
|
||||
{
|
||||
in >> version;
|
||||
return version;
|
||||
}
|
||||
return "unknown";
|
||||
}
|
||||
|
||||
static
|
||||
std::vector<leap_second>
|
||||
find_read_and_leap_seconds()
|
||||
{
|
||||
std::ifstream in(get_tz_dir() + std::string(1, folder_delimiter) + "leapseconds",
|
||||
std::ios_base::binary);
|
||||
if (in)
|
||||
{
|
||||
std::vector<leap_second> leap_seconds;
|
||||
std::string line;
|
||||
while (in)
|
||||
{
|
||||
std::getline(in, line);
|
||||
if (!line.empty() && line[0] != '#')
|
||||
{
|
||||
std::istringstream in(line);
|
||||
in.exceptions(std::ios::failbit | std::ios::badbit);
|
||||
std::string word;
|
||||
in >> word;
|
||||
if (word == "Leap")
|
||||
{
|
||||
int y, m, d;
|
||||
in >> y;
|
||||
m = static_cast<int>(parse_month(in));
|
||||
in >> d;
|
||||
leap_seconds.push_back(leap_second(sys_days{year{y}/m/d} + days{1},
|
||||
detail::undocumented{}));
|
||||
}
|
||||
else
|
||||
{
|
||||
std::cerr << line << '\n';
|
||||
}
|
||||
}
|
||||
}
|
||||
return leap_seconds;
|
||||
}
|
||||
in.clear();
|
||||
in.open(get_tz_dir() + std::string(1, folder_delimiter) + "leap-seconds.list",
|
||||
std::ios_base::binary);
|
||||
if (in)
|
||||
{
|
||||
std::vector<leap_second> leap_seconds;
|
||||
std::string line;
|
||||
const auto offset = sys_days{1970_y/1/1}-sys_days{1900_y/1/1};
|
||||
while (in)
|
||||
{
|
||||
std::getline(in, line);
|
||||
if (!line.empty() && line[0] != '#')
|
||||
{
|
||||
std::istringstream in(line);
|
||||
in.exceptions(std::ios::failbit | std::ios::badbit);
|
||||
using seconds = std::chrono::seconds;
|
||||
seconds::rep s;
|
||||
in >> s;
|
||||
if (s == 2272060800)
|
||||
continue;
|
||||
leap_seconds.push_back(leap_second(sys_seconds{seconds{s}} - offset,
|
||||
detail::undocumented{}));
|
||||
}
|
||||
}
|
||||
return leap_seconds;
|
||||
}
|
||||
in.clear();
|
||||
in.open(get_tz_dir() + std::string(1, folder_delimiter) + "right/UTC",
|
||||
std::ios_base::binary);
|
||||
if (in)
|
||||
{
|
||||
return load_just_leaps(in);
|
||||
}
|
||||
in.clear();
|
||||
in.open(get_tz_dir() + std::string(1, folder_delimiter) + "UTC",
|
||||
std::ios_base::binary);
|
||||
if (in)
|
||||
{
|
||||
return load_just_leaps(in);
|
||||
}
|
||||
return {};
|
||||
}
|
||||
# endif
|
||||
|
||||
static
|
||||
std::unique_ptr<tzdb>
|
||||
@ -2671,6 +2760,7 @@ 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 ||
|
||||
@ -2698,28 +2788,8 @@ init_tzdb()
|
||||
}
|
||||
db->zones.shrink_to_fit();
|
||||
std::sort(db->zones.begin(), db->zones.end());
|
||||
# if !MISSING_LEAP_SECONDS
|
||||
std::ifstream in(get_tz_dir() + std::string(1, folder_delimiter) + "right/UTC",
|
||||
std::ios_base::binary);
|
||||
if (in)
|
||||
{
|
||||
in.exceptions(std::ios::failbit | std::ios::badbit);
|
||||
db->leap_seconds = load_just_leaps(in);
|
||||
}
|
||||
else
|
||||
{
|
||||
in.clear();
|
||||
in.open(get_tz_dir() + std::string(1, folder_delimiter) +
|
||||
"UTC", std::ios_base::binary);
|
||||
if (!in)
|
||||
throw std::runtime_error("Unable to extract leap second information");
|
||||
in.exceptions(std::ios::failbit | std::ios::badbit);
|
||||
db->leap_seconds = load_just_leaps(in);
|
||||
}
|
||||
# endif // !MISSING_LEAP_SECONDS
|
||||
# ifdef __APPLE__
|
||||
db->leap_seconds = find_read_and_leap_seconds();
|
||||
db->version = get_version();
|
||||
# endif
|
||||
return db;
|
||||
}
|
||||
|
||||
@ -3294,8 +3364,8 @@ remote_download(const std::string& version, char* error_buffer)
|
||||
{
|
||||
auto mapping_file = get_download_mapping_file(version);
|
||||
result = download_to_file(
|
||||
"https://raw.githubusercontent.com/unicode-org/cldr/master/"
|
||||
"common/supplemental/windowsZones.xml",
|
||||
"https://raw.githubusercontent.com/unicode-org/cldr/master/"
|
||||
"common/supplemental/windowsZones.xml",
|
||||
mapping_file, download_file_options::text, error_buffer);
|
||||
}
|
||||
# endif // _WIN32
|
||||
@ -3569,11 +3639,9 @@ operator<<(std::ostream& os, const tzdb& db)
|
||||
os << "Version: " << db.version << "\n\n";
|
||||
for (const auto& x : db.zones)
|
||||
os << x << '\n';
|
||||
#if !MISSING_LEAP_SECONDS
|
||||
os << '\n';
|
||||
for (const auto& x : db.leap_seconds)
|
||||
os << x << '\n';
|
||||
#endif // !MISSING_LEAP_SECONDS
|
||||
return os;
|
||||
}
|
||||
|
||||
|
@ -46,19 +46,19 @@ int
|
||||
main()
|
||||
{
|
||||
using namespace date::detail;
|
||||
static_assert(width<0>::value == 0, "");
|
||||
static_assert(width<1>::value == 0, "");
|
||||
static_assert(width<2>::value == 1, "");
|
||||
static_assert(width<3>::value == 19, "");
|
||||
static_assert(width<4>::value == 2, "");
|
||||
static_assert(width<5>::value == 1, "");
|
||||
static_assert(width<6>::value == 19, "");
|
||||
static_assert(width<7>::value == 19, "");
|
||||
static_assert(width<8>::value == 3, "");
|
||||
static_assert(width<9>::value == 19, "");
|
||||
static_assert(width<10>::value == 1, "");
|
||||
static_assert(width<100>::value == 2, "");
|
||||
static_assert(width<1000>::value == 3, "");
|
||||
static_assert(width<10000>::value == 4, "");
|
||||
static_assert(width<625>::value == 4, "");
|
||||
static_assert(width<0, 1>::value == 0, "");
|
||||
static_assert(width<1, 1>::value == 0, "");
|
||||
static_assert(width<1, 2>::value == 1, "");
|
||||
static_assert(width<1, 3>::value == 19, "");
|
||||
static_assert(width<1, 4>::value == 2, "");
|
||||
static_assert(width<1, 5>::value == 1, "");
|
||||
static_assert(width<1, 6>::value == 19, "");
|
||||
static_assert(width<1, 7>::value == 19, "");
|
||||
static_assert(width<1, 8>::value == 3, "");
|
||||
static_assert(width<1, 9>::value == 19, "");
|
||||
static_assert(width<1, 10>::value == 1, "");
|
||||
static_assert(width<1, 100>::value == 2, "");
|
||||
static_assert(width<1, 1000>::value == 3, "");
|
||||
static_assert(width<1, 10000>::value == 4, "");
|
||||
static_assert(width<756, 625>::value == 4, "");
|
||||
}
|
||||
|
36
test/tz_test/tzdb_list.pass.cpp
Normal file
36
test/tz_test/tzdb_list.pass.cpp
Normal file
@ -0,0 +1,36 @@
|
||||
// The MIT License (MIT)
|
||||
//
|
||||
// Copyright (c) 2020 Howard Hinnant
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in all
|
||||
// copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
// SOFTWARE.
|
||||
|
||||
#include "tz.h"
|
||||
#include <type_traits>
|
||||
|
||||
int
|
||||
main()
|
||||
{
|
||||
using namespace date;
|
||||
static_assert( std::is_nothrow_destructible<tzdb_list>{}, "");
|
||||
static_assert( std::is_nothrow_default_constructible<tzdb_list>{}, "");
|
||||
static_assert(!std::is_copy_constructible<tzdb_list>{}, "");
|
||||
static_assert(!std::is_copy_assignable<tzdb_list>{}, "");
|
||||
static_assert( std::is_nothrow_move_constructible<tzdb_list>{}, "");
|
||||
static_assert(!std::is_move_assignable<tzdb_list>{}, "");
|
||||
}
|
Reference in New Issue
Block a user