mirror of
https://github.com/HowardHinnant/date.git
synced 2025-06-25 01:01:33 +02:00
Compare commits
180 Commits
v2.4.1
...
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 |
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
|
||||
|
183
CMakeLists.txt
183
CMakeLists.txt
@ -1,164 +1,23 @@
|
||||
cmake_minimum_required( VERSION 3.1.0 )
|
||||
|
||||
project( date_prj )
|
||||
|
||||
include( GNUInstallDirs )
|
||||
|
||||
find_package( Threads REQUIRED )
|
||||
|
||||
# Override by setting on CMake command line.
|
||||
set( CMAKE_CXX_STANDARD 17 CACHE STRING "The C++ standard whose features are requested.")
|
||||
|
||||
option( USE_SYSTEM_TZ_DB "Use the operating system's timezone database" OFF )
|
||||
option( USE_TZ_DB_IN_DOT "Save the timezone database in the current folder" OFF )
|
||||
option( BUILD_SHARED_LIBS "Build a shared version of library" OFF )
|
||||
option( ENABLE_DATE_TESTING "Enable unit tests" 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_SHARED_LIBS )
|
||||
print_option( ENABLE_DATE_TESTING )
|
||||
|
||||
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
|
||||
)
|
||||
|
||||
add_library( tz ${HEADER_FILES} ${SOURCE_FOLDER}/tz.cpp )
|
||||
|
||||
if( USE_SYSTEM_TZ_DB )
|
||||
target_compile_definitions( tz PRIVATE -DUSE_AUTOLOAD=0 )
|
||||
target_compile_definitions( tz PRIVATE -DHAS_REMOTE_API=0 )
|
||||
# cannot set USE_OS_TZDB to 1 on Windows
|
||||
if( NOT WIN32 )
|
||||
target_compile_definitions( tz PUBLIC -DUSE_OS_TZDB=1 )
|
||||
endif( )
|
||||
else( )
|
||||
target_compile_definitions( tz PRIVATE -DUSE_AUTOLOAD=1 )
|
||||
target_compile_definitions( tz PRIVATE -DHAS_REMOTE_API=1 )
|
||||
target_compile_definitions( tz PUBLIC -DUSE_OS_TZDB=0 )
|
||||
find_package( CURL REQUIRED )
|
||||
include_directories( SYSTEM ${CURL_INCLUDE_DIRS} )
|
||||
set( OPTIONAL_LIBRARIES ${CURL_LIBRARIES} )
|
||||
endif( )
|
||||
|
||||
if( USE_TZ_DB_IN_DOT )
|
||||
target_compile_definitions( tz PRIVATE -DINSTALL=. )
|
||||
endif( )
|
||||
|
||||
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}/include>"
|
||||
$<INSTALL_INTERFACE:include>
|
||||
)
|
||||
|
||||
if(WIN32 AND NOT CYGWIN)
|
||||
set(DEF_INSTALL_CMAKE_DIR CMake)
|
||||
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()
|
||||
set(DEF_INSTALL_CMAKE_DIR ${CMAKE_INSTALL_LIBDIR}/cmake/date)
|
||||
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()
|
||||
|
||||
install( TARGETS date_interface EXPORT dateConfig )
|
||||
install( EXPORT dateConfig DESTINATION ${DEF_INSTALL_CMAKE_DIR} )
|
||||
install( TARGETS tz
|
||||
ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}
|
||||
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
|
||||
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}) # This is for Windows
|
||||
install( DIRECTORY ${HEADER_FOLDER}/ DESTINATION include/ )
|
||||
|
||||
if ( ENABLE_DATE_TESTING )
|
||||
|
||||
enable_testing( )
|
||||
|
||||
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} )
|
||||
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( )
|
||||
endif( )
|
||||
|
30
README.md
30
README.md
@ -1,10 +1,11 @@
|
||||
# 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)
|
||||
|
||||
---
|
||||
|
||||
**[Try it out on wandbox!](https://wandbox.org/permlink/vqwMyTphHJv5iXX7)**
|
||||
**[Try it out on wandbox!](https://wandbox.org/permlink/oyXjibyF680HHoyS)**
|
||||
|
||||
## Summary
|
||||
|
||||
@ -42,7 +43,25 @@ Slightly modified versions of `"date.h"` and `"tz.h"` were voted into the C++20
|
||||
|
||||
## Build & Test
|
||||
|
||||
You will need [CMake](https://cmake.org/) and a recent C++ compiler. Here follows a guide of how to build and test using the CMake Makefile generator.
|
||||
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
|
||||
@ -54,5 +73,12 @@ cmake --build . --target testit # Consider '-- -j4' for multithreading
|
||||
|
||||
* 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( )
|
||||
|
||||
|
4372
include/date/date.h
4372
include/date/date.h
File diff suppressed because it is too large
Load Diff
@ -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
|
||||
|
||||
|
415
src/tz.cpp
415
src/tz.cpp
@ -89,6 +89,7 @@
|
||||
# include "date/ios.h"
|
||||
#else
|
||||
# define TARGET_OS_IPHONE 0
|
||||
# define TARGET_OS_SIMULATOR 0
|
||||
#endif
|
||||
|
||||
#if USE_OS_TZDB
|
||||
@ -98,6 +99,7 @@
|
||||
#include <cctype>
|
||||
#include <cstdlib>
|
||||
#include <cstring>
|
||||
#include <cwchar>
|
||||
#include <exception>
|
||||
#include <fstream>
|
||||
#include <iostream>
|
||||
@ -117,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__)
|
||||
@ -131,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>
|
||||
@ -173,6 +183,7 @@ static CONSTDATA char folder_delimiter = '/';
|
||||
#if !USE_OS_TZDB
|
||||
|
||||
# ifdef _WIN32
|
||||
# ifndef WINRT
|
||||
|
||||
namespace
|
||||
{
|
||||
@ -199,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
|
||||
@ -212,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
|
||||
@ -240,7 +263,7 @@ get_download_folder()
|
||||
return expand_path("~/Downloads");
|
||||
}
|
||||
|
||||
# endif // !defined(INSTALL) || HAS_REMOTE_API
|
||||
# endif // !defined(INSTALL)
|
||||
|
||||
# endif // !_WIN32
|
||||
|
||||
@ -309,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
|
||||
|
||||
@ -339,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))
|
||||
@ -375,11 +402,6 @@ get_tz_dir()
|
||||
// | End Configuration |
|
||||
// +-------------------+
|
||||
|
||||
namespace detail
|
||||
{
|
||||
struct undocumented {explicit undocumented() = default;};
|
||||
}
|
||||
|
||||
#ifndef _MSC_VER
|
||||
static_assert(min_year <= max_year, "Configuration error");
|
||||
#endif
|
||||
@ -398,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;
|
||||
@ -421,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);
|
||||
}
|
||||
@ -443,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
|
||||
@ -499,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.
|
||||
@ -657,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)
|
||||
@ -682,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)
|
||||
@ -1224,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);
|
||||
@ -1907,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;
|
||||
@ -1930,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
|
||||
@ -1986,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
|
||||
@ -2054,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};
|
||||
@ -2102,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;
|
||||
}
|
||||
|
||||
@ -2144,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);
|
||||
@ -2187,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)
|
||||
@ -2541,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_,
|
||||
@ -2592,20 +2622,15 @@ 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()
|
||||
@ -2614,12 +2639,99 @@ get_version()
|
||||
auto path = get_tz_dir() + string("/+VERSION");
|
||||
ifstream in{path};
|
||||
string version;
|
||||
in >> version;
|
||||
if (in.fail())
|
||||
throw std::runtime_error("Unable to get Timezone database version from " + path);
|
||||
return version;
|
||||
if (in)
|
||||
{
|
||||
in >> version;
|
||||
return version;
|
||||
}
|
||||
in.clear();
|
||||
in.open(get_tz_dir() + std::string(1, folder_delimiter) + "version");
|
||||
if (in)
|
||||
{
|
||||
in >> version;
|
||||
return version;
|
||||
}
|
||||
return "unknown";
|
||||
}
|
||||
|
||||
static
|
||||
std::vector<leap_second>
|
||||
find_read_and_leap_seconds()
|
||||
{
|
||||
std::ifstream in(get_tz_dir() + std::string(1, folder_delimiter) + "leapseconds",
|
||||
std::ios_base::binary);
|
||||
if (in)
|
||||
{
|
||||
std::vector<leap_second> leap_seconds;
|
||||
std::string line;
|
||||
while (in)
|
||||
{
|
||||
std::getline(in, line);
|
||||
if (!line.empty() && line[0] != '#')
|
||||
{
|
||||
std::istringstream in(line);
|
||||
in.exceptions(std::ios::failbit | std::ios::badbit);
|
||||
std::string word;
|
||||
in >> word;
|
||||
if (word == "Leap")
|
||||
{
|
||||
int y, m, d;
|
||||
in >> y;
|
||||
m = static_cast<int>(parse_month(in));
|
||||
in >> d;
|
||||
leap_seconds.push_back(leap_second(sys_days{year{y}/m/d} + days{1},
|
||||
detail::undocumented{}));
|
||||
}
|
||||
else
|
||||
{
|
||||
std::cerr << line << '\n';
|
||||
}
|
||||
}
|
||||
}
|
||||
return leap_seconds;
|
||||
}
|
||||
in.clear();
|
||||
in.open(get_tz_dir() + std::string(1, folder_delimiter) + "leap-seconds.list",
|
||||
std::ios_base::binary);
|
||||
if (in)
|
||||
{
|
||||
std::vector<leap_second> leap_seconds;
|
||||
std::string line;
|
||||
const auto offset = sys_days{1970_y/1/1}-sys_days{1900_y/1/1};
|
||||
while (in)
|
||||
{
|
||||
std::getline(in, line);
|
||||
if (!line.empty() && line[0] != '#')
|
||||
{
|
||||
std::istringstream in(line);
|
||||
in.exceptions(std::ios::failbit | std::ios::badbit);
|
||||
using seconds = std::chrono::seconds;
|
||||
seconds::rep s;
|
||||
in >> s;
|
||||
if (s == 2272060800)
|
||||
continue;
|
||||
leap_seconds.push_back(leap_second(sys_seconds{seconds{s}} - offset,
|
||||
detail::undocumented{}));
|
||||
}
|
||||
}
|
||||
return leap_seconds;
|
||||
}
|
||||
in.clear();
|
||||
in.open(get_tz_dir() + std::string(1, folder_delimiter) + "right/UTC",
|
||||
std::ios_base::binary);
|
||||
if (in)
|
||||
{
|
||||
return load_just_leaps(in);
|
||||
}
|
||||
in.clear();
|
||||
in.open(get_tz_dir() + std::string(1, folder_delimiter) + "UTC",
|
||||
std::ios_base::binary);
|
||||
if (in)
|
||||
{
|
||||
return load_just_leaps(in);
|
||||
}
|
||||
return {};
|
||||
}
|
||||
# endif
|
||||
|
||||
static
|
||||
std::unique_ptr<tzdb>
|
||||
@ -2648,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;
|
||||
@ -2673,36 +2788,16 @@ init_tzdb()
|
||||
}
|
||||
db->zones.shrink_to_fit();
|
||||
std::sort(db->zones.begin(), db->zones.end());
|
||||
# if !MISSING_LEAP_SECONDS
|
||||
std::ifstream in(get_tz_dir() + std::string(1, folder_delimiter) + "right/UTC",
|
||||
std::ios_base::binary);
|
||||
if (in)
|
||||
{
|
||||
in.exceptions(std::ios::failbit | std::ios::badbit);
|
||||
db->leaps = load_just_leaps(in);
|
||||
}
|
||||
else
|
||||
{
|
||||
in.clear();
|
||||
in.open(get_tz_dir() + std::string(1, folder_delimiter) +
|
||||
"UTC", std::ios_base::binary);
|
||||
if (!in)
|
||||
throw std::runtime_error("Unable to extract leap second information");
|
||||
in.exceptions(std::ios::failbit | std::ios::badbit);
|
||||
db->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);
|
||||
@ -2712,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);
|
||||
@ -2791,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
|
||||
@ -2815,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
|
||||
{
|
||||
@ -2964,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
|
||||
@ -3241,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());
|
||||
|
||||
@ -3249,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;
|
||||
@ -3415,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")
|
||||
@ -3445,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";
|
||||
@ -3498,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;
|
||||
@ -3539,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;
|
||||
}
|
||||
|
||||
@ -3601,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;
|
||||
}
|
||||
@ -3648,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
|
||||
{
|
||||
@ -3667,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(get_tz_dir());
|
||||
if (pos != result.npos)
|
||||
result.erase(0, get_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
|
||||
|
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());
|
||||
|
@ -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
|
||||
|
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