forked from HowardHinnant/date
Compare commits
169 Commits
Author | SHA1 | Date | |
---|---|---|---|
4c1968b8f0 | |||
9cc3a7bca1 | |||
9a0ee25428 | |||
c8d311f6f1 | |||
fe63f0bb5f | |||
9502bc27a3 | |||
66a5aa482e | |||
b9cd9c3fde | |||
a184309786 | |||
fc4cf092f9 | |||
48433b9892 | |||
4c95165298 | |||
940f4a5ceb | |||
018a50bcd0 | |||
3e376be2e9 | |||
224c71a899 | |||
67e272a54e | |||
d399e10cba | |||
96ffe23f72 | |||
48f1455cd2 | |||
e3186e36c2 | |||
3f0f9b3cbe | |||
23fa1bb86d | |||
4481c75192 | |||
e6d2c08159 | |||
a5c4b4ebf8 | |||
44344000f0 | |||
6d5ff9b958 | |||
375579eac1 | |||
2ced83ceff | |||
718cbe3f9b | |||
961bf06c32 | |||
fe491eff1c | |||
c56f915cc3 | |||
5e57a19abe | |||
9454aeda2b | |||
3a343adf6a | |||
d21333f636 | |||
cb4bf26fc7 | |||
b87eb970c1 | |||
5a0057587d | |||
5345d135b7 | |||
7c020642fb | |||
1d721d9afd | |||
141ba85614 | |||
dca8ddc659 | |||
1f5c192f4a | |||
46ccd69c9c | |||
c0e7b4e2f7 | |||
09d90a8b5e | |||
6f0b645df1 | |||
7ef1a55143 | |||
27d1e1e54e | |||
7817ebf45a | |||
a029f1105d | |||
44215f6781 | |||
ed0368fc75 | |||
429d9ba739 | |||
081e9af55b | |||
8a563041fa | |||
9dc96fd9b5 | |||
8b69087d35 | |||
d5e96f0991 | |||
5ba1c1ad85 | |||
10ab6ae9e5 | |||
e31daf8093 | |||
cb7ca96f68 | |||
b5d025ea2f | |||
f782ae98f0 | |||
d6c5d02068 | |||
16077472af | |||
5a62c405e0 | |||
09a19a09f4 | |||
9cb0013aef | |||
f1326968af | |||
61c3d35634 | |||
4e7e76b981 | |||
90d0440884 | |||
2cb4c34009 | |||
7231a182a4 | |||
0e85704e47 | |||
5f34c40523 | |||
23b1f007fe | |||
a22125ca40 | |||
8f91ef27ed | |||
4b46deb4f9 | |||
54e8516af2 | |||
1eed461d06 | |||
591f572b67 | |||
69e9cd612f | |||
6b51ca8271 | |||
3e82a52d66 | |||
6a4d93a0bd | |||
39d6730665 | |||
de6a03d337 | |||
e86edc3820 | |||
1b32e316db | |||
f46885e632 | |||
2d282e35fa | |||
d50970b32a | |||
af2b2b70b3 | |||
3933a0122d | |||
07876e4433 | |||
0197889505 | |||
b86def339e | |||
aa0494b980 | |||
df31560701 | |||
4b687f4c04 | |||
db60c5eb8e | |||
9f1c4b0110 | |||
da15227f6c | |||
d4fb7eb76d | |||
0e3e84fd56 | |||
3eac2d376e | |||
f5f4d76936 | |||
c7b69d949a | |||
48baa942fc | |||
af415701ba | |||
be2ec2310b | |||
40b83654b6 | |||
6c4d333026 | |||
1fdda81a30 | |||
f33e179936 | |||
328cecaa56 | |||
5d15157bbb | |||
a91ceefb4e | |||
88c661e9f3 | |||
c665992a6e | |||
9d0bcdb63f | |||
973bd393bc | |||
d53db7a1cb | |||
e5c69d84ab | |||
b48a18a1d9 | |||
cdb4b276d9 | |||
1d9e49ea21 | |||
0125d330ab | |||
e7e1482087 | |||
d6b95dc301 | |||
700489e475 | |||
e6941697eb | |||
c311db2f1a | |||
fffa52ac0e | |||
f105595f04 | |||
20f0595b32 | |||
674a9e6953 | |||
bc8cf368e5 | |||
1e8ab50f82 | |||
38c5ca38bb | |||
0bde4ba8c8 | |||
afe61df277 | |||
43d8a4eab0 | |||
ca4036a4b0 | |||
a1ceec19fe | |||
5524dd1ae8 | |||
4ada98d247 | |||
040eed838b | |||
2acf403bcd | |||
637e5d8007 | |||
362cd8f27e | |||
a4ce4bc2d3 | |||
3e5a57467a | |||
3b8372f4fa | |||
6941691de4 | |||
09b78ba92c | |||
28c1c61ac2 | |||
55289f0d73 | |||
b7e58e193f | |||
2b6ee6378c | |||
7d80d89a44 |
147
.travis.yml
Normal file
147
.travis.yml
Normal file
@ -0,0 +1,147 @@
|
||||
language: cpp
|
||||
|
||||
env:
|
||||
global:
|
||||
- CMAKE_EXTRA_CONF="-DCOMPILE_WITH_C_LOCALE=ON"
|
||||
- CTEST_OUTPUT_ON_FAILURE=1
|
||||
|
||||
matrix:
|
||||
include:
|
||||
|
||||
- name: "Ubuntu 16.04 LTS (Xenial Xerus) GCC 7"
|
||||
os: linux
|
||||
dist: xenial
|
||||
addons:
|
||||
apt:
|
||||
sources:
|
||||
- ubuntu-toolchain-r-test
|
||||
packages:
|
||||
- g++-7
|
||||
env:
|
||||
- MATRIX_EVAL="CC=gcc-7 && CXX=g++-7"
|
||||
|
||||
- name: "Ubuntu 16.04 LTS (Xenial Xerus) GCC 8"
|
||||
os: linux
|
||||
dist: xenial
|
||||
addons:
|
||||
apt:
|
||||
sources:
|
||||
- ubuntu-toolchain-r-test
|
||||
packages:
|
||||
- g++-8
|
||||
env:
|
||||
- MATRIX_EVAL="CC=gcc-8 && CXX=g++-8"
|
||||
|
||||
- name: "Ubuntu 16.04 LTS (Xenial Xerus) GCC 9"
|
||||
os: linux
|
||||
dist: xenial
|
||||
addons:
|
||||
apt:
|
||||
sources:
|
||||
- ubuntu-toolchain-r-test
|
||||
packages:
|
||||
- g++-9
|
||||
env:
|
||||
- MATRIX_EVAL="CC=gcc-9 && CXX=g++-9"
|
||||
|
||||
- name: "Ubuntu 18.04 LTS (Bionic Beaver) GCC 7"
|
||||
os: linux
|
||||
dist: bionic
|
||||
addons:
|
||||
apt:
|
||||
sources:
|
||||
- ubuntu-toolchain-r-test
|
||||
packages:
|
||||
- g++-7
|
||||
env:
|
||||
- MATRIX_EVAL="CC=gcc-7 && CXX=g++-7"
|
||||
|
||||
- name: "Ubuntu 18.04 LTS (Bionic Beaver) GCC 8"
|
||||
os: linux
|
||||
dist: bionic
|
||||
addons:
|
||||
apt:
|
||||
sources:
|
||||
- ubuntu-toolchain-r-test
|
||||
packages:
|
||||
- g++-8
|
||||
env:
|
||||
- MATRIX_EVAL="CC=gcc-8 && CXX=g++-8"
|
||||
|
||||
- name: "Ubuntu 18.04 LTS (Bionic Beaver) Clang 6"
|
||||
os: linux
|
||||
dist: bionic
|
||||
addons:
|
||||
apt:
|
||||
sources:
|
||||
- llvm-toolchain-bionic-6.0
|
||||
packages:
|
||||
- clang-6.0
|
||||
env:
|
||||
- MATRIX_EVAL="CC=clang-6.0 && CXX=clang++-6.0"
|
||||
|
||||
- name: "Ubuntu 18.04 LTS (Bionic Beaver) Clang 7"
|
||||
os: linux
|
||||
dist: bionic
|
||||
addons:
|
||||
apt:
|
||||
sources:
|
||||
- llvm-toolchain-bionic-7
|
||||
packages:
|
||||
- clang-7
|
||||
env:
|
||||
- MATRIX_EVAL="CC=clang-7 && CXX=clang++-7"
|
||||
|
||||
- name: "Ubuntu 18.04 LTS (Bionic Beaver) Clang 8"
|
||||
os: linux
|
||||
dist: bionic
|
||||
addons:
|
||||
apt:
|
||||
sources:
|
||||
- llvm-toolchain-bionic-8
|
||||
packages:
|
||||
- clang-8
|
||||
env:
|
||||
- MATRIX_EVAL="CC=clang-8 && CXX=clang++-8"
|
||||
|
||||
- &macos
|
||||
name: xcode10
|
||||
os: osx
|
||||
osx_image: xcode10.2
|
||||
env:
|
||||
- CMAKE_EXTRA_CONF=""
|
||||
addons:
|
||||
homebrew:
|
||||
packages:
|
||||
- bash
|
||||
- ninja
|
||||
|
||||
- <<: *macos
|
||||
name: xcode9
|
||||
# xcode 9 only works if we tell it to use c++14 explicitly
|
||||
env:
|
||||
- CMAKE_EXTRA_CONF="-DCMAKE_CXX_STANDARD=14"
|
||||
osx_image: xcode9.4
|
||||
|
||||
- <<: *macos
|
||||
osx_image: xcode11
|
||||
name: xcode11
|
||||
|
||||
before_install:
|
||||
- eval "${MATRIX_EVAL}"
|
||||
- ci/install_cmake.sh 3.15.2
|
||||
- export OPENSSL_ROOT=$(brew --prefix openssl@1.1)
|
||||
- if [ "$(uname)" = "Darwin" ] ; then export PATH="$HOME/cmake/CMake.app/Contents/bin:${PATH}"; fi
|
||||
- if [ "$(uname)" = "Linux" ] ; then export PATH="$HOME/cmake/bin:${PATH}"; fi
|
||||
|
||||
cache:
|
||||
directories:
|
||||
- $HOME/cmake
|
||||
|
||||
script:
|
||||
- mkdir -p build
|
||||
- cd build
|
||||
- eval cmake -DENABLE_DATE_TESTING=ON -DBUILD_SHARED_LIBS=ON ${CMAKE_EXTRA_CONF} ..
|
||||
- cmake --build . --parallel
|
||||
- cmake --build . --parallel --target testit
|
||||
|
351
CMakeLists.txt
351
CMakeLists.txt
@ -1,161 +1,248 @@
|
||||
cmake_minimum_required( VERSION 3.0.2 )
|
||||
#[===================================================================[
|
||||
date library by Howard Hinnant
|
||||
|
||||
project( date_prj )
|
||||
CMake projects that wish to use this library should consider
|
||||
something like the following :
|
||||
|
||||
find_package( Threads REQUIRED )
|
||||
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)
|
||||
|
||||
enable_testing( )
|
||||
#]===================================================================]
|
||||
|
||||
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_TZ_STATIC "Build a static version of library" ON )
|
||||
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( )
|
||||
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_TZ_STATIC )
|
||||
print_option( BUILD_SHARED_LIBS )
|
||||
print_option( ENABLE_DATE_TESTING )
|
||||
print_option( DISABLE_STRING_VIEW )
|
||||
|
||||
if( USE_SYSTEM_TZ_DB )
|
||||
add_definitions( -DUSE_AUTOLOAD=0 )
|
||||
add_definitions( -DHAS_REMOTE_API=0 )
|
||||
# cannot set USE_OS_TZDB to 1 on Windows
|
||||
if( NOT WIN32 )
|
||||
add_definitions( -DUSE_OS_TZDB=1 )
|
||||
endif( )
|
||||
else( )
|
||||
add_definitions( -DUSE_AUTOLOAD=1 )
|
||||
add_definitions( -DHAS_REMOTE_API=1 )
|
||||
add_definitions( -DUSE_OS_TZDB=0 )
|
||||
find_package( CURL REQUIRED )
|
||||
include_directories( SYSTEM ${CURL_INCLUDE_DIRS} )
|
||||
set( OPTIONAL_LIBRARIES ${CURL_LIBRARIES} )
|
||||
endif( )
|
||||
|
||||
if( USE_TZ_DB_IN_DOT )
|
||||
add_definitions( -DINSTALL=. )
|
||||
endif( )
|
||||
|
||||
set( HEADER_FOLDER "include" )
|
||||
set( SOURCE_FOLDER "src" )
|
||||
set( TEST_FOLDER "test" )
|
||||
|
||||
# This is needed so IDE's live MSVC show header files
|
||||
set( HEADER_FILES
|
||||
${HEADER_FOLDER}/date/chrono_io.h
|
||||
${HEADER_FOLDER}/date/date.h
|
||||
${HEADER_FOLDER}/date/ios.h
|
||||
${HEADER_FOLDER}/date/islamic.h
|
||||
${HEADER_FOLDER}/date/iso_week.h
|
||||
${HEADER_FOLDER}/date/julian.h
|
||||
${HEADER_FOLDER}/date/tz.h
|
||||
${HEADER_FOLDER}/date/tz_private.h
|
||||
#[===================================================================[
|
||||
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> )
|
||||
|
||||
if( BUILD_TZ_STATIC )
|
||||
add_library( tz STATIC ${HEADER_FILES} ${SOURCE_FOLDER}/tz.cpp )
|
||||
else( )
|
||||
add_library( tz SHARED ${HEADER_FILES} ${SOURCE_FOLDER}/tz.cpp )
|
||||
#[===================================================================[
|
||||
tz (compiled) library
|
||||
#]===================================================================]
|
||||
if( BUILD_TZ_LIB )
|
||||
add_library( tz )
|
||||
target_sources( 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 tz )
|
||||
target_link_libraries( tz PUBLIC date )
|
||||
target_include_directories( tz PUBLIC
|
||||
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>
|
||||
$<INSTALL_INTERFACE:include> )
|
||||
target_compile_definitions( 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( 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( tz PUBLIC Threads::Threads )
|
||||
endif( )
|
||||
if( NOT USE_SYSTEM_TZ_DB AND NOT MANUAL_TZ_DB )
|
||||
find_package( CURL REQUIRED )
|
||||
target_include_directories( tz SYSTEM PRIVATE ${CURL_INCLUDE_DIRS} )
|
||||
target_link_libraries( tz PRIVATE ${CURL_LIBRARIES} )
|
||||
endif( )
|
||||
endif( )
|
||||
|
||||
if ( ${CMAKE_MINOR_VERSION} GREATER 7 )
|
||||
set( TZ_CXX_STANDARD 17 )
|
||||
else( )
|
||||
set( TZ_CXX_STANDARD 14 )
|
||||
#[===================================================================[
|
||||
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 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 tz NAMESPACE date:: APPEND FILE dateTargets.cmake )
|
||||
endif( )
|
||||
|
||||
set_property(TARGET tz PROPERTY CXX_STANDARD ${TZ_CXX_STANDARD})
|
||||
target_link_libraries( tz ${CMAKE_THREAD_LIBS_INIT} ${OPTIONAL_LIBRARIES} )
|
||||
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})
|
||||
|
||||
# add include folders to the library and targets that consume it
|
||||
target_include_directories(tz PUBLIC
|
||||
$<BUILD_INTERFACE:
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/${HEADER_FOLDER}
|
||||
>
|
||||
$<INSTALL_INTERFACE:
|
||||
include
|
||||
>
|
||||
)
|
||||
#[===================================================================[
|
||||
testing
|
||||
#]===================================================================]
|
||||
if( ENABLE_DATE_TESTING )
|
||||
enable_testing( )
|
||||
|
||||
add_library(date_interface INTERFACE) # an interface (not a library), to enable automatic include_directory (for when just date.h, but not "tz.h and its lib" are needed)
|
||||
add_custom_target( testit COMMAND ${CMAKE_CTEST_COMMAND} )
|
||||
add_dependencies( testit tz )
|
||||
|
||||
# add include folders to the INTERFACE and targets that consume it
|
||||
target_include_directories(date_interface INTERFACE
|
||||
$<BUILD_INTERFACE:
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/${HEADER_FOLDER}
|
||||
>
|
||||
$<INSTALL_INTERFACE:
|
||||
include
|
||||
>
|
||||
)
|
||||
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} 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( )
|
||||
|
||||
install( TARGETS tz DESTINATION lib )
|
||||
install( DIRECTORY ${HEADER_FOLDER}/ DESTINATION include/ )
|
||||
function( add_fail_tests TEST_GLOB TEST_PREFIX )
|
||||
file( GLOB_RECURSE FILENAMES ${TEST_GLOB} )
|
||||
|
||||
add_custom_target( testit COMMAND ${CMAKE_CTEST_COMMAND} )
|
||||
foreach( TEST_FILE ${FILENAMES} )
|
||||
get_filename_component( TEST_NAME ${TEST_FILE} NAME_WE )
|
||||
get_filename_component( TEST_EXT ${TEST_FILE} EXT )
|
||||
|
||||
add_dependencies( testit tz )
|
||||
function( add_pass_tests TEST_GLOB TEST_PREFIX )
|
||||
file( GLOB_RECURSE FILENAMES ${TEST_GLOB} )
|
||||
include_directories( "${HEADER_FOLDER}/date" )
|
||||
set( TEST_TYPE "_fail" )
|
||||
|
||||
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} )
|
||||
set_property(TARGET ${BIN_NAME} PROPERTY CXX_STANDARD ${TZ_CXX_STANDARD})
|
||||
add_test( ${TST_NAME} ${BIN_NAME} )
|
||||
target_link_libraries( ${BIN_NAME} tz )
|
||||
add_dependencies( testit ${BIN_NAME} )
|
||||
endif( )
|
||||
endforeach( )
|
||||
endfunction( )
|
||||
set( PREFIX "${TEST_PREFIX}_fail_${TEST_NAME}" )
|
||||
set( BIN_NAME ${PREFIX}_bin )
|
||||
set( TST_NAME ${PREFIX}_test )
|
||||
|
||||
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 )
|
||||
|
||||
#target_compile_definitions( ${BIN_NAME} PRIVATE ${TST_NAME} )
|
||||
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}/${HEADER_FOLDER}/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_FOLDER}" "${PROJECT_SOURCE_DIR}/${TEST_FOLDER}/*" )
|
||||
foreach( child ${children} )
|
||||
if( IS_DIRECTORY "${PROJECT_SOURCE_DIR}/${TEST_FOLDER}/${child}" )
|
||||
set( CUR_FOLDER "${PROJECT_SOURCE_DIR}/${TEST_FOLDER}/${child}" )
|
||||
add_pass_tests( "${CUR_FOLDER}/*.cpp" ${child} )
|
||||
if( NOT WIN32 )
|
||||
add_fail_tests( "${CUR_FOLDER}/*.fail.cpp" ${child} )
|
||||
endif( )
|
||||
endif( )
|
||||
endforeach( )
|
||||
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( )
|
||||
|
59
README.md
59
README.md
@ -1,43 +1,72 @@
|
||||
# Date
|
||||
|
||||
[](https://travis-ci.org/HowardHinnant/date)
|
||||
[](https://gitter.im/HowardHinnant/date?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
|
||||
<hr/>
|
||||
|
||||
**[Try it out on wandbox!](https://wandbox.org/permlink/vqwMyTphHJv5iXX7)**
|
||||
---
|
||||
|
||||
This is actually several separate C++11/C++14 libraries:
|
||||
**[Try it out on wandbox!](https://wandbox.org/permlink/L8MwjzSSC3fXXrMd)**
|
||||
|
||||
1. `"date.h"` is a header-only library which builds upon `<chrono>`. It adds some new `duration` types, and new `time_point` types. It also adds "field" types such as `year_month_day` which is a struct `{year, month, day}`. And it provides convenient means to convert between the "field" types and the `time_point` types.
|
||||
## Summary
|
||||
|
||||
This is actually several separate C++11/C++14/C++17 libraries:
|
||||
|
||||
1. `"date.h"` is a header-only library which builds upon `<chrono>`. It adds some new `duration` types, and new `time_point` types. It also adds "field" types such as `year_month_day` which is a struct `{year, month, day}`. And it provides convenient means to convert between the "field" types and the `time_point` types.
|
||||
|
||||
* Documentation: http://howardhinnant.github.io/date/date.html
|
||||
* Video: https://www.youtube.com/watch?v=tzyGjOm8AKo
|
||||
* Slides: http://schd.ws/hosted_files/cppcon2015/43/hinnant_dates.pdf
|
||||
|
||||
2. `"tz.h"` / `"tz.cpp"` are a timezone library built on top of the `"date.h"` library. This timezone library is a complete parser of the IANA timezone database. It provides for an easy way to access all of the data in this database, using the types from `"date.h"` and `<chrono>`. The IANA database also includes data on leap seconds, and this library provides utilities to compute with that information as well.
|
||||
1. `"tz.h"` / `"tz.cpp"` are a timezone library built on top of the `"date.h"` library. This timezone library is a complete parser of the IANA timezone database. It provides for an easy way to access all of the data in this database, using the types from `"date.h"` and `<chrono>`. The IANA database also includes data on leap seconds, and this library provides utilities to compute with that information as well.
|
||||
|
||||
* Documentation: http://howardhinnant.github.io/date/tz.html
|
||||
* Video: https://www.youtube.com/watch?v=Vwd3pduVGKY
|
||||
* Slides: http://schd.ws/hosted_files/cppcon2016/0f/Welcome%20To%20The%20Time%20Zone%20-%20Howard%20Hinnant%20-%20CppCon%202016.pdf
|
||||
|
||||
3. `"iso_week.h"` is a header-only library built on top of the `"date.h"` library which implements the ISO week date calendar.
|
||||
1. `"iso_week.h"` is a header-only library built on top of the `"date.h"` library which implements the ISO week date calendar.
|
||||
|
||||
* Documentation: http://howardhinnant.github.io/date/iso_week.html
|
||||
|
||||
4. `"julian.h"` is a header-only library built on top of the `"date.h"` library which implements a proleptic Julian calendar which is fully interoperable with everything above.
|
||||
1. `"julian.h"` is a header-only library built on top of the `"date.h"` library which implements a proleptic Julian calendar which is fully interoperable with everything above.
|
||||
|
||||
* Documentation: http://howardhinnant.github.io/date/julian.html
|
||||
|
||||
5. `"islamic.h"` is a header-only library built on top of the `"date.h"` library which implements a proleptic Islamic calendar which is fully interoperable with everything above.
|
||||
1. `"islamic.h"` is a header-only library built on top of the `"date.h"` library which implements a proleptic Islamic calendar which is fully interoperable with everything above.
|
||||
|
||||
* Documentation: http://howardhinnant.github.io/date/islamic.html
|
||||
|
||||
`"date.h"` and `"tz.h"` are now being proposed for standardization:
|
||||
## Standardization
|
||||
|
||||
* Current proposal: http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2017/p0355r4.html
|
||||
* Draft revision: http://howardhinnant.github.io/date/d0355r5.html
|
||||
* Status: The proposal was approved by LEWG and forwarded to LWG with the recommendation of targeting C++20 at the Albuquerque, NM meeting in Nov. 2017.
|
||||
Slightly modified versions of `"date.h"` and `"tz.h"` were voted into the C++20 working draft at the Jacksonville FL meeting on 2018-03-17:
|
||||
|
||||
List of projects using this library:
|
||||
* http://howardhinnant.github.io/date/d0355r7.html
|
||||
|
||||
* www.safe.com
|
||||
* www.webtoolkit.eu/wt
|
||||
## Build & Test
|
||||
|
||||
You can download and install Date using the [vcpkg](https://github.com/Microsoft/vcpkg) dependency manager:
|
||||
|
||||
git clone https://github.com/Microsoft/vcpkg.git
|
||||
cd vcpkg
|
||||
./bootstrap-vcpkg.sh
|
||||
./vcpkg integrate install
|
||||
vcpkg install date
|
||||
|
||||
The Date port in vcpkg is updated by Microsoft team members and community contributors. If the version falls behind, please [create an issue or pull request](https://github.com/Microsoft/vcpkg) on the vcpkg repository.
|
||||
|
||||
You can optionally build using [CMake](https://cmake.org/). Here is a guide of how to build and test using the CMake Makefile generator.
|
||||
|
||||
```bash
|
||||
mkdir build
|
||||
cd build
|
||||
cmake ../
|
||||
cmake --build . --target testit # Consider '-- -j4' for multithreading
|
||||
```
|
||||
## Projects using this library
|
||||
|
||||
* www.safe.com
|
||||
* www.webtoolkit.eu/wt
|
||||
* https://github.com/ViewTouch/viewtouch
|
||||
* https://routinghub.com
|
||||
* https://github.com/valhalla
|
||||
|
||||
If you would like your project (or product) on this list, just let me know.
|
||||
|
34
ci/install_cmake.sh
Executable file
34
ci/install_cmake.sh
Executable file
@ -0,0 +1,34 @@
|
||||
#!/usr/bin/env bash
|
||||
set -e
|
||||
|
||||
IFS=. read cm_maj cm_min cm_rel <<<"$1"
|
||||
: ${cm_rel:-0}
|
||||
CMAKE_ROOT=${2:-"${HOME}/cmake"}
|
||||
|
||||
function cmake_version ()
|
||||
{
|
||||
if [[ -d ${CMAKE_ROOT} ]] ; then
|
||||
local perms=$(test $(uname) = "Linux" && echo "/111" || echo "+111")
|
||||
local installed=$(find ${CMAKE_ROOT} -perm ${perms} -type f -name cmake)
|
||||
if [[ "${installed}" != "" ]] ; then
|
||||
echo "$(${installed} --version | head -1)"
|
||||
fi
|
||||
fi
|
||||
}
|
||||
|
||||
installed=$(cmake_version)
|
||||
if [[ "${installed}" != "" && ${installed} =~ ${cm_maj}.${cm_min}.${cm_rel} ]] ; then
|
||||
echo "cmake already installed: ${installed}"
|
||||
exit
|
||||
fi
|
||||
|
||||
pkgname="cmake-${cm_maj}.${cm_min}.${cm_rel}-$(uname)-x86_64.tar.gz"
|
||||
tmppkg="/tmp/cmake.tar.gz"
|
||||
wget --quiet https://cmake.org/files/v${cm_maj}.${cm_min}/${pkgname} -O ${tmppkg}
|
||||
mkdir -p ${CMAKE_ROOT}
|
||||
cd ${CMAKE_ROOT}
|
||||
tar --strip-components 1 -xf ${tmppkg}
|
||||
rm -f ${tmppkg}
|
||||
echo "installed: $(cmake_version)"
|
||||
|
||||
|
11
cmake/dateConfig.cmake
Normal file
11
cmake/dateConfig.cmake
Normal file
@ -0,0 +1,11 @@
|
||||
include( CMakeFindDependencyMacro )
|
||||
include( "${CMAKE_CURRENT_LIST_DIR}/dateTargets.cmake" )
|
||||
if( NOT MSVC AND TARGET date::tz )
|
||||
find_dependency( Threads REQUIRED)
|
||||
get_target_property( _tzill date::tz INTERFACE_LINK_LIBRARIES )
|
||||
if( _tzill AND "${_tzill}" MATCHES "libcurl" )
|
||||
find_dependency( CURL )
|
||||
endif( )
|
||||
endif( )
|
||||
|
||||
|
4411
include/date/date.h
4411
include/date/date.h
File diff suppressed because it is too large
Load Diff
@ -38,6 +38,7 @@
|
||||
{
|
||||
|
||||
std::string get_tzdata_path();
|
||||
std::string get_current_timezone();
|
||||
|
||||
} // namespace iOSUtils
|
||||
} // namespace date
|
||||
|
@ -39,10 +39,10 @@ using days = date::days;
|
||||
using weeks = date::weeks;
|
||||
|
||||
using years = std::chrono::duration
|
||||
<int, std::ratio_multiply<std::ratio<10631, 30>, days::period>>;
|
||||
<int, date::detail::ratio_multiply<std::ratio<10631, 30>, days::period>>;
|
||||
|
||||
using months = std::chrono::duration
|
||||
<int, std::ratio_divide<years::period, std::ratio<12>>>;
|
||||
<int, date::detail::ratio_divide<years::period, std::ratio<12>>>;
|
||||
|
||||
// time_point
|
||||
|
||||
@ -253,7 +253,7 @@ public:
|
||||
CONSTCD14 year& operator+=(const years& y) NOEXCEPT;
|
||||
CONSTCD14 year& operator-=(const years& y) NOEXCEPT;
|
||||
|
||||
CONSTCD11 bool is_leap() const NOEXCEPT;
|
||||
CONSTCD14 bool is_leap() const NOEXCEPT;
|
||||
|
||||
CONSTCD11 explicit operator int() const NOEXCEPT;
|
||||
CONSTCD11 bool ok() const NOEXCEPT;
|
||||
@ -866,7 +866,7 @@ inline
|
||||
std::basic_ostream<CharT, Traits>&
|
||||
operator<<(std::basic_ostream<CharT, Traits>& os, const day& d)
|
||||
{
|
||||
date::detail::save_stream<CharT, Traits> _(os);
|
||||
date::detail::save_ostream<CharT, Traits> _(os);
|
||||
os.fill('0');
|
||||
os.flags(std::ios::dec | std::ios::right);
|
||||
os.width(2);
|
||||
@ -1046,7 +1046,7 @@ CONSTCD14 inline year year::operator--(int) NOEXCEPT {auto tmp(*this); --(*this)
|
||||
CONSTCD14 inline year& year::operator+=(const years& y) NOEXCEPT {*this = *this + y; return *this;}
|
||||
CONSTCD14 inline year& year::operator-=(const years& y) NOEXCEPT {*this = *this - y; return *this;}
|
||||
|
||||
CONSTCD11
|
||||
CONSTCD14
|
||||
inline
|
||||
bool
|
||||
year::is_leap() const NOEXCEPT
|
||||
@ -1177,7 +1177,7 @@ inline
|
||||
std::basic_ostream<CharT, Traits>&
|
||||
operator<<(std::basic_ostream<CharT, Traits>& os, const year& y)
|
||||
{
|
||||
date::detail::save_stream<CharT, Traits> _(os);
|
||||
date::detail::save_ostream<CharT, Traits> _(os);
|
||||
os.fill('0');
|
||||
os.flags(std::ios::dec | std::ios::internal);
|
||||
os.width(4 + (y < year{0}));
|
||||
@ -2236,7 +2236,7 @@ inline
|
||||
std::basic_ostream<CharT, Traits>&
|
||||
operator<<(std::basic_ostream<CharT, Traits>& os, const year_month_day& ymd)
|
||||
{
|
||||
date::detail::save_stream<CharT, Traits> _(os);
|
||||
date::detail::save_ostream<CharT, Traits> _(os);
|
||||
os.fill('0');
|
||||
os.flags(std::ios::dec | std::ios::right);
|
||||
os << ymd.year() << '-';
|
||||
|
@ -451,7 +451,7 @@ weekday::weekday(unsigned wd) NOEXCEPT
|
||||
CONSTCD11
|
||||
inline
|
||||
weekday::weekday(date::weekday wd) NOEXCEPT
|
||||
: wd_(to_iso_encoding(static_cast<unsigned>(wd)))
|
||||
: wd_(wd.iso_encoding())
|
||||
{}
|
||||
|
||||
CONSTCD11
|
||||
@ -607,7 +607,10 @@ inline
|
||||
year
|
||||
year::min() NOEXCEPT
|
||||
{
|
||||
using namespace std::chrono;
|
||||
using std::chrono::seconds;
|
||||
using std::chrono::minutes;
|
||||
using std::chrono::hours;
|
||||
using std::chrono::duration_cast;
|
||||
static_assert(sizeof(seconds)*CHAR_BIT >= 41, "seconds may overflow");
|
||||
static_assert(sizeof(hours)*CHAR_BIT >= 30, "hours may overflow");
|
||||
return sizeof(minutes)*CHAR_BIT < 34 ?
|
||||
@ -620,7 +623,10 @@ inline
|
||||
year
|
||||
year::max() NOEXCEPT
|
||||
{
|
||||
using namespace std::chrono;
|
||||
using std::chrono::seconds;
|
||||
using std::chrono::minutes;
|
||||
using std::chrono::hours;
|
||||
using std::chrono::duration_cast;
|
||||
static_assert(sizeof(seconds)*CHAR_BIT >= 41, "seconds may overflow");
|
||||
static_assert(sizeof(hours)*CHAR_BIT >= 30, "hours may overflow");
|
||||
return sizeof(minutes)*CHAR_BIT < 34 ?
|
||||
@ -713,7 +719,7 @@ inline
|
||||
std::basic_ostream<CharT, Traits>&
|
||||
operator<<(std::basic_ostream<CharT, Traits>& os, const year& y)
|
||||
{
|
||||
date::detail::save_stream<CharT, Traits> _(os);
|
||||
date::detail::save_ostream<CharT, Traits> _(os);
|
||||
os.fill('0');
|
||||
os.flags(std::ios::dec | std::ios::internal);
|
||||
os.width(4 + (y < year{0}));
|
||||
@ -875,7 +881,7 @@ inline
|
||||
std::basic_ostream<CharT, Traits>&
|
||||
operator<<(std::basic_ostream<CharT, Traits>& os, const weeknum& wn)
|
||||
{
|
||||
date::detail::save_stream<CharT, Traits> _(os);
|
||||
date::detail::save_ostream<CharT, Traits> _(os);
|
||||
os << 'W';
|
||||
os.fill('0');
|
||||
os.flags(std::ios::dec | std::ios::right);
|
||||
|
@ -39,10 +39,10 @@ using days = date::days;
|
||||
using weeks = date::weeks;
|
||||
|
||||
using years = std::chrono::duration
|
||||
<int, std::ratio_multiply<std::ratio<1461, 4>, days::period>>;
|
||||
<int, date::detail::ratio_multiply<std::ratio<1461, 4>, days::period>>;
|
||||
|
||||
using months = std::chrono::duration
|
||||
<int, std::ratio_divide<years::period, std::ratio<12>>>;
|
||||
<int, date::detail::ratio_divide<years::period, std::ratio<12>>>;
|
||||
|
||||
// time_point
|
||||
|
||||
@ -879,7 +879,7 @@ inline
|
||||
std::basic_ostream<CharT, Traits>&
|
||||
operator<<(std::basic_ostream<CharT, Traits>& os, const day& d)
|
||||
{
|
||||
date::detail::save_stream<CharT, Traits> _(os);
|
||||
date::detail::save_ostream<CharT, Traits> _(os);
|
||||
os.fill('0');
|
||||
os.flags(std::ios::dec | std::ios::right);
|
||||
os.width(2);
|
||||
@ -1171,7 +1171,7 @@ inline
|
||||
std::basic_ostream<CharT, Traits>&
|
||||
operator<<(std::basic_ostream<CharT, Traits>& os, const year& y)
|
||||
{
|
||||
date::detail::save_stream<CharT, Traits> _(os);
|
||||
date::detail::save_ostream<CharT, Traits> _(os);
|
||||
os.fill('0');
|
||||
os.flags(std::ios::dec | std::ios::internal);
|
||||
os.width(4 + (y < year{0}));
|
||||
@ -2250,7 +2250,7 @@ inline
|
||||
std::basic_ostream<CharT, Traits>&
|
||||
operator<<(std::basic_ostream<CharT, Traits>& os, const year_month_day& ymd)
|
||||
{
|
||||
date::detail::save_stream<CharT, Traits> _(os);
|
||||
date::detail::save_ostream<CharT, Traits> _(os);
|
||||
os.fill('0');
|
||||
os.flags(std::ios::dec | std::ios::right);
|
||||
os << ymd.year() << '-';
|
||||
|
@ -96,19 +96,22 @@ inline
|
||||
date::local_seconds
|
||||
rule::operator()(date::year y) const
|
||||
{
|
||||
using namespace date;
|
||||
using date::local_days;
|
||||
using date::January;
|
||||
using date::days;
|
||||
using date::last;
|
||||
using sec = std::chrono::seconds;
|
||||
date::local_seconds t;
|
||||
switch (mode_)
|
||||
{
|
||||
case J:
|
||||
t = local_days{y/jan/0} + days{n_ + (y.is_leap() && n_ > 59)} + sec{time_};
|
||||
t = local_days{y/January/0} + days{n_ + (y.is_leap() && n_ > 59)} + sec{time_};
|
||||
break;
|
||||
case M:
|
||||
t = (n_ == 5 ? local_days{y/m_/wd_[last]} : local_days{y/m_/wd_[n_]}) + sec{time_};
|
||||
break;
|
||||
case N:
|
||||
t = local_days{y/jan/1} + days{n_} + sec{time_};
|
||||
t = local_days{y/January/1} + days{n_} + sec{time_};
|
||||
break;
|
||||
default:
|
||||
assert(!"rule called with bad mode");
|
||||
@ -180,7 +183,9 @@ public:
|
||||
inline
|
||||
time_zone::time_zone(const detail::string_t& s)
|
||||
{
|
||||
using namespace detail;
|
||||
using detail::read_name;
|
||||
using detail::read_signed_time;
|
||||
using detail::throw_invalid;
|
||||
auto i = read_name(s, 0, std_abbrev_);
|
||||
i = read_signed_time(s, i, offset_);
|
||||
offset_ = -offset_;
|
||||
@ -212,8 +217,19 @@ template <class Duration>
|
||||
date::sys_info
|
||||
time_zone::get_info(date::sys_time<Duration> st) const
|
||||
{
|
||||
using namespace date;
|
||||
using namespace std::chrono;
|
||||
using date::sys_info;
|
||||
using date::year_month_day;
|
||||
using date::sys_seconds;
|
||||
using date::sys_days;
|
||||
using date::floor;
|
||||
using date::ceil;
|
||||
using date::days;
|
||||
using date::years;
|
||||
using date::year;
|
||||
using date::January;
|
||||
using date::December;
|
||||
using date::last;
|
||||
using std::chrono::minutes;
|
||||
sys_info r{};
|
||||
r.offset = offset_;
|
||||
if (start_rule_.ok())
|
||||
@ -245,8 +261,8 @@ time_zone::get_info(date::sys_time<Duration> st) const
|
||||
}
|
||||
else // constant offset
|
||||
{
|
||||
r.begin = sys_days{year::min()/jan/1};
|
||||
r.end = sys_days{year::max()/dec/last};
|
||||
r.begin = sys_days{year::min()/January/1};
|
||||
r.end = sys_days{year::max()/December/last};
|
||||
r.abbrev = std_abbrev_;
|
||||
}
|
||||
return r;
|
||||
@ -256,9 +272,21 @@ template <class Duration>
|
||||
date::local_info
|
||||
time_zone::get_info(date::local_time<Duration> tp) const
|
||||
{
|
||||
using namespace date;
|
||||
using namespace std::chrono;
|
||||
using date::local_info;
|
||||
using date::year_month_day;
|
||||
using date::days;
|
||||
using date::sys_days;
|
||||
using date::sys_seconds;
|
||||
using date::years;
|
||||
using date::year;
|
||||
using date::ceil;
|
||||
using date::January;
|
||||
using date::December;
|
||||
using date::last;
|
||||
using std::chrono::seconds;
|
||||
using std::chrono::minutes;
|
||||
local_info r{};
|
||||
using date::floor;
|
||||
if (start_rule_.ok())
|
||||
{
|
||||
auto y = year_month_day{floor<days>(tp)}.year();
|
||||
@ -323,8 +351,8 @@ time_zone::get_info(date::local_time<Duration> tp) const
|
||||
}
|
||||
else // constant offset
|
||||
{
|
||||
r.first.begin = sys_days{year::min()/jan/1};
|
||||
r.first.end = sys_days{year::max()/dec/last};
|
||||
r.first.begin = sys_days{year::min()/January/1};
|
||||
r.first.end = sys_days{year::max()/December/last};
|
||||
r.first.abbrev = std_abbrev_;
|
||||
r.first.offset = offset_;
|
||||
}
|
||||
@ -335,7 +363,9 @@ template <class Duration>
|
||||
date::sys_time<typename std::common_type<Duration, std::chrono::seconds>::type>
|
||||
time_zone::to_sys(date::local_time<Duration> tp) const
|
||||
{
|
||||
using namespace date;
|
||||
using date::local_info;
|
||||
using date::sys_time;
|
||||
using date::ambiguous_local_time;
|
||||
auto i = get_info(tp);
|
||||
if (i.result == local_info::nonexistent)
|
||||
throw nonexistent_local_time(tp, i);
|
||||
@ -348,7 +378,9 @@ template <class Duration>
|
||||
date::sys_time<typename std::common_type<Duration, std::chrono::seconds>::type>
|
||||
time_zone::to_sys(date::local_time<Duration> tp, date::choose z) const
|
||||
{
|
||||
using namespace date;
|
||||
using date::local_info;
|
||||
using date::sys_time;
|
||||
using date::choose;
|
||||
auto i = get_info(tp);
|
||||
if (i.result == local_info::nonexistent)
|
||||
{
|
||||
@ -366,8 +398,8 @@ template <class Duration>
|
||||
date::local_time<typename std::common_type<Duration, std::chrono::seconds>::type>
|
||||
time_zone::to_local(date::sys_time<Duration> tp) const
|
||||
{
|
||||
using namespace date;
|
||||
using namespace std::chrono;
|
||||
using date::local_time;
|
||||
using std::chrono::seconds;
|
||||
using LT = local_time<typename std::common_type<Duration, seconds>::type>;
|
||||
auto i = get_info(tp);
|
||||
return LT{(tp + i.offset).time_since_epoch()};
|
||||
@ -393,7 +425,7 @@ throw_invalid(const string_t& s, unsigned i, const string_t& message)
|
||||
{
|
||||
throw std::runtime_error(std::string("Invalid time_zone initializer.\n") +
|
||||
std::string(message) + ":\n" +
|
||||
s + '\n' +
|
||||
std::string(s) + '\n' +
|
||||
"\x1b[1;32m" +
|
||||
std::string(i, '~') + '^' +
|
||||
std::string(s.size()-i-1, '~') +
|
||||
@ -404,7 +436,8 @@ inline
|
||||
unsigned
|
||||
read_date(const string_t& s, unsigned i, rule& r)
|
||||
{
|
||||
using namespace date;
|
||||
using date::month;
|
||||
using date::weekday;
|
||||
if (i == s.size())
|
||||
throw_invalid(s, i, "Expected rule but found end of string");
|
||||
if (s[i] == 'J')
|
||||
@ -513,7 +546,9 @@ inline
|
||||
unsigned
|
||||
read_unsigned_time(const string_t& s, unsigned i, std::chrono::seconds& t)
|
||||
{
|
||||
using namespace std::chrono;
|
||||
using std::chrono::seconds;
|
||||
using std::chrono::minutes;
|
||||
using std::chrono::hours;
|
||||
if (i == s.size())
|
||||
throw_invalid(s, i, "Expected to read unsigned time, but found end of string");
|
||||
unsigned x;
|
||||
|
3143
include/date/solar_hijri.h
Normal file
3143
include/date/solar_hijri.h
Normal file
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@ -95,9 +95,9 @@ private:
|
||||
U& operator=(const pair& x);
|
||||
} u;
|
||||
|
||||
std::chrono::hours h_{0};
|
||||
std::chrono::minutes m_{0};
|
||||
std::chrono::seconds s_{0};
|
||||
std::chrono::hours h_{};
|
||||
std::chrono::minutes m_{};
|
||||
std::chrono::seconds s_{};
|
||||
tz zone_{tz::local};
|
||||
|
||||
public:
|
||||
@ -289,11 +289,9 @@ struct transition
|
||||
std::ostream&
|
||||
operator<<(std::ostream& os, const transition& t)
|
||||
{
|
||||
using namespace date;
|
||||
using namespace std::chrono;
|
||||
using date::operator<<;
|
||||
os << t.timepoint << "Z ";
|
||||
if (t.info->offset >= seconds{0})
|
||||
if (t.info->offset >= std::chrono::seconds{0})
|
||||
os << '+';
|
||||
os << make_time(t.info->offset);
|
||||
if (t.info->is_dst > 0)
|
||||
|
@ -22,7 +22,7 @@
|
||||
// SOFTWARE.
|
||||
//
|
||||
|
||||
#include "ios.h"
|
||||
#include "date/ios.h"
|
||||
|
||||
#if TARGET_OS_IPHONE
|
||||
|
244
src/tz.cpp
244
src/tz.cpp
@ -84,10 +84,11 @@
|
||||
#endif // _WIN32
|
||||
|
||||
#include "date/tz_private.h"
|
||||
#include "date/ios.h"
|
||||
|
||||
#ifndef __APPLE__
|
||||
# define TARGET_OS_IPHONE 0
|
||||
#ifdef __APPLE__
|
||||
# include "date/ios.h"
|
||||
#else
|
||||
# define TARGET_OS_IPHONE 0
|
||||
#endif
|
||||
|
||||
#if USE_OS_TZDB
|
||||
@ -97,6 +98,7 @@
|
||||
#include <cctype>
|
||||
#include <cstdlib>
|
||||
#include <cstring>
|
||||
#include <cwchar>
|
||||
#include <exception>
|
||||
#include <fstream>
|
||||
#include <iostream>
|
||||
@ -116,6 +118,14 @@
|
||||
// gcc/mingw supports unistd.h on Win32 but MSVC does not.
|
||||
|
||||
#ifdef _WIN32
|
||||
# ifdef WINAPI_FAMILY
|
||||
# include <winapifamily.h>
|
||||
# if WINAPI_FAMILY != WINAPI_FAMILY_DESKTOP_APP
|
||||
# define WINRT
|
||||
# define INSTALL .
|
||||
# endif
|
||||
# endif
|
||||
|
||||
# include <io.h> // _unlink etc.
|
||||
|
||||
# if defined(__clang__)
|
||||
@ -148,7 +158,7 @@
|
||||
|
||||
#if HAS_REMOTE_API
|
||||
// Note curl includes windows.h so we must include curl AFTER definitions of things
|
||||
// that effect windows.h such as NOMINMAX.
|
||||
// that affect windows.h such as NOMINMAX.
|
||||
#if defined(_MSC_VER) && defined(SHORTENED_CURL_INCLUDE)
|
||||
// For rmt_curl nuget package
|
||||
# include <curl.h>
|
||||
@ -172,6 +182,7 @@ static CONSTDATA char folder_delimiter = '/';
|
||||
#if !USE_OS_TZDB
|
||||
|
||||
# ifdef _WIN32
|
||||
# ifndef WINRT
|
||||
|
||||
namespace
|
||||
{
|
||||
@ -198,11 +209,20 @@ get_known_folder(const GUID& folderid)
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
co_task_mem_ptr folder_ptr(pfolder);
|
||||
folder = std::string(folder_ptr.get(), folder_ptr.get() + wcslen(folder_ptr.get()));
|
||||
const wchar_t* fptr = folder_ptr.get();
|
||||
auto state = std::mbstate_t();
|
||||
const auto required = std::wcsrtombs(nullptr, &fptr, 0, &state);
|
||||
if (required != 0 && required != std::size_t(-1))
|
||||
{
|
||||
folder.resize(required);
|
||||
std::wcsrtombs(&folder[0], &fptr, folder.size(), &state);
|
||||
}
|
||||
}
|
||||
return folder;
|
||||
}
|
||||
|
||||
# ifndef INSTALL
|
||||
|
||||
// Usually something like "c:\Users\username\Downloads".
|
||||
static
|
||||
std::string
|
||||
@ -211,9 +231,12 @@ get_download_folder()
|
||||
return get_known_folder(FOLDERID_Downloads);
|
||||
}
|
||||
|
||||
# endif // !INSTALL
|
||||
|
||||
# endif // WINRT
|
||||
# else // !_WIN32
|
||||
|
||||
# if !defined(INSTALL) || HAS_REMOTE_API
|
||||
# if !defined(INSTALL)
|
||||
|
||||
static
|
||||
std::string
|
||||
@ -239,7 +262,7 @@ get_download_folder()
|
||||
return expand_path("~/Downloads");
|
||||
}
|
||||
|
||||
# endif // !defined(INSTALL) || HAS_REMOTE_API
|
||||
# endif // !defined(INSTALL)
|
||||
|
||||
# endif // !_WIN32
|
||||
|
||||
@ -308,8 +331,8 @@ get_download_gz_file(const std::string& version)
|
||||
CONSTDATA auto min_year = date::year::min();
|
||||
CONSTDATA auto max_year = date::year::max();
|
||||
|
||||
CONSTDATA auto min_day = date::jan/1;
|
||||
CONSTDATA auto max_day = date::dec/31;
|
||||
CONSTDATA auto min_day = date::January/1;
|
||||
CONSTDATA auto max_day = date::December/31;
|
||||
|
||||
#if USE_OS_TZDB
|
||||
|
||||
@ -360,7 +383,13 @@ discover_tz_dir()
|
||||
# endif // __APPLE__
|
||||
}
|
||||
|
||||
static const std::string tz_dir = discover_tz_dir();
|
||||
static
|
||||
const std::string&
|
||||
get_tz_dir()
|
||||
{
|
||||
static const std::string tz_dir = discover_tz_dir();
|
||||
return tz_dir;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
@ -368,11 +397,6 @@ static const std::string tz_dir = discover_tz_dir();
|
||||
// | End Configuration |
|
||||
// +-------------------+
|
||||
|
||||
namespace detail
|
||||
{
|
||||
struct undocumented {explicit undocumented() = default;};
|
||||
}
|
||||
|
||||
#ifndef _MSC_VER
|
||||
static_assert(min_year <= max_year, "Configuration error");
|
||||
#endif
|
||||
@ -492,7 +516,7 @@ native_to_standard_timezone_name(const std::string& native_tz_name,
|
||||
}
|
||||
|
||||
// Parse this XML file:
|
||||
// http://unicode.org/repos/cldr/trunk/common/supplemental/windowsZones.xml
|
||||
// https://raw.githubusercontent.com/unicode-org/cldr/master/common/supplemental/windowsZones.xml
|
||||
// The parsing method is designed to be simple and quick. It is not overly
|
||||
// forgiving of change but it should diagnose basic format issues.
|
||||
// See timezone_mapping structure for more info.
|
||||
@ -609,7 +633,7 @@ load_timezone_mappings_from_xml_file(const std::string& input_path)
|
||||
// NOTE: We could extract the version info that follows the opening
|
||||
// mapTimezones tag and compare that to the version of other data we have.
|
||||
// I would have expected them to be kept in synch but testing has shown
|
||||
// it is typically does not match anyway. So what's the point?
|
||||
// it typically does not match anyway. So what's the point?
|
||||
while (!mapTimezonesCloseTagFound)
|
||||
{
|
||||
std::ws(is);
|
||||
@ -1217,7 +1241,7 @@ detail::operator<<(std::ostream& os, const Rule& r)
|
||||
{
|
||||
using namespace date;
|
||||
using namespace std::chrono;
|
||||
detail::save_stream<char> _(os);
|
||||
detail::save_ostream<char> _(os);
|
||||
os.fill(' ');
|
||||
os.flags(std::ios::dec | std::ios::left);
|
||||
os.width(15);
|
||||
@ -1900,13 +1924,13 @@ load_abbreviations(std::istream& inf, std::int32_t tzh_charcnt)
|
||||
|
||||
template <class TimeType>
|
||||
static
|
||||
std::vector<leap>
|
||||
std::vector<leap_second>
|
||||
load_leaps(std::istream& inf, std::int32_t tzh_leapcnt)
|
||||
{
|
||||
// Read tzh_leapcnt pairs
|
||||
using namespace std::chrono;
|
||||
std::vector<leap> leap_seconds;
|
||||
leap_seconds.reserve(tzh_leapcnt);
|
||||
std::vector<leap_second> leap_seconds;
|
||||
leap_seconds.reserve(static_cast<std::size_t>(tzh_leapcnt));
|
||||
for (std::int32_t i = 0; i < tzh_leapcnt; ++i)
|
||||
{
|
||||
TimeType t0;
|
||||
@ -1923,17 +1947,18 @@ load_leaps(std::istream& inf, std::int32_t tzh_leapcnt)
|
||||
|
||||
template <class TimeType>
|
||||
static
|
||||
std::vector<leap>
|
||||
std::vector<leap_second>
|
||||
load_leap_data(std::istream& inf,
|
||||
std::int32_t tzh_leapcnt, std::int32_t tzh_timecnt,
|
||||
std::int32_t tzh_typecnt, std::int32_t tzh_charcnt)
|
||||
{
|
||||
inf.ignore(tzh_timecnt*sizeof(TimeType) + tzh_timecnt + tzh_typecnt*6 + tzh_charcnt);
|
||||
inf.ignore(tzh_timecnt*static_cast<std::int32_t>(sizeof(TimeType)) + tzh_timecnt +
|
||||
tzh_typecnt*6 + tzh_charcnt);
|
||||
return load_leaps<TimeType>(inf, tzh_leapcnt);
|
||||
}
|
||||
|
||||
static
|
||||
std::vector<leap>
|
||||
std::vector<leap_second>
|
||||
load_just_leaps(std::istream& inf)
|
||||
{
|
||||
// Read tzh_leapcnt pairs
|
||||
@ -1979,7 +2004,7 @@ time_zone::load_data(std::istream& inf,
|
||||
auto infos = load_ttinfo(inf, tzh_typecnt);
|
||||
auto abbrev = load_abbreviations(inf, tzh_charcnt);
|
||||
#if !MISSING_LEAP_SECONDS
|
||||
auto& leap_seconds = get_tzdb_list().front().leaps;
|
||||
auto& leap_seconds = get_tzdb_list().front().leap_seconds;
|
||||
if (leap_seconds.empty() && tzh_leapcnt > 0)
|
||||
leap_seconds = load_leaps<TimeType>(inf, tzh_leapcnt);
|
||||
#endif
|
||||
@ -2011,7 +2036,7 @@ time_zone::init_impl()
|
||||
{
|
||||
using namespace std;
|
||||
using namespace std::chrono;
|
||||
auto name = tz_dir + ('/' + name_);
|
||||
auto name = get_tz_dir() + ('/' + name_);
|
||||
std::ifstream inf(name);
|
||||
if (!inf.is_open())
|
||||
throw std::runtime_error{"Unable to open " + name};
|
||||
@ -2047,7 +2072,7 @@ time_zone::init_impl()
|
||||
#if !MISSING_LEAP_SECONDS
|
||||
if (tzh_leapcnt > 0)
|
||||
{
|
||||
auto& leap_seconds = get_tzdb_list().front().leaps;
|
||||
auto& leap_seconds = get_tzdb_list().front().leap_seconds;
|
||||
auto itr = leap_seconds.begin();
|
||||
auto l = itr->date();
|
||||
seconds leap_count{0};
|
||||
@ -2182,7 +2207,7 @@ operator<<(std::ostream& os, const time_zone& z)
|
||||
|
||||
#if !MISSING_LEAP_SECONDS
|
||||
|
||||
leap::leap(const sys_seconds& s, detail::undocumented)
|
||||
leap_second::leap_second(const sys_seconds& s, detail::undocumented)
|
||||
: date_(s)
|
||||
{
|
||||
}
|
||||
@ -2534,7 +2559,7 @@ operator<<(std::ostream& os, const time_zone& z)
|
||||
{
|
||||
using namespace date;
|
||||
using namespace std::chrono;
|
||||
detail::save_stream<char> _(os);
|
||||
detail::save_ostream<char> _(os);
|
||||
os.fill(' ');
|
||||
os.flags(std::ios::dec | std::ios::left);
|
||||
std::call_once(*z.adjusted_,
|
||||
@ -2588,7 +2613,7 @@ operator<<(std::ostream& os, const time_zone& z)
|
||||
#if !MISSING_LEAP_SECONDS
|
||||
|
||||
std::ostream&
|
||||
operator<<(std::ostream& os, const leap& x)
|
||||
operator<<(std::ostream& os, const leap_second& x)
|
||||
{
|
||||
using namespace date;
|
||||
return os << x.date_ << " +";
|
||||
@ -2604,7 +2629,7 @@ std::string
|
||||
get_version()
|
||||
{
|
||||
using namespace std;
|
||||
auto path = tz_dir + string("/+VERSION");
|
||||
auto path = get_tz_dir() + string("/+VERSION");
|
||||
ifstream in{path};
|
||||
string version;
|
||||
in >> version;
|
||||
@ -2622,7 +2647,7 @@ init_tzdb()
|
||||
|
||||
//Iterate through folders
|
||||
std::queue<std::string> subfolders;
|
||||
subfolders.emplace(tz_dir);
|
||||
subfolders.emplace(get_tz_dir());
|
||||
struct dirent* d;
|
||||
struct stat s;
|
||||
while (!subfolders.empty())
|
||||
@ -2643,6 +2668,8 @@ init_tzdb()
|
||||
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;
|
||||
@ -2657,7 +2684,7 @@ init_tzdb()
|
||||
}
|
||||
else
|
||||
{
|
||||
db->zones.emplace_back(subname.substr(tz_dir.size()+1),
|
||||
db->zones.emplace_back(subname.substr(get_tz_dir().size()+1),
|
||||
detail::undocumented{});
|
||||
}
|
||||
}
|
||||
@ -2667,21 +2694,22 @@ init_tzdb()
|
||||
db->zones.shrink_to_fit();
|
||||
std::sort(db->zones.begin(), db->zones.end());
|
||||
# if !MISSING_LEAP_SECONDS
|
||||
std::ifstream in(tz_dir + std::string(1, folder_delimiter) + "right/UTC",
|
||||
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->leaps = load_just_leaps(in);
|
||||
db->leap_seconds = load_just_leaps(in);
|
||||
}
|
||||
else
|
||||
{
|
||||
in.clear();
|
||||
in.open(tz_dir + std::string(1, folder_delimiter) + "UTC", std::ios_base::binary);
|
||||
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->leaps = load_just_leaps(in);
|
||||
db->leap_seconds = load_just_leaps(in);
|
||||
}
|
||||
# endif // !MISSING_LEAP_SECONDS
|
||||
# ifdef __APPLE__
|
||||
@ -2692,9 +2720,9 @@ init_tzdb()
|
||||
|
||||
#else // !USE_OS_TZDB
|
||||
|
||||
// link
|
||||
// time_zone_link
|
||||
|
||||
link::link(const std::string& s)
|
||||
time_zone_link::time_zone_link(const std::string& s)
|
||||
{
|
||||
using namespace date;
|
||||
std::istringstream in(s);
|
||||
@ -2704,19 +2732,19 @@ link::link(const std::string& s)
|
||||
}
|
||||
|
||||
std::ostream&
|
||||
operator<<(std::ostream& os, const link& x)
|
||||
operator<<(std::ostream& os, const time_zone_link& x)
|
||||
{
|
||||
using namespace date;
|
||||
detail::save_stream<char> _(os);
|
||||
detail::save_ostream<char> _(os);
|
||||
os.fill(' ');
|
||||
os.flags(std::ios::dec | std::ios::left);
|
||||
os.width(35);
|
||||
return os << x.name_ << " --> " << x.target_;
|
||||
}
|
||||
|
||||
// leap
|
||||
// leap_second
|
||||
|
||||
leap::leap(const std::string& s, detail::undocumented)
|
||||
leap_second::leap_second(const std::string& s, detail::undocumented)
|
||||
{
|
||||
using namespace date;
|
||||
std::istringstream in(s);
|
||||
@ -2783,6 +2811,7 @@ download_to_string(const std::string& url, std::string& str)
|
||||
if (!curl)
|
||||
return false;
|
||||
std::string version;
|
||||
curl_easy_setopt(curl.get(), CURLOPT_USERAGENT, "curl");
|
||||
curl_easy_setopt(curl.get(), CURLOPT_URL, url.c_str());
|
||||
curl_write_callback write_cb = [](char* contents, std::size_t size, std::size_t nmemb,
|
||||
void* userp) -> std::size_t
|
||||
@ -2807,13 +2836,15 @@ namespace
|
||||
static
|
||||
bool
|
||||
download_to_file(const std::string& url, const std::string& local_filename,
|
||||
download_file_options opts)
|
||||
download_file_options opts, char* error_buffer)
|
||||
{
|
||||
auto curl = curl_init();
|
||||
if (!curl)
|
||||
return false;
|
||||
curl_easy_setopt(curl.get(), CURLOPT_URL, url.c_str());
|
||||
curl_easy_setopt(curl.get(), CURLOPT_SSL_VERIFYPEER, false);
|
||||
if (error_buffer)
|
||||
curl_easy_setopt(curl.get(), CURLOPT_ERRORBUFFER, error_buffer);
|
||||
curl_write_callback write_cb = [](char* contents, std::size_t size, std::size_t nmemb,
|
||||
void* userp) -> std::size_t
|
||||
{
|
||||
@ -2956,7 +2987,7 @@ make_directory(const std::string& folder)
|
||||
# endif // !USE_SHELL_API
|
||||
# else // !_WIN32
|
||||
# if USE_SHELL_API
|
||||
return std::system(("mkdir " + folder).c_str()) == EXIT_SUCCESS;
|
||||
return std::system(("mkdir -p " + folder).c_str()) == EXIT_SUCCESS;
|
||||
# else // !USE_SHELL_API
|
||||
return mkdir(folder.c_str(), 0777) == 0;
|
||||
# endif // !USE_SHELL_API
|
||||
@ -3233,7 +3264,7 @@ extract_gz_file(const std::string&, const std::string& gz_file, const std::strin
|
||||
# endif // !_WIN32
|
||||
|
||||
bool
|
||||
remote_download(const std::string& version)
|
||||
remote_download(const std::string& version, char* error_buffer)
|
||||
{
|
||||
assert(!version.empty());
|
||||
|
||||
@ -3241,24 +3272,26 @@ remote_download(const std::string& version)
|
||||
// Download folder should be always available for Windows
|
||||
# else // !_WIN32
|
||||
// Create download folder if it does not exist on UNIX system
|
||||
auto download_folder = get_download_folder();
|
||||
auto download_folder = get_install();
|
||||
if (!file_exists(download_folder))
|
||||
{
|
||||
make_directory(download_folder);
|
||||
if (!make_directory(download_folder))
|
||||
return false;
|
||||
}
|
||||
# endif // _WIN32
|
||||
|
||||
auto url = "https://data.iana.org/time-zones/releases/tzdata" + version +
|
||||
".tar.gz";
|
||||
bool result = download_to_file(url, get_download_gz_file(version),
|
||||
download_file_options::binary);
|
||||
download_file_options::binary, error_buffer);
|
||||
# ifdef _WIN32
|
||||
if (result)
|
||||
{
|
||||
auto mapping_file = get_download_mapping_file(version);
|
||||
result = download_to_file("http://unicode.org/repos/cldr/trunk/common/"
|
||||
"supplemental/windowsZones.xml",
|
||||
mapping_file, download_file_options::text);
|
||||
result = download_to_file(
|
||||
"https://raw.githubusercontent.com/unicode-org/cldr/master/"
|
||||
"common/supplemental/windowsZones.xml",
|
||||
mapping_file, download_file_options::text, error_buffer);
|
||||
}
|
||||
# endif // _WIN32
|
||||
return result;
|
||||
@ -3407,12 +3440,12 @@ init_tzdb()
|
||||
}
|
||||
else if (word == "Link")
|
||||
{
|
||||
db->links.push_back(link(line));
|
||||
db->links.push_back(time_zone_link(line));
|
||||
continue_zone = false;
|
||||
}
|
||||
else if (word == "Leap")
|
||||
{
|
||||
db->leaps.push_back(leap(line, detail::undocumented{}));
|
||||
db->leap_seconds.push_back(leap_second(line, detail::undocumented{}));
|
||||
continue_zone = false;
|
||||
}
|
||||
else if (word == "Zone")
|
||||
@ -3437,8 +3470,8 @@ init_tzdb()
|
||||
db->zones.shrink_to_fit();
|
||||
std::sort(db->links.begin(), db->links.end());
|
||||
db->links.shrink_to_fit();
|
||||
std::sort(db->leaps.begin(), db->leaps.end());
|
||||
db->leaps.shrink_to_fit();
|
||||
std::sort(db->leap_seconds.begin(), db->leap_seconds.end());
|
||||
db->leap_seconds.shrink_to_fit();
|
||||
|
||||
#ifdef _WIN32
|
||||
std::string mapping_file = get_install() + folder_delimiter + "windowsZones.xml";
|
||||
@ -3490,9 +3523,9 @@ tzdb::locate_zone(const std::string& tz_name) const
|
||||
#if !USE_OS_TZDB
|
||||
auto li = std::lower_bound(links.begin(), links.end(), tz_name,
|
||||
#if HAS_STRING_VIEW
|
||||
[](const link& z, const std::string_view& nm)
|
||||
[](const time_zone_link& z, const std::string_view& nm)
|
||||
#else
|
||||
[](const link& z, const std::string& nm)
|
||||
[](const time_zone_link& z, const std::string& nm)
|
||||
#endif
|
||||
{
|
||||
return z.name() < nm;
|
||||
@ -3533,7 +3566,7 @@ operator<<(std::ostream& os, const tzdb& db)
|
||||
os << x << '\n';
|
||||
#if !MISSING_LEAP_SECONDS
|
||||
os << '\n';
|
||||
for (const auto& x : db.leaps)
|
||||
for (const auto& x : db.leap_seconds)
|
||||
os << x << '\n';
|
||||
#endif // !MISSING_LEAP_SECONDS
|
||||
return os;
|
||||
@ -3593,7 +3626,7 @@ operator<<(std::ostream& os, const tzdb& db)
|
||||
"---------------------------------------------------------"
|
||||
"--------------------------------------------------------\n");
|
||||
os << title;
|
||||
for (const auto& x : db.leaps)
|
||||
for (const auto& x : db.leap_seconds)
|
||||
os << x << '\n';
|
||||
return os;
|
||||
}
|
||||
@ -3640,6 +3673,56 @@ tzdb::current_zone() const
|
||||
|
||||
#else // !_WIN32
|
||||
|
||||
#if HAS_STRING_VIEW
|
||||
|
||||
static
|
||||
std::string_view
|
||||
extract_tz_name(char const* rp)
|
||||
{
|
||||
using namespace std;
|
||||
string_view result = rp;
|
||||
CONSTDATA string_view zoneinfo = "zoneinfo";
|
||||
size_t pos = result.rfind(zoneinfo);
|
||||
if (pos == result.npos)
|
||||
throw runtime_error(
|
||||
"current_zone() failed to find \"zoneinfo\" in " + string(result));
|
||||
pos = result.find('/', pos);
|
||||
result.remove_prefix(pos + 1);
|
||||
return result;
|
||||
}
|
||||
|
||||
#else // !HAS_STRING_VIEW
|
||||
|
||||
static
|
||||
std::string
|
||||
extract_tz_name(char const* rp)
|
||||
{
|
||||
using namespace std;
|
||||
string result = rp;
|
||||
CONSTDATA char zoneinfo[] = "zoneinfo";
|
||||
size_t pos = result.rfind(zoneinfo);
|
||||
if (pos == result.npos)
|
||||
throw runtime_error(
|
||||
"current_zone() failed to find \"zoneinfo\" in " + result);
|
||||
pos = result.find('/', pos);
|
||||
result.erase(0, pos + 1);
|
||||
return result;
|
||||
}
|
||||
|
||||
#endif // HAS_STRING_VIEW
|
||||
|
||||
static
|
||||
bool
|
||||
sniff_realpath(const char* timezone)
|
||||
{
|
||||
using namespace std;
|
||||
char rp[PATH_MAX+1] = {};
|
||||
if (realpath(timezone, rp) == nullptr)
|
||||
throw system_error(errno, system_category(), "realpath() failed");
|
||||
auto result = extract_tz_name(rp);
|
||||
return result != "posixrules";
|
||||
}
|
||||
|
||||
const time_zone*
|
||||
tzdb::current_zone() const
|
||||
{
|
||||
@ -3651,7 +3734,7 @@ tzdb::current_zone() const
|
||||
// "/usr/share/zoneinfo/America/Los_Angeles"
|
||||
// If it does, we try to determine the current
|
||||
// timezone from the remainder of the path by removing the prefix
|
||||
// and hoping the rest resolves to valid timezone.
|
||||
// and hoping the rest resolves to a valid timezone.
|
||||
// It may not always work though. If it doesn't then an
|
||||
// exception will be thrown by local_timezone.
|
||||
// The path may also take a relative form:
|
||||
@ -3659,19 +3742,22 @@ tzdb::current_zone() const
|
||||
{
|
||||
struct stat sb;
|
||||
CONSTDATA auto timezone = "/etc/localtime";
|
||||
if (lstat(timezone, &sb) == 0 && S_ISLNK(sb.st_mode) && sb.st_size > 0) {
|
||||
if (lstat(timezone, &sb) == 0 && S_ISLNK(sb.st_mode) && sb.st_size > 0)
|
||||
{
|
||||
using namespace std;
|
||||
string result;
|
||||
static const bool use_realpath = sniff_realpath(timezone);
|
||||
char rp[PATH_MAX+1] = {};
|
||||
if (readlink(timezone, rp, sizeof(rp)-1) > 0)
|
||||
result = string(rp);
|
||||
if (use_realpath)
|
||||
{
|
||||
if (realpath(timezone, rp) == nullptr)
|
||||
throw system_error(errno, system_category(), "realpath() failed");
|
||||
}
|
||||
else
|
||||
throw system_error(errno, system_category(), "readlink() failed");
|
||||
|
||||
const size_t pos = result.find(tz_dir);
|
||||
if (pos != result.npos)
|
||||
result.erase(0, tz_dir.size() + 1 + pos);
|
||||
return locate_zone(result);
|
||||
{
|
||||
if (readlink(timezone, rp, sizeof(rp)-1) <= 0)
|
||||
throw system_error(errno, system_category(), "readlink() failed");
|
||||
}
|
||||
return locate_zone(extract_tz_name(rp));
|
||||
}
|
||||
}
|
||||
// On embedded systems e.g. buildroot with uclibc the timezone is linked
|
||||
@ -3696,9 +3782,9 @@ tzdb::current_zone() const
|
||||
else
|
||||
throw system_error(errno, system_category(), "readlink() failed");
|
||||
|
||||
const size_t pos = result.find(tz_dir);
|
||||
const size_t pos = result.find(get_tz_dir());
|
||||
if (pos != result.npos)
|
||||
result.erase(0, tz_dir.size() + 1 + pos);
|
||||
result.erase(0, get_tz_dir().size() + 1 + pos);
|
||||
return locate_zone(result);
|
||||
}
|
||||
}
|
||||
@ -3731,6 +3817,18 @@ tzdb::current_zone() const
|
||||
// Fall through to try other means.
|
||||
}
|
||||
{
|
||||
// On some versions of some bsd distro's (e.g. iOS),
|
||||
// it is not possible to use file based approach,
|
||||
// we switch to system API, calling functions in
|
||||
// CoreFoundation framework.
|
||||
#if TARGET_OS_IPHONE
|
||||
std::string result = date::iOSUtils::get_current_timezone();
|
||||
if (!result.empty())
|
||||
return locate_zone(result);
|
||||
#endif
|
||||
// Fall through to try other means.
|
||||
}
|
||||
{
|
||||
// On some versions of some linux distro's (e.g. Red Hat),
|
||||
// the current timezone might be in the first line of
|
||||
// the /etc/sysconfig/clock file as:
|
||||
|
75
test/clock_cast_test/constexpr.pass.cpp
Normal file
75
test/clock_cast_test/constexpr.pass.cpp
Normal file
@ -0,0 +1,75 @@
|
||||
// The MIT License (MIT)
|
||||
//
|
||||
// Copyright (c) 2019 nanoric
|
||||
//
|
||||
// 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 <cassert>
|
||||
#include <type_traits>
|
||||
|
||||
struct const_clock {
|
||||
using duration =
|
||||
typename std::common_type<std::chrono::system_clock::duration,
|
||||
date::days>::type;
|
||||
using rep = duration::rep;
|
||||
using period = duration::period;
|
||||
using time_point = std::chrono::time_point<const_clock, duration>;
|
||||
|
||||
static constexpr date::sys_days epoch { date::days { 1000 } };
|
||||
|
||||
template <typename Duration>
|
||||
static std::chrono::time_point<std::chrono::system_clock,
|
||||
typename std::common_type<Duration, date::days>::type>
|
||||
CONSTCD11 to_sys(std::chrono::time_point<const_clock, Duration> const& tp)
|
||||
{
|
||||
return epoch + tp.time_since_epoch();
|
||||
}
|
||||
|
||||
template <typename Duration>
|
||||
static std::chrono::time_point<const_clock,
|
||||
typename std::common_type<Duration, date::days>::type>
|
||||
CONSTCD11 from_sys(
|
||||
std::chrono::time_point<std::chrono::system_clock, Duration> const&
|
||||
tp)
|
||||
{
|
||||
using res = std::chrono::time_point<const_clock,
|
||||
typename std::common_type<Duration, date::days>::type>;
|
||||
return res(tp - epoch);
|
||||
}
|
||||
};
|
||||
|
||||
int main()
|
||||
{
|
||||
using namespace date;
|
||||
using namespace std::chrono;
|
||||
using const_days = time_point<const_clock, days>;
|
||||
|
||||
CONSTCD14 sys_days sys { days { 1024 } };
|
||||
static_assert(sys.time_since_epoch().count() == 1024, "");
|
||||
|
||||
CONSTCD14 const_days c {clock_cast<const_clock>(sys)};
|
||||
CONSTCD14 sys_days sys2 {clock_cast<system_clock>(c)};
|
||||
CONSTCD14 sys_days sys3 { clock_cast<system_clock>(const_days(days(48))) };
|
||||
#if __cplusplus >= 201402L
|
||||
static_assert(c.time_since_epoch().count() == 24, "");
|
||||
static_assert(sys2.time_since_epoch().count() == 1024, "");
|
||||
static_assert(sys3.time_since_epoch().count() == 1048, "");
|
||||
#endif
|
||||
}
|
@ -1,6 +1,6 @@
|
||||
// The MIT License (MIT)
|
||||
//
|
||||
// Copyright (c) 2017 Tomasz Kamiński
|
||||
// Copyright (c) 2017, 2018 Tomasz Kamiński
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
@ -30,16 +30,16 @@ int conversions = 0;
|
||||
//to/from impl
|
||||
struct mil_clock
|
||||
{
|
||||
using duration = std::common_type_t<std::chrono::system_clock::duration, date::days>;
|
||||
using duration = typename std::common_type<std::chrono::system_clock::duration, date::days>::type;
|
||||
using rep = duration::rep;
|
||||
using period = duration::period;
|
||||
using time_point = std::chrono::time_point<mil_clock, duration>;
|
||||
|
||||
static constexpr date::sys_days epoch = date::year{2000}/date::month{0}/date::day{1};
|
||||
static constexpr date::sys_days epoch{date::days{1000}};
|
||||
|
||||
template<typename Duration>
|
||||
static
|
||||
std::chrono::time_point<std::chrono::system_clock, std::common_type_t<Duration, date::days>>
|
||||
std::chrono::time_point<std::chrono::system_clock, typename std::common_type<Duration, date::days>::type>
|
||||
to_sys(std::chrono::time_point<mil_clock, Duration> const& tp)
|
||||
{
|
||||
++conversions;
|
||||
@ -48,14 +48,31 @@ struct mil_clock
|
||||
|
||||
template<typename Duration>
|
||||
static
|
||||
std::chrono::time_point<mil_clock, std::common_type_t<Duration, date::days>>
|
||||
std::chrono::time_point<mil_clock, typename std::common_type<Duration, date::days>::type>
|
||||
from_sys(std::chrono::time_point<std::chrono::system_clock, Duration> const& tp)
|
||||
{
|
||||
++conversions;
|
||||
using res = std::chrono::time_point<mil_clock, std::common_type_t<Duration, date::days>>;
|
||||
using res = std::chrono::time_point<mil_clock, typename std::common_type<Duration, date::days>::type>;
|
||||
return res(tp - epoch);
|
||||
}
|
||||
|
||||
template<typename Duration>
|
||||
static
|
||||
std::chrono::time_point<date::local_t, typename std::common_type<Duration, date::days>::type>
|
||||
to_local(std::chrono::time_point<mil_clock, Duration> const& tp)
|
||||
{
|
||||
return date::clock_cast<date::local_t>(to_sys(tp));
|
||||
}
|
||||
|
||||
template<typename Duration>
|
||||
static
|
||||
std::chrono::time_point<mil_clock, typename std::common_type<Duration, date::days>::type>
|
||||
from_local(std::chrono::time_point<date::local_t, Duration> const& tp)
|
||||
{
|
||||
return from_sys(date::clock_cast<std::chrono::system_clock>(tp));
|
||||
}
|
||||
|
||||
|
||||
static time_point now()
|
||||
{
|
||||
return from_sys(std::chrono::system_clock::now());
|
||||
@ -103,11 +120,11 @@ namespace date
|
||||
struct clock_time_conversion<mil_clock, s2s_clock>
|
||||
{
|
||||
template<typename Duration>
|
||||
std::chrono::time_point<mil_clock, std::common_type_t<Duration, date::days>>
|
||||
std::chrono::time_point<mil_clock, typename std::common_type<Duration, date::days>::type>
|
||||
operator()(std::chrono::time_point<s2s_clock, Duration> const& tp)
|
||||
{
|
||||
++conversions;
|
||||
using res = std::chrono::time_point<mil_clock, std::common_type_t<Duration, date::days>>;
|
||||
using res = std::chrono::time_point<mil_clock, typename std::common_type<Duration, date::days>::type>;
|
||||
return res(tp.time_since_epoch() - mil_clock::epoch.time_since_epoch());
|
||||
}
|
||||
};
|
||||
@ -127,6 +144,15 @@ main()
|
||||
assert(clock_cast<mil_clock>(mt) == mt);
|
||||
}
|
||||
|
||||
// mil <-> local
|
||||
{
|
||||
local_days lt(1997_y/dec/12);
|
||||
auto mt = mil_clock::from_local(lt);
|
||||
|
||||
assert(clock_cast<mil_clock>(lt) == mt);
|
||||
assert(clock_cast<local_t>(mt) == lt);
|
||||
}
|
||||
|
||||
// mil <-> sys
|
||||
{
|
||||
sys_days st(1997_y/dec/12);
|
||||
|
132
test/clock_cast_test/local_t.pass.cpp
Normal file
132
test/clock_cast_test/local_t.pass.cpp
Normal file
@ -0,0 +1,132 @@
|
||||
// The MIT License (MIT)
|
||||
//
|
||||
// Copyright (c) 2018 Tomasz Kamiński
|
||||
//
|
||||
// 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 <chrono>
|
||||
#include "date/tz.h"
|
||||
|
||||
int
|
||||
main()
|
||||
{
|
||||
using namespace date;
|
||||
using namespace std::chrono;
|
||||
|
||||
// self
|
||||
{
|
||||
auto ls = local_days{1970_y/January/1_d};
|
||||
assert(clock_cast<local_t>(ls) == ls);
|
||||
}
|
||||
|
||||
/// sys epoch
|
||||
{
|
||||
auto ls = local_days{1970_y/January/1_d};
|
||||
auto st = clock_cast<system_clock>(ls);
|
||||
assert(clock_cast<local_t>(st) == ls);
|
||||
assert(st.time_since_epoch() == seconds(0));
|
||||
}
|
||||
|
||||
/// sys 2000 case
|
||||
{
|
||||
auto ls = local_days{2000_y/January/1_d};
|
||||
auto st = clock_cast<system_clock>(ls);
|
||||
assert(clock_cast<local_t>(st) == ls);
|
||||
assert(st.time_since_epoch() == seconds(946684800));
|
||||
}
|
||||
|
||||
/// utc epoch
|
||||
{
|
||||
auto lu = local_days{1970_y/January/1_d};
|
||||
auto ut = clock_cast<utc_clock>(lu);
|
||||
assert(clock_cast<local_t>(ut) == lu);
|
||||
assert(ut.time_since_epoch() == seconds(0));
|
||||
}
|
||||
|
||||
// utc leap second
|
||||
{
|
||||
auto lu = local_days{2015_y/July/1_d} - milliseconds(1);
|
||||
auto ut = clock_cast<utc_clock>(lu) + milliseconds(50); //into leap second
|
||||
|
||||
assert(clock_cast<local_t>(ut) == lu);
|
||||
}
|
||||
|
||||
/// utc paper example
|
||||
{
|
||||
auto lu = local_days{2000_y/January/1_d};
|
||||
auto ut = clock_cast<utc_clock>(lu);
|
||||
assert(clock_cast<local_t>(ut) == lu);
|
||||
assert(ut.time_since_epoch() == seconds(946684822));
|
||||
}
|
||||
|
||||
/// tai epoch
|
||||
{
|
||||
auto lt = local_days{1958_y/January/1_d};
|
||||
auto tt = clock_cast<tai_clock>(lt);
|
||||
assert(clock_cast<local_t>(tt) == lt);
|
||||
assert(tt.time_since_epoch() == seconds(0));
|
||||
|
||||
auto lu = local_days{1958_y/January/1_d} - seconds(10);
|
||||
auto ut = clock_cast<utc_clock>(lu);
|
||||
assert(clock_cast<tai_clock>(ut) == tt);
|
||||
}
|
||||
|
||||
// tai paper example
|
||||
{
|
||||
auto lt = local_days{2000_y/January/1_d} + seconds(32);
|
||||
auto tt = clock_cast<tai_clock>(lt);
|
||||
assert(clock_cast<local_t>(tt) == lt);
|
||||
|
||||
auto lu = local_days{2000_y/January/1_d};
|
||||
auto ut = clock_cast<utc_clock>(lu);
|
||||
assert(clock_cast<tai_clock>(ut) == tt);
|
||||
}
|
||||
|
||||
/// gps epoch
|
||||
{
|
||||
auto lg = local_days{1980_y/January/Sunday[1]};
|
||||
auto gt = clock_cast<gps_clock>(lg);
|
||||
assert(clock_cast<local_t>(gt) == lg);
|
||||
assert(gt.time_since_epoch() == seconds(0));
|
||||
|
||||
auto lu = local_days{1980_y/January/Sunday[1]};
|
||||
auto ut = clock_cast<utc_clock>(lu);
|
||||
assert(clock_cast<gps_clock>(ut) == gt);
|
||||
|
||||
auto lt = local_days{1980_y/January/Sunday[1]} + seconds(19);
|
||||
auto tt = clock_cast<tai_clock>(lt);
|
||||
assert(clock_cast<gps_clock>(tt) == gt);
|
||||
}
|
||||
|
||||
// gps 2000 example
|
||||
{
|
||||
auto lg = local_days{2000_y/January/1_d};
|
||||
auto gt = clock_cast<gps_clock>(lg);
|
||||
assert(clock_cast<local_t>(gt) == lg);
|
||||
|
||||
auto lu = local_days{2000_y/January/1_d} - seconds(13);
|
||||
auto ut = clock_cast<utc_clock>(lu);
|
||||
assert(clock_cast<gps_clock>(ut) == gt);
|
||||
|
||||
auto lt = local_days{2000_y/January/1_d} + seconds(19);
|
||||
auto tt = clock_cast<tai_clock>(lt);
|
||||
assert(clock_cast<gps_clock>(tt) == gt);
|
||||
}
|
||||
|
||||
}
|
@ -1,6 +1,6 @@
|
||||
// The MIT License (MIT)
|
||||
//
|
||||
// Copyright (c) 2017 Tomasz Kamiński
|
||||
// Copyright (c) 2017, 2018 Tomasz Kamiński
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
@ -194,6 +194,8 @@ main()
|
||||
|
||||
//steady_clock (must be different that sys_clock)
|
||||
static_assert(is_clock_castable<steady_clock, steady_clock>::value, "steady_clock -> steady_clock");
|
||||
static_assert(!is_clock_castable<steady_clock, local_t>::value, "steady_clock -> local_t");
|
||||
static_assert(!is_clock_castable<local_t, steady_clock>::value, "local_t -> steady_clock");
|
||||
static_assert(!is_clock_castable<steady_clock, sys_clock>::value, "steady_clock -> sys_clock");
|
||||
static_assert(!is_clock_castable<sys_clock, steady_clock>::value, "sys_clock -> steady_clock");
|
||||
static_assert(!is_clock_castable<steady_clock, utc_clock>::value, "steady_clock -> utc_clock");
|
||||
@ -203,6 +205,8 @@ main()
|
||||
|
||||
//steady_based_clock (unrelated to sys_clock and utc_clocks)
|
||||
static_assert(is_clock_castable<steady_based_clock, steady_based_clock>::value, "steady_based_clock -> steady_based_clock");
|
||||
static_assert(!is_clock_castable<steady_based_clock, local_t>::value, "steady_based_clock -> local_t");
|
||||
static_assert(!is_clock_castable<local_t, steady_based_clock>::value, "local_t -> steady_based_clock");
|
||||
static_assert(!is_clock_castable<steady_based_clock, sys_clock>::value, "steady_based_clock -> sys_clock");
|
||||
static_assert(!is_clock_castable<sys_clock, steady_based_clock>::value, "sys_clock -> steady_based_clock");
|
||||
static_assert(!is_clock_castable<steady_based_clock, utc_clock>::value, "steady_based_clock -> utc_clock");
|
||||
|
@ -1,6 +1,6 @@
|
||||
// The MIT License (MIT)
|
||||
//
|
||||
// Copyright (c) 2017 Tomasz Kamiński
|
||||
// Copyright (c) 2017, 2018 Tomasz Kamiński
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
@ -34,7 +34,7 @@ struct bad_clock
|
||||
date::utc_time<Duration>
|
||||
to_sys(std::chrono::time_point<bad_clock, Duration> const& tp)
|
||||
{
|
||||
return utc_time<Duration>(tp.time_since_epoch());
|
||||
return date::utc_time<Duration>(tp.time_since_epoch());
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -20,16 +20,16 @@
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
// SOFTWARE.
|
||||
|
||||
// template <class Duration,
|
||||
// unsigned w = width<std::common_type<
|
||||
// Duration,
|
||||
// std::chrono::seconds>::type::period::den>::value>
|
||||
// template <class Duration>
|
||||
// class decimal_format_seconds
|
||||
// {
|
||||
// using CT = typename std::common_type<Duration, std::chrono::seconds>::type;
|
||||
// using rep = typename CT::rep;
|
||||
// public:
|
||||
// using precision = typename make_precision<w>::type;
|
||||
// static auto constexpr width = make_precision<w>::width;
|
||||
//
|
||||
// static unsigned constexpr width = detail::width<CT::period::den>::value < 19 ?
|
||||
// detail::width<CT::period::den>::value : 6u;
|
||||
// using precision = std::chrono::duration<rep,
|
||||
// std::ratio<1, static_pow10<width>::value>>;
|
||||
// private:
|
||||
// std::chrono::seconds s_;
|
||||
// precision sub_s_;
|
||||
@ -55,12 +55,12 @@
|
||||
#include <type_traits>
|
||||
|
||||
using fortnights = std::chrono::duration<date::weeks::rep,
|
||||
std::ratio_multiply<std::ratio<2>,
|
||||
date::weeks::period>>;
|
||||
date::detail::ratio_multiply<std::ratio<2>,
|
||||
date::weeks::period>>;
|
||||
|
||||
using microfortnights = std::chrono::duration<std::int64_t,
|
||||
std::ratio_multiply<fortnights::period,
|
||||
std::micro>>;
|
||||
date::detail::ratio_multiply<fortnights::period,
|
||||
std::micro>>;
|
||||
|
||||
int
|
||||
main()
|
||||
@ -94,7 +94,6 @@ main()
|
||||
{
|
||||
using D = decimal_format_seconds<milliseconds>;
|
||||
static_assert(D::width == 3, "");
|
||||
static_assert(is_same<D::precision, make_precision<D::rep, D::width>::type>{}, "");
|
||||
D dfs{seconds{3}};
|
||||
assert(dfs.seconds() == seconds{3});
|
||||
assert(dfs.to_duration() == seconds{3});
|
||||
@ -106,7 +105,6 @@ main()
|
||||
{
|
||||
using D = decimal_format_seconds<milliseconds>;
|
||||
static_assert(D::width == 3, "");
|
||||
static_assert(is_same<D::precision, make_precision<D::rep, D::width>::type>{}, "");
|
||||
D dfs{milliseconds{3}};
|
||||
assert(dfs.seconds() == seconds{0});
|
||||
assert(dfs.to_duration() == milliseconds{3});
|
||||
@ -118,9 +116,8 @@ main()
|
||||
{
|
||||
using D = decimal_format_seconds<microfortnights>;
|
||||
static_assert(D::width == 4, "");
|
||||
using S = make_precision<D::rep, D::width>::type;
|
||||
static_assert(is_same<D::precision, S>{}, "");
|
||||
D dfs{microfortnights{3}};
|
||||
using S = D::precision;
|
||||
assert(dfs.seconds() == seconds{3});
|
||||
assert(dfs.to_duration() == S{36288});
|
||||
assert(dfs.subseconds() == S{6288});
|
||||
@ -132,9 +129,8 @@ main()
|
||||
using CT = common_type<seconds, microfortnights>::type;
|
||||
using D = decimal_format_seconds<CT>;
|
||||
static_assert(D::width == 4, "");
|
||||
using S = make_precision<D::rep, D::width>::type;
|
||||
static_assert(is_same<D::precision, S>{}, "");
|
||||
D dfs{microfortnights{3}};
|
||||
using S = D::precision;
|
||||
assert(dfs.seconds() == seconds{3});
|
||||
assert(dfs.to_duration() == S{36288});
|
||||
assert(dfs.subseconds() == S{6288});
|
||||
|
@ -1,63 +0,0 @@
|
||||
// The MIT License (MIT)
|
||||
//
|
||||
// Copyright (c) 2017 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.
|
||||
|
||||
// template <unsigned w>
|
||||
// struct make_precision
|
||||
// {
|
||||
// using type = std::chrono::duration<std::int64_t,
|
||||
// std::ratio<1, static_pow10<w>::value>>;
|
||||
// static constexpr unsigned width = w;
|
||||
// };
|
||||
|
||||
#include "date.h"
|
||||
|
||||
#include <cstdint>
|
||||
#include <type_traits>
|
||||
|
||||
int
|
||||
main()
|
||||
{
|
||||
using namespace date::detail;
|
||||
using namespace std;
|
||||
using namespace std::chrono;
|
||||
|
||||
static_assert(make_precision<int64_t, 0>::width == 0, "");
|
||||
static_assert(is_same<make_precision<int64_t, 0>::type, duration<int64_t, ratio<1, 1>>>{}, "");
|
||||
|
||||
static_assert(make_precision<int64_t, 1>::width == 1, "");
|
||||
static_assert(is_same<make_precision<int64_t, 1>::type, duration<int64_t, ratio<1, 10>>>{}, "");
|
||||
|
||||
static_assert(make_precision<int64_t, 2>::width == 2, "");
|
||||
static_assert(is_same<make_precision<int64_t, 2>::type, duration<int64_t, ratio<1, 100>>>{}, "");
|
||||
|
||||
static_assert(make_precision<int64_t, 3>::width == 3, "");
|
||||
static_assert(is_same<make_precision<int64_t, 3>::type, duration<int64_t, ratio<1, 1000>>>{}, "");
|
||||
|
||||
static_assert(make_precision<int64_t, 18>::width == 18, "");
|
||||
static_assert(is_same<make_precision<int64_t, 18>::type, duration<int64_t, ratio<1, 1000000000000000000>>>{}, "");
|
||||
|
||||
static_assert(make_precision<int64_t, 19>::width == 6, "");
|
||||
static_assert(is_same<make_precision<int64_t, 19>::type, microseconds>{}, "");
|
||||
|
||||
static_assert(make_precision<int64_t, 20>::width == 6, "");
|
||||
static_assert(is_same<make_precision<int64_t, 20>::type, microseconds>{}, "");
|
||||
}
|
328
test/date_test/durations_output.pass.cpp
Normal file
328
test/date_test/durations_output.pass.cpp
Normal file
@ -0,0 +1,328 @@
|
||||
// The MIT License (MIT)
|
||||
//
|
||||
// Copyright (c) 2018 Tomasz Kamiński
|
||||
//
|
||||
// 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 "date.h"
|
||||
|
||||
#include <cassert>
|
||||
#include <sstream>
|
||||
|
||||
void test_SI()
|
||||
{
|
||||
using namespace std::chrono;
|
||||
using namespace date;
|
||||
|
||||
std::ostringstream os;
|
||||
|
||||
// atto
|
||||
{
|
||||
duration<int, std::atto> d(13);
|
||||
os << d;
|
||||
assert(os.str() == "13as");
|
||||
os.str("");
|
||||
}
|
||||
|
||||
// femto
|
||||
{
|
||||
duration<int, std::femto> d(13);
|
||||
os << d;
|
||||
assert(os.str() == "13fs");
|
||||
os.str("");
|
||||
}
|
||||
|
||||
// pico
|
||||
{
|
||||
duration<int, std::pico> d(13);
|
||||
os << d;
|
||||
assert(os.str() == "13ps");
|
||||
os.str("");
|
||||
}
|
||||
|
||||
// nano
|
||||
{
|
||||
duration<int, std::nano> d(13);
|
||||
os << d;
|
||||
assert(os.str() == "13ns");
|
||||
os.str("");
|
||||
}
|
||||
|
||||
// mikro
|
||||
{
|
||||
duration<int, std::micro> d(13);
|
||||
os << d;
|
||||
assert(os.str() == "13\xC2\xB5s");
|
||||
os.str("");
|
||||
}
|
||||
|
||||
// milli
|
||||
{
|
||||
duration<int, std::milli> d(13);
|
||||
os << d;
|
||||
assert(os.str() == "13ms");
|
||||
os.str("");
|
||||
}
|
||||
|
||||
// centi
|
||||
{
|
||||
duration<int, std::centi> d(13);
|
||||
os << d;
|
||||
assert(os.str() == "13cs");
|
||||
os.str("");
|
||||
}
|
||||
|
||||
// deci
|
||||
{
|
||||
duration<int, std::deci> d(13);
|
||||
os << d;
|
||||
assert(os.str() == "13ds");
|
||||
os.str("");
|
||||
}
|
||||
|
||||
// seconds
|
||||
{
|
||||
duration<int> d(13);
|
||||
os << d;
|
||||
assert(os.str() == "13s");
|
||||
os.str("");
|
||||
}
|
||||
|
||||
// deca
|
||||
{
|
||||
duration<int, std::deca> d(13);
|
||||
os << d;
|
||||
assert(os.str() == "13das");
|
||||
os.str("");
|
||||
}
|
||||
|
||||
// hecto
|
||||
{
|
||||
duration<int, std::hecto> d(13);
|
||||
os << d;
|
||||
assert(os.str() == "13hs");
|
||||
os.str("");
|
||||
}
|
||||
|
||||
// kilo
|
||||
{
|
||||
duration<int, std::kilo> d(13);
|
||||
os << d;
|
||||
assert(os.str() == "13ks");
|
||||
os.str("");
|
||||
}
|
||||
|
||||
// mega
|
||||
{
|
||||
duration<int, std::mega> d(13);
|
||||
os << d;
|
||||
assert(os.str() == "13Ms");
|
||||
os.str("");
|
||||
}
|
||||
|
||||
// giga
|
||||
{
|
||||
duration<int, std::giga> d(13);
|
||||
os << d;
|
||||
assert(os.str() == "13Gs");
|
||||
os.str("");
|
||||
}
|
||||
|
||||
// tera
|
||||
{
|
||||
duration<int, std::tera> d(13);
|
||||
os << d;
|
||||
assert(os.str() == "13Ts");
|
||||
os.str("");
|
||||
}
|
||||
|
||||
// peta
|
||||
{
|
||||
duration<int, std::peta> d(13);
|
||||
os << d;
|
||||
assert(os.str() == "13Ps");
|
||||
os.str("");
|
||||
}
|
||||
|
||||
// femto
|
||||
{
|
||||
duration<int, std::exa> d(13);
|
||||
os << d;
|
||||
assert(os.str() == "13Es");
|
||||
os.str("");
|
||||
}
|
||||
}
|
||||
|
||||
void test_calendar()
|
||||
{
|
||||
using namespace std::chrono;
|
||||
using namespace date;
|
||||
|
||||
std::ostringstream os;
|
||||
|
||||
// minutes
|
||||
{
|
||||
minutes d(13);
|
||||
os << d;
|
||||
assert(os.str() == "13min");
|
||||
os.str("");
|
||||
}
|
||||
|
||||
// hours
|
||||
{
|
||||
hours d(13);
|
||||
os << d;
|
||||
assert(os.str() == "13h");
|
||||
os.str("");
|
||||
}
|
||||
|
||||
// days
|
||||
{
|
||||
days d(13);
|
||||
os << d;
|
||||
assert(os.str() == "13d");
|
||||
os.str("");
|
||||
}
|
||||
}
|
||||
|
||||
void test_integral_scale()
|
||||
{
|
||||
using namespace std::chrono;
|
||||
using namespace date;
|
||||
|
||||
std::ostringstream os;
|
||||
|
||||
// ratio 123 / 1
|
||||
{
|
||||
duration<int, std::ratio<123, 1>> d(13);
|
||||
os << d;
|
||||
assert(os.str() == "13[123]s");
|
||||
os.str("");
|
||||
}
|
||||
|
||||
// ratio 100 / 4 = ratio 25 / 1
|
||||
{
|
||||
duration<int, std::ratio<25, 1>> d(13);
|
||||
os << d;
|
||||
assert(os.str() == "13[25]s");
|
||||
os.str("");
|
||||
}
|
||||
|
||||
// weeks = ratio 7 * 24 * 60 * 60 / 1 = ratio 604800 / 1
|
||||
{
|
||||
weeks d(13);
|
||||
os << d;
|
||||
assert(os.str() == "13[604800]s");
|
||||
os.str("");
|
||||
}
|
||||
|
||||
// years = 146097/400 days = ratio 146097/400 * 24 * 60 * 60 = ratio 31556952 / 1
|
||||
{
|
||||
years d(13);
|
||||
os << d;
|
||||
assert(os.str() == "13[31556952]s");
|
||||
os.str("");
|
||||
}
|
||||
|
||||
// months = 1/12 years = ratio 1/12 * 31556952 = ratio 2629746 / 1
|
||||
{
|
||||
months d(13);
|
||||
os << d;
|
||||
assert(os.str() == "13[2629746]s");
|
||||
os.str("");
|
||||
}
|
||||
}
|
||||
|
||||
void test_ratio_scale()
|
||||
{
|
||||
using namespace std::chrono;
|
||||
using namespace date;
|
||||
|
||||
std::ostringstream os;
|
||||
|
||||
// ratio 1 / 2
|
||||
{
|
||||
duration<int, std::ratio<1, 2>> d(13);
|
||||
os << d;
|
||||
assert(os.str() == "13[1/2]s");
|
||||
os.str("");
|
||||
}
|
||||
|
||||
// ratio 100 / 3
|
||||
{
|
||||
duration<int, std::ratio<100, 3>> d(13);
|
||||
os << d;
|
||||
assert(os.str() == "13[100/3]s");
|
||||
os.str("");
|
||||
}
|
||||
|
||||
// ratio 100 / 6 = ratio 50 / 3
|
||||
{
|
||||
duration<int, std::ratio<100, 6>> d(13);
|
||||
os << d;
|
||||
assert(os.str() == "13[50/3]s");
|
||||
os.str("");
|
||||
}
|
||||
}
|
||||
|
||||
void test_constexpr()
|
||||
{
|
||||
using date::detail::get_units;
|
||||
|
||||
CONSTCD11 auto as = get_units<char>(std::atto{});
|
||||
CONSTCD11 auto fs = get_units<char>(std::femto{});
|
||||
CONSTCD11 auto ps = get_units<char>(std::pico{});
|
||||
CONSTCD11 auto ns = get_units<char>(std::nano{});
|
||||
CONSTCD11 auto us = get_units<char>(std::micro{});
|
||||
CONSTCD11 auto usw = get_units<wchar_t>(std::micro{});
|
||||
CONSTCD11 auto ms = get_units<char>(std::milli{});
|
||||
CONSTCD11 auto cs = get_units<char>(std::centi{});
|
||||
CONSTCD11 auto ds = get_units<char>(std::deci{});
|
||||
CONSTCD11 auto s = get_units<char>(std::ratio<1>{});
|
||||
CONSTCD11 auto das = get_units<char>(std::deca{});
|
||||
CONSTCD11 auto hs = get_units<char>(std::hecto{});
|
||||
CONSTCD11 auto ks = get_units<char>(std::kilo{});
|
||||
CONSTCD11 auto Ms = get_units<char>(std::mega{});
|
||||
CONSTCD11 auto Gs = get_units<char>(std::giga{});
|
||||
CONSTCD11 auto Ts = get_units<char>(std::tera{});
|
||||
CONSTCD11 auto Ps = get_units<char>(std::peta{});
|
||||
CONSTCD11 auto Es = get_units<char>(std::exa{});
|
||||
(void)as, (void)fs, (void)ps, (void)ns, (void)usw, (void)us,
|
||||
(void)ms, (void)cs, (void)ds, (void)s, (void)das, (void)hs,
|
||||
(void)ks, (void)Ms, (void)Gs, (void)Ts, (void)Ps, (void)Es;
|
||||
|
||||
CONSTCD11 auto min = get_units<char>(std::ratio<60>{});
|
||||
CONSTCD11 auto h = get_units<char>(std::ratio<3600>{});
|
||||
CONSTCD11 auto d = get_units<char>(std::ratio<86400>{});
|
||||
(void)min, (void)h, (void)d;
|
||||
|
||||
CONSTCD14 auto integer = get_units<char>(std::ratio<123>{});
|
||||
CONSTCD14 auto ratio = get_units<char>(std::ratio<123, 3>{});
|
||||
(void)integer, (void)ratio;
|
||||
}
|
||||
|
||||
int
|
||||
main()
|
||||
{
|
||||
test_SI();
|
||||
test_calendar();
|
||||
test_integral_scale();
|
||||
test_ratio_scale();
|
||||
}
|
@ -27,12 +27,12 @@
|
||||
#include <type_traits>
|
||||
|
||||
using fortnights = std::chrono::duration<date::weeks::rep,
|
||||
std::ratio_multiply<std::ratio<2>,
|
||||
date::weeks::period>>;
|
||||
date::detail::ratio_multiply<std::ratio<2>,
|
||||
date::weeks::period>>;
|
||||
|
||||
using microfortnights = std::chrono::duration<std::int64_t,
|
||||
std::ratio_multiply<fortnights::period,
|
||||
std::micro>>;
|
||||
date::detail::ratio_multiply<fortnights::period,
|
||||
std::micro>>;
|
||||
|
||||
int
|
||||
main()
|
||||
@ -69,10 +69,10 @@ main()
|
||||
assert(os.str() == "32767-12-31 00:00:01.2096");
|
||||
os.str("");
|
||||
|
||||
os << format("%F %T", jan/1/year::min());
|
||||
assert(os.str() == "-32767-01-01 00:00:00");
|
||||
os << format("%F", jan/1/year::min());
|
||||
assert(os.str() == "-32767-01-01");
|
||||
os.str("");
|
||||
os << format("%F %T", dec/last/year::max());
|
||||
assert(os.str() == "32767-12-31 00:00:00");
|
||||
os << format("%F", dec/last/year::max());
|
||||
assert(os.str() == "32767-12-31");
|
||||
os.str("");
|
||||
}
|
||||
|
@ -27,27 +27,6 @@
|
||||
// time_of_day<std::chrono::duration<Rep, Period>>
|
||||
// make_time(std::chrono::duration<Rep, Period> d) noexcept;
|
||||
|
||||
// constexpr
|
||||
// time_of_day<std::chrono::hours>
|
||||
// make_time(std::chrono::hours h, unsigned md) noexcept;
|
||||
|
||||
// constexpr
|
||||
// time_of_day<std::chrono::minutes>
|
||||
// make_time(std::chrono::hours h, std::chrono::minutes m, unsigned md) noexcept;
|
||||
|
||||
// constexpr
|
||||
// time_of_day<std::chrono::seconds>
|
||||
// make_time(std::chrono::hours h, std::chrono::minutes m, std::chrono::seconds s,
|
||||
// unsigned md) noexcept;
|
||||
|
||||
// template <class Rep, class Period,
|
||||
// class = typename std::enable_if<std::ratio_less<Period,
|
||||
// std::ratio<1>>::value>::type>
|
||||
// constexpr
|
||||
// time_of_day<std::chrono::duration<Rep, Period>>
|
||||
// make_time(std::chrono::hours h, std::chrono::minutes m, std::chrono::seconds s,
|
||||
// std::chrono::duration<Rep, Period> sub_s, unsigned md) noexcept;
|
||||
|
||||
#include "date.h"
|
||||
|
||||
#include <cassert>
|
||||
@ -68,7 +47,6 @@ main()
|
||||
assert(tod.minutes() == minutes{7});
|
||||
assert(tod.seconds() == seconds{9});
|
||||
assert(tod.subseconds() == nanoseconds{22});
|
||||
assert(tod.mode() == 0);
|
||||
}
|
||||
{
|
||||
static_assert(is_same<decltype(make_time(microseconds{18429000022})),
|
||||
@ -78,7 +56,6 @@ main()
|
||||
assert(tod.minutes() == minutes{7});
|
||||
assert(tod.seconds() == seconds{9});
|
||||
assert(tod.subseconds() == microseconds{22});
|
||||
assert(tod.mode() == 0);
|
||||
}
|
||||
{
|
||||
static_assert(is_same<decltype(make_time(seconds{18429})),
|
||||
@ -87,7 +64,6 @@ main()
|
||||
assert(tod.hours() == hours{5});
|
||||
assert(tod.minutes() == minutes{7});
|
||||
assert(tod.seconds() == seconds{9});
|
||||
assert(tod.mode() == 0);
|
||||
}
|
||||
{
|
||||
static_assert(is_same<decltype(make_time(minutes{307})),
|
||||
@ -95,70 +71,11 @@ main()
|
||||
auto tod = make_time(minutes{307});
|
||||
assert(tod.hours() == hours{5});
|
||||
assert(tod.minutes() == minutes{7});
|
||||
assert(tod.mode() == 0);
|
||||
}
|
||||
{
|
||||
static_assert(is_same<decltype(make_time(hours{5})),
|
||||
time_of_day<hours>>{}, "");
|
||||
auto tod = make_time(hours{5});
|
||||
assert(tod.hours() == hours{5});
|
||||
assert(tod.mode() == 0);
|
||||
}
|
||||
{
|
||||
static_assert(is_same<decltype(make_time(hours{5}, minutes{7}, seconds{9},
|
||||
nanoseconds{22}, pm)),
|
||||
time_of_day<nanoseconds>>{}, "");
|
||||
auto tod = make_time(hours{5}, minutes{7}, seconds{9}, nanoseconds{22}, pm);
|
||||
assert(tod.hours() == hours{5});
|
||||
assert(tod.minutes() == minutes{7});
|
||||
assert(tod.seconds() == seconds{9});
|
||||
assert(tod.subseconds() == nanoseconds{22});
|
||||
assert(tod.mode() == pm);
|
||||
}
|
||||
{
|
||||
static_assert(is_same<decltype(make_time(hours{5}, minutes{7}, seconds{9},
|
||||
microseconds{22}, 0)),
|
||||
time_of_day<microseconds>>{}, "");
|
||||
auto tod = make_time(hours{5}, minutes{7}, seconds{9}, microseconds{22}, 0);
|
||||
assert(tod.hours() == hours{5});
|
||||
assert(tod.minutes() == minutes{7});
|
||||
assert(tod.seconds() == seconds{9});
|
||||
assert(tod.subseconds() == microseconds{22});
|
||||
assert(tod.mode() == 0);
|
||||
}
|
||||
{
|
||||
static_assert(is_same<decltype(make_time(hours{5}, minutes{7}, seconds{9},
|
||||
milliseconds{22}, am)),
|
||||
time_of_day<milliseconds>>{}, "");
|
||||
auto tod = make_time(hours{5}, minutes{7}, seconds{9}, milliseconds{22}, am);
|
||||
assert(tod.hours() == hours{5});
|
||||
assert(tod.minutes() == minutes{7});
|
||||
assert(tod.seconds() == seconds{9});
|
||||
assert(tod.subseconds() == milliseconds{22});
|
||||
assert(tod.mode() == am);
|
||||
}
|
||||
{
|
||||
static_assert(is_same<decltype(make_time(hours{5}, minutes{7}, seconds{9}, am)),
|
||||
time_of_day<seconds>>{}, "");
|
||||
auto tod = make_time(hours{5}, minutes{7}, seconds{9}, am);
|
||||
assert(tod.hours() == hours{5});
|
||||
assert(tod.minutes() == minutes{7});
|
||||
assert(tod.seconds() == seconds{9});
|
||||
assert(tod.mode() == am);
|
||||
}
|
||||
{
|
||||
static_assert(is_same<decltype(make_time(hours{5}, minutes{7}, pm)),
|
||||
time_of_day<minutes>>{}, "");
|
||||
auto tod = make_time(hours{5}, minutes{7}, pm);
|
||||
assert(tod.hours() == hours{5});
|
||||
assert(tod.minutes() == minutes{7});
|
||||
assert(tod.mode() == pm);
|
||||
}
|
||||
{
|
||||
static_assert(is_same<decltype(make_time(hours{5}, 0)),
|
||||
time_of_day<hours>>{}, "");
|
||||
auto tod = make_time(hours{5}, 0);
|
||||
assert(tod.hours() == hours{5});
|
||||
assert(tod.mode() == 0);
|
||||
}
|
||||
}
|
||||
|
487
test/date_test/multi_year_duration_addition.pass.cpp
Normal file
487
test/date_test/multi_year_duration_addition.pass.cpp
Normal file
@ -0,0 +1,487 @@
|
||||
// The MIT License (MIT)
|
||||
//
|
||||
// Copyright (c) 2018 Tomasz Kamiński
|
||||
//
|
||||
// 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 "date.h"
|
||||
#include <chrono>
|
||||
#include <cassert>
|
||||
#include <type_traits>
|
||||
|
||||
#define CPP11_ASSERT(...) static_assert(__VA_ARGS__, "")
|
||||
|
||||
#if __cplusplus >= 201402
|
||||
// C++14
|
||||
# define CPP14_ASSERT(...) static_assert(__VA_ARGS__, "")
|
||||
#else
|
||||
// C++11
|
||||
# define CPP14_ASSERT(...) assert(__VA_ARGS__)
|
||||
#endif
|
||||
|
||||
#define NOEXCEPT_ASSERT(...) static_assert(noexcept(__VA_ARGS__), "")
|
||||
|
||||
//Invocation involves a conversion between duration that is currently
|
||||
//not marked as noexcept.
|
||||
#define NOEXCEPT_CONVERSION(...)
|
||||
|
||||
template<typename T>
|
||||
constexpr T copy(T const& t) noexcept { return t; }
|
||||
|
||||
struct ConvertibleToYears
|
||||
{
|
||||
CONSTCD11 operator date::years() const NOEXCEPT
|
||||
{ return date::years{1}; };
|
||||
};
|
||||
|
||||
struct ConvertibleToMonths
|
||||
{
|
||||
CONSTCD11 operator date::months() const NOEXCEPT
|
||||
{ return date::months{1}; };
|
||||
};
|
||||
|
||||
struct ConvertibleToYearsAndMonths
|
||||
{
|
||||
CONSTCD11 operator date::years() const NOEXCEPT
|
||||
{ return date::years{1}; };
|
||||
|
||||
CONSTCD11 operator date::months() const NOEXCEPT
|
||||
{ return date::months{1}; };
|
||||
|
||||
};
|
||||
|
||||
int
|
||||
main()
|
||||
{
|
||||
using namespace date;
|
||||
using namespace std::chrono;
|
||||
|
||||
using decades = duration<int, date::detail::ratio_multiply<std::ratio<10>, years::period>>;
|
||||
using decamonths = duration<int, date::detail::ratio_multiply<std::ratio<10>, months::period>>;
|
||||
|
||||
constexpr months one_month{1};
|
||||
constexpr years one_year{1};
|
||||
constexpr decades one_decade{1};
|
||||
constexpr decamonths one_decamonth{1};
|
||||
|
||||
constexpr ConvertibleToMonths custom_month;
|
||||
constexpr ConvertibleToYears custom_year;
|
||||
constexpr ConvertibleToYearsAndMonths prefer_year;
|
||||
|
||||
|
||||
{
|
||||
constexpr year_month ym = 2001_y/feb;
|
||||
CPP14_ASSERT(ym + one_month == 2001_y/mar);
|
||||
NOEXCEPT_ASSERT(ym + one_month);
|
||||
CPP14_ASSERT(one_month + ym == 2001_y/mar);
|
||||
NOEXCEPT_ASSERT(one_month + ym);
|
||||
CPP14_ASSERT(ym - one_month == 2001_y/jan);
|
||||
NOEXCEPT_ASSERT(ym - one_month);
|
||||
CPP14_ASSERT((copy(ym) += one_month) == 2001_y/mar);
|
||||
NOEXCEPT_ASSERT(copy(ym) += one_month);
|
||||
CPP14_ASSERT((copy(ym) -= one_month) == 2001_y/jan);
|
||||
NOEXCEPT_ASSERT(copy(ym) -= one_month);
|
||||
|
||||
CPP11_ASSERT(ym + one_year == 2002_y/feb);
|
||||
NOEXCEPT_ASSERT(ym + one_year);
|
||||
CPP11_ASSERT(one_year + ym == 2002_y/feb);
|
||||
NOEXCEPT_ASSERT(one_year + ym);
|
||||
CPP11_ASSERT(ym - one_year == 2000_y/feb);
|
||||
NOEXCEPT_ASSERT(ym - one_year);
|
||||
CPP14_ASSERT((copy(ym) += one_year) == 2002_y/feb);
|
||||
NOEXCEPT_ASSERT(copy(ym) += one_year);
|
||||
CPP14_ASSERT((copy(ym) -= one_year) == 2000_y/feb);
|
||||
NOEXCEPT_ASSERT(copy(ym) -= one_year);
|
||||
|
||||
CPP11_ASSERT(ym + one_decade == 2011_y/feb);
|
||||
NOEXCEPT_CONVERSION(ym + one_decade);
|
||||
CPP11_ASSERT(one_decade + ym == 2011_y/feb);
|
||||
NOEXCEPT_CONVERSION(one_decade + ym);
|
||||
CPP11_ASSERT(ym - one_decade == 1991_y/feb);
|
||||
NOEXCEPT_CONVERSION(ym - one_decade);
|
||||
CPP14_ASSERT((copy(ym) += one_decade) == 2011_y/feb);
|
||||
NOEXCEPT_CONVERSION(copy(ym) += one_decade);
|
||||
CPP14_ASSERT((copy(ym) -= one_decade) == 1991_y/feb);
|
||||
NOEXCEPT_CONVERSION(copy(ym) -= one_decade);
|
||||
|
||||
CPP14_ASSERT(ym + one_decamonth == 2001_y/dec);
|
||||
NOEXCEPT_CONVERSION(ym + one_decamonth);
|
||||
CPP14_ASSERT(one_decamonth + ym == 2001_y/dec);
|
||||
NOEXCEPT_CONVERSION(one_decamonth + ym);
|
||||
CPP14_ASSERT(ym - one_decamonth == 2000_y/apr);
|
||||
NOEXCEPT_CONVERSION(ym - one_decamonth);
|
||||
CPP14_ASSERT((copy(ym) += one_decamonth) == 2001_y/dec);
|
||||
NOEXCEPT_CONVERSION(copy(ym) += one_decamonth);
|
||||
CPP14_ASSERT((copy(ym) -= one_decamonth) == 2000_y/apr);
|
||||
NOEXCEPT_CONVERSION(copy(ym) -= one_decamonth);
|
||||
|
||||
CPP14_ASSERT(ym + custom_month == 2001_y/mar);
|
||||
NOEXCEPT_ASSERT(ym + custom_month);
|
||||
CPP14_ASSERT(custom_month + ym == 2001_y/mar);
|
||||
NOEXCEPT_ASSERT(custom_month + ym);
|
||||
CPP14_ASSERT(ym - custom_month == 2001_y/jan);
|
||||
NOEXCEPT_ASSERT(ym - custom_month);
|
||||
CPP14_ASSERT((copy(ym) += custom_month) == 2001_y/mar);
|
||||
NOEXCEPT_ASSERT(copy(ym) += custom_month);
|
||||
CPP14_ASSERT((copy(ym) -= custom_month) == 2001_y/jan);
|
||||
NOEXCEPT_ASSERT(copy(ym) -= custom_month);
|
||||
|
||||
CPP11_ASSERT(ym + custom_year == 2002_y/feb);
|
||||
NOEXCEPT_ASSERT(ym + custom_year);
|
||||
CPP11_ASSERT(custom_year + ym == 2002_y/feb);
|
||||
NOEXCEPT_ASSERT(custom_year + ym);
|
||||
CPP11_ASSERT(ym - custom_year == 2000_y/feb);
|
||||
NOEXCEPT_ASSERT(ym - custom_year);
|
||||
CPP14_ASSERT((copy(ym) += custom_year) == 2002_y/feb);
|
||||
NOEXCEPT_ASSERT(copy(ym) += custom_year);
|
||||
CPP14_ASSERT((copy(ym) -= custom_year) == 2000_y/feb);
|
||||
NOEXCEPT_ASSERT(copy(ym) -= custom_year);
|
||||
|
||||
CPP11_ASSERT(ym + prefer_year == 2002_y/feb);
|
||||
NOEXCEPT_ASSERT(ym + prefer_year);
|
||||
CPP11_ASSERT(prefer_year + ym == 2002_y/feb);
|
||||
NOEXCEPT_ASSERT(prefer_year + ym);
|
||||
CPP11_ASSERT(ym - prefer_year == 2000_y/feb);
|
||||
NOEXCEPT_ASSERT(ym - prefer_year);
|
||||
CPP14_ASSERT((copy(ym) += prefer_year) == 2002_y/feb);
|
||||
NOEXCEPT_ASSERT(copy(ym) += prefer_year);
|
||||
CPP14_ASSERT((copy(ym) -= prefer_year) == 2000_y/feb);
|
||||
NOEXCEPT_ASSERT(copy(ym) -= prefer_year);
|
||||
}
|
||||
|
||||
{
|
||||
constexpr year_month_day ym = 2001_y/feb/10;
|
||||
CPP14_ASSERT(ym + one_month == 2001_y/mar/10);
|
||||
NOEXCEPT_ASSERT(ym + one_month);
|
||||
CPP14_ASSERT(one_month + ym == 2001_y/mar/10);
|
||||
NOEXCEPT_ASSERT(one_month + ym);
|
||||
CPP14_ASSERT(ym - one_month == 2001_y/jan/10);
|
||||
NOEXCEPT_ASSERT(ym - one_month);
|
||||
CPP14_ASSERT((copy(ym) += one_month) == 2001_y/mar/10);
|
||||
NOEXCEPT_ASSERT(copy(ym) += one_month);
|
||||
CPP14_ASSERT((copy(ym) -= one_month) == 2001_y/jan/10);
|
||||
NOEXCEPT_ASSERT(copy(ym) -= one_month);
|
||||
|
||||
CPP11_ASSERT(ym + one_year == 2002_y/feb/10);
|
||||
NOEXCEPT_ASSERT(ym + one_year);
|
||||
CPP11_ASSERT(one_year + ym == 2002_y/feb/10);
|
||||
NOEXCEPT_ASSERT(one_year + ym);
|
||||
CPP11_ASSERT(ym - one_year == 2000_y/feb/10);
|
||||
NOEXCEPT_ASSERT(ym - one_year);
|
||||
CPP14_ASSERT((copy(ym) += one_year) == 2002_y/feb/10);
|
||||
NOEXCEPT_ASSERT(copy(ym) += one_year);
|
||||
CPP14_ASSERT((copy(ym) -= one_year) == 2000_y/feb/10);
|
||||
NOEXCEPT_ASSERT(copy(ym) -= one_year);
|
||||
|
||||
CPP11_ASSERT(ym + one_decade == 2011_y/feb/10);
|
||||
NOEXCEPT_CONVERSION(ym + one_decade);
|
||||
CPP11_ASSERT(one_decade + ym == 2011_y/feb/10);
|
||||
NOEXCEPT_CONVERSION(one_decade + ym);
|
||||
CPP11_ASSERT(ym - one_decade == 1991_y/feb/10);
|
||||
NOEXCEPT_CONVERSION(ym - one_decade);
|
||||
CPP14_ASSERT((copy(ym) += one_decade) == 2011_y/feb/10);
|
||||
NOEXCEPT_CONVERSION(copy(ym) += one_decade);
|
||||
CPP14_ASSERT((copy(ym) -= one_decade) == 1991_y/feb/10);
|
||||
NOEXCEPT_CONVERSION(copy(ym) -= one_decade);
|
||||
|
||||
CPP14_ASSERT(ym + one_decamonth == 2001_y/dec/10);
|
||||
NOEXCEPT_CONVERSION(ym + one_decamonth);
|
||||
CPP14_ASSERT(one_decamonth + ym == 2001_y/dec/10);
|
||||
NOEXCEPT_CONVERSION(one_decamonth + ym);
|
||||
CPP14_ASSERT(ym - one_decamonth == 2000_y/apr/10);
|
||||
NOEXCEPT_CONVERSION(ym - one_decamonth);
|
||||
CPP14_ASSERT((copy(ym) += one_decamonth) == 2001_y/dec/10);
|
||||
NOEXCEPT_CONVERSION(copy(ym) += one_decamonth);
|
||||
CPP14_ASSERT((copy(ym) -= one_decamonth) == 2000_y/apr/10);
|
||||
NOEXCEPT_CONVERSION(copy(ym) -= one_decamonth);
|
||||
|
||||
CPP14_ASSERT(ym + custom_month == 2001_y/mar/10);
|
||||
NOEXCEPT_ASSERT(ym + custom_month);
|
||||
CPP14_ASSERT(custom_month + ym == 2001_y/mar/10);
|
||||
NOEXCEPT_ASSERT(custom_month + ym);
|
||||
CPP14_ASSERT(ym - custom_month == 2001_y/jan/10);
|
||||
NOEXCEPT_ASSERT(ym - custom_month);
|
||||
CPP14_ASSERT((copy(ym) += custom_month) == 2001_y/mar/10);
|
||||
NOEXCEPT_ASSERT(copy(ym) += custom_month);
|
||||
CPP14_ASSERT((copy(ym) -= custom_month) == 2001_y/jan/10);
|
||||
NOEXCEPT_ASSERT(copy(ym) -= custom_month);
|
||||
|
||||
CPP11_ASSERT(ym + custom_year == 2002_y/feb/10);
|
||||
NOEXCEPT_ASSERT(ym + custom_year);
|
||||
CPP11_ASSERT(custom_year + ym == 2002_y/feb/10);
|
||||
NOEXCEPT_ASSERT(custom_year + ym);
|
||||
CPP11_ASSERT(ym - custom_year == 2000_y/feb/10);
|
||||
NOEXCEPT_ASSERT(ym - custom_year);
|
||||
CPP14_ASSERT((copy(ym) += custom_year) == 2002_y/feb/10);
|
||||
NOEXCEPT_ASSERT(copy(ym) += custom_year);
|
||||
CPP14_ASSERT((copy(ym) -= custom_year) == 2000_y/feb/10);
|
||||
NOEXCEPT_ASSERT(copy(ym) -= custom_year);
|
||||
|
||||
CPP11_ASSERT(ym + prefer_year == 2002_y/feb/10);
|
||||
NOEXCEPT_ASSERT(ym + prefer_year);
|
||||
CPP11_ASSERT(prefer_year + ym == 2002_y/feb/10);
|
||||
NOEXCEPT_ASSERT(prefer_year + ym);
|
||||
CPP11_ASSERT(ym - prefer_year == 2000_y/feb/10);
|
||||
NOEXCEPT_ASSERT(ym - prefer_year);
|
||||
CPP14_ASSERT((copy(ym) += prefer_year) == 2002_y/feb/10);
|
||||
NOEXCEPT_ASSERT(copy(ym) += prefer_year);
|
||||
CPP14_ASSERT((copy(ym) -= prefer_year) == 2000_y/feb/10);
|
||||
NOEXCEPT_ASSERT(copy(ym) -= prefer_year);
|
||||
}
|
||||
|
||||
{
|
||||
constexpr year_month_day_last ym = 2001_y/feb/last;
|
||||
CPP14_ASSERT(ym + one_month == 2001_y/mar/last);
|
||||
NOEXCEPT_ASSERT(ym + one_month);
|
||||
CPP14_ASSERT(one_month + ym == 2001_y/mar/last);
|
||||
NOEXCEPT_ASSERT(one_month + ym);
|
||||
CPP14_ASSERT(ym - one_month == 2001_y/jan/last);
|
||||
NOEXCEPT_ASSERT(ym - one_month);
|
||||
CPP14_ASSERT((copy(ym) += one_month) == 2001_y/mar/last);
|
||||
NOEXCEPT_ASSERT(copy(ym) += one_month);
|
||||
CPP14_ASSERT((copy(ym) -= one_month) == 2001_y/jan/last);
|
||||
NOEXCEPT_ASSERT(copy(ym) -= one_month);
|
||||
|
||||
CPP11_ASSERT(ym + one_year == 2002_y/feb/last);
|
||||
NOEXCEPT_ASSERT(ym + one_year);
|
||||
CPP11_ASSERT(one_year + ym == 2002_y/feb/last);
|
||||
NOEXCEPT_ASSERT(one_year + ym);
|
||||
CPP11_ASSERT(ym - one_year == 2000_y/feb/last);
|
||||
NOEXCEPT_ASSERT(ym - one_year);
|
||||
CPP14_ASSERT((copy(ym) += one_year) == 2002_y/feb/last);
|
||||
NOEXCEPT_ASSERT(copy(ym) += one_year);
|
||||
CPP14_ASSERT((copy(ym) -= one_year) == 2000_y/feb/last);
|
||||
NOEXCEPT_ASSERT(copy(ym) -= one_year);
|
||||
|
||||
CPP11_ASSERT(ym + one_decade == 2011_y/feb/last);
|
||||
NOEXCEPT_CONVERSION(ym + one_decade);
|
||||
CPP11_ASSERT(one_decade + ym == 2011_y/feb/last);
|
||||
NOEXCEPT_CONVERSION(one_decade + ym);
|
||||
CPP11_ASSERT(ym - one_decade == 1991_y/feb/last);
|
||||
NOEXCEPT_CONVERSION(ym - one_decade);
|
||||
CPP14_ASSERT((copy(ym) += one_decade) == 2011_y/feb/last);
|
||||
NOEXCEPT_CONVERSION(copy(ym) += one_decade);
|
||||
CPP14_ASSERT((copy(ym) -= one_decade) == 1991_y/feb/last);
|
||||
NOEXCEPT_CONVERSION(copy(ym) -= one_decade);
|
||||
|
||||
CPP14_ASSERT(ym + one_decamonth == 2001_y/dec/last);
|
||||
NOEXCEPT_CONVERSION(ym + one_decamonth);
|
||||
CPP14_ASSERT(one_decamonth + ym == 2001_y/dec/last);
|
||||
NOEXCEPT_CONVERSION(one_decamonth + ym);
|
||||
CPP14_ASSERT(ym - one_decamonth == 2000_y/apr/last);
|
||||
NOEXCEPT_CONVERSION(ym - one_decamonth);
|
||||
CPP14_ASSERT((copy(ym) += one_decamonth) == 2001_y/dec/last);
|
||||
NOEXCEPT_CONVERSION(copy(ym) += one_decamonth);
|
||||
CPP14_ASSERT((copy(ym) -= one_decamonth) == 2000_y/apr/last);
|
||||
NOEXCEPT_CONVERSION(copy(ym) -= one_decamonth);
|
||||
|
||||
CPP14_ASSERT(ym + custom_month == 2001_y/mar/last);
|
||||
NOEXCEPT_ASSERT(ym + custom_month);
|
||||
CPP14_ASSERT(custom_month + ym == 2001_y/mar/last);
|
||||
NOEXCEPT_ASSERT(custom_month + ym);
|
||||
CPP14_ASSERT(ym - custom_month == 2001_y/jan/last);
|
||||
NOEXCEPT_ASSERT(ym - custom_month);
|
||||
CPP14_ASSERT((copy(ym) += custom_month) == 2001_y/mar/last);
|
||||
NOEXCEPT_ASSERT(copy(ym) += custom_month);
|
||||
CPP14_ASSERT((copy(ym) -= custom_month) == 2001_y/jan/last);
|
||||
NOEXCEPT_ASSERT(copy(ym) -= custom_month);
|
||||
|
||||
CPP11_ASSERT(ym + custom_year == 2002_y/feb/last);
|
||||
NOEXCEPT_ASSERT(ym + custom_year);
|
||||
CPP11_ASSERT(custom_year + ym == 2002_y/feb/last);
|
||||
NOEXCEPT_ASSERT(custom_year + ym);
|
||||
CPP11_ASSERT(ym - custom_year == 2000_y/feb/last);
|
||||
NOEXCEPT_ASSERT(ym - custom_year);
|
||||
CPP14_ASSERT((copy(ym) += custom_year) == 2002_y/feb/last);
|
||||
NOEXCEPT_ASSERT(copy(ym) += custom_year);
|
||||
CPP14_ASSERT((copy(ym) -= custom_year) == 2000_y/feb/last);
|
||||
NOEXCEPT_ASSERT(copy(ym) -= custom_year);
|
||||
|
||||
CPP11_ASSERT(ym + prefer_year == 2002_y/feb/last);
|
||||
NOEXCEPT_ASSERT(ym + prefer_year);
|
||||
CPP11_ASSERT(prefer_year + ym == 2002_y/feb/last);
|
||||
NOEXCEPT_ASSERT(prefer_year + ym);
|
||||
CPP11_ASSERT(ym - prefer_year == 2000_y/feb/last);
|
||||
NOEXCEPT_ASSERT(ym - prefer_year);
|
||||
CPP14_ASSERT((copy(ym) += prefer_year) == 2002_y/feb/last);
|
||||
NOEXCEPT_ASSERT(copy(ym) += prefer_year);
|
||||
CPP14_ASSERT((copy(ym) -= prefer_year) == 2000_y/feb/last);
|
||||
NOEXCEPT_ASSERT(copy(ym) -= prefer_year);
|
||||
}
|
||||
|
||||
{
|
||||
constexpr year_month_weekday ym = 2001_y/feb/fri[4];
|
||||
CPP14_ASSERT(ym + one_month == 2001_y/mar/fri[4]);
|
||||
NOEXCEPT_ASSERT(ym + one_month);
|
||||
CPP14_ASSERT(one_month + ym == 2001_y/mar/fri[4]);
|
||||
NOEXCEPT_ASSERT(one_month + ym);
|
||||
CPP14_ASSERT(ym - one_month == 2001_y/jan/fri[4]);
|
||||
NOEXCEPT_ASSERT(ym - one_month);
|
||||
CPP14_ASSERT((copy(ym) += one_month) == 2001_y/mar/fri[4]);
|
||||
NOEXCEPT_ASSERT(copy(ym) += one_month);
|
||||
CPP14_ASSERT((copy(ym) -= one_month) == 2001_y/jan/fri[4]);
|
||||
NOEXCEPT_ASSERT(copy(ym) -= one_month);
|
||||
|
||||
CPP11_ASSERT(ym + one_year == 2002_y/feb/fri[4]);
|
||||
NOEXCEPT_ASSERT(ym + one_year);
|
||||
CPP11_ASSERT(one_year + ym == 2002_y/feb/fri[4]);
|
||||
NOEXCEPT_ASSERT(one_year + ym);
|
||||
CPP11_ASSERT(ym - one_year == 2000_y/feb/fri[4]);
|
||||
NOEXCEPT_ASSERT(ym - one_year);
|
||||
CPP14_ASSERT((copy(ym) += one_year) == 2002_y/feb/fri[4]);
|
||||
NOEXCEPT_ASSERT(copy(ym) += one_year);
|
||||
CPP14_ASSERT((copy(ym) -= one_year) == 2000_y/feb/fri[4]);
|
||||
NOEXCEPT_ASSERT(copy(ym) -= one_year);
|
||||
|
||||
CPP11_ASSERT(ym + one_decade == 2011_y/feb/fri[4]);
|
||||
NOEXCEPT_CONVERSION(ym + one_decade);
|
||||
CPP11_ASSERT(one_decade + ym == 2011_y/feb/fri[4]);
|
||||
NOEXCEPT_CONVERSION(one_decade + ym);
|
||||
CPP11_ASSERT(ym - one_decade == 1991_y/feb/fri[4]);
|
||||
NOEXCEPT_CONVERSION(ym - one_decade);
|
||||
CPP14_ASSERT((copy(ym) += one_decade) == 2011_y/feb/fri[4]);
|
||||
NOEXCEPT_CONVERSION(copy(ym) += one_decade);
|
||||
CPP14_ASSERT((copy(ym) -= one_decade) == 1991_y/feb/fri[4]);
|
||||
NOEXCEPT_CONVERSION(copy(ym) -= one_decade);
|
||||
|
||||
CPP14_ASSERT(ym + one_decamonth == 2001_y/dec/fri[4]);
|
||||
NOEXCEPT_CONVERSION(ym + one_decamonth);
|
||||
CPP14_ASSERT(one_decamonth + ym == 2001_y/dec/fri[4]);
|
||||
NOEXCEPT_CONVERSION(one_decamonth + ym);
|
||||
CPP14_ASSERT(ym - one_decamonth == 2000_y/apr/fri[4]);
|
||||
NOEXCEPT_CONVERSION(ym - one_decamonth);
|
||||
CPP14_ASSERT((copy(ym) += one_decamonth) == 2001_y/dec/fri[4]);
|
||||
NOEXCEPT_CONVERSION(copy(ym) += one_decamonth);
|
||||
CPP14_ASSERT((copy(ym) -= one_decamonth) == 2000_y/apr/fri[4]);
|
||||
NOEXCEPT_CONVERSION(copy(ym) -= one_decamonth);
|
||||
|
||||
CPP14_ASSERT(ym + custom_month == 2001_y/mar/fri[4]);
|
||||
NOEXCEPT_ASSERT(ym + custom_month);
|
||||
CPP14_ASSERT(custom_month + ym == 2001_y/mar/fri[4]);
|
||||
NOEXCEPT_ASSERT(custom_month + ym);
|
||||
CPP14_ASSERT(ym - custom_month == 2001_y/jan/fri[4]);
|
||||
NOEXCEPT_ASSERT(ym - custom_month);
|
||||
CPP14_ASSERT((copy(ym) += custom_month) == 2001_y/mar/fri[4]);
|
||||
NOEXCEPT_ASSERT(copy(ym) += custom_month);
|
||||
CPP14_ASSERT((copy(ym) -= custom_month) == 2001_y/jan/fri[4]);
|
||||
NOEXCEPT_ASSERT(copy(ym) -= custom_month);
|
||||
|
||||
CPP11_ASSERT(ym + custom_year == 2002_y/feb/fri[4]);
|
||||
NOEXCEPT_ASSERT(ym + custom_year);
|
||||
CPP11_ASSERT(custom_year + ym == 2002_y/feb/fri[4]);
|
||||
NOEXCEPT_ASSERT(custom_year + ym);
|
||||
CPP11_ASSERT(ym - custom_year == 2000_y/feb/fri[4]);
|
||||
NOEXCEPT_ASSERT(ym - custom_year);
|
||||
CPP14_ASSERT((copy(ym) += custom_year) == 2002_y/feb/fri[4]);
|
||||
NOEXCEPT_ASSERT(copy(ym) += custom_year);
|
||||
CPP14_ASSERT((copy(ym) -= custom_year) == 2000_y/feb/fri[4]);
|
||||
NOEXCEPT_ASSERT(copy(ym) -= custom_year);
|
||||
|
||||
CPP11_ASSERT(ym + prefer_year == 2002_y/feb/fri[4]);
|
||||
NOEXCEPT_ASSERT(ym + prefer_year);
|
||||
CPP11_ASSERT(prefer_year + ym == 2002_y/feb/fri[4]);
|
||||
NOEXCEPT_ASSERT(prefer_year + ym);
|
||||
CPP11_ASSERT(ym - prefer_year == 2000_y/feb/fri[4]);
|
||||
NOEXCEPT_ASSERT(ym - prefer_year);
|
||||
CPP14_ASSERT((copy(ym) += prefer_year) == 2002_y/feb/fri[4]);
|
||||
NOEXCEPT_ASSERT(copy(ym) += prefer_year);
|
||||
CPP14_ASSERT((copy(ym) -= prefer_year) == 2000_y/feb/fri[4]);
|
||||
NOEXCEPT_ASSERT(copy(ym) -= prefer_year);
|
||||
}
|
||||
|
||||
{
|
||||
constexpr year_month_weekday_last ym = 2001_y/feb/fri[last];
|
||||
CPP14_ASSERT(ym + one_month == 2001_y/mar/fri[last]);
|
||||
NOEXCEPT_ASSERT(ym + one_month);
|
||||
CPP14_ASSERT(one_month + ym == 2001_y/mar/fri[last]);
|
||||
NOEXCEPT_ASSERT(one_month + ym);
|
||||
CPP14_ASSERT(ym - one_month == 2001_y/jan/fri[last]);
|
||||
NOEXCEPT_ASSERT(ym - one_month);
|
||||
CPP14_ASSERT((copy(ym) += one_month) == 2001_y/mar/fri[last]);
|
||||
NOEXCEPT_ASSERT(copy(ym) += one_month);
|
||||
CPP14_ASSERT((copy(ym) -= one_month) == 2001_y/jan/fri[last]);
|
||||
NOEXCEPT_ASSERT(copy(ym) -= one_month);
|
||||
|
||||
CPP11_ASSERT(ym + one_year == 2002_y/feb/fri[last]);
|
||||
NOEXCEPT_ASSERT(ym + one_year);
|
||||
CPP11_ASSERT(one_year + ym == 2002_y/feb/fri[last]);
|
||||
NOEXCEPT_ASSERT(one_year + ym);
|
||||
CPP11_ASSERT(ym - one_year == 2000_y/feb/fri[last]);
|
||||
NOEXCEPT_ASSERT(ym - one_year);
|
||||
CPP14_ASSERT((copy(ym) += one_year) == 2002_y/feb/fri[last]);
|
||||
NOEXCEPT_ASSERT(copy(ym) += one_year);
|
||||
CPP14_ASSERT((copy(ym) -= one_year) == 2000_y/feb/fri[last]);
|
||||
NOEXCEPT_ASSERT(copy(ym) -= one_year);
|
||||
|
||||
CPP11_ASSERT(ym + one_decade == 2011_y/feb/fri[last]);
|
||||
NOEXCEPT_CONVERSION(ym + one_decade);
|
||||
CPP11_ASSERT(one_decade + ym == 2011_y/feb/fri[last]);
|
||||
NOEXCEPT_CONVERSION(one_decade + ym);
|
||||
CPP11_ASSERT(ym - one_decade == 1991_y/feb/fri[last]);
|
||||
NOEXCEPT_CONVERSION(ym - one_decade);
|
||||
CPP14_ASSERT((copy(ym) += one_decade) == 2011_y/feb/fri[last]);
|
||||
NOEXCEPT_CONVERSION(copy(ym) += one_decade);
|
||||
CPP14_ASSERT((copy(ym) -= one_decade) == 1991_y/feb/fri[last]);
|
||||
NOEXCEPT_CONVERSION(copy(ym) -= one_decade);
|
||||
|
||||
CPP14_ASSERT(ym + one_decamonth == 2001_y/dec/fri[last]);
|
||||
NOEXCEPT_CONVERSION(ym + one_decamonth);
|
||||
CPP14_ASSERT(one_decamonth + ym == 2001_y/dec/fri[last]);
|
||||
NOEXCEPT_CONVERSION(one_decamonth + ym);
|
||||
CPP14_ASSERT(ym - one_decamonth == 2000_y/apr/fri[last]);
|
||||
NOEXCEPT_CONVERSION(ym - one_decamonth);
|
||||
CPP14_ASSERT((copy(ym) += one_decamonth) == 2001_y/dec/fri[last]);
|
||||
NOEXCEPT_CONVERSION(copy(ym) += one_decamonth);
|
||||
CPP14_ASSERT((copy(ym) -= one_decamonth) == 2000_y/apr/fri[last]);
|
||||
NOEXCEPT_CONVERSION(copy(ym) -= one_decamonth);
|
||||
|
||||
CPP14_ASSERT(ym + custom_month == 2001_y/mar/fri[last]);
|
||||
NOEXCEPT_ASSERT(ym + custom_month);
|
||||
CPP14_ASSERT(custom_month + ym == 2001_y/mar/fri[last]);
|
||||
NOEXCEPT_ASSERT(custom_month + ym);
|
||||
CPP14_ASSERT(ym - custom_month == 2001_y/jan/fri[last]);
|
||||
NOEXCEPT_ASSERT(ym - custom_month);
|
||||
CPP14_ASSERT((copy(ym) += custom_month) == 2001_y/mar/fri[last]);
|
||||
NOEXCEPT_ASSERT(copy(ym) += custom_month);
|
||||
CPP14_ASSERT((copy(ym) -= custom_month) == 2001_y/jan/fri[last]);
|
||||
NOEXCEPT_ASSERT(copy(ym) -= custom_month);
|
||||
|
||||
CPP11_ASSERT(ym + custom_year == 2002_y/feb/fri[last]);
|
||||
NOEXCEPT_ASSERT(ym + custom_year);
|
||||
CPP11_ASSERT(custom_year + ym == 2002_y/feb/fri[last]);
|
||||
NOEXCEPT_ASSERT(custom_year + ym);
|
||||
CPP11_ASSERT(ym - custom_year == 2000_y/feb/fri[last]);
|
||||
NOEXCEPT_ASSERT(ym - custom_year);
|
||||
CPP14_ASSERT((copy(ym) += custom_year) == 2002_y/feb/fri[last]);
|
||||
NOEXCEPT_ASSERT(copy(ym) += custom_year);
|
||||
CPP14_ASSERT((copy(ym) -= custom_year) == 2000_y/feb/fri[last]);
|
||||
NOEXCEPT_ASSERT(copy(ym) -= custom_year);
|
||||
|
||||
CPP11_ASSERT(ym + prefer_year == 2002_y/feb/fri[last]);
|
||||
NOEXCEPT_ASSERT(ym + prefer_year);
|
||||
CPP11_ASSERT(prefer_year + ym == 2002_y/feb/fri[last]);
|
||||
NOEXCEPT_ASSERT(prefer_year + ym);
|
||||
CPP11_ASSERT(ym - prefer_year == 2000_y/feb/fri[last]);
|
||||
NOEXCEPT_ASSERT(ym - prefer_year);
|
||||
CPP14_ASSERT((copy(ym) += prefer_year) == 2002_y/feb/fri[last]);
|
||||
NOEXCEPT_ASSERT(copy(ym) += prefer_year);
|
||||
CPP14_ASSERT((copy(ym) -= prefer_year) == 2000_y/feb/fri[last]);
|
||||
NOEXCEPT_ASSERT(copy(ym) -= prefer_year);
|
||||
}
|
||||
}
|
@ -45,6 +45,8 @@ test_a()
|
||||
std::istringstream in{"Sun 2016-12-11"};
|
||||
sys_days tp;
|
||||
in >> parse("%A %F", tp);
|
||||
// this may fail with libstdc++, see https://github.com/HowardHinnant/date/issues/388
|
||||
// possible workaround: compile date.h with -DONLY_C_LOCALE=1
|
||||
assert(!in.fail());
|
||||
assert(!in.bad());
|
||||
assert(!in.eof());
|
||||
@ -360,6 +362,12 @@ test_d()
|
||||
assert(!in.bad());
|
||||
assert(tp == 2016_y/12/9);
|
||||
}
|
||||
{
|
||||
std::istringstream in{"2016 31 11"};
|
||||
sys_days tp;
|
||||
in >> parse("%Y %e %m", tp);
|
||||
assert(in.fail());
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
@ -413,6 +421,12 @@ test_H()
|
||||
assert(!in.bad());
|
||||
assert(tp == sys_days{2016_y/12/11} + hours{15});
|
||||
}
|
||||
{
|
||||
std::istringstream in{"2016-12-11 24"};
|
||||
sys_time<hours> tp;
|
||||
in >> parse("%F %H", tp);
|
||||
assert(in.fail());
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
@ -436,6 +450,12 @@ test_Ip()
|
||||
assert(!in.bad());
|
||||
assert(tp == sys_days{2016_y/12/11} + hours{1});
|
||||
}
|
||||
{
|
||||
std::istringstream in{"2016-12-11 13 am"};
|
||||
sys_time<hours> tp;
|
||||
in >> parse("%F %I %p", tp);
|
||||
assert(in.fail());
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
@ -474,6 +494,12 @@ test_m()
|
||||
assert(!in.bad());
|
||||
assert(tp == 2016_y/9/12);
|
||||
}
|
||||
{
|
||||
std::istringstream in{"2016 12 13"};
|
||||
sys_days tp;
|
||||
in >> parse("%Y %d %m", tp);
|
||||
assert(in.fail());
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
@ -489,6 +515,12 @@ test_M()
|
||||
assert(!in.bad());
|
||||
assert(tp == sys_days{2016_y/12/11} + minutes{15});
|
||||
}
|
||||
{
|
||||
std::istringstream in{"2016-12-11 65"};
|
||||
sys_time<minutes> tp;
|
||||
in >> parse("%F %M", tp);
|
||||
assert(in.fail());
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
@ -512,6 +544,12 @@ test_S()
|
||||
assert(!in.bad());
|
||||
assert(tp == sys_days{2016_y/12/11} + seconds{15} + milliseconds{1});
|
||||
}
|
||||
{
|
||||
std::istringstream in{"2016-12-11 60"};
|
||||
sys_seconds tp;
|
||||
in >> parse("%F %S", tp);
|
||||
assert(in.fail());
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
@ -552,6 +590,24 @@ test_T()
|
||||
assert(!in.bad());
|
||||
assert(d == hours{15} + minutes{43} + seconds{22} + milliseconds{1});
|
||||
}
|
||||
{
|
||||
std::istringstream in{"2016-12-11 24:43:22"};
|
||||
sys_seconds tp;
|
||||
in >> parse("%F %T", tp);
|
||||
assert(in.fail());
|
||||
}
|
||||
{
|
||||
std::istringstream in{"2016-12-11 15:60:22"};
|
||||
sys_seconds tp;
|
||||
in >> parse("%F %T", tp);
|
||||
assert(in.fail());
|
||||
}
|
||||
{
|
||||
std::istringstream in{"2016-12-11 15:43:60"};
|
||||
sys_seconds tp;
|
||||
in >> parse("%F %T", tp);
|
||||
assert(in.fail());
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -57,7 +57,7 @@ main()
|
||||
|
||||
using tod = time_of_day<hours>;
|
||||
|
||||
static_assert(is_same<tod::precision::period, hours::period>{}, "");
|
||||
static_assert(is_same<tod::precision::period, seconds::period>{}, "");
|
||||
|
||||
static_assert( is_trivially_destructible<tod>{}, "");
|
||||
static_assert( is_default_constructible<tod>{}, "");
|
||||
@ -74,7 +74,6 @@ main()
|
||||
|
||||
constexpr tod t1 = tod{hours{13}};
|
||||
static_assert(t1.hours() == hours{13}, "");
|
||||
static_assert(t1.mode() == 0, "");
|
||||
#if __cplusplus >= 201402
|
||||
static_assert(static_cast<tod::precision>(t1) == hours{13}, "");
|
||||
static_assert(t1.to_duration() == hours{13}, "");
|
||||
@ -82,23 +81,14 @@ main()
|
||||
|
||||
auto t2 = t1;
|
||||
assert(t2.hours() == t1.hours());
|
||||
assert(t2.mode() == t1.mode());
|
||||
assert(t2.to_duration() == t1.to_duration());
|
||||
ostringstream os;
|
||||
os << t2;
|
||||
assert(os.str() == "1300");
|
||||
t2.make12();
|
||||
assert(os.str() == "13:00:00");
|
||||
auto h = make12(t2.hours());
|
||||
os.str("");
|
||||
assert(t2.hours() == hours{1});
|
||||
assert(t2.mode() == pm);
|
||||
assert(h == hours{1});
|
||||
assert(t2.to_duration() == t1.to_duration());
|
||||
os << t2;
|
||||
assert(os.str() == "1pm");
|
||||
t2.make24();
|
||||
os.str("");
|
||||
assert(t2.hours() == hours{13});
|
||||
assert(t2.mode() == 0);
|
||||
assert(t2.to_duration() == t1.to_duration());
|
||||
os << t2;
|
||||
assert(os.str() == "1300");
|
||||
assert(!is_am(t2.hours()));
|
||||
assert(is_pm(t2.hours()));
|
||||
}
|
||||
|
@ -57,12 +57,12 @@
|
||||
#include <type_traits>
|
||||
|
||||
using fortnights = std::chrono::duration<date::weeks::rep,
|
||||
std::ratio_multiply<std::ratio<2>,
|
||||
date::weeks::period>>;
|
||||
date::detail::ratio_multiply<std::ratio<2>,
|
||||
date::weeks::period>>;
|
||||
|
||||
using microfortnights = std::chrono::duration<std::int64_t,
|
||||
std::ratio_multiply<fortnights::period,
|
||||
std::micro>>;
|
||||
date::detail::ratio_multiply<fortnights::period,
|
||||
std::micro>>;
|
||||
|
||||
int
|
||||
main()
|
||||
@ -108,12 +108,4 @@ main()
|
||||
ostringstream os;
|
||||
os << t2;
|
||||
assert(os.str() == "13:07:06.0480");
|
||||
t2.make12();
|
||||
os.str("");
|
||||
os << t2;
|
||||
assert(os.str() == "1:07:06.0480pm");
|
||||
t2.make24();
|
||||
os.str("");
|
||||
os << t2;
|
||||
assert(os.str() == "13:07:06.0480");
|
||||
}
|
||||
|
@ -85,7 +85,6 @@ main()
|
||||
static_assert(t1.minutes() == minutes{7}, "");
|
||||
static_assert(t1.seconds() == seconds{5}, "");
|
||||
static_assert(t1.subseconds() == milliseconds{22}, "");
|
||||
static_assert(t1.mode() == 0, "");
|
||||
#if __cplusplus >= 201402
|
||||
static_assert(static_cast<tod::precision>(t1) == hours{13} + minutes{7}
|
||||
+ seconds{5} + milliseconds{22}, "");
|
||||
@ -98,29 +97,8 @@ main()
|
||||
assert(t2.minutes() == t1.minutes());
|
||||
assert(t2.seconds() == t1.seconds());
|
||||
assert(t2.subseconds() == t1.subseconds());
|
||||
assert(t2.mode() == t1.mode());
|
||||
assert(t2.to_duration() == t1.to_duration());
|
||||
ostringstream os;
|
||||
os << t2;
|
||||
assert(os.str() == "13:07:05.022");
|
||||
t2.make12();
|
||||
os.str("");
|
||||
assert(t2.hours() == hours{1});
|
||||
assert(t2.minutes() == minutes{7});
|
||||
assert(t2.seconds() == seconds{5});
|
||||
assert(t2.subseconds() == milliseconds{22});
|
||||
assert(t2.mode() == pm);
|
||||
assert(t2.to_duration() == t1.to_duration());
|
||||
os << t2;
|
||||
assert(os.str() == "1:07:05.022pm");
|
||||
t2.make24();
|
||||
os.str("");
|
||||
assert(t2.hours() == hours{13});
|
||||
assert(t2.minutes() == minutes{7});
|
||||
assert(t2.seconds() == seconds{5});
|
||||
assert(t2.subseconds() == milliseconds{22});
|
||||
assert(t2.mode() == 0);
|
||||
assert(t2.to_duration() == t1.to_duration());
|
||||
os << t2;
|
||||
assert(os.str() == "13:07:05.022");
|
||||
}
|
||||
|
@ -59,7 +59,7 @@ main()
|
||||
|
||||
using tod = time_of_day<minutes>;
|
||||
|
||||
static_assert(is_same<tod::precision::period, minutes::period>{}, "");
|
||||
static_assert(is_same<tod::precision::period, seconds::period>{}, "");
|
||||
|
||||
static_assert( is_trivially_destructible<tod>{}, "");
|
||||
static_assert( is_default_constructible<tod>{}, "");
|
||||
@ -77,7 +77,6 @@ main()
|
||||
constexpr tod t1 = tod{hours{13} + minutes{7}};
|
||||
static_assert(t1.hours() == hours{13}, "");
|
||||
static_assert(t1.minutes() == minutes{7}, "");
|
||||
static_assert(t1.mode() == 0, "");
|
||||
#if __cplusplus >= 201402
|
||||
static_assert(static_cast<tod::precision>(t1) == hours{13} + minutes{7}, "");
|
||||
static_assert(t1.to_duration() == hours{13} + minutes{7}, "");
|
||||
@ -86,25 +85,8 @@ main()
|
||||
auto t2 = t1;
|
||||
assert(t2.hours() == t1.hours());
|
||||
assert(t2.minutes() == t1.minutes());
|
||||
assert(t2.mode() == t1.mode());
|
||||
assert(t2.to_duration() == t1.to_duration());
|
||||
ostringstream os;
|
||||
os << t2;
|
||||
assert(os.str() == "13:07");
|
||||
t2.make12();
|
||||
os.str("");
|
||||
assert(t2.hours() == hours{1});
|
||||
assert(t2.minutes() == minutes{7});
|
||||
assert(t2.mode() == pm);
|
||||
assert(t2.to_duration() == t1.to_duration());
|
||||
os << t2;
|
||||
assert(os.str() == "1:07pm");
|
||||
t2.make24();
|
||||
os.str("");
|
||||
assert(t2.hours() == hours{13});
|
||||
assert(t2.minutes() == minutes{7});
|
||||
assert(t2.mode() == 0);
|
||||
assert(t2.to_duration() == t1.to_duration());
|
||||
os << t2;
|
||||
assert(os.str() == "13:07");
|
||||
assert(os.str() == "13:07:00");
|
||||
}
|
||||
|
@ -85,7 +85,6 @@ main()
|
||||
static_assert(t1.minutes() == minutes{7}, "");
|
||||
static_assert(t1.seconds() == seconds{5}, "");
|
||||
static_assert(t1.subseconds() == nanoseconds{22}, "");
|
||||
static_assert(t1.mode() == 0, "");
|
||||
#if __cplusplus >= 201402
|
||||
static_assert(static_cast<tod::precision>(t1) == hours{13} + minutes{7}
|
||||
+ seconds{5} + nanoseconds{22}, "");
|
||||
@ -98,29 +97,8 @@ main()
|
||||
assert(t2.minutes() == t1.minutes());
|
||||
assert(t2.seconds() == t1.seconds());
|
||||
assert(t2.subseconds() == t1.subseconds());
|
||||
assert(t2.mode() == t1.mode());
|
||||
assert(t2.to_duration() == t1.to_duration());
|
||||
ostringstream os;
|
||||
os << t2;
|
||||
assert(os.str() == "13:07:05.000000022");
|
||||
t2.make12();
|
||||
os.str("");
|
||||
assert(t2.hours() == hours{1});
|
||||
assert(t2.minutes() == minutes{7});
|
||||
assert(t2.seconds() == seconds{5});
|
||||
assert(t2.subseconds() == nanoseconds{22});
|
||||
assert(t2.mode() == pm);
|
||||
assert(t2.to_duration() == t1.to_duration());
|
||||
os << t2;
|
||||
assert(os.str() == "1:07:05.000000022pm");
|
||||
t2.make24();
|
||||
os.str("");
|
||||
assert(t2.hours() == hours{13});
|
||||
assert(t2.minutes() == minutes{7});
|
||||
assert(t2.seconds() == seconds{5});
|
||||
assert(t2.subseconds() == nanoseconds{22});
|
||||
assert(t2.mode() == 0);
|
||||
assert(t2.to_duration() == t1.to_duration());
|
||||
os << t2;
|
||||
assert(os.str() == "13:07:05.000000022");
|
||||
}
|
||||
|
@ -79,7 +79,6 @@ main()
|
||||
static_assert(t1.hours() == hours{13}, "");
|
||||
static_assert(t1.minutes() == minutes{7}, "");
|
||||
static_assert(t1.seconds() == seconds{5}, "");
|
||||
static_assert(t1.mode() == 0, "");
|
||||
#if __cplusplus >= 201402
|
||||
static_assert(static_cast<tod::precision>(t1) == hours{13} + minutes{7}
|
||||
+ seconds{5}, "");
|
||||
@ -90,27 +89,8 @@ main()
|
||||
assert(t2.hours() == t1.hours());
|
||||
assert(t2.minutes() == t1.minutes());
|
||||
assert(t2.seconds() == t1.seconds());
|
||||
assert(t2.mode() == t1.mode());
|
||||
assert(t2.to_duration() == t1.to_duration());
|
||||
ostringstream os;
|
||||
os << t2;
|
||||
assert(os.str() == "13:07:05");
|
||||
t2.make12();
|
||||
os.str("");
|
||||
assert(t2.hours() == hours{1});
|
||||
assert(t2.minutes() == minutes{7});
|
||||
assert(t2.seconds() == seconds{5});
|
||||
assert(t2.mode() == pm);
|
||||
assert(t2.to_duration() == t1.to_duration());
|
||||
os << t2;
|
||||
assert(os.str() == "1:07:05pm");
|
||||
t2.make24();
|
||||
os.str("");
|
||||
assert(t2.hours() == hours{13});
|
||||
assert(t2.minutes() == minutes{7});
|
||||
assert(t2.seconds() == seconds{5});
|
||||
assert(t2.mode() == 0);
|
||||
assert(t2.to_duration() == t1.to_duration());
|
||||
os << t2;
|
||||
assert(os.str() == "13:07:05");
|
||||
}
|
||||
|
@ -77,11 +77,9 @@ static_assert( std::is_trivially_move_assignable<date::weekday>{}, "");
|
||||
|
||||
static_assert( std::is_nothrow_constructible<date::weekday, unsigned>{}, "");
|
||||
static_assert( std::is_nothrow_constructible<date::weekday, date::sys_days>{}, "");
|
||||
static_assert( std::is_nothrow_constructible<unsigned, date::weekday>{}, "");
|
||||
static_assert(!std::is_convertible<unsigned, date::weekday>{}, "");
|
||||
static_assert( std::is_convertible<date::sys_days, date::weekday>{}, "");
|
||||
static_assert(!std::is_convertible<date::weekday, unsigned>{}, "");
|
||||
static_assert(static_cast<unsigned>(date::weekday{1u}) == 1, "");
|
||||
|
||||
static_assert( date::weekday{0u}.ok(), "");
|
||||
static_assert( date::weekday{1u}.ok(), "");
|
||||
@ -90,7 +88,8 @@ static_assert( date::weekday{3u}.ok(), "");
|
||||
static_assert( date::weekday{4u}.ok(), "");
|
||||
static_assert( date::weekday{5u}.ok(), "");
|
||||
static_assert( date::weekday{6u}.ok(), "");
|
||||
static_assert(!date::weekday{7u}.ok(), "");
|
||||
static_assert( date::weekday{7u}.ok(), "");
|
||||
static_assert(!date::weekday{8u}.ok(), "");
|
||||
|
||||
void
|
||||
test_weekday_arithmetic()
|
||||
|
@ -107,7 +107,7 @@ main()
|
||||
static_assert(year::max().ok(), "");
|
||||
|
||||
#if __cplusplus >= 201402
|
||||
using int64_t = std::int64_t;
|
||||
using std::int64_t;
|
||||
static_assert(sys_days(year::min()/jan/1) - sys_days(1970_y/jan/1)
|
||||
>= as<int64_t>(days::min()), "");
|
||||
static_assert(sys_days(year::min()/jan/1) - sys_days(1970_y/jan/1)
|
||||
|
@ -109,6 +109,90 @@ test_arithmetic()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void test_arithemtic_not_ok()
|
||||
{
|
||||
using namespace date;
|
||||
using namespace std::chrono;
|
||||
|
||||
year_month ym{2018_y, month{14}};
|
||||
|
||||
{
|
||||
year_month ym2{2019_y, month{2}};
|
||||
assert(ym + months{0} == ym2);
|
||||
assert(ym - months{0} == ym2);
|
||||
assert(ym - ym2 == months{0});
|
||||
assert(ym2 - ym == months{0});
|
||||
|
||||
auto ymc = ym;
|
||||
ymc += months{0};
|
||||
assert(ymc.ok());
|
||||
assert(ymc == ym2);
|
||||
}
|
||||
|
||||
{
|
||||
year_month ym2{2019_y, month{6}};
|
||||
assert(ym + months{4} == ym2);
|
||||
assert(ym2 - ym == months{4});
|
||||
assert(ym - ym2 == -months{4});
|
||||
|
||||
auto ymc = ym;
|
||||
ymc += months{4};
|
||||
assert(ymc.ok());
|
||||
assert(ymc == ym2);
|
||||
}
|
||||
|
||||
{
|
||||
year_month ym2{2018_y, month{10}};
|
||||
assert(ym - months{4} == ym2);
|
||||
assert(ym2 - ym == -months{4});
|
||||
assert(ym - ym2 == months{4});
|
||||
|
||||
auto ymc = ym;
|
||||
ymc -= months{4};
|
||||
assert(ymc.ok());
|
||||
assert(ymc == ym2);
|
||||
}
|
||||
|
||||
|
||||
{
|
||||
year_month ym2{2020_y, month{6}};
|
||||
assert(ym + months{16} == ym2);
|
||||
assert(ym2 - ym == months{16});
|
||||
assert(ym - ym2 == -months{16});
|
||||
|
||||
auto ymc = ym;
|
||||
ymc += months{16};
|
||||
assert(ymc.ok());
|
||||
assert(ymc == ym2);
|
||||
}
|
||||
|
||||
{
|
||||
year_month ym2{2017_y, month{10}};
|
||||
assert(ym - months{16} == ym2);
|
||||
assert(ym2 - ym == -months{16});
|
||||
assert(ym - ym2 == months(16));
|
||||
|
||||
auto ymc = ym;
|
||||
ymc -= months{16};
|
||||
assert(ymc.ok());
|
||||
assert(ymc == ym2);
|
||||
}
|
||||
|
||||
{
|
||||
year_month ym2{2018_y, month{25}};
|
||||
assert(ym2 - ym == months{11});
|
||||
assert(ym - ym2 == -months{11});
|
||||
}
|
||||
|
||||
{
|
||||
year_month ym2{2019_y, month{25}};
|
||||
assert(ym2 - ym == months{23});
|
||||
assert(ym - ym2 == -months{23});
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
int
|
||||
main()
|
||||
{
|
||||
@ -135,6 +219,7 @@ main()
|
||||
static_assert(ym1 - ym2 == -months{11}, "");
|
||||
|
||||
test_arithmetic();
|
||||
test_arithemtic_not_ok();
|
||||
|
||||
std::ostringstream os;
|
||||
os << ym1;
|
||||
|
@ -171,7 +171,7 @@ test_with_date_weekday()
|
||||
auto constexpr d1 = iso_week::sun;
|
||||
static_assert(unsigned{d1} == 7, "");
|
||||
auto constexpr d2 = date::weekday{d1};
|
||||
static_assert(unsigned{d2} == 0, "");
|
||||
static_assert(d2 == date::Sunday, "");
|
||||
auto constexpr d3 = iso_week::weekday{d2};
|
||||
static_assert(unsigned{d3} == 7, "");
|
||||
}
|
||||
|
237
test/solar_hijri_test/parse.pass.cpp
Normal file
237
test/solar_hijri_test/parse.pass.cpp
Normal file
@ -0,0 +1,237 @@
|
||||
// The MIT License (MIT)
|
||||
//
|
||||
// Copyright (c) 2020 Asad. Gharighi
|
||||
// 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 "date.h"
|
||||
#include "solar_hijri.h"
|
||||
#include "islamic.h"
|
||||
#include "tz.h"
|
||||
#include <cassert>
|
||||
#include <iostream>
|
||||
#include <chrono>
|
||||
#include <math.h>
|
||||
|
||||
void
|
||||
test_a() {
|
||||
constexpr auto civil = date::year{2020}/date::January/27;
|
||||
using namespace solar_hijri;
|
||||
static_assert(year_month_day{civil} == 1398_y/11/07, "");
|
||||
}
|
||||
|
||||
void
|
||||
test_b() {
|
||||
using namespace solar_hijri::literals;
|
||||
static_assert(date::year_month_day{475_y/far/1} == date::year{1096}/03/21, "");
|
||||
static_assert(date::year_month_weekday{475_y/far/1} ==
|
||||
date::year{1096}/03/date::Saturday[3], "");
|
||||
}
|
||||
|
||||
void
|
||||
test_c() {
|
||||
using namespace solar_hijri;
|
||||
auto date = solar_hijri::year_month_day{1398_y/bah/6};
|
||||
for (auto i = 0; i < 24; i++) {
|
||||
auto weekday = solar_hijri::weekday{date};
|
||||
assert(date == 1398_y/11/06 + months{i});
|
||||
assert(date.month() == month{(i+10u)%12 + 1});
|
||||
assert(weekday == (weekday[1]/date.month()/date.year()).weekday());
|
||||
auto k = weekday;
|
||||
for (auto j = 0; j < 14; j++, k++) {
|
||||
assert(weekday + days{j} == k);
|
||||
}
|
||||
date+=solar_hijri::months(1);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
test_d() {
|
||||
auto zt = date::make_zoned(date::current_zone(), std::chrono::system_clock::now());
|
||||
auto ld = date::floor<date::days>(zt.get_local_time());
|
||||
solar_hijri::year_month_day ymd{ld};
|
||||
auto time = date::make_time(zt.get_local_time() - ld);
|
||||
(void)time;
|
||||
}
|
||||
|
||||
void
|
||||
test_e() {
|
||||
auto sd = date::floor<solar_hijri::days>(std::chrono::system_clock::now());
|
||||
auto today = solar_hijri::year_month_day{sd};
|
||||
assert(solar_hijri::year_month_weekday{today}.weekday() == solar_hijri::weekday{sd});
|
||||
}
|
||||
|
||||
void
|
||||
test_f() {
|
||||
constexpr auto isl = islamic::year{1441}/6/1;
|
||||
using namespace solar_hijri;
|
||||
static_assert(year_month_day{isl} == 1398_y/11/07, "");
|
||||
}
|
||||
|
||||
void
|
||||
test_g() {
|
||||
date::year_month_day ymdd[] = {
|
||||
date::year{1583}/date::November/21,
|
||||
date::year{1583}/date::November/22,
|
||||
date::year{1583}/date::December/6,
|
||||
date::year{1591}/date::December/26,
|
||||
date::year{1616}/date::October/20,
|
||||
date::year{1619}/date::October/13,
|
||||
date::year{1627}/date::August/9,
|
||||
date::year{1649}/date::October/15,
|
||||
date::year{1657}/date::August/9,
|
||||
date::year{1682}/date::June/23,
|
||||
date::year{1691}/date::October/12,
|
||||
date::year{1712}/date::September/13,
|
||||
date::year{1718}/date::July/17,
|
||||
date::year{1747}/date::January/4,
|
||||
date::year{1756}/date::January/1,
|
||||
date::year{1770}/date::January/15,
|
||||
date::year{1798}/date::October/24,
|
||||
date::year{1809}/date::July/11,
|
||||
date::year{1834}/date::July/17,
|
||||
date::year{1850}/date::September/9,
|
||||
date::year{1865}/date::November/4,
|
||||
date::year{1902}/date::December/21,
|
||||
date::year{1926}/date::March/21,
|
||||
date::year{1926}/date::March/22,
|
||||
date::year{1957}/date::June/1,
|
||||
date::year{1977}/date::March/7,
|
||||
date::year{1982}/date::May/30,
|
||||
date::year{1992}/date::December/8
|
||||
};
|
||||
|
||||
solar_hijri::year_month_day ymdh[] = {
|
||||
solar_hijri::year{962}/solar_hijri::Aban/30,
|
||||
solar_hijri::year{962}/solar_hijri::Azar/1,
|
||||
solar_hijri::year{962}/solar_hijri::Azar/15,
|
||||
solar_hijri::year{970}/solar_hijri::Dey/5,
|
||||
solar_hijri::year{995}/solar_hijri::Mehr/29,
|
||||
solar_hijri::year{998}/solar_hijri::Mehr/21,
|
||||
solar_hijri::year{1006}/solar_hijri::Mordad/18,
|
||||
solar_hijri::year{1028}/solar_hijri::Mehr/24,
|
||||
solar_hijri::year{1036}/solar_hijri::Mordad/19,
|
||||
solar_hijri::year{1061}/solar_hijri::Tir/3,
|
||||
solar_hijri::year{1070}/solar_hijri::Mehr/20,
|
||||
solar_hijri::year{1091}/solar_hijri::Shahrivar/22,
|
||||
solar_hijri::year{1097}/solar_hijri::Tir/26,
|
||||
solar_hijri::year{1125}/solar_hijri::Dey/14,
|
||||
solar_hijri::year{1134}/solar_hijri::Dey/11,
|
||||
solar_hijri::year{1148}/solar_hijri::Dey/26,
|
||||
solar_hijri::year{1177}/solar_hijri::Aban/2,
|
||||
solar_hijri::year{1188}/solar_hijri::Tir/20,
|
||||
solar_hijri::year{1213}/solar_hijri::Tir/26,
|
||||
solar_hijri::year{1229}/solar_hijri::Shahrivar/18,
|
||||
solar_hijri::year{1244}/solar_hijri::Aban/13,
|
||||
solar_hijri::year{1281}/solar_hijri::Azar/29,
|
||||
solar_hijri::year{1304}/solar_hijri::Esfand/30,
|
||||
solar_hijri::year{1305}/solar_hijri::Farvardin/1,
|
||||
solar_hijri::year{1336}/solar_hijri::Khordad/11,
|
||||
solar_hijri::year{1355}/solar_hijri::Esfand/16,
|
||||
solar_hijri::year{1361}/solar_hijri::Khordad/9,
|
||||
solar_hijri::year{1371}/solar_hijri::Azar/17
|
||||
};
|
||||
|
||||
solar_hijri::year_month_weekday ymdwd[] = {
|
||||
solar_hijri::year{962}/solar_hijri::Aban/solar_hijri::Doshanbe[5],
|
||||
solar_hijri::year{962}/solar_hijri::Azar/solar_hijri::Seshanbe[1],
|
||||
solar_hijri::year{962}/solar_hijri::Azar/solar_hijri::Seshanbe[3],
|
||||
solar_hijri::year{970}/solar_hijri::Dey/solar_hijri::Panjshanbe[1],
|
||||
solar_hijri::year{995}/solar_hijri::Mehr/solar_hijri::Panjshanbe[5],
|
||||
solar_hijri::year{998}/solar_hijri::Mehr/solar_hijri::Yekshanbe[3],
|
||||
solar_hijri::year{1006}/solar_hijri::Mordad/solar_hijri::Doshanbe[3],
|
||||
solar_hijri::year{1028}/solar_hijri::Mehr/solar_hijri::Adine[4],
|
||||
solar_hijri::year{1036}/solar_hijri::Mordad/solar_hijri::Panjshanbe[3],
|
||||
solar_hijri::year{1061}/solar_hijri::Tir/solar_hijri::Seshanbe[1],
|
||||
solar_hijri::year{1070}/solar_hijri::Mehr/solar_hijri::Adine[3],
|
||||
solar_hijri::year{1091}/solar_hijri::Shahrivar/solar_hijri::Seshanbe[4],
|
||||
solar_hijri::year{1097}/solar_hijri::Tir/solar_hijri::Yekshanbe[4],
|
||||
solar_hijri::year{1125}/solar_hijri::Dey/solar_hijri::Chaharshanbe[2],
|
||||
solar_hijri::year{1134}/solar_hijri::Dey/solar_hijri::Panjshanbe[2],
|
||||
solar_hijri::year{1148}/solar_hijri::Dey/solar_hijri::Doshanbe[4],
|
||||
solar_hijri::year{1177}/solar_hijri::Aban/solar_hijri::Chaharshanbe[1],
|
||||
solar_hijri::year{1188}/solar_hijri::Tir/solar_hijri::Seshanbe[3],
|
||||
solar_hijri::year{1213}/solar_hijri::Tir/solar_hijri::Panjshanbe[4],
|
||||
solar_hijri::year{1229}/solar_hijri::Shahrivar/solar_hijri::Doshanbe[3],
|
||||
solar_hijri::year{1244}/solar_hijri::Aban/solar_hijri::Shanbe[2],
|
||||
solar_hijri::year{1281}/solar_hijri::Azar/solar_hijri::Yekshanbe[5],
|
||||
solar_hijri::year{1304}/solar_hijri::Esfand/solar_hijri::Yekshanbe[5],
|
||||
solar_hijri::year{1305}/solar_hijri::Farvardin/solar_hijri::Doshanbe[1],
|
||||
solar_hijri::year{1336}/solar_hijri::Khordad/solar_hijri::Shanbe[2],
|
||||
solar_hijri::year{1355}/solar_hijri::Esfand/solar_hijri::Doshanbe[3],
|
||||
solar_hijri::year{1361}/solar_hijri::Khordad/solar_hijri::Yekshanbe[2],
|
||||
solar_hijri::year{1371}/solar_hijri::Azar/solar_hijri::Seshanbe[3]
|
||||
};
|
||||
|
||||
bool leaps[] = {
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
false,
|
||||
false,
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
true,
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
true,
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
false
|
||||
};
|
||||
|
||||
static_assert(sizeof(ymdd)/sizeof(ymdd[0]) == sizeof(ymdwd)/sizeof(ymdwd[0]), "");
|
||||
static_assert(sizeof(ymdd)/sizeof(ymdd[0]) == sizeof(ymdh)/sizeof(ymdh[0]), "");
|
||||
static_assert(sizeof(ymdd)/sizeof(ymdd[0]) == sizeof(leaps)/sizeof(leaps[0]), "");
|
||||
|
||||
for (auto i = 0; i < sizeof(ymdd)/sizeof(ymdd[0]); ++i)
|
||||
{
|
||||
assert(solar_hijri::year_month_day{ymdd[i]} == ymdh[i]);
|
||||
assert(ymdd[i] == date::year_month_day{ymdh[i]});
|
||||
assert(ymdh[i].year().is_leap() == leaps[i]);
|
||||
assert(solar_hijri::year_month_weekday{ymdd[i]} == ymdwd[i]);
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
main()
|
||||
{
|
||||
test_a();
|
||||
test_b();
|
||||
test_c();
|
||||
test_d();
|
||||
test_e();
|
||||
test_f();
|
||||
test_g();
|
||||
}
|
168
test/solar_hijri_test/year_month_day.pass.cpp
Normal file
168
test/solar_hijri_test/year_month_day.pass.cpp
Normal file
@ -0,0 +1,168 @@
|
||||
// The MIT License (MIT)
|
||||
//
|
||||
// Copyright (c) 2020 Asad. Gharighi
|
||||
// Copyright (c) 2015, 2016 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.
|
||||
|
||||
// class year_month_day
|
||||
// {
|
||||
// public:
|
||||
// constexpr year_month_day(const date::year& y, const date::month& m,
|
||||
// const date::day& d) noexcept;
|
||||
// constexpr year_month_day(const year_month_day_last& ymdl) noexcept;
|
||||
// constexpr year_month_day(const sys_days& dp) noexcept;
|
||||
//
|
||||
// year_month_day& operator+=(const months& m) noexcept;
|
||||
// year_month_day& operator-=(const months& m) noexcept;
|
||||
// year_month_day& operator+=(const years& y) noexcept;
|
||||
// year_month_day& operator-=(const years& y) noexcept;
|
||||
//
|
||||
// constexpr date::year year() const noexcept;
|
||||
// constexpr date::month month() const noexcept;
|
||||
// constexpr date::day day() const noexcept;
|
||||
//
|
||||
// constexpr operator sys_days() const noexcept;
|
||||
// constexpr bool ok() const noexcept;
|
||||
// };
|
||||
|
||||
// constexpr bool operator==(const year_month_day& x, const year_month_day& y) noexcept;
|
||||
// constexpr bool operator!=(const year_month_day& x, const year_month_day& y) noexcept;
|
||||
// constexpr bool operator< (const year_month_day& x, const year_month_day& y) noexcept;
|
||||
// constexpr bool operator> (const year_month_day& x, const year_month_day& y) noexcept;
|
||||
// constexpr bool operator<=(const year_month_day& x, const year_month_day& y) noexcept;
|
||||
// constexpr bool operator>=(const year_month_day& x, const year_month_day& y) noexcept;
|
||||
|
||||
// constexpr year_month_day operator+(const year_month_day& ymd, const months& dm) noexcept;
|
||||
// constexpr year_month_day operator+(const months& dm, const year_month_day& ymd) noexcept;
|
||||
// constexpr year_month_day operator-(const year_month_day& ymd, const months& dm) noexcept;
|
||||
// constexpr year_month_day operator+(const year_month_day& ymd, const years& dy) noexcept;
|
||||
// constexpr year_month_day operator+(const years& dy, const year_month_day& ymd) noexcept;
|
||||
// constexpr year_month_day operator-(const year_month_day& ymd, const years& dy) noexcept;
|
||||
|
||||
// std::ostream& operator<<(std::ostream& os, const year_month_day& ymd);
|
||||
|
||||
#include "date.h"
|
||||
#include "solar_hijri.h"
|
||||
|
||||
#include <iostream>
|
||||
#include <cassert>
|
||||
#include <sstream>
|
||||
#include <type_traits>
|
||||
|
||||
static_assert( std::is_trivially_destructible<solar_hijri::year_month_day>{}, "");
|
||||
static_assert( std::is_default_constructible<solar_hijri::year_month_day>{}, "");
|
||||
static_assert( std::is_trivially_copy_constructible<solar_hijri::year_month_day>{}, "");
|
||||
static_assert( std::is_trivially_copy_assignable<solar_hijri::year_month_day>{}, "");
|
||||
static_assert( std::is_trivially_move_constructible<solar_hijri::year_month_day>{}, "");
|
||||
static_assert( std::is_trivially_move_assignable<solar_hijri::year_month_day>{}, "");
|
||||
|
||||
static_assert(std::is_nothrow_constructible<solar_hijri::year_month_day, solar_hijri::year,
|
||||
solar_hijri::month,
|
||||
solar_hijri::day>{}, "");
|
||||
static_assert(std::is_nothrow_constructible<solar_hijri::year_month_day,
|
||||
solar_hijri::year_month_day_last>{}, "");
|
||||
static_assert(std::is_convertible<solar_hijri::year_month_day_last, solar_hijri::year_month_day>{}, "");
|
||||
static_assert(std::is_nothrow_constructible<solar_hijri::year_month_day, solar_hijri::sys_days>{}, "");
|
||||
static_assert(std::is_convertible<solar_hijri::sys_days, solar_hijri::year_month_day>{}, "");
|
||||
static_assert(std::is_nothrow_constructible<solar_hijri::sys_days, solar_hijri::year_month_day>{}, "");
|
||||
static_assert(std::is_convertible<solar_hijri::year_month_day, solar_hijri::sys_days>{}, "");
|
||||
|
||||
void
|
||||
test_arithmetic()
|
||||
{
|
||||
using namespace solar_hijri;
|
||||
|
||||
for (int y1 = 1380; y1 <= 1400; ++y1)
|
||||
{
|
||||
for (unsigned m1 = 1; m1 <= 12; ++m1)
|
||||
{
|
||||
year_month_day ymd1{year{y1}, month{m1}, 9_d};
|
||||
year_month_day ymd2 = ymd1 + months(24);
|
||||
assert((ymd2 == year_month_day{year{y1+2}, ymd1.month(), ymd1.day()}));
|
||||
ymd2 = ymd1 - months(24);
|
||||
assert((ymd2 == year_month_day{year{y1-2}, ymd1.month(), ymd1.day()}));
|
||||
for (int m2 = -24; m2 <= 24; ++m2)
|
||||
{
|
||||
months m{m2};
|
||||
year_month_day ymd3 = ymd1 + m;
|
||||
months dm = year_month{ymd3.year(), ymd3.month()} -
|
||||
year_month{ymd2.year(), ymd2.month()};
|
||||
assert(dm == m + years{2});
|
||||
assert(ymd3 - m == ymd1);
|
||||
assert(ymd3 + -m == ymd1);
|
||||
assert(-m + ymd3 == ymd1);
|
||||
assert((year_month_day{ymd1} += m) == ymd3);
|
||||
assert((year_month_day{ymd3} -= m) == ymd1);
|
||||
}
|
||||
for (int y2 = -2; y2 <= 5; ++y2)
|
||||
{
|
||||
years y{y2};
|
||||
year_month_day ymd3 = ymd1 + y;
|
||||
years dy = date::floor<years>(year_month{ymd3.year(), ymd3.month()} -
|
||||
year_month{ymd2.year(), ymd2.month()});
|
||||
assert(dy == y + years{2});
|
||||
assert(ymd3 - y == ymd1);
|
||||
assert(ymd3 + -y == ymd1);
|
||||
assert(-y + ymd3 == ymd1);
|
||||
assert((year_month_day{ymd1} += y) == ymd3);
|
||||
assert((year_month_day{ymd3} -= y) == ymd1);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
test_day_point_conversion()
|
||||
{
|
||||
using namespace solar_hijri;
|
||||
year y = year{-30000};
|
||||
year end = 30000_y;
|
||||
sys_days prev_dp = sys_days(year_month_day{y, far, 1_d}) - days{1};
|
||||
weekday prev_wd = weekday{prev_dp};
|
||||
for (; y <= end; ++y)
|
||||
{
|
||||
month m = far;
|
||||
do
|
||||
{
|
||||
day last_day = year_month_day_last{y, month_day_last{m}}.day();
|
||||
for (day d = 1_d; d <= last_day; ++d)
|
||||
{
|
||||
year_month_day ymd = {y, m, d};
|
||||
assert(ymd.ok());
|
||||
sys_days dp = sys_days(ymd);
|
||||
assert(dp == prev_dp + days{1});
|
||||
year_month_day ymd2 = dp;
|
||||
assert(ymd2 == ymd);
|
||||
weekday wd = dp;
|
||||
assert(wd.ok());
|
||||
assert(wd == prev_wd + days{1});
|
||||
prev_wd = wd;
|
||||
prev_dp = dp;
|
||||
}
|
||||
} while (++m != far);
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
main()
|
||||
{
|
||||
test_arithmetic();
|
||||
test_day_point_conversion();
|
||||
}
|
73
test/tz_test/OffsetZone.h
Normal file
73
test/tz_test/OffsetZone.h
Normal file
@ -0,0 +1,73 @@
|
||||
#ifndef OFFSET_ZONE_H
|
||||
#define OFFSET_ZONE_H
|
||||
|
||||
// The MIT License (MIT)
|
||||
//
|
||||
// Copyright (c) 2017 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.
|
||||
|
||||
// Test custom time zone support
|
||||
|
||||
#include "tz.h"
|
||||
|
||||
class OffsetZone
|
||||
{
|
||||
std::chrono::minutes offset_;
|
||||
|
||||
public:
|
||||
explicit OffsetZone(std::chrono::minutes offset)
|
||||
: offset_{offset}
|
||||
{}
|
||||
|
||||
template <class Duration>
|
||||
auto
|
||||
to_local(date::sys_time<Duration> tp) const
|
||||
{
|
||||
using namespace date;
|
||||
using namespace std::chrono;
|
||||
using LT = local_time<std::common_type_t<Duration, minutes>>;
|
||||
return LT{(tp + offset_).time_since_epoch()};
|
||||
}
|
||||
|
||||
template <class Duration>
|
||||
auto
|
||||
to_sys(date::local_time<Duration> tp, date::choose = date::choose::earliest) const
|
||||
{
|
||||
using namespace date;
|
||||
using namespace std::chrono;
|
||||
using ST = sys_time<std::common_type_t<Duration, minutes>>;
|
||||
return ST{(tp - offset_).time_since_epoch()};
|
||||
}
|
||||
|
||||
template <class Duration>
|
||||
date::sys_info
|
||||
get_info(date::sys_time<Duration> st) const
|
||||
{
|
||||
using namespace date;
|
||||
using namespace std::chrono;
|
||||
return {sys_seconds::min(), sys_seconds::max(), offset_,
|
||||
minutes{0}, offset_ >= minutes{0} ? "+" + date::format("%H%M", offset_)
|
||||
: "-" + date::format("%H%M", -offset_)};
|
||||
}
|
||||
|
||||
const OffsetZone* operator->() const {return this;}
|
||||
};
|
||||
|
||||
#endif // OFFSET_ZONE_H
|
@ -23,50 +23,7 @@
|
||||
// Test custom time zone support
|
||||
|
||||
#include "tz.h"
|
||||
|
||||
class OffsetZone
|
||||
{
|
||||
std::chrono::minutes offset_;
|
||||
|
||||
public:
|
||||
explicit OffsetZone(std::chrono::minutes offset)
|
||||
: offset_{offset}
|
||||
{}
|
||||
|
||||
template <class Duration>
|
||||
auto
|
||||
to_local(date::sys_time<Duration> tp) const
|
||||
{
|
||||
using namespace date;
|
||||
using namespace std::chrono;
|
||||
using LT = local_time<std::common_type_t<Duration, minutes>>;
|
||||
return LT{(tp + offset_).time_since_epoch()};
|
||||
}
|
||||
|
||||
template <class Duration>
|
||||
auto
|
||||
to_sys(date::local_time<Duration> tp) const
|
||||
{
|
||||
using namespace date;
|
||||
using namespace std::chrono;
|
||||
using ST = sys_time<std::common_type_t<Duration, minutes>>;
|
||||
return ST{(tp - offset_).time_since_epoch()};
|
||||
}
|
||||
|
||||
template <class Duration>
|
||||
date::sys_info
|
||||
get_info(date::sys_time<Duration> st) const
|
||||
{
|
||||
using namespace date;
|
||||
using namespace std::chrono;
|
||||
return {sys_seconds::min(), sys_seconds::max(), offset_,
|
||||
minutes{0}, offset_ >= minutes{0} ? "+" + date::format("%H%M", offset_)
|
||||
: "-" + date::format("%H%M", -offset_)};
|
||||
}
|
||||
|
||||
const OffsetZone* operator->() const {return this;}
|
||||
};
|
||||
|
||||
#include "OffsetZone.h"
|
||||
#include <cassert>
|
||||
|
||||
int
|
||||
|
@ -1,21 +1,15 @@
|
||||
To test: * Install tz.cpp by downloading the IANA timezone database
|
||||
at: http://www.iana.org/time-zones You only need the data, not the
|
||||
code.
|
||||
# TZ Test
|
||||
|
||||
* Change the string `install` in tz.cpp to point to your downloaded
|
||||
IANA database.
|
||||
## How to Test
|
||||
|
||||
* Install tz.cpp by downloading the IANA timezone database at: http://www.iana.org/time-zones You only need the data, not the code.
|
||||
* Change the string `install` in tz.cpp to point to your downloaded IANA database.
|
||||
* Compile validate.cpp along with tz.cpp.
|
||||
|
||||
* Run the binary and direct the terminal output to a temporary file.
|
||||
* Unzip the tzdata file that has the version corresponding to the IANA database you downloaded (e.g. tzdata2015f.txt.zip).
|
||||
* Compare the unzipped txt file with the output of your validate test program. If they are identical, the test passes, else it fails.
|
||||
|
||||
* Unzip the tzdata file that has the version corresponding to the IANA
|
||||
database you downloaded (e.g. tzdata2015f.txt.zip).
|
||||
|
||||
* Compare the unzipped txt file with the output of your validate test
|
||||
program. If they are identical, the test passes, else it fails.
|
||||
|
||||
Miscellaneous:
|
||||
## Miscellaneous
|
||||
|
||||
You can also compare one version of the tzdatabase with another using
|
||||
these uncompressed text files. The text files contain for each
|
||||
@ -25,4 +19,4 @@ versions change, minor updates to the set of these transitions are
|
||||
typically made, typically due to changes in government policies.
|
||||
|
||||
The tests in this section will run much faster with optimizations
|
||||
cranked up.
|
||||
cranked up.
|
||||
|
@ -1,3 +1,25 @@
|
||||
// The MIT License (MIT)
|
||||
//
|
||||
// Copyright (c) 2015, 2016 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>
|
||||
|
||||
|
246
test/tz_test/zoned_time_deduction.pass.cpp
Normal file
246
test/tz_test/zoned_time_deduction.pass.cpp
Normal file
@ -0,0 +1,246 @@
|
||||
// The MIT License (MIT)
|
||||
//
|
||||
// Copyright (c) 2019 Tomasz Kamiński
|
||||
//
|
||||
// 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 "OffsetZone.h"
|
||||
#include <cassert>
|
||||
#include <type_traits>
|
||||
#include <string>
|
||||
|
||||
#if HAS_DEDUCTION_GUIDES
|
||||
#include <string_view>
|
||||
|
||||
template<typename TimeZonePtr, typename Source>
|
||||
void testDeductionFrom(Source&& s)
|
||||
{
|
||||
using namespace date;
|
||||
using namespace std::chrono;
|
||||
|
||||
// No time point
|
||||
{
|
||||
zoned_time zt(std::forward<Source>(s));
|
||||
static_assert(std::is_same<decltype(zt), zoned_time<seconds, TimeZonePtr>>::value, "");
|
||||
}
|
||||
|
||||
// sys_time
|
||||
{
|
||||
sys_days sd(2017_y/feb/20);
|
||||
zoned_time ztd(std::forward<Source>(s), sd);
|
||||
static_assert(std::is_same<decltype(ztd), zoned_time<seconds, TimeZonePtr>>::value, "");
|
||||
|
||||
sys_time<seconds> ss(sd);
|
||||
zoned_time zts(std::forward<Source>(s), ss);
|
||||
static_assert(std::is_same<decltype(zts), zoned_time<seconds, TimeZonePtr>>::value, "");
|
||||
|
||||
sys_time<milliseconds> sms(ss);
|
||||
zoned_time ztms(std::forward<Source>(s), sms);
|
||||
static_assert(std::is_same<decltype(ztms), zoned_time<milliseconds, TimeZonePtr>>::value, "");
|
||||
}
|
||||
|
||||
// local_time
|
||||
{
|
||||
local_days ld(2017_y/feb/20);
|
||||
zoned_time ztd(std::forward<Source>(s), ld);
|
||||
static_assert(std::is_same<decltype(ztd), zoned_time<seconds, TimeZonePtr>>::value, "");
|
||||
|
||||
local_time<seconds> ls(ld);
|
||||
zoned_time zts(std::forward<Source>(s), ls);
|
||||
static_assert(std::is_same<decltype(zts), zoned_time<seconds, TimeZonePtr>>::value, "");
|
||||
|
||||
local_time<milliseconds> lms(ls);
|
||||
zoned_time ztms(std::forward<Source>(s), lms);
|
||||
static_assert(std::is_same<decltype(ztms), zoned_time<milliseconds, TimeZonePtr>>::value, "");
|
||||
}
|
||||
|
||||
// local_time, choose
|
||||
{
|
||||
local_days ld(2017_y/feb/20);
|
||||
zoned_time ztd(std::forward<Source>(s), ld, choose::earliest);
|
||||
static_assert(std::is_same<decltype(ztd), zoned_time<seconds, TimeZonePtr>>::value, "");
|
||||
|
||||
local_time<seconds> ls(ld);
|
||||
zoned_time zts(std::forward<Source>(s), ls, choose::earliest);
|
||||
static_assert(std::is_same<decltype(zts), zoned_time<seconds, TimeZonePtr>>::value, "");
|
||||
|
||||
local_time<milliseconds> lms(ls);
|
||||
zoned_time ztms(std::forward<Source>(s), lms, choose::earliest);
|
||||
static_assert(std::is_same<decltype(ztms), zoned_time<milliseconds, TimeZonePtr>>::value, "");
|
||||
}
|
||||
|
||||
// zoned_time
|
||||
{
|
||||
zoned_time<days> zd(sys_days(2017_y/feb/20));
|
||||
zoned_time ztd(std::forward<Source>(s), zd);
|
||||
static_assert(std::is_same<decltype(ztd), zoned_time<seconds, TimeZonePtr>>::value, "");
|
||||
|
||||
zoned_time<seconds> zs(zd);
|
||||
zoned_time zts(std::forward<Source>(s), zs);
|
||||
static_assert(std::is_same<decltype(zts), zoned_time<seconds, TimeZonePtr>>::value, "");
|
||||
|
||||
zoned_time<milliseconds> zms(zs);
|
||||
zoned_time ztms(std::forward<Source>(s), zms);
|
||||
static_assert(std::is_same<decltype(ztms), zoned_time<milliseconds, TimeZonePtr>>::value, "");
|
||||
}
|
||||
|
||||
// zoned_time, choose
|
||||
{
|
||||
zoned_time<days> zd(sys_days(2017_y/feb/20));
|
||||
zoned_time ztd(std::forward<Source>(s), zd, choose::earliest);
|
||||
static_assert(std::is_same<decltype(ztd), zoned_time<seconds, TimeZonePtr>>::value, "");
|
||||
|
||||
zoned_time<seconds> zs(zd);
|
||||
zoned_time zts(std::forward<Source>(s), zs, choose::earliest);
|
||||
static_assert(std::is_same<decltype(zts), zoned_time<seconds, TimeZonePtr>>::value, "");
|
||||
|
||||
zoned_time<milliseconds> zms(zs);
|
||||
zoned_time ztms(std::forward<Source>(s), zms, choose::earliest);
|
||||
static_assert(std::is_same<decltype(ztms), zoned_time<milliseconds, TimeZonePtr>>::value, "");
|
||||
}
|
||||
}
|
||||
|
||||
struct MyString
|
||||
{
|
||||
MyString(std::string s) : ms(std::move(s)) {}
|
||||
|
||||
operator std::string_view() const { return ms; }
|
||||
|
||||
private:
|
||||
std::string ms;
|
||||
};
|
||||
|
||||
struct OnlyLValueString
|
||||
{
|
||||
OnlyLValueString(std::string s) : ms(std::move(s)) {}
|
||||
|
||||
operator std::string_view() & { return ms; }
|
||||
|
||||
private:
|
||||
std::string ms;
|
||||
};
|
||||
|
||||
#endif // HAS_DEDUCTION_GUIDES
|
||||
|
||||
template<typename T>
|
||||
T const& to_const(T& t) { return t; }
|
||||
|
||||
|
||||
int
|
||||
main()
|
||||
{
|
||||
using namespace date;
|
||||
using namespace std::chrono;
|
||||
|
||||
#if HAS_DEDUCTION_GUIDES
|
||||
// no arguments
|
||||
{
|
||||
zoned_time zt{};
|
||||
static_assert(std::is_same<decltype(zt), zoned_time<seconds>>::value, "");
|
||||
}
|
||||
|
||||
// zoned_time
|
||||
{
|
||||
zoned_time<days> zd(sys_days(2017_y/feb/20));
|
||||
zoned_time ztd(zd);
|
||||
static_assert(std::is_same<decltype(ztd), zoned_time<days>>::value, "");
|
||||
|
||||
zoned_time<seconds> zs(zd);
|
||||
zoned_time zts(zs);
|
||||
static_assert(std::is_same<decltype(zts), zoned_time<seconds>>::value, "");
|
||||
|
||||
zoned_time<milliseconds> zms(zs);
|
||||
zoned_time ztms(zms);
|
||||
static_assert(std::is_same<decltype(ztms), zoned_time<milliseconds>>::value, "");
|
||||
}
|
||||
|
||||
// sys_time
|
||||
{
|
||||
sys_days sd(2017_y/feb/20);
|
||||
zoned_time ztd(sd);
|
||||
static_assert(std::is_same<decltype(ztd), zoned_time<seconds>>::value, "");
|
||||
|
||||
sys_time<seconds> ss(sd);
|
||||
zoned_time zts(ss);
|
||||
static_assert(std::is_same<decltype(zts), zoned_time<seconds>>::value, "");
|
||||
|
||||
sys_time<milliseconds> sms(ss);
|
||||
zoned_time ztms(sms);
|
||||
static_assert(std::is_same<decltype(ztms), zoned_time<milliseconds>>::value, "");
|
||||
}
|
||||
|
||||
// time_zone const*
|
||||
{
|
||||
time_zone const* tz = current_zone();
|
||||
testDeductionFrom<time_zone const*>(tz);
|
||||
testDeductionFrom<time_zone const*>(to_const(tz));
|
||||
testDeductionFrom<time_zone const*>(std::move(tz));
|
||||
}
|
||||
|
||||
// char const*
|
||||
{
|
||||
char const* tz = "Europe/Warsaw";
|
||||
testDeductionFrom<time_zone const*>(tz);
|
||||
testDeductionFrom<time_zone const*>(to_const(tz));
|
||||
testDeductionFrom<time_zone const*>(std::move(tz));
|
||||
}
|
||||
|
||||
// std::string
|
||||
{
|
||||
std::string tz = "Europe/Warsaw";
|
||||
testDeductionFrom<time_zone const*>(tz);
|
||||
testDeductionFrom<time_zone const*>(to_const(tz));
|
||||
testDeductionFrom<time_zone const*>(std::move(tz));
|
||||
}
|
||||
|
||||
// std::string_view
|
||||
{
|
||||
std::string_view tz = "Europe/Warsaw";
|
||||
testDeductionFrom<time_zone const*>(tz);
|
||||
testDeductionFrom<time_zone const*>(to_const(tz));
|
||||
testDeductionFrom<time_zone const*>(std::move(tz));
|
||||
}
|
||||
|
||||
// MyString
|
||||
{
|
||||
MyString tz("Europe/Warsaw");
|
||||
testDeductionFrom<time_zone const*>(tz);
|
||||
testDeductionFrom<time_zone const*>(to_const(tz));
|
||||
testDeductionFrom<time_zone const*>(std::move(tz));
|
||||
}
|
||||
|
||||
// custom time zone
|
||||
{
|
||||
OffsetZone tz(minutes(45));
|
||||
testDeductionFrom<OffsetZone>(tz);
|
||||
testDeductionFrom<OffsetZone>(to_const(tz));
|
||||
testDeductionFrom<OffsetZone>(std::move(tz));
|
||||
}
|
||||
|
||||
// OnlyLValue
|
||||
{
|
||||
OnlyLValueString tz("Europe/Warsaw");
|
||||
testDeductionFrom<time_zone const*>(tz);
|
||||
//testDeductionFrom<time_zone const*>(to_const(tz));
|
||||
//testDeductionFrom<time_zone const*>(std::move(tz));
|
||||
}
|
||||
|
||||
#endif // HAS_DEDUCTION_GUIDES
|
||||
}
|
Reference in New Issue
Block a user