mirror of
https://github.com/HowardHinnant/date.git
synced 2025-06-25 01:01:33 +02:00
Compare commits
213 Commits
v2.4
...
esp-idf-re
Author | SHA1 | Date | |
---|---|---|---|
1658637448 | |||
4bbbffdf4c | |||
8ec7f3a36d | |||
b1a75847d5 | |||
49d78d1837 | |||
a32ff4f07e | |||
3be6b76d70 | |||
bf79dd5a81 | |||
26fc2bd372 | |||
97246a638a | |||
432bab81f9 | |||
215cacff56 | |||
3cbfa4318f | |||
115dd428cf | |||
7848566815 | |||
393b52f21b | |||
0b72599bd4 | |||
ba99134b8a | |||
5e18488899 | |||
313189b0a8 | |||
057b441ceb | |||
d7a0bf1fa7 | |||
8140d979cd | |||
7990eae740 | |||
1ec2ea0295 | |||
658a3b9495 | |||
e7969c32e8 | |||
569b2d6785 | |||
abe3ada04f | |||
9537addfc4 | |||
6952fb50a6 | |||
fe2f9c7eac | |||
a6243ce56f | |||
a55f1a103b | |||
d544e5af25 | |||
cac99da8dc | |||
a088baf9a5 | |||
e6adff6754 | |||
d784766640 | |||
9343e31599 | |||
f43c39fcf1 | |||
e12095f26f | |||
7d811743e0 | |||
a2fdba1adc | |||
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
|
||||
|
182
CMakeLists.txt
182
CMakeLists.txt
@ -1,161 +1,23 @@
|
||||
cmake_minimum_required( VERSION 3.0.2 )
|
||||
|
||||
project( date_prj )
|
||||
|
||||
find_package( Threads REQUIRED )
|
||||
|
||||
enable_testing( )
|
||||
|
||||
option( USE_SYSTEM_TZ_DB "Use the operating system's timezone database" 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 )
|
||||
|
||||
function( print_option OPT )
|
||||
if ( NOT DEFINED PRINT_OPTION_CURR_${OPT} OR ( NOT PRINT_OPTION_CURR_${OPT} STREQUAL ${OPT} ) )
|
||||
set( PRINT_OPTION_CURR_${OPT} ${${OPT}} CACHE BOOL "" )
|
||||
mark_as_advanced(PRINT_OPTION_CURR_${OPT})
|
||||
message( "# date: ${OPT} ${${OPT}}" )
|
||||
endif( )
|
||||
endfunction( )
|
||||
|
||||
print_option( USE_SYSTEM_TZ_DB )
|
||||
print_option( USE_TZ_DB_IN_DOT )
|
||||
print_option( BUILD_TZ_STATIC )
|
||||
|
||||
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
|
||||
)
|
||||
|
||||
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 )
|
||||
endif( )
|
||||
|
||||
if ( ${CMAKE_MINOR_VERSION} GREATER 7 )
|
||||
set( TZ_CXX_STANDARD 17 )
|
||||
else( )
|
||||
set( TZ_CXX_STANDARD 14 )
|
||||
endif( )
|
||||
|
||||
set_property(TARGET tz PROPERTY CXX_STANDARD ${TZ_CXX_STANDARD})
|
||||
target_link_libraries( tz ${CMAKE_THREAD_LIBS_INIT} ${OPTIONAL_LIBRARIES} )
|
||||
|
||||
# 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
|
||||
>
|
||||
)
|
||||
|
||||
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 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
|
||||
>
|
||||
)
|
||||
|
||||
|
||||
install( TARGETS tz DESTINATION lib )
|
||||
install( DIRECTORY ${HEADER_FOLDER}/ DESTINATION include/ )
|
||||
|
||||
add_custom_target( testit COMMAND ${CMAKE_CTEST_COMMAND} )
|
||||
|
||||
add_dependencies( testit tz )
|
||||
function( add_pass_tests TEST_GLOB TEST_PREFIX )
|
||||
file( GLOB_RECURSE FILENAMES ${TEST_GLOB} )
|
||||
include_directories( "${HEADER_FOLDER}/date" )
|
||||
|
||||
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( )
|
||||
|
||||
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( )
|
||||
if(DEFINED IDF_TARGET)
|
||||
idf_component_register(INCLUDE_DIRS include)
|
||||
set_property(TARGET ${COMPONENT_LIB} PROPERTY CXX_STANDARD 23)
|
||||
target_compile_definitions(${COMPONENT_TARGET} INTERFACE HAS_UNCAUGHT_EXCEPTIONS=1)
|
||||
else()
|
||||
add_library(date
|
||||
include/date/chrono_io.h
|
||||
include/date/date.h
|
||||
include/date/ios.h
|
||||
include/date/islamic.h
|
||||
include/date/iso_week.h
|
||||
include/date/julian.h
|
||||
include/date/ptz.h
|
||||
include/date/solar_hijri.h
|
||||
include/date/tz.h
|
||||
include/date/tz_private.h
|
||||
src/tz.cpp
|
||||
)
|
||||
|
||||
target_include_directories(date PUBLIC
|
||||
include/
|
||||
)
|
||||
endif()
|
||||
|
71
README.md
71
README.md
@ -1,43 +1,84 @@
|
||||
# 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/oyXjibyF680HHoyS)**
|
||||
|
||||
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
|
||||
|
||||
The recommended way to use any of these libraries besides `"tz.h"` is to just include it. These are header-only libraries (except `"tz.h"`).
|
||||
|
||||
To use `"tz.h"`, there is a single source file (`src/tz.cpp`) that needs to be compiled. Here are the recommended directions: https://howardhinnant.github.io/date/tz.html#Installation.
|
||||
|
||||
One can run tests by cd'ing into the `test` subdirectory and running `testit`. There are known failures on all platforms except for macOS. And even on macOS if C++11 is used. If any of these failures present problems for you, there exist workarounds.
|
||||
|
||||
Additionally there is unsupported support for [vcpkg](https://github.com/Microsoft/vcpkg) and [CMake](https://cmake.org/). I don't personally use or maintain these systems as for me they cause more problems than they solve (for this small project). If you would like to contribute to these build systems please feel free to file a PR.
|
||||
|
||||
You can download and install Date using the [vcpkg](https://github.com/Microsoft/vcpkg) dependency manager:
|
||||
|
||||
git clone https://github.com/Microsoft/vcpkg.git
|
||||
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
|
||||
* https://github.com/siodb/siodb
|
||||
* https://github.com/KomodoPlatform/atomicDEX-Pro
|
||||
* https://github.com/Kotlin/kotlinx-datetime
|
||||
* https://github.com/royalbee/jewish_date
|
||||
|
||||
If you would like your project (or product) on this list, just let me know.
|
||||
|
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::date-tz )
|
||||
find_dependency( Threads REQUIRED)
|
||||
get_target_property( _tzill date::date-tz INTERFACE_LINK_LIBRARIES )
|
||||
if( _tzill AND "${_tzill}" MATCHES "libcurl" )
|
||||
find_dependency( CURL )
|
||||
endif( )
|
||||
endif( )
|
||||
|
||||
|
4494
include/date/date.h
4494
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}));
|
||||
@ -1655,9 +1655,12 @@ inline
|
||||
bool
|
||||
month_day::ok() const NOEXCEPT
|
||||
{
|
||||
CONSTDATA julian::day d[] =
|
||||
{31_d, 29_d, 31_d, 30_d, 31_d, 30_d, 31_d, 31_d, 30_d, 31_d, 30_d, 31_d};
|
||||
return m_.ok() && 1_d <= d_ && d_ <= d[static_cast<unsigned>(m_)-1];
|
||||
CONSTDATA julian::day d[] = {
|
||||
julian::day(31), julian::day(29), julian::day(31), julian::day(30),
|
||||
julian::day(31), julian::day(30), julian::day(31), julian::day(31),
|
||||
julian::day(30), julian::day(31), julian::day(30), julian::day(31)
|
||||
};
|
||||
return m_.ok() && julian::day(1) <= d_ && d_ <= d[static_cast<unsigned>(m_)-1];
|
||||
}
|
||||
|
||||
CONSTCD11
|
||||
@ -1946,9 +1949,12 @@ inline
|
||||
day
|
||||
year_month_day_last::day() const NOEXCEPT
|
||||
{
|
||||
CONSTDATA julian::day d[] =
|
||||
{31_d, 28_d, 31_d, 30_d, 31_d, 30_d, 31_d, 31_d, 30_d, 31_d, 30_d, 31_d};
|
||||
return month() != feb || !y_.is_leap() ? d[static_cast<unsigned>(month())-1] : 29_d;
|
||||
CONSTDATA julian::day d[] = {
|
||||
julian::day(31), julian::day(28), julian::day(31), julian::day(30),
|
||||
julian::day(31), julian::day(30), julian::day(31), julian::day(31),
|
||||
julian::day(30), julian::day(31), julian::day(30), julian::day(31)
|
||||
};
|
||||
return month() != feb || !y_.is_leap() ? d[static_cast<unsigned>(month())-1] : julian::day(29);
|
||||
}
|
||||
|
||||
CONSTCD14
|
||||
@ -2190,7 +2196,7 @@ year_month_day::ok() const NOEXCEPT
|
||||
{
|
||||
if (!(y_.ok() && m_.ok()))
|
||||
return false;
|
||||
return 1_d <= d_ && d_ <= (y_/m_/last).day();
|
||||
return julian::day(1) <= d_ && d_ <= (y_/m_/last).day();
|
||||
}
|
||||
|
||||
CONSTCD11
|
||||
@ -2250,7 +2256,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() << '-';
|
||||
|
@ -36,6 +36,9 @@
|
||||
// Posix::time_zone tz{"EST5EDT,M3.2.0,M11.1.0"};
|
||||
// zoned_time<system_clock::duration, Posix::time_zone> zt{tz, system_clock::now()};
|
||||
//
|
||||
// If the rule set is missing (everything starting with ','), then the rule is that the
|
||||
// alternate offset is never enabled.
|
||||
//
|
||||
// Note, Posix-style time zones are not recommended for all of the reasons described here:
|
||||
// https://stackoverflow.com/tags/timezone/info
|
||||
//
|
||||
@ -70,7 +73,8 @@ unsigned read_date(const string_t& s, unsigned i, rule& r);
|
||||
unsigned read_name(const string_t& s, unsigned i, std::string& name);
|
||||
unsigned read_signed_time(const string_t& s, unsigned i, std::chrono::seconds& t);
|
||||
unsigned read_unsigned_time(const string_t& s, unsigned i, std::chrono::seconds& t);
|
||||
unsigned read_unsigned(const string_t& s, unsigned i, unsigned limit, unsigned& u);
|
||||
unsigned read_unsigned(const string_t& s, unsigned i, unsigned limit, unsigned& u,
|
||||
const string_t& message = string_t{});
|
||||
|
||||
class rule
|
||||
{
|
||||
@ -87,28 +91,58 @@ public:
|
||||
|
||||
bool ok() const {return mode_ != off;}
|
||||
date::local_seconds operator()(date::year y) const;
|
||||
std::string to_string() const;
|
||||
|
||||
friend std::ostream& operator<<(std::ostream& os, const rule& r);
|
||||
friend unsigned read_date(const string_t& s, unsigned i, rule& r);
|
||||
friend bool operator==(const rule& x, const rule& y);
|
||||
};
|
||||
|
||||
inline
|
||||
bool
|
||||
operator==(const rule& x, const rule& y)
|
||||
{
|
||||
if (x.mode_ != y.mode_)
|
||||
return false;
|
||||
switch (x.mode_)
|
||||
{
|
||||
case rule::J:
|
||||
case rule::N:
|
||||
return x.n_ == y.n_;
|
||||
case rule::M:
|
||||
return x.m_ == y.m_ && x.n_ == y.n_ && x.wd_ == y.wd_;
|
||||
default:
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
inline
|
||||
bool
|
||||
operator!=(const rule& x, const rule& y)
|
||||
{
|
||||
return !(x == y);
|
||||
}
|
||||
|
||||
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");
|
||||
@ -116,6 +150,62 @@ rule::operator()(date::year y) const
|
||||
return t;
|
||||
}
|
||||
|
||||
inline
|
||||
std::string
|
||||
rule::to_string() const
|
||||
{
|
||||
using namespace std::chrono;
|
||||
auto print_offset = [](seconds off)
|
||||
{
|
||||
std::string nm;
|
||||
if (off != hours{2})
|
||||
{
|
||||
date::hh_mm_ss<seconds> offset{off};
|
||||
nm = '/';
|
||||
nm += std::to_string(offset.hours().count());
|
||||
if (offset.minutes() != minutes{0} || offset.seconds() != seconds{0})
|
||||
{
|
||||
nm += ':';
|
||||
if (offset.minutes() < minutes{10})
|
||||
nm += '0';
|
||||
nm += std::to_string(offset.minutes().count());
|
||||
if (offset.seconds() != seconds{0})
|
||||
{
|
||||
nm += ':';
|
||||
if (offset.seconds() < seconds{10})
|
||||
nm += '0';
|
||||
nm += std::to_string(offset.seconds().count());
|
||||
}
|
||||
}
|
||||
}
|
||||
return nm;
|
||||
};
|
||||
|
||||
std::string nm;
|
||||
switch (mode_)
|
||||
{
|
||||
case rule::J:
|
||||
nm = 'J';
|
||||
nm += std::to_string(n_);
|
||||
break;
|
||||
case rule::M:
|
||||
nm = 'M';
|
||||
nm += std::to_string(static_cast<unsigned>(m_));
|
||||
nm += '.';
|
||||
nm += std::to_string(n_);
|
||||
nm += '.';
|
||||
nm += std::to_string(wd_.c_encoding());
|
||||
break;
|
||||
case rule::N:
|
||||
nm = std::to_string(n_);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
nm += print_offset(time_);
|
||||
return nm;
|
||||
}
|
||||
|
||||
inline
|
||||
std::ostream&
|
||||
operator<<(std::ostream& os, const rule& r)
|
||||
@ -175,12 +265,18 @@ public:
|
||||
friend std::ostream& operator<<(std::ostream& os, const time_zone& z);
|
||||
|
||||
const time_zone* operator->() const {return this;}
|
||||
|
||||
std::string name() const;
|
||||
|
||||
friend bool operator==(const time_zone& x, const time_zone& y);
|
||||
};
|
||||
|
||||
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_;
|
||||
@ -190,7 +286,10 @@ time_zone::time_zone(const detail::string_t& s)
|
||||
if (i != s.size())
|
||||
{
|
||||
if (s[i] != ',')
|
||||
{
|
||||
i = read_signed_time(s, i, save_);
|
||||
save_ = -save_ - offset_;
|
||||
}
|
||||
if (i != s.size())
|
||||
{
|
||||
if (s[i] != ',')
|
||||
@ -212,8 +311,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 +355,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 +366,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 +445,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 +457,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 +472,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 +492,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()};
|
||||
@ -384,6 +510,72 @@ operator<<(std::ostream& os, const time_zone& z)
|
||||
return os;
|
||||
}
|
||||
|
||||
inline
|
||||
std::string
|
||||
time_zone::name() const
|
||||
{
|
||||
using namespace date;
|
||||
using namespace std::chrono;
|
||||
auto nm = std_abbrev_;
|
||||
auto print_offset = [](seconds off)
|
||||
{
|
||||
std::string nm;
|
||||
hh_mm_ss<seconds> offset{-off};
|
||||
if (offset.is_negative())
|
||||
nm += '-';
|
||||
nm += std::to_string(offset.hours().count());
|
||||
if (offset.minutes() != minutes{0} || offset.seconds() != seconds{0})
|
||||
{
|
||||
nm += ':';
|
||||
if (offset.minutes() < minutes{10})
|
||||
nm += '0';
|
||||
nm += std::to_string(offset.minutes().count());
|
||||
if (offset.seconds() != seconds{0})
|
||||
{
|
||||
nm += ':';
|
||||
if (offset.seconds() < seconds{10})
|
||||
nm += '0';
|
||||
nm += std::to_string(offset.seconds().count());
|
||||
}
|
||||
}
|
||||
return nm;
|
||||
};
|
||||
nm += print_offset(offset_);
|
||||
if (!dst_abbrev_.empty())
|
||||
{
|
||||
nm += dst_abbrev_;
|
||||
if (save_ != hours{1})
|
||||
nm += print_offset(offset_+save_);
|
||||
if (start_rule_.ok())
|
||||
{
|
||||
nm += ',';
|
||||
nm += start_rule_.to_string();
|
||||
nm += ',';
|
||||
nm += end_rule_.to_string();
|
||||
}
|
||||
}
|
||||
return nm;
|
||||
}
|
||||
|
||||
inline
|
||||
bool
|
||||
operator==(const time_zone& x, const time_zone& y)
|
||||
{
|
||||
return x.std_abbrev_ == y.std_abbrev_ &&
|
||||
x.dst_abbrev_ == y. dst_abbrev_ &&
|
||||
x.offset_ == y.offset_ &&
|
||||
x.save_ == y.save_ &&
|
||||
x.start_rule_ == y.start_rule_ &&
|
||||
x.end_rule_ == y.end_rule_;
|
||||
}
|
||||
|
||||
inline
|
||||
bool
|
||||
operator!=(const time_zone& x, const time_zone& y)
|
||||
{
|
||||
return !(x == y);
|
||||
}
|
||||
|
||||
namespace detail
|
||||
{
|
||||
|
||||
@ -393,10 +585,10 @@ 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, '~') +
|
||||
std::string(i < s.size() ? s.size()-i-1 : 0, '~') +
|
||||
"\x1b[0m");
|
||||
}
|
||||
|
||||
@ -404,14 +596,15 @@ 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')
|
||||
{
|
||||
++i;
|
||||
unsigned n;
|
||||
i = read_unsigned(s, i, 3, n);
|
||||
i = read_unsigned(s, i, 3, n, "Expected to find the Julian day [1, 365]");
|
||||
r.mode_ = rule::J;
|
||||
r.n_ = n;
|
||||
}
|
||||
@ -419,17 +612,17 @@ read_date(const string_t& s, unsigned i, rule& r)
|
||||
{
|
||||
++i;
|
||||
unsigned m;
|
||||
i = read_unsigned(s, i, 2, m);
|
||||
i = read_unsigned(s, i, 2, m, "Expected to find month [1, 12]");
|
||||
if (i == s.size() || s[i] != '.')
|
||||
throw_invalid(s, i, "Expected '.' after month");
|
||||
++i;
|
||||
unsigned n;
|
||||
i = read_unsigned(s, i, 1, n);
|
||||
i = read_unsigned(s, i, 1, n, "Expected to find week number [1, 5]");
|
||||
if (i == s.size() || s[i] != '.')
|
||||
throw_invalid(s, i, "Expected '.' after weekday index");
|
||||
++i;
|
||||
unsigned wd;
|
||||
i = read_unsigned(s, i, 1, wd);
|
||||
i = read_unsigned(s, i, 1, wd, "Expected to find day of week [0, 6]");
|
||||
r.mode_ = rule::M;
|
||||
r.m_ = month{m};
|
||||
r.wd_ = weekday{wd};
|
||||
@ -513,21 +706,23 @@ 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;
|
||||
i = read_unsigned(s, i, 2, x);
|
||||
i = read_unsigned(s, i, 2, x, "Expected to find hours [0, 24]");
|
||||
t = hours{x};
|
||||
if (i != s.size() && s[i] == ':')
|
||||
{
|
||||
++i;
|
||||
i = read_unsigned(s, i, 2, x);
|
||||
i = read_unsigned(s, i, 2, x, "Expected to find minutes [0, 59]");
|
||||
t += minutes{x};
|
||||
if (i != s.size() && s[i] == ':')
|
||||
{
|
||||
++i;
|
||||
i = read_unsigned(s, i, 2, x);
|
||||
i = read_unsigned(s, i, 2, x, "Expected to find seconds [0, 59]");
|
||||
t += seconds{x};
|
||||
}
|
||||
}
|
||||
@ -536,10 +731,11 @@ read_unsigned_time(const string_t& s, unsigned i, std::chrono::seconds& t)
|
||||
|
||||
inline
|
||||
unsigned
|
||||
read_unsigned(const string_t& s, unsigned i, unsigned limit, unsigned& u)
|
||||
read_unsigned(const string_t& s, unsigned i, unsigned limit, unsigned& u,
|
||||
const string_t& message)
|
||||
{
|
||||
if (i == s.size() || !std::isdigit(s[i]))
|
||||
throw_invalid(s, i, "Expected to find a decimal digit");
|
||||
throw_invalid(s, i, message);
|
||||
u = static_cast<unsigned>(s[i] - '0');
|
||||
unsigned count = 1;
|
||||
for (++i; count < limit && i != s.size() && std::isdigit(s[i]); ++i, ++count)
|
||||
|
3151
include/date/solar_hijri.h
Normal file
3151
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
@ -245,7 +245,7 @@ struct zonelet
|
||||
sys_seconds until_utc_;
|
||||
local_seconds until_std_;
|
||||
local_seconds until_loc_;
|
||||
std::chrono::minutes initial_save_{};
|
||||
std::chrono::minutes initial_save_{0};
|
||||
std::string initial_abbrev_;
|
||||
std::pair<const Rule*, date::year> first_rule_{nullptr, date::year::min()};
|
||||
std::pair<const Rule*, date::year> last_rule_{nullptr, date::year::max()};
|
||||
@ -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)
|
||||
|
11
library.json
Normal file
11
library.json
Normal file
@ -0,0 +1,11 @@
|
||||
{
|
||||
"name": "date",
|
||||
"version": "1.0.0",
|
||||
"build": {
|
||||
"includeDir": "include",
|
||||
"srcFilter":
|
||||
[
|
||||
"+<->"
|
||||
]
|
||||
}
|
||||
}
|
@ -22,7 +22,7 @@
|
||||
// SOFTWARE.
|
||||
//
|
||||
|
||||
#include "ios.h"
|
||||
#include "date/ios.h"
|
||||
|
||||
#if TARGET_OS_IPHONE
|
||||
|
459
src/tz.cpp
459
src/tz.cpp
@ -84,10 +84,12 @@
|
||||
#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
|
||||
# define TARGET_OS_SIMULATOR 0
|
||||
#endif
|
||||
|
||||
#if USE_OS_TZDB
|
||||
@ -97,6 +99,7 @@
|
||||
#include <cctype>
|
||||
#include <cstdlib>
|
||||
#include <cstring>
|
||||
#include <cwchar>
|
||||
#include <exception>
|
||||
#include <fstream>
|
||||
#include <iostream>
|
||||
@ -116,6 +119,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__)
|
||||
@ -130,7 +141,7 @@
|
||||
# endif // HAS_REMOTE_API
|
||||
#else // !_WIN32
|
||||
# include <unistd.h>
|
||||
# if !USE_OS_TZDB
|
||||
# if !USE_OS_TZDB && !defined(INSTALL)
|
||||
# include <wordexp.h>
|
||||
# endif
|
||||
# include <limits.h>
|
||||
@ -148,7 +159,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 +183,7 @@ static CONSTDATA char folder_delimiter = '/';
|
||||
#if !USE_OS_TZDB
|
||||
|
||||
# ifdef _WIN32
|
||||
# ifndef WINRT
|
||||
|
||||
namespace
|
||||
{
|
||||
@ -198,11 +210,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 +232,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 +263,7 @@ get_download_folder()
|
||||
return expand_path("~/Downloads");
|
||||
}
|
||||
|
||||
# endif // !defined(INSTALL) || HAS_REMOTE_API
|
||||
# endif // !defined(INSTALL)
|
||||
|
||||
# endif // !_WIN32
|
||||
|
||||
@ -308,8 +332,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
|
||||
|
||||
@ -338,7 +362,11 @@ discover_tz_dir()
|
||||
throw runtime_error("discover_tz_dir failed to find zoneinfo\n");
|
||||
# else // __APPLE__
|
||||
# if TARGET_OS_IPHONE
|
||||
# if TARGET_OS_SIMULATOR
|
||||
return "/usr/share/zoneinfo";
|
||||
# else
|
||||
return "/var/db/timezone/zoneinfo";
|
||||
# endif
|
||||
# else
|
||||
CONSTDATA auto timezone = "/etc/localtime";
|
||||
if (!(lstat(timezone, &sb) == 0 && S_ISLNK(sb.st_mode) && sb.st_size > 0))
|
||||
@ -360,7 +388,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 +402,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
|
||||
@ -391,20 +420,20 @@ tzdb_list::~tzdb_list()
|
||||
}
|
||||
}
|
||||
|
||||
tzdb_list::tzdb_list(tzdb_list&& x) noexcept
|
||||
tzdb_list::tzdb_list(tzdb_list&& x) NOEXCEPT
|
||||
: head_{x.head_.exchange(nullptr)}
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
tzdb_list::push_front(tzdb* tzdb) noexcept
|
||||
tzdb_list::push_front(tzdb* tzdb) NOEXCEPT
|
||||
{
|
||||
tzdb->next = head_;
|
||||
head_ = tzdb;
|
||||
}
|
||||
|
||||
tzdb_list::const_iterator
|
||||
tzdb_list::erase_after(const_iterator p) noexcept
|
||||
tzdb_list::erase_after(const_iterator p) NOEXCEPT
|
||||
{
|
||||
auto t = p.p_->next;
|
||||
p.p_->next = p.p_->next->next;
|
||||
@ -414,7 +443,7 @@ tzdb_list::erase_after(const_iterator p) noexcept
|
||||
|
||||
struct tzdb_list::undocumented_helper
|
||||
{
|
||||
static void push_front(tzdb_list& db_list, tzdb* tzdb) noexcept
|
||||
static void push_front(tzdb_list& db_list, tzdb* tzdb) NOEXCEPT
|
||||
{
|
||||
db_list.push_front(tzdb);
|
||||
}
|
||||
@ -436,6 +465,32 @@ get_tzdb_list()
|
||||
return tz_db;
|
||||
}
|
||||
|
||||
static
|
||||
std::string
|
||||
parse3(std::istream& in)
|
||||
{
|
||||
std::string r(3, ' ');
|
||||
ws(in);
|
||||
r[0] = static_cast<char>(in.get());
|
||||
r[1] = static_cast<char>(in.get());
|
||||
r[2] = static_cast<char>(in.get());
|
||||
return r;
|
||||
}
|
||||
|
||||
static
|
||||
unsigned
|
||||
parse_month(std::istream& in)
|
||||
{
|
||||
CONSTDATA char*const month_names[] =
|
||||
{"Jan", "Feb", "Mar", "Apr", "May", "Jun",
|
||||
"Jul", "Aug", "Sep", "Oct", "Nov", "Dec"};
|
||||
auto s = parse3(in);
|
||||
auto m = std::find(std::begin(month_names), std::end(month_names), s) - month_names;
|
||||
if (m >= std::end(month_names) - std::begin(month_names))
|
||||
throw std::runtime_error("oops: bad month name: " + s);
|
||||
return static_cast<unsigned>(++m);
|
||||
}
|
||||
|
||||
#if !USE_OS_TZDB
|
||||
|
||||
#ifdef _WIN32
|
||||
@ -492,7 +547,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 +664,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);
|
||||
@ -650,18 +705,6 @@ load_timezone_mappings_from_xml_file(const std::string& input_path)
|
||||
|
||||
// Parsing helpers
|
||||
|
||||
static
|
||||
std::string
|
||||
parse3(std::istream& in)
|
||||
{
|
||||
std::string r(3, ' ');
|
||||
ws(in);
|
||||
r[0] = static_cast<char>(in.get());
|
||||
r[1] = static_cast<char>(in.get());
|
||||
r[2] = static_cast<char>(in.get());
|
||||
return r;
|
||||
}
|
||||
|
||||
static
|
||||
unsigned
|
||||
parse_dow(std::istream& in)
|
||||
@ -675,20 +718,6 @@ parse_dow(std::istream& in)
|
||||
return static_cast<unsigned>(dow);
|
||||
}
|
||||
|
||||
static
|
||||
unsigned
|
||||
parse_month(std::istream& in)
|
||||
{
|
||||
CONSTDATA char*const month_names[] =
|
||||
{"Jan", "Feb", "Mar", "Apr", "May", "Jun",
|
||||
"Jul", "Aug", "Sep", "Oct", "Nov", "Dec"};
|
||||
auto s = parse3(in);
|
||||
auto m = std::find(std::begin(month_names), std::end(month_names), s) - month_names;
|
||||
if (m >= std::end(month_names) - std::begin(month_names))
|
||||
throw std::runtime_error("oops: bad month name: " + s);
|
||||
return static_cast<unsigned>(++m);
|
||||
}
|
||||
|
||||
static
|
||||
std::chrono::seconds
|
||||
parse_unsigned_time(std::istream& in)
|
||||
@ -1217,7 +1246,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 +1929,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 +1952,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 +2009,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 +2041,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 +2077,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};
|
||||
@ -2095,14 +2125,25 @@ time_zone::load_sys_info(std::vector<detail::transition>::const_iterator i) cons
|
||||
{
|
||||
using namespace std::chrono;
|
||||
assert(!transitions_.empty());
|
||||
assert(i != transitions_.begin());
|
||||
sys_info r;
|
||||
r.begin = i[-1].timepoint;
|
||||
r.end = i != transitions_.end() ? i->timepoint :
|
||||
sys_seconds(sys_days(year::max()/max_day));
|
||||
r.offset = i[-1].info->offset;
|
||||
r.save = i[-1].info->is_dst ? minutes{1} : minutes{0};
|
||||
r.abbrev = i[-1].info->abbrev;
|
||||
if (i != transitions_.begin())
|
||||
{
|
||||
r.begin = i[-1].timepoint;
|
||||
r.end = i != transitions_.end() ? i->timepoint :
|
||||
sys_seconds(sys_days(year::max()/max_day));
|
||||
r.offset = i[-1].info->offset;
|
||||
r.save = i[-1].info->is_dst ? minutes{1} : minutes{0};
|
||||
r.abbrev = i[-1].info->abbrev;
|
||||
}
|
||||
else
|
||||
{
|
||||
r.begin = sys_days(year::min()/min_day);
|
||||
r.end = i+1 != transitions_.end() ? i[1].timepoint :
|
||||
sys_seconds(sys_days(year::max()/max_day));
|
||||
r.offset = i[0].info->offset;
|
||||
r.save = i[0].info->is_dst ? minutes{1} : minutes{0};
|
||||
r.abbrev = i[0].info->abbrev;
|
||||
}
|
||||
return r;
|
||||
}
|
||||
|
||||
@ -2137,7 +2178,7 @@ time_zone::get_info_impl(local_seconds tp) const
|
||||
{
|
||||
i.second = load_sys_info(--tr);
|
||||
tps = sys_seconds{(tp - i.second.offset).time_since_epoch()};
|
||||
if (tps < i.second.end)
|
||||
if (tps < i.second.end && i.first.end != i.second.end)
|
||||
{
|
||||
i.result = local_info::ambiguous;
|
||||
std::swap(i.first, i.second);
|
||||
@ -2180,15 +2221,11 @@ operator<<(std::ostream& os, const time_zone& z)
|
||||
return os;
|
||||
}
|
||||
|
||||
#if !MISSING_LEAP_SECONDS
|
||||
|
||||
leap::leap(const sys_seconds& s, detail::undocumented)
|
||||
leap_second::leap_second(const sys_seconds& s, detail::undocumented)
|
||||
: date_(s)
|
||||
{
|
||||
}
|
||||
|
||||
#endif // !MISSING_LEAP_SECONDS
|
||||
|
||||
#else // !USE_OS_TZDB
|
||||
|
||||
time_zone::time_zone(const std::string& s, detail::undocumented)
|
||||
@ -2534,7 +2571,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_,
|
||||
@ -2585,34 +2622,116 @@ operator<<(std::ostream& os, const time_zone& z)
|
||||
|
||||
#endif // !USE_OS_TZDB
|
||||
|
||||
#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_ << " +";
|
||||
}
|
||||
|
||||
#endif // !MISSING_LEAP_SECONDS
|
||||
|
||||
#if USE_OS_TZDB
|
||||
|
||||
# ifdef __APPLE__
|
||||
static
|
||||
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;
|
||||
if (in.fail())
|
||||
throw std::runtime_error("Unable to get Timezone database version from " + path);
|
||||
return version;
|
||||
if (in)
|
||||
{
|
||||
in >> version;
|
||||
return version;
|
||||
}
|
||||
in.clear();
|
||||
in.open(get_tz_dir() + std::string(1, folder_delimiter) + "version");
|
||||
if (in)
|
||||
{
|
||||
in >> version;
|
||||
return version;
|
||||
}
|
||||
return "unknown";
|
||||
}
|
||||
|
||||
static
|
||||
std::vector<leap_second>
|
||||
find_read_and_leap_seconds()
|
||||
{
|
||||
std::ifstream in(get_tz_dir() + std::string(1, folder_delimiter) + "leapseconds",
|
||||
std::ios_base::binary);
|
||||
if (in)
|
||||
{
|
||||
std::vector<leap_second> leap_seconds;
|
||||
std::string line;
|
||||
while (in)
|
||||
{
|
||||
std::getline(in, line);
|
||||
if (!line.empty() && line[0] != '#')
|
||||
{
|
||||
std::istringstream in(line);
|
||||
in.exceptions(std::ios::failbit | std::ios::badbit);
|
||||
std::string word;
|
||||
in >> word;
|
||||
if (word == "Leap")
|
||||
{
|
||||
int y, m, d;
|
||||
in >> y;
|
||||
m = static_cast<int>(parse_month(in));
|
||||
in >> d;
|
||||
leap_seconds.push_back(leap_second(sys_days{year{y}/m/d} + days{1},
|
||||
detail::undocumented{}));
|
||||
}
|
||||
else
|
||||
{
|
||||
std::cerr << line << '\n';
|
||||
}
|
||||
}
|
||||
}
|
||||
return leap_seconds;
|
||||
}
|
||||
in.clear();
|
||||
in.open(get_tz_dir() + std::string(1, folder_delimiter) + "leap-seconds.list",
|
||||
std::ios_base::binary);
|
||||
if (in)
|
||||
{
|
||||
std::vector<leap_second> leap_seconds;
|
||||
std::string line;
|
||||
const auto offset = sys_days{1970_y/1/1}-sys_days{1900_y/1/1};
|
||||
while (in)
|
||||
{
|
||||
std::getline(in, line);
|
||||
if (!line.empty() && line[0] != '#')
|
||||
{
|
||||
std::istringstream in(line);
|
||||
in.exceptions(std::ios::failbit | std::ios::badbit);
|
||||
using seconds = std::chrono::seconds;
|
||||
seconds::rep s;
|
||||
in >> s;
|
||||
if (s == 2272060800)
|
||||
continue;
|
||||
leap_seconds.push_back(leap_second(sys_seconds{seconds{s}} - offset,
|
||||
detail::undocumented{}));
|
||||
}
|
||||
}
|
||||
return leap_seconds;
|
||||
}
|
||||
in.clear();
|
||||
in.open(get_tz_dir() + std::string(1, folder_delimiter) + "right/UTC",
|
||||
std::ios_base::binary);
|
||||
if (in)
|
||||
{
|
||||
return load_just_leaps(in);
|
||||
}
|
||||
in.clear();
|
||||
in.open(get_tz_dir() + std::string(1, folder_delimiter) + "UTC",
|
||||
std::ios_base::binary);
|
||||
if (in)
|
||||
{
|
||||
return load_just_leaps(in);
|
||||
}
|
||||
return {};
|
||||
}
|
||||
# endif
|
||||
|
||||
static
|
||||
std::unique_ptr<tzdb>
|
||||
@ -2622,7 +2741,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())
|
||||
@ -2641,8 +2760,11 @@ init_tzdb()
|
||||
strcmp(d->d_name, "iso3166.tab") == 0 ||
|
||||
strcmp(d->d_name, "right") == 0 ||
|
||||
strcmp(d->d_name, "+VERSION") == 0 ||
|
||||
strcmp(d->d_name, "version") == 0 ||
|
||||
strcmp(d->d_name, "zone.tab") == 0 ||
|
||||
strcmp(d->d_name, "zone1970.tab") == 0 ||
|
||||
strcmp(d->d_name, "tzdata.zi") == 0 ||
|
||||
strcmp(d->d_name, "leapseconds") == 0 ||
|
||||
strcmp(d->d_name, "leap-seconds.list") == 0 )
|
||||
continue;
|
||||
auto subname = dirname + folder_delimiter + d->d_name;
|
||||
@ -2657,7 +2779,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{});
|
||||
}
|
||||
}
|
||||
@ -2666,35 +2788,16 @@ 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::ios_base::binary);
|
||||
if (in)
|
||||
{
|
||||
in.exceptions(std::ios::failbit | std::ios::badbit);
|
||||
db->leaps = load_just_leaps(in);
|
||||
}
|
||||
else
|
||||
{
|
||||
in.clear();
|
||||
in.open(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);
|
||||
}
|
||||
# endif // !MISSING_LEAP_SECONDS
|
||||
# ifdef __APPLE__
|
||||
db->leap_seconds = find_read_and_leap_seconds();
|
||||
db->version = get_version();
|
||||
# endif
|
||||
return db;
|
||||
}
|
||||
|
||||
#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 +2807,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 +2886,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 +2911,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 +3062,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 +3339,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 +3347,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 +3515,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 +3545,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 +3598,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;
|
||||
@ -3531,11 +3639,9 @@ operator<<(std::ostream& os, const tzdb& db)
|
||||
os << "Version: " << db.version << "\n\n";
|
||||
for (const auto& x : db.zones)
|
||||
os << x << '\n';
|
||||
#if !MISSING_LEAP_SECONDS
|
||||
os << '\n';
|
||||
for (const auto& x : db.leaps)
|
||||
for (const auto& x : db.leap_seconds)
|
||||
os << x << '\n';
|
||||
#endif // !MISSING_LEAP_SECONDS
|
||||
return os;
|
||||
}
|
||||
|
||||
@ -3593,7 +3699,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 +3746,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 +3807,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 +3815,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 +3855,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 +3890,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>{}, "");
|
||||
}
|
@ -46,19 +46,19 @@ int
|
||||
main()
|
||||
{
|
||||
using namespace date::detail;
|
||||
static_assert(width<0>::value == 0, "");
|
||||
static_assert(width<1>::value == 0, "");
|
||||
static_assert(width<2>::value == 1, "");
|
||||
static_assert(width<3>::value == 19, "");
|
||||
static_assert(width<4>::value == 2, "");
|
||||
static_assert(width<5>::value == 1, "");
|
||||
static_assert(width<6>::value == 19, "");
|
||||
static_assert(width<7>::value == 19, "");
|
||||
static_assert(width<8>::value == 3, "");
|
||||
static_assert(width<9>::value == 19, "");
|
||||
static_assert(width<10>::value == 1, "");
|
||||
static_assert(width<100>::value == 2, "");
|
||||
static_assert(width<1000>::value == 3, "");
|
||||
static_assert(width<10000>::value == 4, "");
|
||||
static_assert(width<625>::value == 4, "");
|
||||
static_assert(width<0, 1>::value == 0, "");
|
||||
static_assert(width<1, 1>::value == 0, "");
|
||||
static_assert(width<1, 2>::value == 1, "");
|
||||
static_assert(width<1, 3>::value == 19, "");
|
||||
static_assert(width<1, 4>::value == 2, "");
|
||||
static_assert(width<1, 5>::value == 1, "");
|
||||
static_assert(width<1, 6>::value == 19, "");
|
||||
static_assert(width<1, 7>::value == 19, "");
|
||||
static_assert(width<1, 8>::value == 3, "");
|
||||
static_assert(width<1, 9>::value == 19, "");
|
||||
static_assert(width<1, 10>::value == 1, "");
|
||||
static_assert(width<1, 100>::value == 2, "");
|
||||
static_assert(width<1, 1000>::value == 3, "");
|
||||
static_assert(width<1, 10000>::value == 4, "");
|
||||
static_assert(width<756, 625>::value == 4, "");
|
||||
}
|
||||
|
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.
|
||||
|
36
test/tz_test/tzdb_list.pass.cpp
Normal file
36
test/tz_test/tzdb_list.pass.cpp
Normal file
@ -0,0 +1,36 @@
|
||||
// The MIT License (MIT)
|
||||
//
|
||||
// Copyright (c) 2020 Howard Hinnant
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in all
|
||||
// copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
// SOFTWARE.
|
||||
|
||||
#include "tz.h"
|
||||
#include <type_traits>
|
||||
|
||||
int
|
||||
main()
|
||||
{
|
||||
using namespace date;
|
||||
static_assert( std::is_nothrow_destructible<tzdb_list>{}, "");
|
||||
static_assert( std::is_nothrow_default_constructible<tzdb_list>{}, "");
|
||||
static_assert(!std::is_copy_constructible<tzdb_list>{}, "");
|
||||
static_assert(!std::is_copy_assignable<tzdb_list>{}, "");
|
||||
static_assert( std::is_nothrow_move_constructible<tzdb_list>{}, "");
|
||||
static_assert(!std::is_move_assignable<tzdb_list>{}, "");
|
||||
}
|
@ -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