forked from HowardHinnant/date
Compare commits
383 Commits
Author | SHA1 | Date | |
---|---|---|---|
5f49afc1e9 | |||
9502bc27a3 | |||
66a5aa482e | |||
b9cd9c3fde | |||
a184309786 | |||
fc4cf092f9 | |||
48433b9892 | |||
4c95165298 | |||
940f4a5ceb | |||
018a50bcd0 | |||
3e376be2e9 | |||
224c71a899 | |||
67e272a54e | |||
d399e10cba | |||
96ffe23f72 | |||
48f1455cd2 | |||
e3186e36c2 | |||
3f0f9b3cbe | |||
23fa1bb86d | |||
4481c75192 | |||
e6d2c08159 | |||
a5c4b4ebf8 | |||
44344000f0 | |||
6d5ff9b958 | |||
375579eac1 | |||
2ced83ceff | |||
718cbe3f9b | |||
961bf06c32 | |||
fe491eff1c | |||
c56f915cc3 | |||
5e57a19abe | |||
9454aeda2b | |||
3a343adf6a | |||
d21333f636 | |||
cb4bf26fc7 | |||
b87eb970c1 | |||
5a0057587d | |||
5345d135b7 | |||
7c020642fb | |||
1d721d9afd | |||
141ba85614 | |||
dca8ddc659 | |||
1f5c192f4a | |||
46ccd69c9c | |||
c0e7b4e2f7 | |||
09d90a8b5e | |||
6f0b645df1 | |||
7ef1a55143 | |||
27d1e1e54e | |||
7817ebf45a | |||
a029f1105d | |||
44215f6781 | |||
ed0368fc75 | |||
429d9ba739 | |||
081e9af55b | |||
8a563041fa | |||
9dc96fd9b5 | |||
8b69087d35 | |||
d5e96f0991 | |||
5ba1c1ad85 | |||
10ab6ae9e5 | |||
e31daf8093 | |||
cb7ca96f68 | |||
b5d025ea2f | |||
f782ae98f0 | |||
d6c5d02068 | |||
16077472af | |||
5a62c405e0 | |||
09a19a09f4 | |||
9cb0013aef | |||
f1326968af | |||
61c3d35634 | |||
4e7e76b981 | |||
90d0440884 | |||
2cb4c34009 | |||
7231a182a4 | |||
0e85704e47 | |||
5f34c40523 | |||
23b1f007fe | |||
a22125ca40 | |||
8f91ef27ed | |||
4b46deb4f9 | |||
54e8516af2 | |||
1eed461d06 | |||
591f572b67 | |||
69e9cd612f | |||
6b51ca8271 | |||
3e82a52d66 | |||
6a4d93a0bd | |||
39d6730665 | |||
de6a03d337 | |||
e86edc3820 | |||
1b32e316db | |||
f46885e632 | |||
2d282e35fa | |||
d50970b32a | |||
af2b2b70b3 | |||
3933a0122d | |||
07876e4433 | |||
0197889505 | |||
b86def339e | |||
aa0494b980 | |||
df31560701 | |||
4b687f4c04 | |||
db60c5eb8e | |||
9f1c4b0110 | |||
da15227f6c | |||
d4fb7eb76d | |||
0e3e84fd56 | |||
3eac2d376e | |||
f5f4d76936 | |||
c7b69d949a | |||
48baa942fc | |||
af415701ba | |||
be2ec2310b | |||
40b83654b6 | |||
6c4d333026 | |||
1fdda81a30 | |||
f33e179936 | |||
328cecaa56 | |||
5d15157bbb | |||
a91ceefb4e | |||
88c661e9f3 | |||
c665992a6e | |||
9d0bcdb63f | |||
973bd393bc | |||
d53db7a1cb | |||
e5c69d84ab | |||
b48a18a1d9 | |||
cdb4b276d9 | |||
1d9e49ea21 | |||
0125d330ab | |||
e7e1482087 | |||
d6b95dc301 | |||
700489e475 | |||
e6941697eb | |||
c311db2f1a | |||
fffa52ac0e | |||
f105595f04 | |||
20f0595b32 | |||
674a9e6953 | |||
bc8cf368e5 | |||
1e8ab50f82 | |||
38c5ca38bb | |||
0bde4ba8c8 | |||
afe61df277 | |||
43d8a4eab0 | |||
ca4036a4b0 | |||
a1ceec19fe | |||
5524dd1ae8 | |||
4ada98d247 | |||
040eed838b | |||
2acf403bcd | |||
637e5d8007 | |||
362cd8f27e | |||
a4ce4bc2d3 | |||
3e5a57467a | |||
3b8372f4fa | |||
6941691de4 | |||
09b78ba92c | |||
28c1c61ac2 | |||
55289f0d73 | |||
b7e58e193f | |||
2b6ee6378c | |||
7d80d89a44 | |||
d9052cffa2 | |||
447687870f | |||
dbd6e6e388 | |||
9178193ad2 | |||
44c2515280 | |||
0af7654764 | |||
1eeb4cd652 | |||
b49bdc3ca7 | |||
c7e5a4d08e | |||
5653e9e3a9 | |||
d3b8d4af8d | |||
c2e139ef53 | |||
a3e8f399c4 | |||
443a29df53 | |||
1902b8e8fb | |||
c513a20691 | |||
87ed7f83cf | |||
f8cc62c396 | |||
2d2b65906a | |||
53629fa30c | |||
748a1fd5a9 | |||
524517b369 | |||
98ae1e5241 | |||
9b88763dbf | |||
f3741d68ff | |||
080df4988f | |||
1f27fb7d42 | |||
3e47883c41 | |||
3a33cdca7d | |||
3c4f0b5ada | |||
c0a3e528a3 | |||
9c67d94f2f | |||
9c39772731 | |||
15a63ec819 | |||
543315b700 | |||
7c69f1570d | |||
dd91be668e | |||
b13c859ff1 | |||
d4592bd497 | |||
9910f5fcc3 | |||
58a4a9518a | |||
5a9b44a37a | |||
a9d2907fa1 | |||
bf5a4f3cd5 | |||
e1099ef3ab | |||
4614ebda4a | |||
c286981b3b | |||
9ca582d9da | |||
f4b12ab023 | |||
bd51baf31e | |||
16439a8ce2 | |||
d97bc984c7 | |||
c9ef0a8f05 | |||
4832ea0ddb | |||
ec514101a6 | |||
517c0f2704 | |||
e12f7c66f0 | |||
3a5e8c9384 | |||
fa6529a2fc | |||
4b73a42d02 | |||
25696b7fb3 | |||
9381e894a5 | |||
5563d31b2e | |||
202041e531 | |||
0b7d9c6dbe | |||
66a97f907e | |||
94eb182256 | |||
f328d8c84a | |||
8b9f0515b5 | |||
ce975cadb0 | |||
2032fccbb7 | |||
2e213abb76 | |||
3acb299f3f | |||
22a229af91 | |||
fc917fe303 | |||
bff551b2a5 | |||
9f6c8d8c10 | |||
3c3ba68906 | |||
c5e58fd015 | |||
ef6d53595d | |||
0f658db2cd | |||
481771ef5e | |||
5f01382e24 | |||
41563c46e8 | |||
bba9aeafab | |||
4cb893c780 | |||
c09d35534d | |||
272d487b3d | |||
aad6010831 | |||
0707cc4932 | |||
d3fcf00d55 | |||
2402a0bd25 | |||
873aa0515e | |||
49b50c43d9 | |||
38c24b4090 | |||
2515dfd1b5 | |||
c3ab69ee0d | |||
be871e6c85 | |||
eced00fc1c | |||
859a50a70e | |||
80a142407a | |||
d4d6eda861 | |||
07ada69385 | |||
e7c3ca0e90 | |||
82de27d339 | |||
922abf1299 | |||
c4dcd5eb78 | |||
9c181a1440 | |||
e2a38e600c | |||
4ae416f06a | |||
5726b70bb7 | |||
e6b1e0fe58 | |||
170ebfd354 | |||
a5b77bb0fe | |||
5a53cb38a3 | |||
494fee4e1b | |||
a034eeed23 | |||
a1b19a2ed6 | |||
496497d16e | |||
a828109809 | |||
2129b813c9 | |||
c8d3cc14da | |||
893cf51fd8 | |||
6067371127 | |||
0c8b1f5967 | |||
16dd16e64e | |||
ea0158c779 | |||
a0b8883763 | |||
156bdf8bc6 | |||
2d1d8f2255 | |||
e0c962a8ce | |||
7cbc4d8013 | |||
090b66beb8 | |||
791de2d9fc | |||
77a703afe2 | |||
bee4f27d4a | |||
56cec17500 | |||
d359399090 | |||
a003ad28fa | |||
012f2c6135 | |||
edcd9bd9c1 | |||
9f0d511be6 | |||
ccd857ff6d | |||
88890939d5 | |||
1139c9b64f | |||
ec412a1de0 | |||
aa4dafcc46 | |||
cc81c9ea50 | |||
a610f087c1 | |||
5132385454 | |||
5c38ad84e8 | |||
8b743db4b6 | |||
9c9ddeba37 | |||
0fb3921e5b | |||
83c8b4d522 | |||
f493bd67f2 | |||
cf0481b9af | |||
f57432d7b4 | |||
e8f0dca452 | |||
44f6dfc58e | |||
ec7db09085 | |||
cb83bc2501 | |||
faec35eaf1 | |||
20efec5b16 | |||
b2dc8b1f6e | |||
2f8997d3ed | |||
c64d69b1e1 | |||
885910375f | |||
d15491103b | |||
05db422ca9 | |||
2c094f5559 | |||
096bad2622 | |||
fc3d4d97fe | |||
4f27361378 | |||
a4eef8e20c | |||
1fd0806757 | |||
3daf8c1ffe | |||
c4c2550b29 | |||
f30450b4c5 | |||
d29cd4e343 | |||
5afd241be6 | |||
f044cb0583 | |||
3495c513a1 | |||
3ab6510cab | |||
5eff31acdd | |||
5e86f2c5ba | |||
dbee0e7da4 | |||
d110f07f59 | |||
9e1120c676 | |||
f4292e6aca | |||
a811a20748 | |||
3df43424ac | |||
1e7e7a214d | |||
ffc8cd0a3b | |||
e9d36c6200 | |||
3233cbaf9a | |||
3e906a2409 | |||
c7f2995d0b | |||
0d6de15043 | |||
5c09ae73f2 | |||
098223cf6d | |||
6a31edcb38 | |||
800ae143aa | |||
c1034550d2 | |||
3a9880999d | |||
ce67ee0997 | |||
2b8e6562ae | |||
186dbb2891 | |||
49a59e5665 | |||
095f66af28 | |||
ea1717e8ab | |||
659cdca5dc | |||
634b84eb60 | |||
41093d05d8 | |||
c6f3dd2832 | |||
e203304afd | |||
4e44539a59 | |||
09537c4e19 |
194
.gitignore
vendored
Normal file
194
.gitignore
vendored
Normal file
@ -0,0 +1,194 @@
|
||||
#ignore thumbnails created by windows
|
||||
Thumbs.db
|
||||
#Ignore files build by Visual Studio
|
||||
*.obj
|
||||
*.exe
|
||||
*.pdb
|
||||
*.user
|
||||
*.aps
|
||||
*.pch
|
||||
*.vspscc
|
||||
*_i.c
|
||||
*_p.c
|
||||
*.ncb
|
||||
*.suo
|
||||
*.tlb
|
||||
*.tlh
|
||||
*.bak
|
||||
*.cache
|
||||
*.ilk
|
||||
*.log
|
||||
[Bb]in
|
||||
[Dd]ebug*/
|
||||
*.lib
|
||||
*.sbr
|
||||
obj/
|
||||
[Rr]elease*/
|
||||
_ReSharper*/
|
||||
[Tt]est[Rr]esult*
|
||||
.idea/
|
||||
*.opensdf
|
||||
## Ignore Visual Studio temporary files, build results, and
|
||||
## files generated by popular Visual Studio add-ons.
|
||||
# User-specific files
|
||||
*.suo
|
||||
*.user
|
||||
*.userosscache
|
||||
*.sln.docstates
|
||||
# User-specific folders
|
||||
*.sln.ide/
|
||||
# Build results
|
||||
[Dd]ebug/
|
||||
[Dd]ebugPublic/
|
||||
[Rr]elease/
|
||||
[Rr]eleases/
|
||||
x64/
|
||||
x86/
|
||||
build/
|
||||
bld/
|
||||
[Bb]in/
|
||||
[Oo]bj/
|
||||
# Roslyn cache directories
|
||||
*.ide/
|
||||
# MSTest test Results
|
||||
[Tt]est[Rr]esult*/
|
||||
[Bb]uild[Ll]og.*
|
||||
#NUNIT
|
||||
*.VisualState.xml
|
||||
TestResult.xml
|
||||
# Build Results of an ATL Project
|
||||
[Dd]ebugPS/
|
||||
[Rr]eleasePS/
|
||||
dlldata.c
|
||||
*_i.c
|
||||
*_p.c
|
||||
*_i.h
|
||||
*.ilk
|
||||
*.meta
|
||||
*.obj
|
||||
*.pch
|
||||
*.pdb
|
||||
*.pgc
|
||||
*.pgd
|
||||
*.rsp
|
||||
*.sbr
|
||||
*.tlb
|
||||
*.tli
|
||||
*.tlh
|
||||
*.tmp
|
||||
*.tmp_proj
|
||||
*.log
|
||||
*.vspscc
|
||||
*.vssscc
|
||||
.builds
|
||||
*.pidb
|
||||
*.svclog
|
||||
*.scc
|
||||
# Chutzpah Test files
|
||||
_Chutzpah*
|
||||
# Visual C++ cache files
|
||||
ipch/
|
||||
*.aps
|
||||
*.ncb
|
||||
*.opensdf
|
||||
*.sdf
|
||||
*.cachefile
|
||||
# Visual Studio profiler
|
||||
*.psess
|
||||
*.vsp
|
||||
*.vspx
|
||||
# TFS 2012 Local Workspace
|
||||
$tf/
|
||||
# Guidance Automation Toolkit
|
||||
*.gpState
|
||||
# ReSharper is a .NET coding add-in
|
||||
_ReSharper*/
|
||||
*.[Rr]e[Ss]harper
|
||||
*.DotSettings.user
|
||||
# JustCode is a .NET coding addin-in
|
||||
.JustCode
|
||||
# TeamCity is a build add-in
|
||||
_TeamCity*
|
||||
# DotCover is a Code Coverage Tool
|
||||
*.dotCover
|
||||
# NCrunch
|
||||
_NCrunch_*
|
||||
.*crunch*.local.xml
|
||||
# MightyMoose
|
||||
*.mm.*
|
||||
AutoTest.Net/
|
||||
# Web workbench (sass)
|
||||
.sass-cache/
|
||||
# Installshield output folder
|
||||
[Ee]xpress/
|
||||
# DocProject is a documentation generator add-in
|
||||
DocProject/buildhelp/
|
||||
DocProject/Help/*.HxT
|
||||
DocProject/Help/*.HxC
|
||||
DocProject/Help/*.hhc
|
||||
DocProject/Help/*.hhk
|
||||
DocProject/Help/*.hhp
|
||||
DocProject/Help/Html2
|
||||
DocProject/Help/html
|
||||
# Click-Once directory
|
||||
publish/
|
||||
# Publish Web Output
|
||||
*.[Pp]ublish.xml
|
||||
*.azurePubxml
|
||||
# TODO: Comment the next line if you want to checkin your web deploy settings
|
||||
# but database connection strings (with potential passwords) will be unencrypted
|
||||
*.pubxml
|
||||
*.publishproj
|
||||
# NuGet Packages
|
||||
*.nupkg
|
||||
# The packages folder can be ignored because of Package Restore
|
||||
**/packages/*
|
||||
# except build/, which is used as an MSBuild target.
|
||||
!**/packages/build/
|
||||
# If using the old MSBuild-Integrated Package Restore, uncomment this:
|
||||
#!**/packages/repositories.config
|
||||
# Windows Azure Build Output
|
||||
csx/
|
||||
*.build.csdef
|
||||
# Windows Store app package directory
|
||||
AppPackages/
|
||||
# Others
|
||||
sql/
|
||||
*.Cache
|
||||
ClientBin/
|
||||
[Ss]tyle[Cc]op.*
|
||||
~$*
|
||||
*~
|
||||
*.dbmdl
|
||||
*.dbproj.schemaview
|
||||
*.pfx
|
||||
*.publishsettings
|
||||
node_modules/
|
||||
bower_components/
|
||||
# RIA/Silverlight projects
|
||||
Generated_Code/
|
||||
# Backup & report files from converting an old project file
|
||||
# to a newer Visual Studio version. Backup files are not needed,
|
||||
# because we have git ;-)
|
||||
_UpgradeReport_Files/
|
||||
Backup*/
|
||||
UpgradeLog*.XML
|
||||
UpgradeLog*.htm
|
||||
# SQL Server files
|
||||
*.mdf
|
||||
*.ldf
|
||||
# Business Intelligence projects
|
||||
*.rdl.data
|
||||
*.bim.layout
|
||||
*.bim_*.settings
|
||||
# Microsoft Fakes
|
||||
FakesAssemblies/
|
||||
*.suo
|
||||
*.vcxproj.filters
|
||||
*.npp
|
||||
CMakeFiles/*
|
||||
nbproject/*
|
||||
*.cd
|
||||
*.cd
|
||||
a.out
|
||||
cmake-build-debug/*
|
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
|
||||
|
244
CMakeLists.txt
Normal file
244
CMakeLists.txt
Normal file
@ -0,0 +1,244 @@
|
||||
#[===================================================================[
|
||||
date library by Howard Hinnant
|
||||
|
||||
CMake projects that wish to use this library should consider
|
||||
something like the following :
|
||||
|
||||
include( FetchContent )
|
||||
FetchContent_Declare( date_src
|
||||
GIT_REPOSITORY https://github.com/HowardHinnant/date.git
|
||||
GIT_TAG 2.4.2 # adjust tag/branch/commit as needed
|
||||
)
|
||||
FetchContent_MakeAvailable(date_src)
|
||||
...
|
||||
target_link_libraries (my_target PRIVATE date::date)
|
||||
|
||||
#]===================================================================]
|
||||
|
||||
cmake_minimum_required( VERSION 3.7 )
|
||||
|
||||
project( date VERSION 2.4.1 )
|
||||
|
||||
include( GNUInstallDirs )
|
||||
|
||||
get_directory_property( has_parent PARENT_DIRECTORY )
|
||||
|
||||
# Override by setting on CMake command line.
|
||||
set( CMAKE_CXX_STANDARD 17 CACHE STRING "The C++ standard whose features are requested." )
|
||||
|
||||
option( USE_SYSTEM_TZ_DB "Use the operating system's timezone database" OFF )
|
||||
option( USE_TZ_DB_IN_DOT "Save the timezone database in the current folder" OFF )
|
||||
option( BUILD_SHARED_LIBS "Build a shared version of library" OFF )
|
||||
option( ENABLE_DATE_TESTING "Enable unit tests" OFF )
|
||||
option( DISABLE_STRING_VIEW "Disable string view" OFF )
|
||||
option( COMPILE_WITH_C_LOCALE "define ONLY_C_LOCALE=1" OFF )
|
||||
option( BUILD_TZ_LIB "build/install of TZ library" OFF )
|
||||
|
||||
if( ENABLE_DATE_TESTING AND NOT BUILD_TZ_LIB )
|
||||
message(WARNING "Testing requested, bug BUILD_TZ_LIB not ON - forcing the latter")
|
||||
set (BUILD_TZ_LIB ON CACHE BOOL "required for testing" FORCE)
|
||||
endif( )
|
||||
|
||||
function( print_option OPT )
|
||||
if ( NOT DEFINED PRINT_OPTION_CURR_${OPT} OR ( NOT PRINT_OPTION_CURR_${OPT} STREQUAL ${OPT} ) )
|
||||
set( PRINT_OPTION_CURR_${OPT} ${${OPT}} CACHE BOOL "" )
|
||||
mark_as_advanced(PRINT_OPTION_CURR_${OPT})
|
||||
message( "# date: ${OPT} ${${OPT}}" )
|
||||
endif( )
|
||||
endfunction( )
|
||||
|
||||
print_option( USE_SYSTEM_TZ_DB )
|
||||
print_option( USE_TZ_DB_IN_DOT )
|
||||
print_option( BUILD_SHARED_LIBS )
|
||||
print_option( ENABLE_DATE_TESTING )
|
||||
print_option( DISABLE_STRING_VIEW )
|
||||
|
||||
#[===================================================================[
|
||||
date (header only) library
|
||||
#]===================================================================]
|
||||
add_library( date INTERFACE )
|
||||
add_library( date::date ALIAS date )
|
||||
target_include_directories( date INTERFACE
|
||||
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>
|
||||
$<INSTALL_INTERFACE:include> )
|
||||
# adding header sources just helps IDEs
|
||||
target_sources( date INTERFACE
|
||||
$<BUILD_INTERFACE:${CMAKE_CURRENT_LIST_DIR}/include>$<INSTALL_INTERFACE:include>/date/date.h
|
||||
# the rest of these are not currently part of the public interface of the library:
|
||||
$<BUILD_INTERFACE:${CMAKE_CURRENT_LIST_DIR}/include/date/islamic.h>
|
||||
$<BUILD_INTERFACE:${CMAKE_CURRENT_LIST_DIR}/include/date/iso_week.h>
|
||||
$<BUILD_INTERFACE:${CMAKE_CURRENT_LIST_DIR}/include/date/julian.h>
|
||||
)
|
||||
if (CMAKE_VERSION VERSION_GREATER_EQUAL 3.15)
|
||||
# public headers will get installed:
|
||||
set_target_properties( date PROPERTIES PUBLIC_HEADER include/date/date.h )
|
||||
endif ()
|
||||
target_compile_definitions( date INTERFACE
|
||||
#To workaround libstdc++ issue https://github.com/HowardHinnant/date/issues/388
|
||||
ONLY_C_LOCALE=$<IF:$<BOOL:${COMPILE_WITH_C_LOCALE}>,1,0>
|
||||
$<$<BOOL:${DISABLE_STRING_VIEW}>:HAS_STRING_VIEW=0> )
|
||||
|
||||
#[===================================================================[
|
||||
tz (compiled) library
|
||||
#]===================================================================]
|
||||
if( BUILD_TZ_LIB )
|
||||
add_library( tz )
|
||||
target_sources( tz
|
||||
PUBLIC
|
||||
$<BUILD_INTERFACE:${CMAKE_CURRENT_LIST_DIR}/include>$<INSTALL_INTERFACE:include>/date/tz.h
|
||||
$<$<BOOL:${IOS}>:$<BUILD_INTERFACE:${CMAKE_CURRENT_LIST_DIR}/include>$<INSTALL_INTERFACE:include>/date/ios.h>
|
||||
PRIVATE
|
||||
include/date/tz_private.h
|
||||
$<$<BOOL:${IOS}>:src/ios.mm>
|
||||
src/tz.cpp )
|
||||
add_library( date::tz ALIAS tz )
|
||||
target_link_libraries( tz PUBLIC date )
|
||||
target_include_directories( tz PUBLIC
|
||||
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>
|
||||
$<INSTALL_INTERFACE:include> )
|
||||
target_compile_definitions( tz
|
||||
PRIVATE
|
||||
AUTO_DOWNLOAD=$<IF:$<BOOL:${USE_SYSTEM_TZ_DB}>,0,1>
|
||||
HAS_REMOTE_API=$<IF:$<BOOL:${USE_SYSTEM_TZ_DB}>,0,1>
|
||||
$<$<AND:$<BOOL:${WIN32}>,$<BOOL:${BUILD_SHARED_LIBS}>>:DATE_BUILD_DLL=1>
|
||||
$<$<BOOL:${USE_TZ_DB_IN_DOT}>:INSTALL=.>
|
||||
PUBLIC
|
||||
USE_OS_TZDB=$<IF:$<AND:$<BOOL:${USE_SYSTEM_TZ_DB}>,$<NOT:$<BOOL:${WIN32}>>>,1,0>
|
||||
INTERFACE
|
||||
$<$<AND:$<BOOL:${WIN32}>,$<BOOL:${BUILD_SHARED_LIBS}>>:DATE_USE_DLL=1> )
|
||||
set(TZ_HEADERS include/date/tz.h)
|
||||
if( IOS )
|
||||
list(APPEND TZ_HEADERS include/date/ios.h)
|
||||
endif( )
|
||||
set_target_properties( tz PROPERTIES
|
||||
POSITION_INDEPENDENT_CODE ON
|
||||
PUBLIC_HEADER "${TZ_HEADERS}"
|
||||
VERSION "${PROJECT_VERSION}"
|
||||
SOVERSION "${PROJECT_VERSION}" )
|
||||
if( NOT MSVC )
|
||||
find_package( Threads )
|
||||
target_link_libraries( tz PUBLIC Threads::Threads )
|
||||
endif( )
|
||||
if( NOT USE_SYSTEM_TZ_DB )
|
||||
find_package( CURL REQUIRED )
|
||||
target_link_libraries( tz PRIVATE CURL::libcurl )
|
||||
endif( )
|
||||
endif( )
|
||||
|
||||
#[===================================================================[
|
||||
installation
|
||||
#]===================================================================]
|
||||
set( version_config "${CMAKE_CURRENT_BINARY_DIR}/dateConfigVersion.cmake" )
|
||||
|
||||
include( CMakePackageConfigHelpers )
|
||||
write_basic_package_version_file( "${version_config}"
|
||||
VERSION ${PROJECT_VERSION}
|
||||
COMPATIBILITY SameMajorVersion )
|
||||
|
||||
install( TARGETS date
|
||||
EXPORT dateConfig
|
||||
PUBLIC_HEADER DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/date )
|
||||
export( TARGETS date NAMESPACE date:: FILE dateTargets.cmake )
|
||||
if (CMAKE_VERSION VERSION_LESS 3.15)
|
||||
install(
|
||||
FILES include/date/date.h
|
||||
DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/date )
|
||||
endif ()
|
||||
|
||||
if( BUILD_TZ_LIB )
|
||||
install( TARGETS tz
|
||||
EXPORT dateConfig
|
||||
PUBLIC_HEADER DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/date
|
||||
ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}
|
||||
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
|
||||
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} ) # This is for Windows
|
||||
export( TARGETS tz NAMESPACE date:: APPEND FILE dateTargets.cmake )
|
||||
endif( )
|
||||
|
||||
if( WIN32 AND NOT CYGWIN)
|
||||
set( CONFIG_LOC CMake )
|
||||
else( )
|
||||
set( CONFIG_LOC "${CMAKE_INSTALL_LIBDIR}/cmake/date" )
|
||||
endif( )
|
||||
install( EXPORT dateConfig
|
||||
FILE dateTargets.cmake
|
||||
NAMESPACE date::
|
||||
DESTINATION ${CONFIG_LOC} )
|
||||
install (
|
||||
FILES cmake/dateConfig.cmake "${version_config}"
|
||||
DESTINATION ${CONFIG_LOC})
|
||||
|
||||
#[===================================================================[
|
||||
testing
|
||||
#]===================================================================]
|
||||
if( ENABLE_DATE_TESTING )
|
||||
enable_testing( )
|
||||
|
||||
add_custom_target( testit COMMAND ${CMAKE_CTEST_COMMAND} )
|
||||
add_dependencies( testit tz )
|
||||
|
||||
function( add_pass_tests TEST_GLOB TEST_PREFIX )
|
||||
file( GLOB_RECURSE FILENAMES ${TEST_GLOB} )
|
||||
|
||||
foreach( TEST_FILE ${FILENAMES} )
|
||||
get_filename_component( TEST_NAME ${TEST_FILE} NAME_WE )
|
||||
get_filename_component( TEST_EXT ${TEST_FILE} EXT )
|
||||
if( NOT ${TEST_EXT} STREQUAL ".fail.cpp" )
|
||||
set( PREFIX "${TEST_PREFIX}_pass_${TEST_NAME}" )
|
||||
set( BIN_NAME ${PREFIX}_bin )
|
||||
set( TST_NAME ${PREFIX}_test )
|
||||
add_executable( ${BIN_NAME} EXCLUDE_FROM_ALL ${TEST_FILE} )
|
||||
add_test( ${TST_NAME} ${BIN_NAME} )
|
||||
target_link_libraries( ${BIN_NAME} tz )
|
||||
# HACK: because the test files don't use FQ includes:
|
||||
target_include_directories( ${BIN_NAME} PRIVATE include/date )
|
||||
add_dependencies( testit ${BIN_NAME} )
|
||||
endif( )
|
||||
endforeach( )
|
||||
endfunction( )
|
||||
|
||||
function( add_fail_tests TEST_GLOB TEST_PREFIX )
|
||||
file( GLOB_RECURSE FILENAMES ${TEST_GLOB} )
|
||||
|
||||
foreach( TEST_FILE ${FILENAMES} )
|
||||
get_filename_component( TEST_NAME ${TEST_FILE} NAME_WE )
|
||||
get_filename_component( TEST_EXT ${TEST_FILE} EXT )
|
||||
|
||||
set( TEST_TYPE "_fail" )
|
||||
|
||||
set( PREFIX "${TEST_PREFIX}_fail_${TEST_NAME}" )
|
||||
set( BIN_NAME ${PREFIX}_bin )
|
||||
set( TST_NAME ${PREFIX}_test )
|
||||
|
||||
set( TEST_BIN_NAME ${CMAKE_BINARY_DIR}/${BIN_NAME} )
|
||||
add_custom_target( ${BIN_NAME}
|
||||
COMMAND
|
||||
${PROJECT_SOURCE_DIR}/compile_fail.sh
|
||||
${TEST_BIN_NAME}
|
||||
${CMAKE_CXX_COMPILER}
|
||||
-std=c++14
|
||||
-L${CMAKE_BINARY_DIR}/
|
||||
-ltz
|
||||
-I${PROJECT_SOURCE_DIR}/include
|
||||
-I${PROJECT_SOURCE_DIR}/include/date
|
||||
-o ${BIN_NAME}
|
||||
${TEST_FILE}
|
||||
WORKING_DIRECTORY ${CMAKE_BINARY_DIR}
|
||||
COMMENT ${TST_NAME} )
|
||||
add_test( ${TST_NAME} "${PROJECT_SOURCE_DIR}/test_fail.sh" ${CMAKE_BINARY_DIR}/${BIN_NAME} WORKING_DIRECTORY "${PROJECT_SOURCE_DIR}/" )
|
||||
#set_tests_properties( ${TST_NAME} PROPERTIES WILL_FAIL TRUE)
|
||||
add_dependencies( testit ${BIN_NAME} )
|
||||
endforeach( )
|
||||
endfunction( )
|
||||
|
||||
file( GLOB children RELATIVE "${PROJECT_SOURCE_DIR}/test" "${PROJECT_SOURCE_DIR}/test/*" )
|
||||
foreach( child ${children} )
|
||||
if( IS_DIRECTORY "${PROJECT_SOURCE_DIR}/test/${child}" )
|
||||
set( CUR_FOLDER "${PROJECT_SOURCE_DIR}/test/${child}" )
|
||||
add_pass_tests( "${CUR_FOLDER}/*.cpp" ${child} )
|
||||
if( NOT WIN32 )
|
||||
add_fail_tests( "${CUR_FOLDER}/*.fail.cpp" ${child} )
|
||||
endif( )
|
||||
endif( )
|
||||
endforeach( )
|
||||
endif( )
|
31
LICENSE.txt
Normal file
31
LICENSE.txt
Normal file
@ -0,0 +1,31 @@
|
||||
The source code in this project is released using the MIT License. There is no
|
||||
global license for the project because each file is licensed individually with
|
||||
different author names and/or dates.
|
||||
|
||||
If you contribute to this project, please add your name to the license of each
|
||||
file you modify. If you have already contributed to this project and forgot to
|
||||
add your name to the license, please feel free to submit a new P/R to add your
|
||||
name to the license in each file you modified.
|
||||
|
||||
For convenience, here is a copy of the MIT license found in each file except
|
||||
without author names or dates:
|
||||
|
||||
The MIT License (MIT)
|
||||
|
||||
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.
|
75
README.md
75
README.md
@ -1,37 +1,72 @@
|
||||
# Date
|
||||
|
||||
[](https://travis-ci.org/HowardHinnant/date)
|
||||
[](https://gitter.im/HowardHinnant/date?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
|
||||
<hr/>
|
||||
IMPORTANT UPDATE:
|
||||
|
||||
Recently IANA changed how they reported the database version. If you have `AUTO_DOWNLOAD` enabled in the tz library, you must update to include this commit:
|
||||
---
|
||||
|
||||
https://github.com/HowardHinnant/date/commit/19c83e47ed411a45e0b5a45d772c47c6ee23ac3f
|
||||
**[Try it out on wandbox!](https://wandbox.org/permlink/L8MwjzSSC3fXXrMd)**
|
||||
|
||||
Without this update your tz lib will download a new copy of the database everytime you start your program.
|
||||
<hr/>
|
||||
_**[Try it out on wandbox!](http://melpon.org/wandbox/permlink/PodYB3AwdYNFKbMv)**_
|
||||
## Summary
|
||||
|
||||
This is actually several separate C++11/C++14 libraries:
|
||||
This is actually several separate C++11/C++14/C++17 libraries:
|
||||
|
||||
1. `"date.h"` is a header-only library which builds upon `<chrono>`. It adds some new `duration` types, and new `time_point` types. It also adds "field" types such as `year_month_day` which is a struct `{year, month, day}`. And it provides convenient means to convert between the "field" types and the `time_point` types. See http://howardhinnant.github.io/date/date.html for more details.
|
||||
1. `"date.h"` is a header-only library which builds upon `<chrono>`. It adds some new `duration` types, and new `time_point` types. It also adds "field" types such as `year_month_day` which is a struct `{year, month, day}`. And it provides convenient means to convert between the "field" types and the `time_point` types.
|
||||
|
||||
Here is the Cppcon 2015 presentation on date.h: https://www.youtube.com/watch?v=tzyGjOm8AKo
|
||||
* Documentation: http://howardhinnant.github.io/date/date.html
|
||||
* Video: https://www.youtube.com/watch?v=tzyGjOm8AKo
|
||||
* Slides: http://schd.ws/hosted_files/cppcon2015/43/hinnant_dates.pdf
|
||||
|
||||
Here are the Cppcon 2015 slides on date.h: http://schd.ws/hosted_files/cppcon2015/43/hinnant_dates.pdf
|
||||
1. `"tz.h"` / `"tz.cpp"` are a timezone library built on top of the `"date.h"` library. This timezone library is a complete parser of the IANA timezone database. It provides for an easy way to access all of the data in this database, using the types from `"date.h"` and `<chrono>`. The IANA database also includes data on leap seconds, and this library provides utilities to compute with that information as well.
|
||||
|
||||
2. `"tz.h"` / `"tz.cpp"` are a timezone library built on top of the `"date.h"` library. This timezone library is a complete parser of the IANA timezone database. It provides for an easy way to access all of the data in this database, using the types from `"date.h"` and `<chrono>`. The IANA database also includes data on leap seconds, and this library provides utilities to compute with that information as well. See http://howardhinnant.github.io/date/tz.html for more details.
|
||||
* Documentation: http://howardhinnant.github.io/date/tz.html
|
||||
* Video: https://www.youtube.com/watch?v=Vwd3pduVGKY
|
||||
* Slides: http://schd.ws/hosted_files/cppcon2016/0f/Welcome%20To%20The%20Time%20Zone%20-%20Howard%20Hinnant%20-%20CppCon%202016.pdf
|
||||
|
||||
Here is the Cppcon 2016 presentation on tz.h: https://www.youtube.com/watch?v=Vwd3pduVGKY
|
||||
1. `"iso_week.h"` is a header-only library built on top of the `"date.h"` library which implements the ISO week date calendar.
|
||||
|
||||
Here are the Cppcon 2016 slides on tz.h: http://schd.ws/hosted_files/cppcon2016/0f/Welcome%20To%20The%20Time%20Zone%20-%20Howard%20Hinnant%20-%20CppCon%202016.pdf
|
||||
* Documentation: http://howardhinnant.github.io/date/iso_week.html
|
||||
|
||||
3. `"chrono_io.h"` is a header-only library for streaming out chrono durations. See http://howardhinnant.github.io/date/chrono_io.html for more details.
|
||||
1. `"julian.h"` is a header-only library built on top of the `"date.h"` library which implements a proleptic Julian calendar which is fully interoperable with everything above.
|
||||
|
||||
4. `"iso_week.h"` is a header-only library built on top of the `"date.h"` library which implements the ISO week date calendar. See http://howardhinnant.github.io/date/iso_week.html for more details.
|
||||
* Documentation: http://howardhinnant.github.io/date/julian.html
|
||||
|
||||
5. `"julian.h"` is a header-only library built on top of the `"date.h"` library which implements a proleptic Julian calendar which is fully interoperable with everything above. See http://howardhinnant.github.io/date/julian.html for more details.
|
||||
1. `"islamic.h"` is a header-only library built on top of the `"date.h"` library which implements a proleptic Islamic calendar which is fully interoperable with everything above.
|
||||
|
||||
6. `"islamic.h"` is a header-only library built on top of the `"date.h"` library which implements a proleptic Islamic calendar which is fully interoperable with everything above. See http://howardhinnant.github.io/date/islamic.html for more details.
|
||||
* Documentation: http://howardhinnant.github.io/date/islamic.html
|
||||
|
||||
There has been a recent change in the library design. If you are trying to migrate from the previous design, rename `day_point` to `sys_days` everywhere, and that ought to bring the number of errors down to a small roar.
|
||||
## Standardization
|
||||
|
||||
`"date.h"` and `"tz.h"` are now being proposed for standardization: http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2016/p0355r1.html
|
||||
Slightly modified versions of `"date.h"` and `"tz.h"` were voted into the C++20 working draft at the Jacksonville FL meeting on 2018-03-17:
|
||||
|
||||
* http://howardhinnant.github.io/date/d0355r7.html
|
||||
|
||||
## Build & Test
|
||||
|
||||
You can download and install Date using the [vcpkg](https://github.com/Microsoft/vcpkg) dependency manager:
|
||||
|
||||
git clone https://github.com/Microsoft/vcpkg.git
|
||||
cd vcpkg
|
||||
./bootstrap-vcpkg.sh
|
||||
./vcpkg integrate install
|
||||
vcpkg install date
|
||||
|
||||
The Date port in vcpkg is updated by Microsoft team members and community contributors. If the version falls behind, please [create an issue or pull request](https://github.com/Microsoft/vcpkg) on the vcpkg repository.
|
||||
|
||||
You can optionally build using [CMake](https://cmake.org/). Here is a guide of how to build and test using the CMake Makefile generator.
|
||||
|
||||
```bash
|
||||
mkdir build
|
||||
cd build
|
||||
cmake ../
|
||||
cmake --build . --target testit # Consider '-- -j4' for multithreading
|
||||
```
|
||||
## Projects using this library
|
||||
|
||||
* www.safe.com
|
||||
* www.webtoolkit.eu/wt
|
||||
* https://github.com/ViewTouch/viewtouch
|
||||
* https://routinghub.com
|
||||
* https://github.com/valhalla
|
||||
|
||||
If you would like your project (or product) on this list, just let me know.
|
||||
|
668
chrono_io.h
668
chrono_io.h
@ -1,668 +0,0 @@
|
||||
#ifndef CHRONO_IO_H
|
||||
#define CHRONO_IO_H
|
||||
|
||||
// The MIT License (MIT)
|
||||
//
|
||||
// Copyright (c) 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.
|
||||
//
|
||||
// Our apologies. When the previous paragraph was written, lowercase had not yet
|
||||
// been invented (that woud involve another several millennia of evolution).
|
||||
// We did not mean to shout.
|
||||
|
||||
#include <chrono>
|
||||
#include <cstddef>
|
||||
#include <cstdint>
|
||||
#include <iosfwd>
|
||||
#include <ratio>
|
||||
#include <string>
|
||||
#include <type_traits>
|
||||
|
||||
namespace date
|
||||
{
|
||||
|
||||
namespace detail
|
||||
{
|
||||
|
||||
#if __cplusplus >= 201402
|
||||
|
||||
template <class CharT, std::size_t N>
|
||||
class string_literal
|
||||
{
|
||||
CharT p_[N];
|
||||
|
||||
public:
|
||||
using const_iterator = const CharT*;
|
||||
|
||||
string_literal(string_literal const&) = default;
|
||||
string_literal& operator=(string_literal const&) = delete;
|
||||
|
||||
template <std::size_t N1 = 2,
|
||||
class = std::enable_if_t<N1 == N>>
|
||||
constexpr string_literal(CharT c) noexcept
|
||||
: p_{c}
|
||||
{
|
||||
}
|
||||
|
||||
constexpr string_literal(const CharT(&a)[N]) noexcept
|
||||
: p_{}
|
||||
{
|
||||
for (std::size_t i = 0; i < N; ++i)
|
||||
p_[i] = a[i];
|
||||
}
|
||||
|
||||
template <class U = CharT, class = std::enable_if_t<1 < sizeof(U)>>
|
||||
constexpr string_literal(const char(&a)[N]) noexcept
|
||||
: p_{}
|
||||
{
|
||||
for (std::size_t i = 0; i < N; ++i)
|
||||
p_[i] = a[i];
|
||||
}
|
||||
|
||||
template <class CharT2, class = std::enable_if_t<!std::is_same<CharT2, CharT>{}>>
|
||||
constexpr string_literal(string_literal<CharT2, N> const& a) noexcept
|
||||
: p_{}
|
||||
{
|
||||
for (std::size_t i = 0; i < N; ++i)
|
||||
p_[i] = a[i];
|
||||
}
|
||||
|
||||
template <std::size_t N1, std::size_t N2,
|
||||
class = std::enable_if_t<N1 + N2 - 1 == N>>
|
||||
constexpr string_literal(const string_literal<CharT, N1>& x,
|
||||
const string_literal<CharT, N2>& y) noexcept
|
||||
: p_{}
|
||||
{
|
||||
std::size_t i = 0;
|
||||
for (; i < N1-1; ++i)
|
||||
p_[i] = x[i];
|
||||
for (std::size_t j = 0; j < N2; ++j, ++i)
|
||||
p_[i] = y[j];
|
||||
}
|
||||
|
||||
constexpr const CharT* data() const noexcept {return p_;}
|
||||
constexpr std::size_t size() const noexcept {return N-1;}
|
||||
|
||||
constexpr const_iterator begin() const noexcept {return p_;}
|
||||
constexpr const_iterator end() const noexcept {return p_ + N-1;}
|
||||
|
||||
constexpr CharT const& operator[](std::size_t n) const noexcept
|
||||
{
|
||||
return p_[n];
|
||||
}
|
||||
|
||||
template <class Traits>
|
||||
friend
|
||||
std::basic_ostream<CharT, Traits>&
|
||||
operator<<(std::basic_ostream<CharT, Traits>& os, const string_literal& s)
|
||||
{
|
||||
return os << s.p_;
|
||||
}
|
||||
};
|
||||
|
||||
template <class CharT1, class CharT2, std::size_t N1, std::size_t N2>
|
||||
constexpr
|
||||
inline
|
||||
string_literal<std::conditional_t<sizeof(CharT2) <= sizeof(CharT1), CharT1, CharT2>,
|
||||
N1 + N2 - 1>
|
||||
operator+(const string_literal<CharT1, N1>& x, const string_literal<CharT2, N2>& y) noexcept
|
||||
{
|
||||
using CharT = std::conditional_t<sizeof(CharT2) <= sizeof(CharT1), CharT1, CharT2>;
|
||||
return string_literal<CharT, N1 + N2 - 1>{string_literal<CharT, N1>{x},
|
||||
string_literal<CharT, N2>{y}};
|
||||
}
|
||||
|
||||
template <class CharT, std::size_t N>
|
||||
constexpr
|
||||
inline
|
||||
string_literal<CharT, N>
|
||||
msl(const CharT(&a)[N]) noexcept
|
||||
{
|
||||
return string_literal<CharT, N>{a};
|
||||
}
|
||||
|
||||
template <class CharT,
|
||||
class = std::enable_if_t<std::is_same<CharT, char>{} ||
|
||||
std::is_same<CharT, wchar_t>{} ||
|
||||
std::is_same<CharT, char16_t>{} ||
|
||||
std::is_same<CharT, char32_t>{}>>
|
||||
constexpr
|
||||
inline
|
||||
string_literal<CharT, 2>
|
||||
msl(CharT c) noexcept
|
||||
{
|
||||
return string_literal<CharT, 2>{c};
|
||||
}
|
||||
|
||||
constexpr
|
||||
std::size_t
|
||||
to_string_len(std::intmax_t i)
|
||||
{
|
||||
std::size_t r = 0;
|
||||
do
|
||||
{
|
||||
i /= 10;
|
||||
++r;
|
||||
} while (i > 0);
|
||||
return r;
|
||||
}
|
||||
|
||||
template <std::intmax_t N>
|
||||
constexpr
|
||||
inline
|
||||
std::enable_if_t
|
||||
<
|
||||
N < 10,
|
||||
string_literal<char, to_string_len(N)+1>
|
||||
>
|
||||
msl() noexcept
|
||||
{
|
||||
return msl(char(N % 10 + '0'));
|
||||
}
|
||||
|
||||
template <std::intmax_t N>
|
||||
constexpr
|
||||
inline
|
||||
std::enable_if_t
|
||||
<
|
||||
10 <= N,
|
||||
string_literal<char, to_string_len(N)+1>
|
||||
>
|
||||
msl() noexcept
|
||||
{
|
||||
return msl<N/10>() + msl(char(N % 10 + '0'));
|
||||
}
|
||||
|
||||
template <class CharT, std::intmax_t N, std::intmax_t D>
|
||||
constexpr
|
||||
inline
|
||||
std::enable_if_t
|
||||
<
|
||||
std::ratio<N, D>::type::den != 1,
|
||||
string_literal<CharT, to_string_len(std::ratio<N, D>::type::num) +
|
||||
to_string_len(std::ratio<N, D>::type::den) + 4>
|
||||
>
|
||||
msl(std::ratio<N, D>) noexcept
|
||||
{
|
||||
using R = typename std::ratio<N, D>::type;
|
||||
return msl(CharT{'['}) + msl<R::num>() + msl(CharT{'/'}) +
|
||||
msl<R::den>() + msl(CharT{']'});
|
||||
}
|
||||
|
||||
template <class CharT, std::intmax_t N, std::intmax_t D>
|
||||
constexpr
|
||||
inline
|
||||
std::enable_if_t
|
||||
<
|
||||
std::ratio<N, D>::type::den == 1,
|
||||
string_literal<CharT, to_string_len(std::ratio<N, D>::type::num) + 3>
|
||||
>
|
||||
msl(std::ratio<N, D>) noexcept
|
||||
{
|
||||
using R = typename std::ratio<N, D>::type;
|
||||
return msl(CharT{'['}) + msl<R::num>() + msl(CharT{']'});
|
||||
}
|
||||
|
||||
template <class CharT>
|
||||
constexpr
|
||||
inline
|
||||
auto
|
||||
msl(std::atto) noexcept
|
||||
{
|
||||
return msl(CharT{'a'});
|
||||
}
|
||||
|
||||
template <class CharT>
|
||||
constexpr
|
||||
inline
|
||||
auto
|
||||
msl(std::femto) noexcept
|
||||
{
|
||||
return msl(CharT{'f'});
|
||||
}
|
||||
|
||||
template <class CharT>
|
||||
constexpr
|
||||
inline
|
||||
auto
|
||||
msl(std::pico) noexcept
|
||||
{
|
||||
return msl(CharT{'p'});
|
||||
}
|
||||
|
||||
template <class CharT>
|
||||
constexpr
|
||||
inline
|
||||
auto
|
||||
msl(std::nano) noexcept
|
||||
{
|
||||
return msl(CharT{'n'});
|
||||
}
|
||||
|
||||
template <class CharT>
|
||||
constexpr
|
||||
inline
|
||||
std::enable_if_t
|
||||
<
|
||||
std::is_same<CharT, char>{},
|
||||
string_literal<char, 3>
|
||||
>
|
||||
msl(std::micro) noexcept
|
||||
{
|
||||
return string_literal<char, 3>{"\xC2\xB5"};
|
||||
}
|
||||
|
||||
template <class CharT>
|
||||
constexpr
|
||||
inline
|
||||
std::enable_if_t
|
||||
<
|
||||
!std::is_same<CharT, char>{},
|
||||
string_literal<CharT, 2>
|
||||
>
|
||||
msl(std::micro) noexcept
|
||||
{
|
||||
return string_literal<CharT, 2>{CharT{static_cast<unsigned char>('\xB5')}};
|
||||
}
|
||||
|
||||
template <class CharT>
|
||||
constexpr
|
||||
inline
|
||||
auto
|
||||
msl(std::milli) noexcept
|
||||
{
|
||||
return msl(CharT{'m'});
|
||||
}
|
||||
|
||||
template <class CharT>
|
||||
constexpr
|
||||
inline
|
||||
auto
|
||||
msl(std::centi) noexcept
|
||||
{
|
||||
return msl(CharT{'c'});
|
||||
}
|
||||
|
||||
template <class CharT>
|
||||
constexpr
|
||||
inline
|
||||
auto
|
||||
msl(std::deci) noexcept
|
||||
{
|
||||
return msl(CharT{'d'});
|
||||
}
|
||||
|
||||
template <class CharT>
|
||||
constexpr
|
||||
inline
|
||||
auto
|
||||
msl(std::deca) noexcept
|
||||
{
|
||||
return string_literal<CharT, 3>{"da"};
|
||||
}
|
||||
|
||||
template <class CharT>
|
||||
constexpr
|
||||
inline
|
||||
auto
|
||||
msl(std::hecto) noexcept
|
||||
{
|
||||
return msl(CharT{'h'});
|
||||
}
|
||||
|
||||
template <class CharT>
|
||||
constexpr
|
||||
inline
|
||||
auto
|
||||
msl(std::kilo) noexcept
|
||||
{
|
||||
return msl(CharT{'k'});
|
||||
}
|
||||
|
||||
template <class CharT>
|
||||
constexpr
|
||||
inline
|
||||
auto
|
||||
msl(std::mega) noexcept
|
||||
{
|
||||
return msl(CharT{'M'});
|
||||
}
|
||||
|
||||
template <class CharT>
|
||||
constexpr
|
||||
inline
|
||||
auto
|
||||
msl(std::giga) noexcept
|
||||
{
|
||||
return msl(CharT{'G'});
|
||||
}
|
||||
|
||||
template <class CharT>
|
||||
constexpr
|
||||
inline
|
||||
auto
|
||||
msl(std::tera) noexcept
|
||||
{
|
||||
return msl(CharT{'T'});
|
||||
}
|
||||
|
||||
template <class CharT>
|
||||
constexpr
|
||||
inline
|
||||
auto
|
||||
msl(std::peta) noexcept
|
||||
{
|
||||
return msl(CharT{'P'});
|
||||
}
|
||||
|
||||
template <class CharT>
|
||||
constexpr
|
||||
inline
|
||||
auto
|
||||
msl(std::exa) noexcept
|
||||
{
|
||||
return msl(CharT{'E'});
|
||||
}
|
||||
|
||||
template <class CharT, class Period>
|
||||
constexpr
|
||||
auto
|
||||
get_units(Period p)
|
||||
{
|
||||
return msl<CharT>(p) + string_literal<CharT, 2>{"s"};
|
||||
}
|
||||
|
||||
template <class CharT>
|
||||
constexpr
|
||||
auto
|
||||
get_units(std::ratio<1>)
|
||||
{
|
||||
return string_literal<CharT, 2>{"s"};
|
||||
}
|
||||
|
||||
template <class CharT>
|
||||
constexpr
|
||||
auto
|
||||
get_units(std::ratio<60>)
|
||||
{
|
||||
return string_literal<CharT, 4>{"min"};
|
||||
}
|
||||
|
||||
template <class CharT>
|
||||
constexpr
|
||||
auto
|
||||
get_units(std::ratio<3600>)
|
||||
{
|
||||
return string_literal<CharT, 2>{"h"};
|
||||
}
|
||||
|
||||
#else // __cplusplus < 201402
|
||||
|
||||
inline
|
||||
std::string
|
||||
to_string(std::uint64_t x)
|
||||
{
|
||||
return std::to_string(x);
|
||||
}
|
||||
|
||||
template <class CharT>
|
||||
std::basic_string<CharT>
|
||||
to_string(std::uint64_t x)
|
||||
{
|
||||
auto y = std::to_string(x);
|
||||
return std::basic_string<CharT>(y.begin(), y.end());
|
||||
}
|
||||
|
||||
template <class CharT, std::intmax_t N, std::intmax_t D>
|
||||
constexpr
|
||||
inline
|
||||
typename std::enable_if
|
||||
<
|
||||
std::ratio<N, D>::type::den != 1,
|
||||
std::basic_string<CharT>
|
||||
>::type
|
||||
msl(std::ratio<N, D>) noexcept
|
||||
{
|
||||
using R = typename std::ratio<N, D>::type;
|
||||
return std::basic_string<CharT>(1, '[') + to_string<CharT>(R::num) + CharT{'/'} +
|
||||
to_string<CharT>(R::den) + CharT{']'};
|
||||
}
|
||||
|
||||
template <class CharT, std::intmax_t N, std::intmax_t D>
|
||||
constexpr
|
||||
inline
|
||||
typename std::enable_if
|
||||
<
|
||||
std::ratio<N, D>::type::den == 1,
|
||||
std::basic_string<CharT>
|
||||
>::type
|
||||
msl(std::ratio<N, D>) noexcept
|
||||
{
|
||||
using R = typename std::ratio<N, D>::type;
|
||||
return std::basic_string<CharT>(1, '[') + to_string<CharT>(R::num) + CharT{']'};
|
||||
}
|
||||
|
||||
template <class CharT>
|
||||
constexpr
|
||||
inline
|
||||
std::basic_string<CharT>
|
||||
msl(std::atto) noexcept
|
||||
{
|
||||
return {'a'};
|
||||
}
|
||||
|
||||
template <class CharT>
|
||||
constexpr
|
||||
inline
|
||||
std::basic_string<CharT>
|
||||
msl(std::femto) noexcept
|
||||
{
|
||||
return {'f'};
|
||||
}
|
||||
|
||||
template <class CharT>
|
||||
constexpr
|
||||
inline
|
||||
std::basic_string<CharT>
|
||||
msl(std::pico) noexcept
|
||||
{
|
||||
return {'p'};
|
||||
}
|
||||
|
||||
template <class CharT>
|
||||
constexpr
|
||||
inline
|
||||
std::basic_string<CharT>
|
||||
msl(std::nano) noexcept
|
||||
{
|
||||
return {'n'};
|
||||
}
|
||||
|
||||
template <class CharT>
|
||||
constexpr
|
||||
inline
|
||||
typename std::enable_if
|
||||
<
|
||||
std::is_same<CharT, char>::value,
|
||||
std::string
|
||||
>::type
|
||||
msl(std::micro) noexcept
|
||||
{
|
||||
return "\xC2\xB5";
|
||||
}
|
||||
|
||||
template <class CharT>
|
||||
constexpr
|
||||
inline
|
||||
typename std::enable_if
|
||||
<
|
||||
!std::is_same<CharT, char>::value,
|
||||
std::basic_string<CharT>
|
||||
>::type
|
||||
msl(std::micro) noexcept
|
||||
{
|
||||
return {CharT(static_cast<unsigned char>('\xB5'))};
|
||||
}
|
||||
|
||||
template <class CharT>
|
||||
constexpr
|
||||
inline
|
||||
std::basic_string<CharT>
|
||||
msl(std::milli) noexcept
|
||||
{
|
||||
return {'m'};
|
||||
}
|
||||
|
||||
template <class CharT>
|
||||
constexpr
|
||||
inline
|
||||
std::basic_string<CharT>
|
||||
msl(std::centi) noexcept
|
||||
{
|
||||
return {'c'};
|
||||
}
|
||||
|
||||
template <class CharT>
|
||||
constexpr
|
||||
inline
|
||||
std::basic_string<CharT>
|
||||
msl(std::deci) noexcept
|
||||
{
|
||||
return {'d'};
|
||||
}
|
||||
|
||||
template <class CharT>
|
||||
constexpr
|
||||
inline
|
||||
std::basic_string<CharT>
|
||||
msl(std::deca) noexcept
|
||||
{
|
||||
return {'d', 'a'};
|
||||
}
|
||||
|
||||
template <class CharT>
|
||||
constexpr
|
||||
inline
|
||||
std::basic_string<CharT>
|
||||
msl(std::hecto) noexcept
|
||||
{
|
||||
return {'h'};
|
||||
}
|
||||
|
||||
template <class CharT>
|
||||
constexpr
|
||||
inline
|
||||
std::basic_string<CharT>
|
||||
msl(std::kilo) noexcept
|
||||
{
|
||||
return {'k'};
|
||||
}
|
||||
|
||||
template <class CharT>
|
||||
constexpr
|
||||
inline
|
||||
std::basic_string<CharT>
|
||||
msl(std::mega) noexcept
|
||||
{
|
||||
return {'M'};
|
||||
}
|
||||
|
||||
template <class CharT>
|
||||
constexpr
|
||||
inline
|
||||
std::basic_string<CharT>
|
||||
msl(std::giga) noexcept
|
||||
{
|
||||
return {'G'};
|
||||
}
|
||||
|
||||
template <class CharT>
|
||||
constexpr
|
||||
inline
|
||||
std::basic_string<CharT>
|
||||
msl(std::tera) noexcept
|
||||
{
|
||||
return {'T'};
|
||||
}
|
||||
|
||||
template <class CharT>
|
||||
constexpr
|
||||
inline
|
||||
std::basic_string<CharT>
|
||||
msl(std::peta) noexcept
|
||||
{
|
||||
return {'P'};
|
||||
}
|
||||
|
||||
template <class CharT>
|
||||
constexpr
|
||||
inline
|
||||
std::basic_string<CharT>
|
||||
msl(std::exa) noexcept
|
||||
{
|
||||
return {'E'};
|
||||
}
|
||||
|
||||
template <class CharT, class Period>
|
||||
std::basic_string<CharT>
|
||||
get_units(Period p)
|
||||
{
|
||||
return msl<CharT>(p) + CharT{'s'};
|
||||
}
|
||||
|
||||
template <class CharT>
|
||||
std::basic_string<CharT>
|
||||
get_units(std::ratio<1>)
|
||||
{
|
||||
return {'s'};
|
||||
}
|
||||
|
||||
template <class CharT>
|
||||
std::basic_string<CharT>
|
||||
get_units(std::ratio<60>)
|
||||
{
|
||||
return {'m', 'i', 'n'};
|
||||
}
|
||||
|
||||
template <class CharT>
|
||||
std::basic_string<CharT>
|
||||
get_units(std::ratio<3600>)
|
||||
{
|
||||
return {'h'};
|
||||
}
|
||||
|
||||
#endif // __cplusplus >= 201402
|
||||
|
||||
} // namespace detail
|
||||
|
||||
template <class CharT, class Traits, class Rep, class Period>
|
||||
inline
|
||||
std::basic_ostream<CharT, Traits>&
|
||||
operator<<(std::basic_ostream<CharT, Traits>& os,
|
||||
const std::chrono::duration<Rep, Period>& d)
|
||||
{
|
||||
using namespace std::chrono;
|
||||
return os << d.count()
|
||||
<< detail::get_units<CharT>(typename Period::type{});
|
||||
}
|
||||
|
||||
} // namespace date
|
||||
|
||||
#endif // CHRONO_IO_H
|
34
ci/install_cmake.sh
Executable file
34
ci/install_cmake.sh
Executable file
@ -0,0 +1,34 @@
|
||||
#!/usr/bin/env bash
|
||||
set -e
|
||||
|
||||
IFS=. read cm_maj cm_min cm_rel <<<"$1"
|
||||
: ${cm_rel:-0}
|
||||
CMAKE_ROOT=${2:-"${HOME}/cmake"}
|
||||
|
||||
function cmake_version ()
|
||||
{
|
||||
if [[ -d ${CMAKE_ROOT} ]] ; then
|
||||
local perms=$(test $(uname) = "Linux" && echo "/111" || echo "+111")
|
||||
local installed=$(find ${CMAKE_ROOT} -perm ${perms} -type f -name cmake)
|
||||
if [[ "${installed}" != "" ]] ; then
|
||||
echo "$(${installed} --version | head -1)"
|
||||
fi
|
||||
fi
|
||||
}
|
||||
|
||||
installed=$(cmake_version)
|
||||
if [[ "${installed}" != "" && ${installed} =~ ${cm_maj}.${cm_min}.${cm_rel} ]] ; then
|
||||
echo "cmake already installed: ${installed}"
|
||||
exit
|
||||
fi
|
||||
|
||||
pkgname="cmake-${cm_maj}.${cm_min}.${cm_rel}-$(uname)-x86_64.tar.gz"
|
||||
tmppkg="/tmp/cmake.tar.gz"
|
||||
wget --quiet https://cmake.org/files/v${cm_maj}.${cm_min}/${pkgname} -O ${tmppkg}
|
||||
mkdir -p ${CMAKE_ROOT}
|
||||
cd ${CMAKE_ROOT}
|
||||
tar --strip-components 1 -xf ${tmppkg}
|
||||
rm -f ${tmppkg}
|
||||
echo "installed: $(cmake_version)"
|
||||
|
||||
|
11
cmake/dateConfig.cmake
Normal file
11
cmake/dateConfig.cmake
Normal file
@ -0,0 +1,11 @@
|
||||
include( CMakeFindDependencyMacro )
|
||||
include( "${CMAKE_CURRENT_LIST_DIR}/dateTargets.cmake" )
|
||||
if( NOT MSVC AND TARGET date::tz )
|
||||
find_dependency( Threads REQUIRED)
|
||||
get_target_property( _tzill date::tz INTERFACE_LINK_LIBRARIES )
|
||||
if( _tzill AND "${_tzill}" MATCHES "libcurl" )
|
||||
find_dependency( CURL )
|
||||
endif( )
|
||||
endif( )
|
||||
|
||||
|
16
compile_fail.sh
Executable file
16
compile_fail.sh
Executable file
@ -0,0 +1,16 @@
|
||||
#!/bin/bash
|
||||
export TEST_BIN_NAME=$1
|
||||
#echo "Building ${TEST_BIN_NAME}"
|
||||
shift 1
|
||||
export BUILD_COMMAND=$@
|
||||
#echo "Build command: ${BUILD_COMMAND}"
|
||||
eval ${BUILD_COMMAND} >/dev/null 2>/dev/null
|
||||
|
||||
if [ $? -eq 0 ]; then
|
||||
echo -ne "#!/bin/bash\nexit 1;" > ${TEST_BIN_NAME}
|
||||
else
|
||||
echo -ne "#!/bin/bash\nexit 0;" > ${TEST_BIN_NAME}
|
||||
fi
|
||||
chmod u+x ${TEST_BIN_NAME}
|
||||
exit 0;
|
||||
|
34
include/date/chrono_io.h
Normal file
34
include/date/chrono_io.h
Normal file
@ -0,0 +1,34 @@
|
||||
#ifndef CHRONO_IO_H
|
||||
#define CHRONO_IO_H
|
||||
|
||||
// The MIT License (MIT)
|
||||
//
|
||||
// Copyright (c) 2016, 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.
|
||||
//
|
||||
// Our apologies. When the previous paragraph was written, lowercase had not yet
|
||||
// been invented (that would involve another several millennia of evolution).
|
||||
// We did not mean to shout.
|
||||
|
||||
// This functionality has moved to "date.h"
|
||||
|
||||
#include "date.h"
|
||||
|
||||
#endif // CHRONO_IO_H
|
File diff suppressed because it is too large
Load Diff
@ -38,6 +38,7 @@
|
||||
{
|
||||
|
||||
std::string get_tzdata_path();
|
||||
std::string get_current_timezone();
|
||||
|
||||
} // namespace iOSUtils
|
||||
} // namespace date
|
@ -24,7 +24,7 @@
|
||||
// SOFTWARE.
|
||||
//
|
||||
// Our apologies. When the previous paragraph was written, lowercase had not yet
|
||||
// been invented (that woud involve another several millennia of evolution).
|
||||
// been invented (that would involve another several millennia of evolution).
|
||||
// We did not mean to shout.
|
||||
|
||||
#include "date.h"
|
||||
@ -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() << '-';
|
@ -3,7 +3,7 @@
|
||||
|
||||
// The MIT License (MIT)
|
||||
//
|
||||
// Copyright (c) 2015, 2016 Howard Hinnant
|
||||
// Copyright (c) 2015, 2016, 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
|
||||
@ -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);
|
||||
@ -1015,9 +1021,9 @@ weeknum
|
||||
year_lastweek::weeknum() const NOEXCEPT
|
||||
{
|
||||
const auto y = date::year{static_cast<int>(y_)};
|
||||
const auto s0 = sys_days{(y-years{1})/12/date::thu[date::last]};
|
||||
const auto s1 = sys_days{y/12/date::thu[date::last]};
|
||||
return iso_week::weeknum(date::trunc<weeks>(s1-s0).count());
|
||||
const auto s0 = sys_days((y-years{1})/12/date::thu[date::last]);
|
||||
const auto s1 = sys_days(y/12/date::thu[date::last]);
|
||||
return iso_week::weeknum(static_cast<unsigned>(date::trunc<weeks>(s1-s0).count()));
|
||||
}
|
||||
|
||||
CONSTCD11 inline bool year_lastweek::ok() const NOEXCEPT {return y_.ok();}
|
||||
@ -1313,16 +1319,16 @@ CONSTCD14
|
||||
inline
|
||||
year_lastweek_weekday::operator sys_days() const NOEXCEPT
|
||||
{
|
||||
return sys_days{date::year{static_cast<int>(y_)}/date::dec/date::thu[date::last]}
|
||||
+ (mon - thu) - (mon - wd_);
|
||||
return sys_days(date::year{static_cast<int>(y_)}/date::dec/date::thu[date::last])
|
||||
+ (sun - thu) - (sun - wd_);
|
||||
}
|
||||
|
||||
CONSTCD14
|
||||
inline
|
||||
year_lastweek_weekday::operator local_days() const NOEXCEPT
|
||||
{
|
||||
return local_days{date::year{static_cast<int>(y_)}/date::dec/date::thu[date::last]}
|
||||
+ (mon - thu) - (mon - wd_);
|
||||
return local_days(date::year{static_cast<int>(y_)}/date::dec/date::thu[date::last])
|
||||
+ (sun - thu) - (sun - wd_);
|
||||
}
|
||||
|
||||
CONSTCD11
|
||||
@ -1471,7 +1477,7 @@ CONSTCD14
|
||||
inline
|
||||
year_weeknum_weekday::operator sys_days() const NOEXCEPT
|
||||
{
|
||||
return sys_days{date::year{static_cast<int>(y_)-1}/date::dec/date::thu[date::last]}
|
||||
return sys_days(date::year{static_cast<int>(y_)-1}/date::dec/date::thu[date::last])
|
||||
+ (date::mon - date::thu) + weeks{static_cast<unsigned>(wn_)-1} + (wd_ - mon);
|
||||
}
|
||||
|
||||
@ -1479,7 +1485,7 @@ CONSTCD14
|
||||
inline
|
||||
year_weeknum_weekday::operator local_days() const NOEXCEPT
|
||||
{
|
||||
return local_days{date::year{static_cast<int>(y_)-1}/date::dec/date::thu[date::last]}
|
||||
return local_days(date::year{static_cast<int>(y_)-1}/date::dec/date::thu[date::last])
|
||||
+ (date::mon - date::thu) + weeks{static_cast<unsigned>(wn_)-1} + (wd_ - mon);
|
||||
}
|
||||
|
||||
@ -1499,13 +1505,14 @@ year_weeknum_weekday::from_days(days d) NOEXCEPT
|
||||
const auto dp = sys_days{d};
|
||||
const auto wd = iso_week::weekday{dp};
|
||||
auto y = date::year_month_day{dp + days{3}}.year();
|
||||
auto start = sys_days{(y - date::years{1})/date::dec/date::thu[date::last]} + (mon-thu);
|
||||
auto start = sys_days((y - date::years{1})/date::dec/date::thu[date::last]) + (mon-thu);
|
||||
if (dp < start)
|
||||
{
|
||||
--y;
|
||||
start = sys_days{(y - date::years{1})/date::dec/date::thu[date::last]} + (mon-thu);
|
||||
start = sys_days((y - date::years{1})/date::dec/date::thu[date::last]) + (mon-thu);
|
||||
}
|
||||
const auto wn = iso_week::weeknum(date::trunc<weeks>(dp - start).count() + 1);
|
||||
const auto wn = iso_week::weeknum(
|
||||
static_cast<unsigned>(date::trunc<weeks>(dp - start).count() + 1));
|
||||
return {iso_week::year(static_cast<int>(y)), wn, wd};
|
||||
}
|
||||
|
||||
@ -1608,7 +1615,7 @@ inline
|
||||
year_weeknum
|
||||
operator/(const year& y, int wn) NOEXCEPT
|
||||
{
|
||||
return y/weeknum(wn);
|
||||
return y/weeknum(static_cast<unsigned>(wn));
|
||||
}
|
||||
|
||||
CONSTCD11
|
@ -24,7 +24,7 @@
|
||||
// SOFTWARE.
|
||||
//
|
||||
// Our apologies. When the previous paragraph was written, lowercase had not yet
|
||||
// been invented (that woud involve another several millennia of evolution).
|
||||
// been invented (that would involve another several millennia of evolution).
|
||||
// We did not mean to shout.
|
||||
|
||||
#include "date.h"
|
||||
@ -39,10 +39,10 @@ using days = date::days;
|
||||
using weeks = date::weeks;
|
||||
|
||||
using years = std::chrono::duration
|
||||
<int, std::ratio_multiply<std::ratio<1461, 4>, days::period>>;
|
||||
<int, date::detail::ratio_multiply<std::ratio<1461, 4>, days::period>>;
|
||||
|
||||
using months = std::chrono::duration
|
||||
<int, std::ratio_divide<years::period, std::ratio<12>>>;
|
||||
<int, date::detail::ratio_divide<years::period, std::ratio<12>>>;
|
||||
|
||||
// time_point
|
||||
|
||||
@ -879,7 +879,7 @@ inline
|
||||
std::basic_ostream<CharT, Traits>&
|
||||
operator<<(std::basic_ostream<CharT, Traits>& os, const day& d)
|
||||
{
|
||||
date::detail::save_stream<CharT, Traits> _(os);
|
||||
date::detail::save_ostream<CharT, Traits> _(os);
|
||||
os.fill('0');
|
||||
os.flags(std::ios::dec | std::ios::right);
|
||||
os.width(2);
|
||||
@ -1171,7 +1171,7 @@ inline
|
||||
std::basic_ostream<CharT, Traits>&
|
||||
operator<<(std::basic_ostream<CharT, Traits>& os, const year& y)
|
||||
{
|
||||
date::detail::save_stream<CharT, Traits> _(os);
|
||||
date::detail::save_ostream<CharT, Traits> _(os);
|
||||
os.fill('0');
|
||||
os.flags(std::ios::dec | std::ios::internal);
|
||||
os.width(4 + (y < year{0}));
|
||||
@ -2250,7 +2250,7 @@ inline
|
||||
std::basic_ostream<CharT, Traits>&
|
||||
operator<<(std::basic_ostream<CharT, Traits>& os, const year_month_day& ymd)
|
||||
{
|
||||
date::detail::save_stream<CharT, Traits> _(os);
|
||||
date::detail::save_ostream<CharT, Traits> _(os);
|
||||
os.fill('0');
|
||||
os.flags(std::ios::dec | std::ios::right);
|
||||
os << ymd.year() << '-';
|
627
include/date/ptz.h
Normal file
627
include/date/ptz.h
Normal file
@ -0,0 +1,627 @@
|
||||
#ifndef PTZ_H
|
||||
#define PTZ_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.
|
||||
|
||||
// This header allows Posix-style time zones as specified for TZ here:
|
||||
// http://pubs.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap08.html#tag_08_03
|
||||
//
|
||||
// Posix::time_zone can be constructed with a posix-style string and then used in
|
||||
// a zoned_time like so:
|
||||
//
|
||||
// zoned_time<system_clock::duration, Posix::time_zone> zt{"EST5EDT,M3.2.0,M11.1.0",
|
||||
// system_clock::now()};
|
||||
// or:
|
||||
//
|
||||
// Posix::time_zone tz{"EST5EDT,M3.2.0,M11.1.0"};
|
||||
// zoned_time<system_clock::duration, Posix::time_zone> zt{tz, system_clock::now()};
|
||||
//
|
||||
// Note, Posix-style time zones are not recommended for all of the reasons described here:
|
||||
// https://stackoverflow.com/tags/timezone/info
|
||||
//
|
||||
// They are provided here as a non-trivial custom time zone example, and if you really
|
||||
// have to have Posix time zones, you're welcome to use this one.
|
||||
|
||||
#include "date/tz.h"
|
||||
#include <cctype>
|
||||
#include <ostream>
|
||||
#include <string>
|
||||
|
||||
namespace Posix
|
||||
{
|
||||
|
||||
namespace detail
|
||||
{
|
||||
|
||||
#if HAS_STRING_VIEW
|
||||
|
||||
using string_t = std::string_view;
|
||||
|
||||
#else // !HAS_STRING_VIEW
|
||||
|
||||
using string_t = std::string;
|
||||
|
||||
#endif // !HAS_STRING_VIEW
|
||||
|
||||
class rule;
|
||||
|
||||
void throw_invalid(const string_t& s, unsigned i, const string_t& message);
|
||||
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);
|
||||
|
||||
class rule
|
||||
{
|
||||
enum {off, J, M, N};
|
||||
|
||||
date::month m_;
|
||||
date::weekday wd_;
|
||||
unsigned short n_ : 14;
|
||||
unsigned short mode_ : 2;
|
||||
std::chrono::duration<std::int32_t> time_ = std::chrono::hours{2};
|
||||
|
||||
public:
|
||||
rule() : mode_(off) {}
|
||||
|
||||
bool ok() const {return mode_ != off;}
|
||||
date::local_seconds operator()(date::year y) const;
|
||||
|
||||
friend std::ostream& operator<<(std::ostream& os, const rule& r);
|
||||
friend unsigned read_date(const string_t& s, unsigned i, rule& r);
|
||||
};
|
||||
|
||||
inline
|
||||
date::local_seconds
|
||||
rule::operator()(date::year y) const
|
||||
{
|
||||
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/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/January/1} + days{n_} + sec{time_};
|
||||
break;
|
||||
default:
|
||||
assert(!"rule called with bad mode");
|
||||
}
|
||||
return t;
|
||||
}
|
||||
|
||||
inline
|
||||
std::ostream&
|
||||
operator<<(std::ostream& os, const rule& r)
|
||||
{
|
||||
switch (r.mode_)
|
||||
{
|
||||
case rule::J:
|
||||
os << 'J' << r.n_ << date::format(" %T", r.time_);
|
||||
break;
|
||||
case rule::M:
|
||||
if (r.n_ == 5)
|
||||
os << r.m_/r.wd_[date::last];
|
||||
else
|
||||
os << r.m_/r.wd_[r.n_];
|
||||
os << date::format(" %T", r.time_);
|
||||
break;
|
||||
case rule::N:
|
||||
os << r.n_ << date::format(" %T", r.time_);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return os;
|
||||
}
|
||||
|
||||
} // namespace detail
|
||||
|
||||
class time_zone
|
||||
{
|
||||
std::string std_abbrev_;
|
||||
std::string dst_abbrev_ = {};
|
||||
std::chrono::seconds offset_;
|
||||
std::chrono::seconds save_ = std::chrono::hours{1};
|
||||
detail::rule start_rule_;
|
||||
detail::rule end_rule_;
|
||||
|
||||
public:
|
||||
explicit time_zone(const detail::string_t& name);
|
||||
|
||||
template <class Duration>
|
||||
date::sys_info get_info(date::sys_time<Duration> st) const;
|
||||
template <class Duration>
|
||||
date::local_info get_info(date::local_time<Duration> tp) const;
|
||||
|
||||
template <class Duration>
|
||||
date::sys_time<typename std::common_type<Duration, std::chrono::seconds>::type>
|
||||
to_sys(date::local_time<Duration> tp) const;
|
||||
|
||||
template <class Duration>
|
||||
date::sys_time<typename std::common_type<Duration, std::chrono::seconds>::type>
|
||||
to_sys(date::local_time<Duration> tp, date::choose z) const;
|
||||
|
||||
template <class Duration>
|
||||
date::local_time<typename std::common_type<Duration, std::chrono::seconds>::type>
|
||||
to_local(date::sys_time<Duration> tp) const;
|
||||
|
||||
friend std::ostream& operator<<(std::ostream& os, const time_zone& z);
|
||||
|
||||
const time_zone* operator->() const {return this;}
|
||||
};
|
||||
|
||||
inline
|
||||
time_zone::time_zone(const detail::string_t& s)
|
||||
{
|
||||
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_;
|
||||
if (i != s.size())
|
||||
{
|
||||
i = read_name(s, i, dst_abbrev_);
|
||||
if (i != s.size())
|
||||
{
|
||||
if (s[i] != ',')
|
||||
i = read_signed_time(s, i, save_);
|
||||
if (i != s.size())
|
||||
{
|
||||
if (s[i] != ',')
|
||||
throw_invalid(s, i, "Expecting end of string or ',' to start rule");
|
||||
++i;
|
||||
i = read_date(s, i, start_rule_);
|
||||
if (i == s.size() || s[i] != ',')
|
||||
throw_invalid(s, i, "Expecting ',' and then the ending rule");
|
||||
++i;
|
||||
i = read_date(s, i, end_rule_);
|
||||
if (i != s.size())
|
||||
throw_invalid(s, i, "Found unexpected trailing characters");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template <class Duration>
|
||||
date::sys_info
|
||||
time_zone::get_info(date::sys_time<Duration> st) const
|
||||
{
|
||||
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())
|
||||
{
|
||||
auto y = year_month_day{floor<days>(st)}.year();
|
||||
auto start = sys_seconds{(start_rule_(y) - offset_).time_since_epoch()};
|
||||
auto end = sys_seconds{(end_rule_(y) - (offset_ + save_)).time_since_epoch()};
|
||||
if (start <= st && st < end)
|
||||
{
|
||||
r.begin = start;
|
||||
r.end = end;
|
||||
r.offset += save_;
|
||||
r.save = ceil<minutes>(save_);
|
||||
r.abbrev = dst_abbrev_;
|
||||
}
|
||||
else if (st < start)
|
||||
{
|
||||
r.begin = sys_seconds{(end_rule_(y-years{1}) -
|
||||
(offset_ + save_)).time_since_epoch()};
|
||||
r.end = start;
|
||||
r.abbrev = std_abbrev_;
|
||||
}
|
||||
else // st >= end
|
||||
{
|
||||
r.begin = end;
|
||||
r.end = sys_seconds{(start_rule_(y+years{1}) - offset_).time_since_epoch()};
|
||||
r.abbrev = std_abbrev_;
|
||||
}
|
||||
}
|
||||
else // constant offset
|
||||
{
|
||||
r.begin = sys_days{year::min()/January/1};
|
||||
r.end = sys_days{year::max()/December/last};
|
||||
r.abbrev = std_abbrev_;
|
||||
}
|
||||
return r;
|
||||
}
|
||||
|
||||
template <class Duration>
|
||||
date::local_info
|
||||
time_zone::get_info(date::local_time<Duration> tp) const
|
||||
{
|
||||
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();
|
||||
auto start = sys_seconds{(start_rule_(y) - offset_).time_since_epoch()};
|
||||
auto end = sys_seconds{(end_rule_(y) - (offset_ + save_)).time_since_epoch()};
|
||||
auto utcs = sys_seconds{floor<seconds>(tp - offset_).time_since_epoch()};
|
||||
auto utcd = sys_seconds{floor<seconds>(tp - (offset_ + save_)).time_since_epoch()};
|
||||
if ((utcs < start) != (utcd < start))
|
||||
{
|
||||
r.first.begin = sys_seconds{(end_rule_(y-years{1}) -
|
||||
(offset_ + save_)).time_since_epoch()};
|
||||
r.first.end = start;
|
||||
r.first.offset = offset_;
|
||||
r.first.abbrev = std_abbrev_;
|
||||
r.second.begin = start;
|
||||
r.second.end = end;
|
||||
r.second.abbrev = dst_abbrev_;
|
||||
r.second.offset = offset_ + save_;
|
||||
r.second.save = ceil<minutes>(save_);
|
||||
r.result = save_ > seconds{0} ? local_info::nonexistent
|
||||
: local_info::ambiguous;
|
||||
}
|
||||
else if ((utcs < end) != (utcd < end))
|
||||
{
|
||||
r.first.begin = start;
|
||||
r.first.end = end;
|
||||
r.first.offset = offset_ + save_;
|
||||
r.first.save = ceil<minutes>(save_);
|
||||
r.first.abbrev = dst_abbrev_;
|
||||
r.second.begin = end;
|
||||
r.second.end = sys_seconds{(start_rule_(y+years{1}) -
|
||||
offset_).time_since_epoch()};
|
||||
r.second.abbrev = std_abbrev_;
|
||||
r.second.offset = offset_;
|
||||
r.result = save_ > seconds{0} ? local_info::ambiguous
|
||||
: local_info::nonexistent;
|
||||
}
|
||||
else if (utcs < start)
|
||||
{
|
||||
r.first.begin = sys_seconds{(end_rule_(y-years{1}) -
|
||||
(offset_ + save_)).time_since_epoch()};
|
||||
r.first.end = start;
|
||||
r.first.offset = offset_;
|
||||
r.first.abbrev = std_abbrev_;
|
||||
}
|
||||
else if (utcs < end)
|
||||
{
|
||||
r.first.begin = start;
|
||||
r.first.end = end;
|
||||
r.first.offset = offset_ + save_;
|
||||
r.first.save = ceil<minutes>(save_);
|
||||
r.first.abbrev = dst_abbrev_;
|
||||
}
|
||||
else
|
||||
{
|
||||
r.first.begin = end;
|
||||
r.first.end = sys_seconds{(start_rule_(y+years{1}) -
|
||||
offset_).time_since_epoch()};
|
||||
r.first.abbrev = std_abbrev_;
|
||||
r.first.offset = offset_;
|
||||
}
|
||||
}
|
||||
else // constant offset
|
||||
{
|
||||
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_;
|
||||
}
|
||||
return r;
|
||||
}
|
||||
|
||||
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 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);
|
||||
else if (i.result == local_info::ambiguous)
|
||||
throw ambiguous_local_time(tp, i);
|
||||
return sys_time<Duration>{tp.time_since_epoch()} - i.first.offset;
|
||||
}
|
||||
|
||||
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 date::local_info;
|
||||
using date::sys_time;
|
||||
using date::choose;
|
||||
auto i = get_info(tp);
|
||||
if (i.result == local_info::nonexistent)
|
||||
{
|
||||
return i.first.end;
|
||||
}
|
||||
else if (i.result == local_info::ambiguous)
|
||||
{
|
||||
if (z == choose::latest)
|
||||
return sys_time<Duration>{tp.time_since_epoch()} - i.second.offset;
|
||||
}
|
||||
return sys_time<Duration>{tp.time_since_epoch()} - i.first.offset;
|
||||
}
|
||||
|
||||
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 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()};
|
||||
}
|
||||
|
||||
inline
|
||||
std::ostream&
|
||||
operator<<(std::ostream& os, const time_zone& z)
|
||||
{
|
||||
using date::operator<<;
|
||||
os << '{';
|
||||
os << z.std_abbrev_ << ", " << z.dst_abbrev_ << date::format(", %T, ", z.offset_)
|
||||
<< date::format("%T, [", z.save_) << z.start_rule_ << ", " << z.end_rule_ << ")}";
|
||||
return os;
|
||||
}
|
||||
|
||||
namespace detail
|
||||
{
|
||||
|
||||
inline
|
||||
void
|
||||
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" +
|
||||
std::string(s) + '\n' +
|
||||
"\x1b[1;32m" +
|
||||
std::string(i, '~') + '^' +
|
||||
std::string(s.size()-i-1, '~') +
|
||||
"\x1b[0m");
|
||||
}
|
||||
|
||||
inline
|
||||
unsigned
|
||||
read_date(const string_t& s, unsigned i, rule& r)
|
||||
{
|
||||
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);
|
||||
r.mode_ = rule::J;
|
||||
r.n_ = n;
|
||||
}
|
||||
else if (s[i] == 'M')
|
||||
{
|
||||
++i;
|
||||
unsigned m;
|
||||
i = read_unsigned(s, i, 2, m);
|
||||
if (i == s.size() || s[i] != '.')
|
||||
throw_invalid(s, i, "Expected '.' after month");
|
||||
++i;
|
||||
unsigned n;
|
||||
i = read_unsigned(s, i, 1, n);
|
||||
if (i == s.size() || s[i] != '.')
|
||||
throw_invalid(s, i, "Expected '.' after weekday index");
|
||||
++i;
|
||||
unsigned wd;
|
||||
i = read_unsigned(s, i, 1, wd);
|
||||
r.mode_ = rule::M;
|
||||
r.m_ = month{m};
|
||||
r.wd_ = weekday{wd};
|
||||
r.n_ = n;
|
||||
}
|
||||
else if (std::isdigit(s[i]))
|
||||
{
|
||||
unsigned n;
|
||||
i = read_unsigned(s, i, 3, n);
|
||||
r.mode_ = rule::N;
|
||||
r.n_ = n;
|
||||
}
|
||||
else
|
||||
throw_invalid(s, i, "Expected 'J', 'M', or a digit to start rule");
|
||||
if (i != s.size() && s[i] == '/')
|
||||
{
|
||||
++i;
|
||||
std::chrono::seconds t;
|
||||
i = read_unsigned_time(s, i, t);
|
||||
r.time_ = t;
|
||||
}
|
||||
return i;
|
||||
}
|
||||
|
||||
inline
|
||||
unsigned
|
||||
read_name(const string_t& s, unsigned i, std::string& name)
|
||||
{
|
||||
if (i == s.size())
|
||||
throw_invalid(s, i, "Expected a name but found end of string");
|
||||
if (s[i] == '<')
|
||||
{
|
||||
++i;
|
||||
while (true)
|
||||
{
|
||||
if (i == s.size())
|
||||
throw_invalid(s, i,
|
||||
"Expected to find closing '>', but found end of string");
|
||||
if (s[i] == '>')
|
||||
break;
|
||||
name.push_back(s[i]);
|
||||
++i;
|
||||
}
|
||||
++i;
|
||||
}
|
||||
else
|
||||
{
|
||||
while (i != s.size() && std::isalpha(s[i]))
|
||||
{
|
||||
name.push_back(s[i]);
|
||||
++i;
|
||||
}
|
||||
}
|
||||
if (name.size() < 3)
|
||||
throw_invalid(s, i, "Found name to be shorter than 3 characters");
|
||||
return i;
|
||||
}
|
||||
|
||||
inline
|
||||
unsigned
|
||||
read_signed_time(const string_t& s, unsigned i,
|
||||
std::chrono::seconds& t)
|
||||
{
|
||||
if (i == s.size())
|
||||
throw_invalid(s, i, "Expected to read signed time, but found end of string");
|
||||
bool negative = false;
|
||||
if (s[i] == '-')
|
||||
{
|
||||
negative = true;
|
||||
++i;
|
||||
}
|
||||
else if (s[i] == '+')
|
||||
++i;
|
||||
i = read_unsigned_time(s, i, t);
|
||||
if (negative)
|
||||
t = -t;
|
||||
return i;
|
||||
}
|
||||
|
||||
inline
|
||||
unsigned
|
||||
read_unsigned_time(const string_t& s, unsigned i, std::chrono::seconds& t)
|
||||
{
|
||||
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);
|
||||
t = hours{x};
|
||||
if (i != s.size() && s[i] == ':')
|
||||
{
|
||||
++i;
|
||||
i = read_unsigned(s, i, 2, x);
|
||||
t += minutes{x};
|
||||
if (i != s.size() && s[i] == ':')
|
||||
{
|
||||
++i;
|
||||
i = read_unsigned(s, i, 2, x);
|
||||
t += seconds{x};
|
||||
}
|
||||
}
|
||||
return i;
|
||||
}
|
||||
|
||||
inline
|
||||
unsigned
|
||||
read_unsigned(const string_t& s, unsigned i, unsigned limit, unsigned& u)
|
||||
{
|
||||
if (i == s.size() || !std::isdigit(s[i]))
|
||||
throw_invalid(s, i, "Expected to find a decimal digit");
|
||||
u = static_cast<unsigned>(s[i] - '0');
|
||||
unsigned count = 1;
|
||||
for (++i; count < limit && i != s.size() && std::isdigit(s[i]); ++i, ++count)
|
||||
u = u * 10 + static_cast<unsigned>(s[i] - '0');
|
||||
return i;
|
||||
}
|
||||
|
||||
} // namespace detail
|
||||
|
||||
} // namespace Posix
|
||||
|
||||
namespace date
|
||||
{
|
||||
|
||||
template <>
|
||||
struct zoned_traits<Posix::time_zone>
|
||||
{
|
||||
|
||||
#if HAS_STRING_VIEW
|
||||
|
||||
static
|
||||
Posix::time_zone
|
||||
locate_zone(std::string_view name)
|
||||
{
|
||||
return Posix::time_zone{name};
|
||||
}
|
||||
|
||||
#else // !HAS_STRING_VIEW
|
||||
|
||||
static
|
||||
Posix::time_zone
|
||||
locate_zone(const std::string& name)
|
||||
{
|
||||
return Posix::time_zone{name};
|
||||
}
|
||||
|
||||
static
|
||||
Posix::time_zone
|
||||
locate_zone(const char* name)
|
||||
{
|
||||
return Posix::time_zone{name};
|
||||
}
|
||||
|
||||
#endif // !HAS_STRING_VIEW
|
||||
|
||||
};
|
||||
|
||||
} // namespace date
|
||||
|
||||
#endif // PTZ_H
|
2794
include/date/tz.h
Normal file
2794
include/date/tz.h
Normal file
File diff suppressed because it is too large
Load Diff
@ -24,7 +24,7 @@
|
||||
// SOFTWARE.
|
||||
//
|
||||
// Our apologies. When the previous paragraph was written, lowercase had not yet
|
||||
// been invented (that woud involve another several millennia of evolution).
|
||||
// been invented (that would involve another several millennia of evolution).
|
||||
// We did not mean to shout.
|
||||
|
||||
#if !defined(_MSC_VER) || (_MSC_VER >= 1900)
|
||||
@ -40,6 +40,8 @@ namespace date
|
||||
namespace detail
|
||||
{
|
||||
|
||||
#if !USE_OS_TZDB
|
||||
|
||||
enum class tz {utc, local, standard};
|
||||
|
||||
//forward declare to avoid warnings in gcc 6.2
|
||||
@ -93,9 +95,9 @@ private:
|
||||
U& operator=(const pair& x);
|
||||
} u;
|
||||
|
||||
std::chrono::hours h_{0};
|
||||
std::chrono::minutes m_{0};
|
||||
std::chrono::seconds s_{0};
|
||||
std::chrono::hours h_{};
|
||||
std::chrono::minutes m_{};
|
||||
std::chrono::seconds s_{};
|
||||
tz zone_{tz::local};
|
||||
|
||||
public:
|
||||
@ -124,7 +126,7 @@ public:
|
||||
// A Rule specifies one or more set of datetimes without using an offset.
|
||||
// Multiple dates are specified with multiple years. The years in effect
|
||||
// go from starting_year_ to ending_year_, inclusive. starting_year_ <=
|
||||
// ending_year_. save_ is ineffect for times from the specified time
|
||||
// ending_year_. save_ is in effect for times from the specified time
|
||||
// onward, including the specified time. When the specified time is
|
||||
// local, it uses the save_ from the chronologically previous Rule, or if
|
||||
// there is none, 0.
|
||||
@ -254,6 +256,55 @@ struct zonelet
|
||||
zonelet& operator=(const zonelet&) = delete;
|
||||
};
|
||||
|
||||
#else // USE_OS_TZDB
|
||||
|
||||
struct ttinfo
|
||||
{
|
||||
std::int32_t tt_gmtoff;
|
||||
unsigned char tt_isdst;
|
||||
unsigned char tt_abbrind;
|
||||
unsigned char pad[2];
|
||||
};
|
||||
|
||||
static_assert(sizeof(ttinfo) == 8, "");
|
||||
|
||||
struct expanded_ttinfo
|
||||
{
|
||||
std::chrono::seconds offset;
|
||||
std::string abbrev;
|
||||
bool is_dst;
|
||||
};
|
||||
|
||||
struct transition
|
||||
{
|
||||
sys_seconds timepoint;
|
||||
const expanded_ttinfo* info;
|
||||
|
||||
transition(sys_seconds tp, const expanded_ttinfo* i = nullptr)
|
||||
: timepoint(tp)
|
||||
, info(i)
|
||||
{}
|
||||
|
||||
friend
|
||||
std::ostream&
|
||||
operator<<(std::ostream& os, const transition& t)
|
||||
{
|
||||
using date::operator<<;
|
||||
os << t.timepoint << "Z ";
|
||||
if (t.info->offset >= std::chrono::seconds{0})
|
||||
os << '+';
|
||||
os << make_time(t.info->offset);
|
||||
if (t.info->is_dst > 0)
|
||||
os << " daylight ";
|
||||
else
|
||||
os << " standard ";
|
||||
os << t.info->abbrev;
|
||||
return os;
|
||||
}
|
||||
};
|
||||
|
||||
#endif // USE_OS_TZDB
|
||||
|
||||
} // namespace detail
|
||||
|
||||
} // namespace date
|
405
ios.mm
405
ios.mm
@ -1,405 +0,0 @@
|
||||
//
|
||||
// The MIT License (MIT)
|
||||
//
|
||||
// Copyright (c) 2016 Alexander Kormanovsky
|
||||
//
|
||||
// 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 "ios.h"
|
||||
|
||||
#if TARGET_OS_IPHONE
|
||||
|
||||
#include <Foundation/Foundation.h>
|
||||
|
||||
#include <iostream>
|
||||
#include <zlib.h>
|
||||
#include <sys/stat.h>
|
||||
|
||||
#ifndef TAR_DEBUG
|
||||
# define TAR_DEBUG 0
|
||||
#endif
|
||||
|
||||
#define INTERNAL_DIR "Library/tzdata"
|
||||
#define TARGZ_EXTENSION "tar.gz"
|
||||
|
||||
#define TAR_BLOCK_SIZE 512
|
||||
#define TAR_TYPE_POSITION 156
|
||||
#define TAR_NAME_POSITION 0
|
||||
#define TAR_NAME_SIZE 100
|
||||
#define TAR_SIZE_POSITION 124
|
||||
#define TAR_SIZE_SIZE 12
|
||||
|
||||
namespace date
|
||||
{
|
||||
namespace iOSUtils
|
||||
{
|
||||
|
||||
struct TarInfo
|
||||
{
|
||||
char objType;
|
||||
std::string objName;
|
||||
int64_t realContentSize; // writable size without padding zeroes
|
||||
int64_t blocksContentSize; // adjusted size to 512 bytes blocks
|
||||
bool success;
|
||||
};
|
||||
|
||||
char* convertCFStringRefPathToCStringPath(CFStringRef ref);
|
||||
bool extractTzdata(CFURLRef homeUrl, CFURLRef archiveUrl, std::string destPath);
|
||||
TarInfo getTarObjectInfo(CFReadStreamRef readStream, int64_t location);
|
||||
std::string getTarObject(CFReadStreamRef readStream, int64_t size);
|
||||
bool writeFile(CFURLRef tzdataUrl, std::string fileName, std::string data,
|
||||
int64_t realContentSize);
|
||||
|
||||
std::string
|
||||
date::iOSUtils::get_tzdata_path()
|
||||
{
|
||||
CFURLRef ref = CFCopyHomeDirectoryURL();
|
||||
CFStringRef homePath = CFURLCopyPath(CFCopyHomeDirectoryURL());
|
||||
std::string tzdata_path(std::string(convertCFStringRefPathToCStringPath(homePath)) +
|
||||
INTERNAL_DIR);
|
||||
|
||||
if (access(tzdata_path.c_str(), F_OK) == 0)
|
||||
{
|
||||
#if TAR_DEBUG
|
||||
printf("tzdata exists\n");
|
||||
#endif
|
||||
return tzdata_path;
|
||||
}
|
||||
|
||||
CFBundleRef mainBundle = CFBundleGetMainBundle();
|
||||
CFArrayRef paths = CFBundleCopyResourceURLsOfType(mainBundle, CFSTR(TARGZ_EXTENSION),
|
||||
NULL);
|
||||
|
||||
if (CFArrayGetCount(paths) != 0)
|
||||
{
|
||||
// get archive path, assume there is no other tar.gz in bundle
|
||||
CFURLRef archiveUrl = static_cast<CFURLRef>(CFArrayGetValueAtIndex(paths, 0));
|
||||
CFStringRef archiveName= CFURLCopyPath(archiveUrl);
|
||||
archiveUrl = CFBundleCopyResourceURL(mainBundle, archiveName, NULL, NULL);
|
||||
|
||||
extractTzdata(CFCopyHomeDirectoryURL(), archiveUrl, tzdata_path);
|
||||
}
|
||||
|
||||
return tzdata_path;
|
||||
}
|
||||
|
||||
char*
|
||||
convertCFStringRefPathToCStringPath(CFStringRef ref)
|
||||
{
|
||||
CFIndex bufferSize = CFStringGetMaximumSizeOfFileSystemRepresentation(ref);
|
||||
char *buffer = new char[bufferSize];
|
||||
CFStringGetFileSystemRepresentation(ref, buffer, bufferSize);
|
||||
return buffer;
|
||||
}
|
||||
|
||||
bool extractTzdata(CFURLRef homeUrl, CFURLRef archiveUrl, std::string destPath)
|
||||
{
|
||||
const char *TAR_TMP_PATH = "/tmp.tar";
|
||||
|
||||
// create Library path
|
||||
CFStringRef libraryStr = CFStringCreateWithCString(NULL, "Library",
|
||||
CFStringGetSystemEncoding());
|
||||
CFURLRef libraryUrl = CFURLCreateCopyAppendingPathComponent(kCFAllocatorDefault,
|
||||
homeUrl, libraryStr,
|
||||
false);
|
||||
|
||||
// create tzdata path
|
||||
CFStringRef tzdataPathRef = CFStringCreateWithCString(NULL, INTERNAL_DIR,
|
||||
CFStringGetSystemEncoding());
|
||||
CFURLRef tzdataPathUrl = CFURLCreateCopyAppendingPathComponent(NULL, homeUrl,
|
||||
tzdataPathRef, false);
|
||||
|
||||
// create src archive path
|
||||
CFStringRef archivePath = CFURLCopyPath(archiveUrl);
|
||||
gzFile tarFile = gzopen(convertCFStringRefPathToCStringPath(archivePath), "rb");
|
||||
|
||||
// create tar unpacking path
|
||||
CFStringRef tarName = CFStringCreateWithCString(NULL, TAR_TMP_PATH,
|
||||
CFStringGetSystemEncoding());
|
||||
CFURLRef tarUrl = CFURLCreateCopyAppendingPathComponent(NULL, libraryUrl, tarName,
|
||||
false);
|
||||
const char *tarPath = convertCFStringRefPathToCStringPath(CFURLCopyPath(tarUrl));
|
||||
|
||||
// create tzdata directory
|
||||
mkdir(destPath.c_str(), S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH);
|
||||
|
||||
// create stream
|
||||
CFWriteStreamRef writeStream = CFWriteStreamCreateWithFile(NULL, tarUrl);
|
||||
bool success = true;
|
||||
|
||||
if (!CFWriteStreamOpen(writeStream))
|
||||
{
|
||||
CFStreamError err = CFWriteStreamGetError(writeStream);
|
||||
|
||||
if (err.domain == kCFStreamErrorDomainPOSIX)
|
||||
{
|
||||
printf("kCFStreamErrorDomainPOSIX %i\n", err.error);
|
||||
}
|
||||
else if(err.domain == kCFStreamErrorDomainMacOSStatus)
|
||||
{
|
||||
printf("kCFStreamErrorDomainMacOSStatus %i\n", err.error);
|
||||
}
|
||||
|
||||
success = false;
|
||||
}
|
||||
|
||||
if (!success)
|
||||
{
|
||||
remove(tarPath);
|
||||
return false;
|
||||
}
|
||||
|
||||
// ======= extract tar ========
|
||||
|
||||
unsigned int bufferLength = 1024 * 256; // 256Kb
|
||||
void *buffer = malloc(bufferLength);
|
||||
|
||||
while (true)
|
||||
{
|
||||
int readBytes = gzread(tarFile, buffer, bufferLength);
|
||||
|
||||
if (readBytes > 0)
|
||||
{
|
||||
CFIndex writtenBytes = CFWriteStreamWrite(writeStream, (unsigned char*)buffer,
|
||||
readBytes);
|
||||
|
||||
if (writtenBytes < 0)
|
||||
{
|
||||
CFStreamError err = CFWriteStreamGetError(writeStream);
|
||||
printf("write stream error %i\n", err.error);
|
||||
success = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else if (readBytes == 0)
|
||||
{
|
||||
break;
|
||||
}
|
||||
else if (readBytes == -1)
|
||||
{
|
||||
printf("decompression failed\n");
|
||||
success = false;
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
printf("unexpected zlib state\n");
|
||||
success = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
CFWriteStreamClose(writeStream);
|
||||
CFRelease(writeStream);
|
||||
free(buffer);
|
||||
gzclose(tarFile);
|
||||
|
||||
if (!success)
|
||||
{
|
||||
remove(tarPath);
|
||||
return false;
|
||||
}
|
||||
|
||||
// ======== extract files =========
|
||||
|
||||
uint64_t location = 0; // Position in the file
|
||||
|
||||
// get file size
|
||||
struct stat stat_buf;
|
||||
int res = stat(tarPath, &stat_buf);
|
||||
if (res != 0)
|
||||
{
|
||||
printf("error file size\n");
|
||||
remove(tarPath);
|
||||
return false;
|
||||
}
|
||||
int64_t tarSize = stat_buf.st_size;
|
||||
|
||||
// create read stream
|
||||
CFReadStreamRef readStream = CFReadStreamCreateWithFile(kCFAllocatorDefault, tarUrl);
|
||||
|
||||
if (!CFReadStreamOpen(readStream))
|
||||
{
|
||||
CFStreamError err = CFReadStreamGetError(readStream);
|
||||
|
||||
if (err.domain == kCFStreamErrorDomainPOSIX)
|
||||
{
|
||||
printf("kCFStreamErrorDomainPOSIX %i", err.error);
|
||||
}
|
||||
else if(err.domain == kCFStreamErrorDomainMacOSStatus)
|
||||
{
|
||||
printf("kCFStreamErrorDomainMacOSStatus %i", err.error);
|
||||
}
|
||||
|
||||
success = false;
|
||||
}
|
||||
|
||||
if (!success)
|
||||
{
|
||||
CFRelease(readStream);
|
||||
remove(tarPath);
|
||||
return false;
|
||||
}
|
||||
|
||||
int count = 0;
|
||||
long size = 0;
|
||||
|
||||
// process files
|
||||
while (location < tarSize)
|
||||
{
|
||||
TarInfo info = getTarObjectInfo(readStream, location);
|
||||
|
||||
if (!info.success || info.realContentSize == 0)
|
||||
{
|
||||
break; // something wrong or all files are read
|
||||
}
|
||||
|
||||
switch (info.objType)
|
||||
{
|
||||
case '0': // file
|
||||
case '\0': //
|
||||
{
|
||||
std::string obj = getTarObject(readStream, info.blocksContentSize);
|
||||
#if TAR_DEBUG
|
||||
size += info.realContentSize;
|
||||
printf("#%i %s file size %lld written total %ld from %lld\n", ++count,
|
||||
info.objName.c_str(), info.realContentSize, size, tarSize);
|
||||
#endif
|
||||
writeFile(tzdataPathUrl, info.objName, obj, info.realContentSize);
|
||||
location += info.blocksContentSize;
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
CFReadStreamClose(readStream);
|
||||
CFRelease(readStream);
|
||||
|
||||
remove(tarPath);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
TarInfo
|
||||
getTarObjectInfo(CFReadStreamRef readStream, int64_t location)
|
||||
{
|
||||
int64_t length = TAR_BLOCK_SIZE;
|
||||
uint8_t buffer[length];
|
||||
|
||||
char type;
|
||||
char name[TAR_NAME_SIZE + 1];
|
||||
char sizeBuf[TAR_SIZE_SIZE + 1];
|
||||
CFIndex bytesRead;
|
||||
|
||||
bool avail = CFReadStreamHasBytesAvailable(readStream);
|
||||
|
||||
bytesRead = CFReadStreamRead(readStream, buffer, length);
|
||||
|
||||
if (bytesRead < 0)
|
||||
{
|
||||
CFStreamError err = CFReadStreamGetError(readStream);
|
||||
printf("error reading tar object info %i", err.error);
|
||||
return {false};
|
||||
}
|
||||
|
||||
memcpy(&type, &buffer[TAR_TYPE_POSITION], 1);
|
||||
|
||||
memset(&name, '\0', TAR_NAME_SIZE + 1);
|
||||
memcpy(&name, &buffer[TAR_NAME_POSITION], TAR_NAME_SIZE);
|
||||
|
||||
memset(&sizeBuf, '\0', TAR_SIZE_SIZE + 1);
|
||||
memcpy(&sizeBuf, &buffer[TAR_SIZE_POSITION], TAR_SIZE_SIZE);
|
||||
int64_t realSize = strtol(sizeBuf, NULL, 8);
|
||||
int64_t blocksSize = realSize + (TAR_BLOCK_SIZE - (realSize % TAR_BLOCK_SIZE));
|
||||
|
||||
return {type, std::string(name), realSize, blocksSize, true};
|
||||
}
|
||||
|
||||
std::string
|
||||
getTarObject(CFReadStreamRef readStream, int64_t size)
|
||||
{
|
||||
uint8_t buffer[size];
|
||||
|
||||
CFIndex bytesRead = CFReadStreamRead(readStream, buffer, size);
|
||||
|
||||
if (bytesRead < 0)
|
||||
{
|
||||
CFStreamError err = CFReadStreamGetError(readStream);
|
||||
printf("error reading tar object info %i", err.error);
|
||||
}
|
||||
|
||||
return std::string((char *)buffer);
|
||||
}
|
||||
|
||||
bool
|
||||
writeFile(CFURLRef tzdataUrl, std::string fileName, std::string data,
|
||||
int64_t realContentSize)
|
||||
{
|
||||
// create stream
|
||||
CFStringRef fileNameRef = CFStringCreateWithCString(NULL, fileName.c_str(),
|
||||
CFStringGetSystemEncoding());
|
||||
CFURLRef url = CFURLCreateCopyAppendingPathComponent(NULL, tzdataUrl, fileNameRef,
|
||||
false);
|
||||
CFWriteStreamRef writeStream = CFWriteStreamCreateWithFile(NULL, url);
|
||||
|
||||
// open stream
|
||||
if (!CFWriteStreamOpen(writeStream))
|
||||
{
|
||||
CFStreamError err = CFWriteStreamGetError(writeStream);
|
||||
|
||||
if (err.domain == kCFStreamErrorDomainPOSIX)
|
||||
{
|
||||
printf("kCFStreamErrorDomainPOSIX %i\n", err.error);
|
||||
}
|
||||
else if(err.domain == kCFStreamErrorDomainMacOSStatus)
|
||||
{
|
||||
printf("kCFStreamErrorDomainMacOSStatus %i\n", err.error);
|
||||
}
|
||||
|
||||
CFRelease(writeStream);
|
||||
return false;
|
||||
}
|
||||
|
||||
// trim empty space
|
||||
uint8_t trimmedData[realContentSize + 1];
|
||||
memset(&trimmedData, '\0', realContentSize);
|
||||
memcpy(&trimmedData, data.c_str(), realContentSize);
|
||||
|
||||
// write
|
||||
CFIndex writtenBytes = CFWriteStreamWrite(writeStream, trimmedData, realContentSize);
|
||||
|
||||
if (writtenBytes < 0)
|
||||
{
|
||||
CFStreamError err = CFWriteStreamGetError(writeStream);
|
||||
printf("write stream error %i\n", err.error);
|
||||
}
|
||||
|
||||
CFWriteStreamClose(writeStream);
|
||||
CFRelease(writeStream);
|
||||
writeStream = NULL;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
} // namespace iOSUtils
|
||||
} // namespace date
|
||||
|
||||
#endif // TARGET_OS_IPHONE
|
337
src/ios.mm
Normal file
337
src/ios.mm
Normal file
@ -0,0 +1,337 @@
|
||||
//
|
||||
// The MIT License (MIT)
|
||||
//
|
||||
// Copyright (c) 2016 Alexander Kormanovsky
|
||||
//
|
||||
// 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/ios.h"
|
||||
|
||||
#if TARGET_OS_IPHONE
|
||||
|
||||
#include <Foundation/Foundation.h>
|
||||
|
||||
#include <fstream>
|
||||
#include <zlib.h>
|
||||
#include <sys/stat.h>
|
||||
|
||||
#ifndef TAR_DEBUG
|
||||
# define TAR_DEBUG 0
|
||||
#endif
|
||||
|
||||
#define INTERNAL_DIR "Library"
|
||||
#define TZDATA_DIR "tzdata"
|
||||
#define TARGZ_EXTENSION "tar.gz"
|
||||
|
||||
#define TAR_BLOCK_SIZE 512
|
||||
#define TAR_TYPE_POSITION 156
|
||||
#define TAR_NAME_POSITION 0
|
||||
#define TAR_NAME_SIZE 100
|
||||
#define TAR_SIZE_POSITION 124
|
||||
#define TAR_SIZE_SIZE 12
|
||||
|
||||
namespace date
|
||||
{
|
||||
namespace iOSUtils
|
||||
{
|
||||
|
||||
struct TarInfo
|
||||
{
|
||||
char objType;
|
||||
std::string objName;
|
||||
size_t realContentSize; // writable size without padding zeroes
|
||||
size_t blocksContentSize; // adjusted size to 512 bytes blocks
|
||||
bool success;
|
||||
};
|
||||
|
||||
std::string convertCFStringRefPathToCStringPath(CFStringRef ref);
|
||||
bool extractTzdata(CFURLRef homeUrl, CFURLRef archiveUrl, std::string destPath);
|
||||
TarInfo getTarObjectInfo(std::ifstream &readStream);
|
||||
std::string getTarObject(std::ifstream &readStream, int64_t size);
|
||||
bool writeFile(const std::string &tzdataPath, const std::string &fileName,
|
||||
const std::string &data, size_t realContentSize);
|
||||
|
||||
std::string
|
||||
get_current_timezone()
|
||||
{
|
||||
CFTimeZoneRef tzRef = CFTimeZoneCopySystem();
|
||||
CFStringRef tzNameRef = CFTimeZoneGetName(tzRef);
|
||||
CFIndex bufferSize = CFStringGetLength(tzNameRef) + 1;
|
||||
char buffer[bufferSize];
|
||||
|
||||
if (CFStringGetCString(tzNameRef, buffer, bufferSize, kCFStringEncodingUTF8))
|
||||
{
|
||||
CFRelease(tzRef);
|
||||
return std::string(buffer);
|
||||
}
|
||||
|
||||
CFRelease(tzRef);
|
||||
|
||||
return "";
|
||||
}
|
||||
|
||||
std::string
|
||||
get_tzdata_path()
|
||||
{
|
||||
CFURLRef homeUrlRef = CFCopyHomeDirectoryURL();
|
||||
CFStringRef homePath = CFURLCopyPath(homeUrlRef);
|
||||
std::string path(std::string(convertCFStringRefPathToCStringPath(homePath)) +
|
||||
INTERNAL_DIR + "/" + TZDATA_DIR);
|
||||
std::string result_path(std::string(convertCFStringRefPathToCStringPath(homePath)) +
|
||||
INTERNAL_DIR);
|
||||
|
||||
if (access(path.c_str(), F_OK) == 0)
|
||||
{
|
||||
#if TAR_DEBUG
|
||||
printf("tzdata dir exists\n");
|
||||
#endif
|
||||
CFRelease(homeUrlRef);
|
||||
CFRelease(homePath);
|
||||
|
||||
return result_path;
|
||||
}
|
||||
|
||||
CFBundleRef mainBundle = CFBundleGetMainBundle();
|
||||
CFArrayRef paths = CFBundleCopyResourceURLsOfType(mainBundle, CFSTR(TARGZ_EXTENSION),
|
||||
NULL);
|
||||
|
||||
if (CFArrayGetCount(paths) != 0)
|
||||
{
|
||||
// get archive path, assume there is no other tar.gz in bundle
|
||||
CFURLRef archiveUrl = static_cast<CFURLRef>(CFArrayGetValueAtIndex(paths, 0));
|
||||
CFStringRef archiveName = CFURLCopyPath(archiveUrl);
|
||||
archiveUrl = CFBundleCopyResourceURL(mainBundle, archiveName, NULL, NULL);
|
||||
|
||||
extractTzdata(homeUrlRef, archiveUrl, path);
|
||||
|
||||
CFRelease(archiveUrl);
|
||||
CFRelease(archiveName);
|
||||
}
|
||||
|
||||
CFRelease(homeUrlRef);
|
||||
CFRelease(homePath);
|
||||
CFRelease(paths);
|
||||
|
||||
return result_path;
|
||||
}
|
||||
|
||||
std::string
|
||||
convertCFStringRefPathToCStringPath(CFStringRef ref)
|
||||
{
|
||||
CFIndex bufferSize = CFStringGetMaximumSizeOfFileSystemRepresentation(ref);
|
||||
char *buffer = new char[bufferSize];
|
||||
CFStringGetFileSystemRepresentation(ref, buffer, bufferSize);
|
||||
auto result = std::string(buffer);
|
||||
delete[] buffer;
|
||||
return result;
|
||||
}
|
||||
|
||||
bool
|
||||
extractTzdata(CFURLRef homeUrl, CFURLRef archiveUrl, std::string destPath)
|
||||
{
|
||||
std::string TAR_TMP_PATH = "/tmp.tar";
|
||||
|
||||
CFStringRef homeStringRef = CFURLCopyPath(homeUrl);
|
||||
auto homePath = convertCFStringRefPathToCStringPath(homeStringRef);
|
||||
CFRelease(homeStringRef);
|
||||
|
||||
CFStringRef archiveStringRef = CFURLCopyPath(archiveUrl);
|
||||
auto archivePath = convertCFStringRefPathToCStringPath(archiveStringRef);
|
||||
CFRelease(archiveStringRef);
|
||||
|
||||
// create Library path
|
||||
auto libraryPath = homePath + INTERNAL_DIR;
|
||||
|
||||
// create tzdata path
|
||||
auto tzdataPath = libraryPath + "/" + TZDATA_DIR;
|
||||
|
||||
// -- replace %20 with " "
|
||||
const std::string search = "%20";
|
||||
const std::string replacement = " ";
|
||||
size_t pos = 0;
|
||||
|
||||
while ((pos = archivePath.find(search, pos)) != std::string::npos) {
|
||||
archivePath.replace(pos, search.length(), replacement);
|
||||
pos += replacement.length();
|
||||
}
|
||||
|
||||
gzFile tarFile = gzopen(archivePath.c_str(), "rb");
|
||||
|
||||
// create tar unpacking path
|
||||
auto tarPath = libraryPath + TAR_TMP_PATH;
|
||||
|
||||
// create tzdata directory
|
||||
mkdir(destPath.c_str(), S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH);
|
||||
|
||||
// ======= extract tar ========
|
||||
|
||||
std::ofstream os(tarPath.c_str(), std::ofstream::out | std::ofstream::app);
|
||||
unsigned int bufferLength = 1024 * 256; // 256Kb
|
||||
unsigned char *buffer = (unsigned char *)malloc(bufferLength);
|
||||
bool success = true;
|
||||
|
||||
while (true)
|
||||
{
|
||||
int readBytes = gzread(tarFile, buffer, bufferLength);
|
||||
|
||||
if (readBytes > 0)
|
||||
{
|
||||
os.write((char *) &buffer[0], readBytes);
|
||||
}
|
||||
else
|
||||
if (readBytes == 0)
|
||||
{
|
||||
break;
|
||||
}
|
||||
else
|
||||
if (readBytes == -1)
|
||||
{
|
||||
printf("decompression failed\n");
|
||||
success = false;
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
printf("unexpected zlib state\n");
|
||||
success = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
os.close();
|
||||
free(buffer);
|
||||
gzclose(tarFile);
|
||||
|
||||
if (!success)
|
||||
{
|
||||
remove(tarPath.c_str());
|
||||
return false;
|
||||
}
|
||||
|
||||
// ======== extract files =========
|
||||
|
||||
uint64_t location = 0; // Position in the file
|
||||
|
||||
// get file size
|
||||
struct stat stat_buf;
|
||||
int res = stat(tarPath.c_str(), &stat_buf);
|
||||
if (res != 0)
|
||||
{
|
||||
printf("error file size\n");
|
||||
remove(tarPath.c_str());
|
||||
return false;
|
||||
}
|
||||
int64_t tarSize = stat_buf.st_size;
|
||||
|
||||
// create read stream
|
||||
std::ifstream is(tarPath.c_str(), std::ifstream::in | std::ifstream::binary);
|
||||
|
||||
// process files
|
||||
while (location < tarSize)
|
||||
{
|
||||
TarInfo info = getTarObjectInfo(is);
|
||||
|
||||
if (!info.success || info.realContentSize == 0)
|
||||
{
|
||||
break; // something wrong or all files are read
|
||||
}
|
||||
|
||||
switch (info.objType)
|
||||
{
|
||||
case '0': // file
|
||||
case '\0': //
|
||||
{
|
||||
std::string obj = getTarObject(is, info.blocksContentSize);
|
||||
#if TAR_DEBUG
|
||||
size += info.realContentSize;
|
||||
printf("#%i %s file size %lld written total %ld from %lld\n", ++count,
|
||||
info.objName.c_str(), info.realContentSize, size, tarSize);
|
||||
#endif
|
||||
writeFile(tzdataPath, info.objName, obj, info.realContentSize);
|
||||
location += info.blocksContentSize;
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
remove(tarPath.c_str());
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
TarInfo
|
||||
getTarObjectInfo(std::ifstream &readStream)
|
||||
{
|
||||
int64_t length = TAR_BLOCK_SIZE;
|
||||
char buffer[length];
|
||||
char type;
|
||||
char name[TAR_NAME_SIZE + 1];
|
||||
char sizeBuf[TAR_SIZE_SIZE + 1];
|
||||
|
||||
readStream.read(buffer, length);
|
||||
|
||||
memcpy(&type, &buffer[TAR_TYPE_POSITION], 1);
|
||||
|
||||
memset(&name, '\0', TAR_NAME_SIZE + 1);
|
||||
memcpy(&name, &buffer[TAR_NAME_POSITION], TAR_NAME_SIZE);
|
||||
|
||||
memset(&sizeBuf, '\0', TAR_SIZE_SIZE + 1);
|
||||
memcpy(&sizeBuf, &buffer[TAR_SIZE_POSITION], TAR_SIZE_SIZE);
|
||||
size_t realSize = strtol(sizeBuf, NULL, 8);
|
||||
size_t blocksSize = realSize + (TAR_BLOCK_SIZE - (realSize % TAR_BLOCK_SIZE));
|
||||
|
||||
return {type, std::string(name), realSize, blocksSize, true};
|
||||
}
|
||||
|
||||
std::string
|
||||
getTarObject(std::ifstream &readStream, int64_t size)
|
||||
{
|
||||
char buffer[size];
|
||||
readStream.read(buffer, size);
|
||||
return std::string(buffer);
|
||||
}
|
||||
|
||||
bool
|
||||
writeFile(const std::string &tzdataPath, const std::string &fileName, const std::string &data,
|
||||
size_t realContentSize)
|
||||
{
|
||||
std::ofstream os(tzdataPath + "/" + fileName, std::ofstream::out | std::ofstream::binary);
|
||||
|
||||
if (!os) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// trim empty space
|
||||
char trimmedData[realContentSize + 1];
|
||||
memset(&trimmedData, '\0', realContentSize);
|
||||
memcpy(&trimmedData, data.c_str(), realContentSize);
|
||||
|
||||
// write
|
||||
os.write(trimmedData, realContentSize);
|
||||
os.close();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
} // namespace iOSUtils
|
||||
} // namespace date
|
||||
|
||||
#endif // TARGET_OS_IPHONE
|
2274
tz.cpp → src/tz.cpp
2274
tz.cpp → src/tz.cpp
File diff suppressed because it is too large
Load Diff
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
|
||||
}
|
213
test/clock_cast_test/custom_clock.pass.cpp
Normal file
213
test/clock_cast_test/custom_clock.pass.cpp
Normal file
@ -0,0 +1,213 @@
|
||||
// The MIT License (MIT)
|
||||
//
|
||||
// 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
|
||||
// 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>
|
||||
|
||||
//used to count number of conversion
|
||||
int conversions = 0;
|
||||
|
||||
//to/from impl
|
||||
struct mil_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<mil_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>
|
||||
to_sys(std::chrono::time_point<mil_clock, Duration> const& tp)
|
||||
{
|
||||
++conversions;
|
||||
return epoch + tp.time_since_epoch();
|
||||
}
|
||||
|
||||
template<typename Duration>
|
||||
static
|
||||
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, 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());
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
date::sys_days const mil_clock::epoch;
|
||||
|
||||
// traits example
|
||||
struct s2s_clock
|
||||
{
|
||||
using duration = std::chrono::system_clock::duration;
|
||||
using rep = duration::rep;
|
||||
using period = duration::period;
|
||||
using time_point = std::chrono::time_point<s2s_clock, duration>;
|
||||
|
||||
template<typename Duration>
|
||||
static
|
||||
std::chrono::time_point<std::chrono::system_clock, Duration>
|
||||
to_sys(std::chrono::time_point<s2s_clock, Duration> const& tp)
|
||||
{
|
||||
++conversions;
|
||||
return std::chrono::time_point<std::chrono::system_clock, Duration>(tp.time_since_epoch());
|
||||
}
|
||||
|
||||
template<typename Duration>
|
||||
static
|
||||
std::chrono::time_point<s2s_clock, Duration>
|
||||
from_sys(std::chrono::time_point<std::chrono::system_clock, Duration> const& tp)
|
||||
{
|
||||
++conversions;
|
||||
return std::chrono::time_point<s2s_clock, Duration>(tp.time_since_epoch());
|
||||
}
|
||||
|
||||
static time_point now()
|
||||
{
|
||||
return from_sys(std::chrono::system_clock::now());
|
||||
}
|
||||
};
|
||||
|
||||
namespace date
|
||||
{
|
||||
template<>
|
||||
struct clock_time_conversion<mil_clock, s2s_clock>
|
||||
{
|
||||
template<typename Duration>
|
||||
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, typename std::common_type<Duration, date::days>::type>;
|
||||
return res(tp.time_since_epoch() - mil_clock::epoch.time_since_epoch());
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
int
|
||||
main()
|
||||
{
|
||||
using namespace date;
|
||||
using sys_clock = std::chrono::system_clock;
|
||||
|
||||
// self
|
||||
{
|
||||
sys_days st(1997_y/dec/12);
|
||||
auto mt = mil_clock::from_sys(st);
|
||||
|
||||
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);
|
||||
auto mt = mil_clock::from_sys(st);
|
||||
|
||||
assert(clock_cast<mil_clock>(st) == mt);
|
||||
assert(clock_cast<sys_clock>(mt) == st);
|
||||
}
|
||||
|
||||
// mil <-> utc
|
||||
{
|
||||
sys_days st(1997_y/dec/12);
|
||||
auto mt = mil_clock::from_sys(st);
|
||||
auto ut = utc_clock::from_sys(st);
|
||||
|
||||
assert(clock_cast<mil_clock>(ut) == mt);
|
||||
assert(clock_cast<utc_clock>(mt) == ut);
|
||||
}
|
||||
|
||||
// mil <-> tai
|
||||
{
|
||||
sys_days st(1997_y/dec/12);
|
||||
auto mt = mil_clock::from_sys(st);
|
||||
auto ut = utc_clock::from_sys(st);
|
||||
auto tt = tai_clock::from_utc(ut);
|
||||
|
||||
assert(clock_cast<tai_clock>(mt) == tt);
|
||||
assert(clock_cast<mil_clock>(tt) == mt);
|
||||
}
|
||||
|
||||
// mil <-> gps
|
||||
{
|
||||
sys_days st(1997_y/dec/12);
|
||||
auto mt = mil_clock::from_sys(st);
|
||||
auto ut = utc_clock::from_sys(st);
|
||||
auto gt = gps_clock::from_utc(ut);
|
||||
|
||||
assert(clock_cast<gps_clock>(mt) == gt);
|
||||
assert(clock_cast<mil_clock>(gt) == mt);
|
||||
}
|
||||
|
||||
// s2s -> mil
|
||||
{
|
||||
sys_days st(1997_y/dec/12);
|
||||
auto mt = mil_clock::from_sys(st);
|
||||
auto s2t = s2s_clock::from_sys(st);
|
||||
|
||||
//direct trait conversion
|
||||
conversions = 0;
|
||||
assert(clock_cast<mil_clock>(s2t) == mt);
|
||||
assert(conversions == 1);
|
||||
|
||||
//uses sys_clock
|
||||
conversions = 0;
|
||||
assert(clock_cast<s2s_clock>(mt) == s2t);
|
||||
assert(conversions == 2);
|
||||
}
|
||||
}
|
90
test/clock_cast_test/deprecated.pass.cpp
Normal file
90
test/clock_cast_test/deprecated.pass.cpp
Normal file
@ -0,0 +1,90 @@
|
||||
// The MIT License (MIT)
|
||||
//
|
||||
// Copyright (c) 2017 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 <cassert>
|
||||
|
||||
int
|
||||
main()
|
||||
{
|
||||
using namespace date;
|
||||
|
||||
// sys <-> utc
|
||||
{
|
||||
sys_days st(1997_y/dec/12);
|
||||
auto ut = utc_clock::from_sys(st);
|
||||
|
||||
assert(to_utc_time(st) == ut);
|
||||
assert(to_sys_time(ut) == st);
|
||||
}
|
||||
|
||||
// tai <-> utc
|
||||
{
|
||||
sys_days st(1997_y/dec/12);
|
||||
auto ut = utc_clock::from_sys(st);
|
||||
auto tt = tai_clock::from_utc(ut);
|
||||
|
||||
assert(to_tai_time(ut) == tt);
|
||||
assert(to_utc_time(tt) == ut);
|
||||
}
|
||||
|
||||
// tai <-> sys
|
||||
{
|
||||
sys_days st(1997_y/dec/12);
|
||||
auto ut = utc_clock::from_sys(st);
|
||||
auto tt = tai_clock::from_utc(ut);
|
||||
|
||||
assert(to_tai_time(st) == tt);
|
||||
assert(to_sys_time(tt) == st);
|
||||
}
|
||||
|
||||
// gps <-> utc
|
||||
{
|
||||
sys_days st(1997_y/dec/12);
|
||||
auto ut = utc_clock::from_sys(st);
|
||||
auto gt = gps_clock::from_utc(ut);
|
||||
|
||||
assert(to_gps_time(ut) == gt);
|
||||
assert(to_utc_time(gt) == ut);
|
||||
}
|
||||
|
||||
// gps <-> sys
|
||||
{
|
||||
sys_days st(1997_y/dec/12);
|
||||
auto ut = utc_clock::from_sys(st);
|
||||
auto gt = gps_clock::from_utc(ut);
|
||||
|
||||
assert(to_gps_time(st) == gt);
|
||||
assert(to_sys_time(gt) == st);
|
||||
}
|
||||
|
||||
// tai <-> gps
|
||||
{
|
||||
sys_days st(1997_y/dec/12);
|
||||
auto ut = utc_clock::from_sys(st);
|
||||
auto tt = tai_clock::from_utc(ut);
|
||||
auto gt = gps_clock::from_utc(ut);
|
||||
|
||||
assert(to_gps_time(tt) == gt);
|
||||
assert(to_tai_time(gt) == tt);
|
||||
}
|
||||
}
|
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);
|
||||
}
|
||||
|
||||
}
|
251
test/clock_cast_test/noncastable.pass.cpp
Normal file
251
test/clock_cast_test/noncastable.pass.cpp
Normal file
@ -0,0 +1,251 @@
|
||||
// The MIT License (MIT)
|
||||
//
|
||||
// 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
|
||||
// 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>
|
||||
#include <cassert>
|
||||
|
||||
template<typename SourceClock, typename DestClock, typename = void>
|
||||
struct is_clock_castable
|
||||
: std::false_type
|
||||
{};
|
||||
|
||||
template<typename SourceClock, typename DestClock>
|
||||
struct is_clock_castable<SourceClock, DestClock, decltype(date::clock_cast<DestClock>(typename SourceClock::time_point()), void())>
|
||||
: std::true_type
|
||||
{};
|
||||
|
||||
|
||||
//Clock based on steady clock, not related to wall time (sys_clock/utc_clock)
|
||||
struct steady_based_clock
|
||||
{
|
||||
using duration = std::chrono::steady_clock::duration;
|
||||
using rep = duration::rep;
|
||||
using period = duration::period;
|
||||
using time_point = std::chrono::time_point<steady_based_clock, duration>;
|
||||
|
||||
static time_point now()
|
||||
{
|
||||
return time_point(std::chrono::steady_clock::now().time_since_epoch());
|
||||
}
|
||||
};
|
||||
|
||||
//Traits that allow conversion between steady_clock and steady_based clock
|
||||
//Does not use wall-time clocks as rally (sys/utc)
|
||||
namespace date
|
||||
{
|
||||
template<>
|
||||
struct clock_time_conversion<std::chrono::steady_clock, steady_based_clock>
|
||||
{
|
||||
template<typename Duration>
|
||||
std::chrono::time_point<std::chrono::steady_clock, Duration>
|
||||
operator()(std::chrono::time_point<steady_based_clock, Duration> const& tp) const
|
||||
{
|
||||
using res = std::chrono::time_point<std::chrono::steady_clock, Duration>;
|
||||
return res(tp.time_since_epoch());
|
||||
}
|
||||
};
|
||||
|
||||
template<>
|
||||
struct clock_time_conversion<steady_based_clock, std::chrono::steady_clock>
|
||||
{
|
||||
template<typename Duration>
|
||||
std::chrono::time_point<steady_based_clock, Duration>
|
||||
operator()(std::chrono::time_point<std::chrono::steady_clock, Duration> const& tp) const
|
||||
{
|
||||
using res = std::chrono::time_point<steady_based_clock, Duration>;
|
||||
return res(tp.time_since_epoch());
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
//Ambigous clocks both providing to/from_sys and to/from_utc
|
||||
//They are mock_ups just returning zero time_point
|
||||
struct amb1_clock
|
||||
{
|
||||
using duration = std::chrono::seconds;
|
||||
using rep = duration::rep;
|
||||
using period = duration::period;
|
||||
using time_point = std::chrono::time_point<amb1_clock>;
|
||||
|
||||
static time_point now()
|
||||
{
|
||||
return {};
|
||||
}
|
||||
|
||||
template<typename Duration>
|
||||
static
|
||||
std::chrono::time_point<std::chrono::system_clock, Duration>
|
||||
to_sys(std::chrono::time_point<amb1_clock, Duration> const&)
|
||||
{
|
||||
return {};
|
||||
}
|
||||
|
||||
template<typename Duration>
|
||||
static
|
||||
std::chrono::time_point<amb1_clock, Duration>
|
||||
from_sys(std::chrono::time_point<std::chrono::system_clock, Duration> const&)
|
||||
{
|
||||
return {};
|
||||
}
|
||||
|
||||
template<typename Duration>
|
||||
static
|
||||
std::chrono::time_point<date::utc_clock, Duration>
|
||||
to_utc(std::chrono::time_point<amb1_clock, Duration> const&)
|
||||
{
|
||||
return {};
|
||||
}
|
||||
|
||||
template<typename Duration>
|
||||
static
|
||||
std::chrono::time_point<amb1_clock, Duration>
|
||||
from_utc(std::chrono::time_point<date::utc_clock, Duration> const&)
|
||||
{
|
||||
return {};
|
||||
}
|
||||
};
|
||||
|
||||
struct amb2_clock
|
||||
{
|
||||
using duration = std::chrono::seconds;
|
||||
using rep = duration::rep;
|
||||
using period = duration::period;
|
||||
using time_point = std::chrono::time_point<amb2_clock>;
|
||||
|
||||
static time_point now()
|
||||
{
|
||||
return {};
|
||||
}
|
||||
|
||||
template<typename Duration>
|
||||
static
|
||||
std::chrono::time_point<std::chrono::system_clock, Duration>
|
||||
to_sys(std::chrono::time_point<amb2_clock, Duration> const&)
|
||||
{
|
||||
return {};
|
||||
}
|
||||
|
||||
template<typename Duration>
|
||||
static
|
||||
std::chrono::time_point<amb2_clock, Duration>
|
||||
from_sys(std::chrono::time_point<std::chrono::system_clock, Duration> const&)
|
||||
{
|
||||
return {};
|
||||
}
|
||||
|
||||
template<typename Duration>
|
||||
static
|
||||
std::chrono::time_point<date::utc_clock, Duration>
|
||||
to_utc(std::chrono::time_point<amb2_clock, Duration> const&)
|
||||
{
|
||||
return {};
|
||||
}
|
||||
|
||||
template<typename Duration>
|
||||
static
|
||||
std::chrono::time_point<amb2_clock, Duration>
|
||||
from_utc(std::chrono::time_point<date::utc_clock, Duration> const&)
|
||||
{
|
||||
return {};
|
||||
}
|
||||
};
|
||||
|
||||
namespace date
|
||||
{
|
||||
//Disambiguates that sys_clock is preffered
|
||||
template<>
|
||||
struct clock_time_conversion<amb1_clock, amb2_clock>
|
||||
{
|
||||
template<typename Duration>
|
||||
std::chrono::time_point<amb1_clock, Duration>
|
||||
operator()(std::chrono::time_point<amb2_clock, Duration> const& tp) const
|
||||
{
|
||||
return amb1_clock::from_sys(amb2_clock::to_sys(tp));
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
int
|
||||
main()
|
||||
{
|
||||
using namespace date;
|
||||
using namespace std::chrono;
|
||||
using sys_clock = std::chrono::system_clock;
|
||||
|
||||
//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");
|
||||
static_assert(!is_clock_castable<utc_clock, steady_clock>::value, "utc_clock -> steady_clock");
|
||||
static_assert(!is_clock_castable<steady_clock, tai_clock>::value, "steady_clock -> tai_clock");
|
||||
static_assert(!is_clock_castable<tai_clock, steady_clock>::value, "tai_clock -> steady_clock");
|
||||
|
||||
//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");
|
||||
static_assert(!is_clock_castable<utc_clock, steady_based_clock>::value, "utc_clock -> steady_based_clock");
|
||||
static_assert(!is_clock_castable<steady_based_clock, tai_clock>::value, "steady_based_clock -> tai_clock");
|
||||
static_assert(!is_clock_castable<tai_clock, steady_based_clock>::value, "tai_clock -> steady_based_clock");
|
||||
|
||||
//steady_based <-> steady_clock
|
||||
{
|
||||
auto s1 = steady_clock::time_point(steady_clock::duration(200));
|
||||
auto s2 = steady_based_clock::time_point(steady_based_clock::duration(200));
|
||||
|
||||
assert(clock_cast<steady_based_clock>(s1) == s2);
|
||||
assert(clock_cast<steady_clock>(s2) == s1);
|
||||
}
|
||||
|
||||
//ambX <-> sys/utc works as one rally can be used in each case, or one lead to quicker conversione
|
||||
static_assert(is_clock_castable<amb1_clock, amb1_clock>::value, "amb1_clock -> amb1_clock");
|
||||
static_assert(is_clock_castable<amb1_clock, sys_clock>::value, "amb1_clock -> sys_clock");
|
||||
static_assert(is_clock_castable<sys_clock, amb1_clock>::value, "sys_clock -> amb1_clock");
|
||||
static_assert(is_clock_castable<amb1_clock, utc_clock>::value, "amb1_clock -> utc_clock");
|
||||
static_assert(is_clock_castable<utc_clock, amb1_clock>::value, "utc_clock -> amb1_clock");
|
||||
static_assert(is_clock_castable<amb1_clock, tai_clock>::value, "amb1_clock -> tai_clock");
|
||||
static_assert(is_clock_castable<tai_clock, amb1_clock>::value, "tai_clock -> amb1_clock");
|
||||
static_assert(is_clock_castable<amb1_clock, tai_clock>::value, "amb1_clock -> tai_clock");
|
||||
static_assert(is_clock_castable<gps_clock, amb1_clock>::value, "gps_clock -> amb1_clock");
|
||||
static_assert(is_clock_castable<amb2_clock, amb2_clock>::value, "amb2_clock -> amb2_clock");
|
||||
static_assert(is_clock_castable<amb2_clock, sys_clock>::value, "amb2_clock -> sys_clock");
|
||||
static_assert(is_clock_castable<sys_clock, amb2_clock>::value, "sys_clock -> amb2_clock");
|
||||
static_assert(is_clock_castable<amb2_clock, utc_clock>::value, "amb2_clock -> utc_clock");
|
||||
static_assert(is_clock_castable<utc_clock, amb2_clock>::value, "utc_clock -> amb2_clock");
|
||||
static_assert(is_clock_castable<amb2_clock, tai_clock>::value, "amb2_clock -> tai_clock");
|
||||
static_assert(is_clock_castable<tai_clock, amb2_clock>::value, "tai_clock -> amb2_clock");
|
||||
static_assert(is_clock_castable<amb2_clock, tai_clock>::value, "amb2_clock -> tai_clock");
|
||||
static_assert(is_clock_castable<gps_clock, amb2_clock>::value, "gps_clock -> amb2_clock");
|
||||
|
||||
//amb1 -> amb2: ambigous because can either go trough sys_clock or utc_clock
|
||||
static_assert(!is_clock_castable<amb1_clock, amb2_clock>::value, "amb1_clock -> amb2_clock");
|
||||
|
||||
//amb2 -> amb1: disambiguated via trait specialization
|
||||
static_assert(is_clock_castable<amb2_clock, amb1_clock>::value, "amb2_clock -> amb1_clock");
|
||||
}
|
102
test/clock_cast_test/normal_clocks.pass.cpp
Normal file
102
test/clock_cast_test/normal_clocks.pass.cpp
Normal file
@ -0,0 +1,102 @@
|
||||
// The MIT License (MIT)
|
||||
//
|
||||
// Copyright (c) 2017 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 <cassert>
|
||||
|
||||
int
|
||||
main()
|
||||
{
|
||||
using namespace date;
|
||||
using sys_clock = std::chrono::system_clock;
|
||||
|
||||
// self
|
||||
{
|
||||
sys_days st(1997_y/dec/12);
|
||||
auto ut = utc_clock::from_sys(st);
|
||||
auto tt = tai_clock::from_utc(ut);
|
||||
|
||||
assert(clock_cast<sys_clock>(st) == st);
|
||||
assert(clock_cast<utc_clock>(ut) == ut);
|
||||
assert(clock_cast<tai_clock>(tt) == tt);
|
||||
}
|
||||
|
||||
// sys <-> utc
|
||||
{
|
||||
sys_days st(1997_y/dec/12);
|
||||
auto ut = utc_clock::from_sys(st);
|
||||
|
||||
assert(clock_cast<utc_clock>(st) == ut);
|
||||
assert(clock_cast<sys_clock>(ut) == st);
|
||||
}
|
||||
|
||||
// tai <-> utc
|
||||
{
|
||||
sys_days st(1997_y/dec/12);
|
||||
auto ut = utc_clock::from_sys(st);
|
||||
auto tt = tai_clock::from_utc(ut);
|
||||
|
||||
assert(clock_cast<tai_clock>(ut) == tt);
|
||||
assert(clock_cast<utc_clock>(tt) == ut);
|
||||
}
|
||||
|
||||
// tai <-> sys
|
||||
{
|
||||
sys_days st(1997_y/dec/12);
|
||||
auto ut = utc_clock::from_sys(st);
|
||||
auto tt = tai_clock::from_utc(ut);
|
||||
|
||||
assert(clock_cast<tai_clock>(st) == tt);
|
||||
assert(clock_cast<sys_clock>(tt) == st);
|
||||
}
|
||||
|
||||
// gps <-> utc
|
||||
{
|
||||
sys_days st(1997_y/dec/12);
|
||||
auto ut = utc_clock::from_sys(st);
|
||||
auto gt = gps_clock::from_utc(ut);
|
||||
|
||||
assert(clock_cast<gps_clock>(ut) == gt);
|
||||
assert(clock_cast<utc_clock>(gt) == ut);
|
||||
}
|
||||
|
||||
// gps <-> sys
|
||||
{
|
||||
sys_days st(1997_y/dec/12);
|
||||
auto ut = utc_clock::from_sys(st);
|
||||
auto gt = gps_clock::from_utc(ut);
|
||||
|
||||
assert(clock_cast<gps_clock>(st) == gt);
|
||||
assert(clock_cast<sys_clock>(gt) == st);
|
||||
}
|
||||
|
||||
// tai <-> gps
|
||||
{
|
||||
sys_days st(1997_y/dec/12);
|
||||
auto ut = utc_clock::from_sys(st);
|
||||
auto tt = tai_clock::from_utc(ut);
|
||||
auto gt = gps_clock::from_utc(ut);
|
||||
|
||||
assert(clock_cast<gps_clock>(tt) == gt);
|
||||
assert(clock_cast<tai_clock>(gt) == tt);
|
||||
}
|
||||
}
|
49
test/clock_cast_test/to_sys_return_int.fail.cpp
Normal file
49
test/clock_cast_test/to_sys_return_int.fail.cpp
Normal file
@ -0,0 +1,49 @@
|
||||
// The MIT License (MIT)
|
||||
//
|
||||
// Copyright (c) 2017 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"
|
||||
|
||||
struct bad_clock
|
||||
{
|
||||
using duration = std::chrono::system_clock::duration;
|
||||
using rep = duration::rep;
|
||||
using period = duration::period;
|
||||
using time_point = std::chrono::time_point<bad_clock, duration>;
|
||||
|
||||
template<typename Duration>
|
||||
static
|
||||
int
|
||||
to_sys(std::chrono::time_point<bad_clock, Duration> const& tp)
|
||||
{
|
||||
return tp.time_since_epoch().count();
|
||||
}
|
||||
};
|
||||
|
||||
int
|
||||
main()
|
||||
{
|
||||
using namespace date;
|
||||
using sys_clock = std::chrono::system_clock;
|
||||
|
||||
auto bt = bad_clock::time_point();
|
||||
clock_cast<sys_clock>(bt);
|
||||
}
|
51
test/clock_cast_test/to_sys_return_reference.fail.cpp
Normal file
51
test/clock_cast_test/to_sys_return_reference.fail.cpp
Normal file
@ -0,0 +1,51 @@
|
||||
// The MIT License (MIT)
|
||||
//
|
||||
// Copyright (c) 2017 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"
|
||||
|
||||
struct bad_clock
|
||||
{
|
||||
using duration = std::chrono::system_clock::duration;
|
||||
using rep = duration::rep;
|
||||
using period = duration::period;
|
||||
using time_point = std::chrono::time_point<bad_clock, duration>;
|
||||
|
||||
template<typename Duration>
|
||||
static
|
||||
date::sys_time<Duration> const&
|
||||
to_sys(std::chrono::time_point<bad_clock, Duration> const& tp)
|
||||
{
|
||||
static date::sys_time<Duration> val;
|
||||
val = date::sys_time<Duration>(tp.time_since_epoch());
|
||||
return val;
|
||||
}
|
||||
};
|
||||
|
||||
int
|
||||
main()
|
||||
{
|
||||
using namespace date;
|
||||
using sys_clock = std::chrono::system_clock;
|
||||
|
||||
auto bt = bad_clock::time_point();
|
||||
clock_cast<sys_clock>(bt);
|
||||
}
|
49
test/clock_cast_test/to_sys_return_utc_time.fail.cpp
Normal file
49
test/clock_cast_test/to_sys_return_utc_time.fail.cpp
Normal file
@ -0,0 +1,49 @@
|
||||
// The MIT License (MIT)
|
||||
//
|
||||
// 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
|
||||
// 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"
|
||||
|
||||
struct bad_clock
|
||||
{
|
||||
using duration = std::chrono::system_clock::duration;
|
||||
using rep = duration::rep;
|
||||
using period = duration::period;
|
||||
using time_point = std::chrono::time_point<bad_clock, duration>;
|
||||
|
||||
template<typename Duration>
|
||||
static
|
||||
date::utc_time<Duration>
|
||||
to_sys(std::chrono::time_point<bad_clock, Duration> const& tp)
|
||||
{
|
||||
return date::utc_time<Duration>(tp.time_since_epoch());
|
||||
}
|
||||
};
|
||||
|
||||
int
|
||||
main()
|
||||
{
|
||||
using namespace date;
|
||||
using sys_clock = std::chrono::system_clock;
|
||||
|
||||
auto bt = bad_clock::time_point();
|
||||
clock_cast<sys_clock>(bt);
|
||||
}
|
141
test/date_test/detail/decimal_format_seconds.pass.cpp
Normal file
141
test/date_test/detail/decimal_format_seconds.pass.cpp
Normal file
@ -0,0 +1,141 @@
|
||||
// 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 <class Duration>
|
||||
// class decimal_format_seconds
|
||||
// {
|
||||
// using CT = typename std::common_type<Duration, std::chrono::seconds>::type;
|
||||
// using rep = typename CT::rep;
|
||||
// public:
|
||||
// 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_;
|
||||
//
|
||||
// public:
|
||||
// constexpr explicit decimal_format_seconds(const Duration& d) noexcept;
|
||||
//
|
||||
// constexpr std::chrono::seconds& seconds() noexcept;
|
||||
// constexpr std::chrono::seconds seconds() const noexcept;
|
||||
// constexpr precision subseconds() const noexcept;
|
||||
// constexpr precision to_duration() const noexcept;
|
||||
//
|
||||
// template <class CharT, class Traits>
|
||||
// friend
|
||||
// std::basic_ostream<CharT, Traits>&
|
||||
// operator<<(std::basic_ostream<CharT, Traits>& os, const decimal_format_seconds& x);
|
||||
// };
|
||||
|
||||
#include "date.h"
|
||||
|
||||
#include <cassert>
|
||||
#include <sstream>
|
||||
#include <type_traits>
|
||||
|
||||
using fortnights = std::chrono::duration<date::weeks::rep,
|
||||
date::detail::ratio_multiply<std::ratio<2>,
|
||||
date::weeks::period>>;
|
||||
|
||||
using microfortnights = std::chrono::duration<std::int64_t,
|
||||
date::detail::ratio_multiply<fortnights::period,
|
||||
std::micro>>;
|
||||
|
||||
int
|
||||
main()
|
||||
{
|
||||
using namespace date::detail;
|
||||
using namespace std;
|
||||
using namespace std::chrono;
|
||||
|
||||
{
|
||||
using D = decimal_format_seconds<minutes>;
|
||||
static_assert(is_same<D::precision, seconds>{}, "");
|
||||
static_assert(D::width == 0, "");
|
||||
D dfs{minutes{3}};
|
||||
assert(dfs.seconds() == seconds{180});
|
||||
assert(dfs.to_duration() == seconds{180});
|
||||
ostringstream out;
|
||||
out << dfs;
|
||||
assert(out.str() == "180");
|
||||
}
|
||||
{
|
||||
using D = decimal_format_seconds<seconds>;
|
||||
static_assert(is_same<D::precision, seconds>{}, "");
|
||||
static_assert(D::width == 0, "");
|
||||
D dfs{seconds{3}};
|
||||
assert(dfs.seconds() == seconds{3});
|
||||
assert(dfs.to_duration() == seconds{3});
|
||||
ostringstream out;
|
||||
out << dfs;
|
||||
assert(out.str() == "03");
|
||||
}
|
||||
{
|
||||
using D = decimal_format_seconds<milliseconds>;
|
||||
static_assert(D::width == 3, "");
|
||||
D dfs{seconds{3}};
|
||||
assert(dfs.seconds() == seconds{3});
|
||||
assert(dfs.to_duration() == seconds{3});
|
||||
assert(dfs.subseconds() == milliseconds{0});
|
||||
ostringstream out;
|
||||
out << dfs;
|
||||
assert(out.str() == "03.000");
|
||||
}
|
||||
{
|
||||
using D = decimal_format_seconds<milliseconds>;
|
||||
static_assert(D::width == 3, "");
|
||||
D dfs{milliseconds{3}};
|
||||
assert(dfs.seconds() == seconds{0});
|
||||
assert(dfs.to_duration() == milliseconds{3});
|
||||
assert(dfs.subseconds() == milliseconds{3});
|
||||
ostringstream out;
|
||||
out << dfs;
|
||||
assert(out.str() == "00.003");
|
||||
}
|
||||
{
|
||||
using D = decimal_format_seconds<microfortnights>;
|
||||
static_assert(D::width == 4, "");
|
||||
D dfs{microfortnights{3}};
|
||||
using S = D::precision;
|
||||
assert(dfs.seconds() == seconds{3});
|
||||
assert(dfs.to_duration() == S{36288});
|
||||
assert(dfs.subseconds() == S{6288});
|
||||
ostringstream out;
|
||||
out << dfs;
|
||||
assert(out.str() == "03.6288");
|
||||
}
|
||||
{
|
||||
using CT = common_type<seconds, microfortnights>::type;
|
||||
using D = decimal_format_seconds<CT>;
|
||||
static_assert(D::width == 4, "");
|
||||
D dfs{microfortnights{3}};
|
||||
using S = D::precision;
|
||||
assert(dfs.seconds() == seconds{3});
|
||||
assert(dfs.to_duration() == S{36288});
|
||||
assert(dfs.subseconds() == S{6288});
|
||||
ostringstream out;
|
||||
out << dfs;
|
||||
assert(out.str() == "03.6288");
|
||||
}
|
||||
}
|
50
test/date_test/detail/static_pow10.pass.cpp
Normal file
50
test/date_test/detail/static_pow10.pass.cpp
Normal file
@ -0,0 +1,50 @@
|
||||
// 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 exp>
|
||||
// struct static_pow10
|
||||
// {
|
||||
// static constepxr std::uint64_t value = ...;
|
||||
// };
|
||||
|
||||
#include "date.h"
|
||||
|
||||
#include <cassert>
|
||||
#include <sstream>
|
||||
#include <type_traits>
|
||||
|
||||
int
|
||||
main()
|
||||
{
|
||||
using namespace date::detail;
|
||||
static_assert(static_pow10<0>::value == 1, "");
|
||||
static_assert(static_pow10<1>::value == 10, "");
|
||||
static_assert(static_pow10<2>::value == 100, "");
|
||||
static_assert(static_pow10<3>::value == 1000, "");
|
||||
static_assert(static_pow10<4>::value == 10000, "");
|
||||
static_assert(static_pow10<5>::value == 100000, "");
|
||||
static_assert(static_pow10<6>::value == 1000000, "");
|
||||
static_assert(static_pow10<7>::value == 10000000, "");
|
||||
static_assert(static_pow10<8>::value == 100000000, "");
|
||||
static_assert(static_pow10<9>::value == 1000000000, "");
|
||||
static_assert(static_pow10<10>::value == 10000000000, "");
|
||||
}
|
64
test/date_test/detail/width.pass.cpp
Normal file
64
test/date_test/detail/width.pass.cpp
Normal file
@ -0,0 +1,64 @@
|
||||
// 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.
|
||||
|
||||
// width<n>::value is the number of fractional decimal digits in 1/n
|
||||
// width<0>::value and width<1>::value are defined to be 0
|
||||
// If 1/n takes more than 18 fractional decimal digits,
|
||||
// the result is truncated to 19.
|
||||
// Example: width<2>::value == 1
|
||||
// Example: width<3>::value == 19
|
||||
// Example: width<4>::value == 2
|
||||
// Example: width<10>::value == 1
|
||||
// Example: width<1000>::value == 3
|
||||
// template <std::uint64_t n>
|
||||
//
|
||||
// struct width
|
||||
// {
|
||||
// static constexpr unsigned value = ...;
|
||||
// };
|
||||
|
||||
#include "date.h"
|
||||
|
||||
#include <cassert>
|
||||
#include <sstream>
|
||||
#include <type_traits>
|
||||
|
||||
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, "");
|
||||
}
|
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();
|
||||
}
|
52
test/date_test/format/misc.pass.cpp
Normal file
52
test/date_test/format/misc.pass.cpp
Normal file
@ -0,0 +1,52 @@
|
||||
// The MIT License (MIT)
|
||||
//
|
||||
// Copyright (c) 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 "date.h"
|
||||
#include <cassert>
|
||||
#include <sstream>
|
||||
|
||||
template <class T>
|
||||
void
|
||||
test(const std::string& in_fmt, const std::string& input,
|
||||
const std::string& out_fmt, const std::string& output)
|
||||
{
|
||||
using namespace date;
|
||||
std::istringstream in{input};
|
||||
T t;
|
||||
in >> parse(in_fmt, t);
|
||||
assert(!in.fail());
|
||||
auto s = format(out_fmt, t);
|
||||
assert(s == output);
|
||||
}
|
||||
|
||||
int
|
||||
main()
|
||||
{
|
||||
using namespace date;
|
||||
test<year>("%Y", "2017", "%Y", "2017");
|
||||
test<month>("%m", "3", "%m", "03");
|
||||
test<day>("%d", "25", "%d", "25");
|
||||
test<year_month>("%Y-%m", "2017-03", "%Y-%m", "2017-03");
|
||||
test<year_month>("%y%m", "1703", "%Y-%m", "2017-03");
|
||||
test<month_day>("%m/%d", "3/25", "%m/%d", "03/25");
|
||||
test<weekday>("%w", "3", "%w", "3");
|
||||
}
|
@ -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()
|
||||
@ -41,7 +41,7 @@ main()
|
||||
using namespace std::chrono;
|
||||
std::ostringstream os;
|
||||
os << format("%F %T", sys_days{jan/1/year::min()});
|
||||
assert(os.str() == "-32768-01-01 00:00:00");
|
||||
assert(os.str() == "-32767-01-01 00:00:00");
|
||||
os.str("");
|
||||
os << format("%F %T", sys_days{dec/last/year::max()});
|
||||
assert(os.str() == "32767-12-31 00:00:00");
|
||||
@ -52,7 +52,7 @@ main()
|
||||
os.str("");
|
||||
|
||||
os << format("%Y-%m-%d %H:%M:%S", sys_days{jan/1/year::min()});
|
||||
assert(os.str() == "-32768-01-01 00:00:00");
|
||||
assert(os.str() == "-32767-01-01 00:00:00");
|
||||
os.str("");
|
||||
os << format("%Y-%m-%d %H:%M:%S", sys_days{dec/last/year::max()});
|
||||
assert(os.str() == "32767-12-31 00:00:00");
|
||||
@ -63,8 +63,16 @@ main()
|
||||
os.str("");
|
||||
|
||||
os << format("%F %T", sys_days{jan/1/year::min()} + microfortnights{1});
|
||||
assert(os.str() == "-32768-01-01 00:00:01.2096");
|
||||
assert(os.str() == "-32767-01-01 00:00:01.2096");
|
||||
os.str("");
|
||||
os << format("%F %T", sys_days{dec/last/year::max()} + microfortnights{1});
|
||||
assert(os.str() == "32767-12-31 00:00:01.2096");
|
||||
os.str("");
|
||||
|
||||
os << format("%F", jan/1/year::min());
|
||||
assert(os.str() == "-32767-01-01");
|
||||
os.str("");
|
||||
os << format("%F", dec/last/year::max());
|
||||
assert(os.str() == "32767-12-31");
|
||||
os.str("");
|
||||
}
|
||||
|
@ -117,5 +117,5 @@ main()
|
||||
|
||||
os.str("");
|
||||
os << format("%y", sys_days{jun/1/year::min()});
|
||||
assert(os.str() == "68");
|
||||
assert(os.str() == "67");
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
@ -34,7 +34,7 @@ test_a()
|
||||
// correct abbreviation
|
||||
std::istringstream in{"Sun 2016-12-11"};
|
||||
sys_days tp;
|
||||
parse(in, "%a %F", tp);
|
||||
in >> parse("%a %F", tp);
|
||||
assert(!in.fail());
|
||||
assert(!in.bad());
|
||||
assert(!in.eof());
|
||||
@ -44,7 +44,9 @@ test_a()
|
||||
// correct abbreviation
|
||||
std::istringstream in{"Sun 2016-12-11"};
|
||||
sys_days tp;
|
||||
parse(in, "%A %F", 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());
|
||||
@ -54,7 +56,7 @@ test_a()
|
||||
// correct full name
|
||||
std::istringstream in{"Sunday 2016-12-11"};
|
||||
sys_days tp;
|
||||
parse(in, "%a %F", tp);
|
||||
in >> parse("%a %F", tp);
|
||||
assert(!in.fail());
|
||||
assert(!in.bad());
|
||||
assert(!in.eof());
|
||||
@ -64,7 +66,7 @@ test_a()
|
||||
// correct full name
|
||||
std::istringstream in{"Sunday 2016-12-11"};
|
||||
sys_days tp;
|
||||
parse(in, "%A %F", tp);
|
||||
in >> parse("%A %F", tp);
|
||||
assert(!in.fail());
|
||||
assert(!in.bad());
|
||||
assert(!in.eof());
|
||||
@ -74,7 +76,7 @@ test_a()
|
||||
// not a valid name
|
||||
std::istringstream in{"Dec 2016-12-11"};
|
||||
sys_days tp;
|
||||
parse(in, "%a %F", tp);
|
||||
in >> parse("%a %F", tp);
|
||||
assert( in.fail());
|
||||
assert(!in.bad());
|
||||
assert(!in.eof());
|
||||
@ -84,7 +86,7 @@ test_a()
|
||||
// wrong name
|
||||
std::istringstream in{"Sat 2016-12-11"};
|
||||
sys_days tp;
|
||||
parse(in, "%a %F", tp);
|
||||
in >> parse("%a %F", tp);
|
||||
assert( in.fail());
|
||||
assert(!in.bad());
|
||||
assert(!in.eof());
|
||||
@ -94,7 +96,7 @@ test_a()
|
||||
// extra ws in input
|
||||
std::istringstream in{"Sun 2016-12-11"};
|
||||
sys_days tp;
|
||||
parse(in, "%a %F", tp);
|
||||
in >> parse("%a %F", tp);
|
||||
assert(!in.fail());
|
||||
assert(!in.bad());
|
||||
assert(!in.eof());
|
||||
@ -104,7 +106,7 @@ test_a()
|
||||
// extra ws in format
|
||||
std::istringstream in{"Sun 2016-12-11"};
|
||||
sys_days tp;
|
||||
parse(in, "%a %F", tp);
|
||||
in >> parse("%a %F", tp);
|
||||
assert(!in.fail());
|
||||
assert(!in.bad());
|
||||
assert(!in.eof());
|
||||
@ -120,7 +122,7 @@ test_b()
|
||||
// correct abbreviation
|
||||
std::istringstream in{"Dec 11 2016"};
|
||||
sys_days tp;
|
||||
parse(in, "%b %d %Y", tp);
|
||||
in >> parse("%b %d %Y", tp);
|
||||
assert(!in.fail());
|
||||
assert(!in.bad());
|
||||
assert(!in.eof());
|
||||
@ -130,7 +132,7 @@ test_b()
|
||||
// correct abbreviation
|
||||
std::istringstream in{"Dec 11 2016"};
|
||||
sys_days tp;
|
||||
parse(in, "%B %d %Y", tp);
|
||||
in >> parse("%B %d %Y", tp);
|
||||
assert(!in.fail());
|
||||
assert(!in.bad());
|
||||
assert(!in.eof());
|
||||
@ -140,7 +142,7 @@ test_b()
|
||||
// correct abbreviation
|
||||
std::istringstream in{"Dec 11 2016"};
|
||||
sys_days tp;
|
||||
parse(in, "%h %d %Y", tp);
|
||||
in >> parse("%h %d %Y", tp);
|
||||
assert(!in.fail());
|
||||
assert(!in.bad());
|
||||
assert(!in.eof());
|
||||
@ -150,7 +152,7 @@ test_b()
|
||||
// correct full name
|
||||
std::istringstream in{"December 11 2016"};
|
||||
sys_days tp;
|
||||
parse(in, "%b %d %Y", tp);
|
||||
in >> parse("%b %d %Y", tp);
|
||||
assert(!in.fail());
|
||||
assert(!in.bad());
|
||||
assert(!in.eof());
|
||||
@ -160,7 +162,7 @@ test_b()
|
||||
// correct full name
|
||||
std::istringstream in{"December 11 2016"};
|
||||
sys_days tp;
|
||||
parse(in, "%B %d %Y", tp);
|
||||
in >> parse("%B %d %Y", tp);
|
||||
assert(!in.fail());
|
||||
assert(!in.bad());
|
||||
assert(!in.eof());
|
||||
@ -170,7 +172,7 @@ test_b()
|
||||
// correct full name
|
||||
std::istringstream in{"December 11 2016"};
|
||||
sys_days tp;
|
||||
parse(in, "%h %d %Y", tp);
|
||||
in >> parse("%h %d %Y", tp);
|
||||
assert(!in.fail());
|
||||
assert(!in.bad());
|
||||
assert(!in.eof());
|
||||
@ -180,7 +182,7 @@ test_b()
|
||||
// incorrect abbreviation
|
||||
std::istringstream in{"Dece 11 2016"};
|
||||
sys_days tp;
|
||||
parse(in, "%b %d %Y", tp);
|
||||
in >> parse("%b %d %Y", tp);
|
||||
assert( in.fail());
|
||||
assert(!in.bad());
|
||||
assert(!in.eof());
|
||||
@ -197,7 +199,7 @@ test_c()
|
||||
// correct abbreviation
|
||||
std::istringstream in{"Sun Dec 11 14:02:43 2016"};
|
||||
sys_seconds tp;
|
||||
parse(in, "%c", tp);
|
||||
in >> parse("%c", tp);
|
||||
assert(!in.fail());
|
||||
assert(!in.bad());
|
||||
assert(tp == sys_days{2016_y/12/11} + hours{14} + minutes{2} + seconds{43});
|
||||
@ -213,7 +215,7 @@ test_x()
|
||||
// correct abbreviation
|
||||
std::istringstream in{"12/11/16"};
|
||||
sys_seconds tp;
|
||||
parse(in, "%x", tp);
|
||||
in >> parse("%x", tp);
|
||||
assert(!in.fail());
|
||||
assert(!in.bad());
|
||||
assert(tp == sys_days{2016_y/12/11});
|
||||
@ -229,7 +231,7 @@ test_X()
|
||||
// correct abbreviation
|
||||
std::istringstream in{"2016-12-11 14:02:43"};
|
||||
sys_seconds tp;
|
||||
parse(in, "%F %X", tp);
|
||||
in >> parse("%F %X", tp);
|
||||
assert(!in.fail());
|
||||
assert(!in.bad());
|
||||
assert(tp == sys_days{2016_y/12/11} + hours{14} + minutes{2} + seconds{43});
|
||||
@ -244,7 +246,7 @@ test_C()
|
||||
{
|
||||
std::istringstream in{"20 16 12 11"};
|
||||
sys_days tp;
|
||||
parse(in, "%C %y %m %d", tp);
|
||||
in >> parse("%C %y %m %d", tp);
|
||||
assert(!in.fail());
|
||||
assert(!in.bad());
|
||||
assert(tp == 2016_y/12/11);
|
||||
@ -252,7 +254,7 @@ test_C()
|
||||
{
|
||||
std::istringstream in{"-2 1 12 11"};
|
||||
sys_days tp;
|
||||
parse(in, "%C %y %m %d", tp);
|
||||
in >> parse("%C %y %m %d", tp);
|
||||
assert(!in.fail());
|
||||
assert(!in.bad());
|
||||
assert(tp == -101_y/12/11);
|
||||
@ -260,7 +262,7 @@ test_C()
|
||||
{
|
||||
std::istringstream in{"-1 0 12 11"};
|
||||
sys_days tp;
|
||||
parse(in, "%C %y %m %d", tp);
|
||||
in >> parse("%C %y %m %d", tp);
|
||||
assert(!in.fail());
|
||||
assert(!in.bad());
|
||||
assert(tp == -100_y/12/11);
|
||||
@ -268,7 +270,7 @@ test_C()
|
||||
{
|
||||
std::istringstream in{"-1 99 12 11"};
|
||||
sys_days tp;
|
||||
parse(in, "%C %y %m %d", tp);
|
||||
in >> parse("%C %y %m %d", tp);
|
||||
assert(!in.fail());
|
||||
assert(!in.bad());
|
||||
assert(tp == -99_y/12/11);
|
||||
@ -276,7 +278,7 @@ test_C()
|
||||
{
|
||||
std::istringstream in{"-1 1 12 11"};
|
||||
sys_days tp;
|
||||
parse(in, "%C %y %m %d", tp);
|
||||
in >> parse("%C %y %m %d", tp);
|
||||
assert(!in.fail());
|
||||
assert(!in.bad());
|
||||
assert(tp == -1_y/12/11);
|
||||
@ -284,7 +286,7 @@ test_C()
|
||||
{
|
||||
std::istringstream in{"0 0 12 11"};
|
||||
sys_days tp;
|
||||
parse(in, "%C %y %m %d", tp);
|
||||
in >> parse("%C %y %m %d", tp);
|
||||
assert(!in.fail());
|
||||
assert(!in.bad());
|
||||
assert(tp == 0_y/12/11);
|
||||
@ -292,7 +294,7 @@ test_C()
|
||||
{
|
||||
std::istringstream in{"0 1 12 11"};
|
||||
sys_days tp;
|
||||
parse(in, "%C %y %m %d", tp);
|
||||
in >> parse("%C %y %m %d", tp);
|
||||
assert(!in.fail());
|
||||
assert(!in.bad());
|
||||
assert(tp == 1_y/12/11);
|
||||
@ -300,7 +302,7 @@ test_C()
|
||||
{
|
||||
std::istringstream in{"0 99 12 11"};
|
||||
sys_days tp;
|
||||
parse(in, "%C %y %m %d", tp);
|
||||
in >> parse("%C %y %m %d", tp);
|
||||
assert(!in.fail());
|
||||
assert(!in.bad());
|
||||
assert(tp == 99_y/12/11);
|
||||
@ -308,7 +310,7 @@ test_C()
|
||||
{
|
||||
std::istringstream in{"1 0 12 11"};
|
||||
sys_days tp;
|
||||
parse(in, "%C %y %m %d", tp);
|
||||
in >> parse("%C %y %m %d", tp);
|
||||
assert(!in.fail());
|
||||
assert(!in.bad());
|
||||
assert(tp == 100_y/12/11);
|
||||
@ -316,7 +318,7 @@ test_C()
|
||||
{
|
||||
std::istringstream in{"1 1 12 11"};
|
||||
sys_days tp;
|
||||
parse(in, "%C %y %m %d", tp);
|
||||
in >> parse("%C %y %m %d", tp);
|
||||
assert(!in.fail());
|
||||
assert(!in.bad());
|
||||
assert(tp == 101_y/12/11);
|
||||
@ -331,7 +333,7 @@ test_d()
|
||||
{
|
||||
std::istringstream in{"2016 09 12"};
|
||||
sys_days tp;
|
||||
parse(in, "%Y %d %m", tp);
|
||||
in >> parse("%Y %d %m", tp);
|
||||
assert(!in.fail());
|
||||
assert(!in.bad());
|
||||
assert(tp == 2016_y/12/9);
|
||||
@ -339,7 +341,7 @@ test_d()
|
||||
{
|
||||
std::istringstream in{"2016 09 12"};
|
||||
sys_days tp;
|
||||
parse(in, "%Y %e %m", tp);
|
||||
in >> parse("%Y %e %m", tp);
|
||||
assert(!in.fail());
|
||||
assert(!in.bad());
|
||||
assert(tp == 2016_y/12/9);
|
||||
@ -347,7 +349,7 @@ test_d()
|
||||
{
|
||||
std::istringstream in{"2016 9 12"};
|
||||
sys_days tp;
|
||||
parse(in, "%Y %d %m", tp);
|
||||
in >> parse("%Y %d %m", tp);
|
||||
assert(!in.fail());
|
||||
assert(!in.bad());
|
||||
assert(tp == 2016_y/12/9);
|
||||
@ -355,11 +357,17 @@ test_d()
|
||||
{
|
||||
std::istringstream in{"2016 9 12"};
|
||||
sys_days tp;
|
||||
parse(in, "%Y %e %m", tp);
|
||||
in >> parse("%Y %e %m", tp);
|
||||
assert(!in.fail());
|
||||
assert(!in.bad());
|
||||
assert(tp == 2016_y/12/9);
|
||||
}
|
||||
{
|
||||
std::istringstream in{"2016 31 11"};
|
||||
sys_days tp;
|
||||
in >> parse("%Y %e %m", tp);
|
||||
assert(in.fail());
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
@ -370,7 +378,7 @@ test_D()
|
||||
{
|
||||
std::istringstream in{"12/11/16"};
|
||||
sys_days tp;
|
||||
parse(in, "%D", tp);
|
||||
in >> parse("%D", tp);
|
||||
assert(!in.fail());
|
||||
assert(!in.bad());
|
||||
assert(tp == 2016_y/12/11);
|
||||
@ -385,7 +393,15 @@ test_F()
|
||||
{
|
||||
std::istringstream in{"2016-12-13"};
|
||||
sys_days tp;
|
||||
parse(in, "%F", tp);
|
||||
in >> parse("%F", tp);
|
||||
assert(!in.fail());
|
||||
assert(!in.bad());
|
||||
assert(tp == 2016_y/12/13);
|
||||
}
|
||||
{
|
||||
std::istringstream in{"2016-12-13"};
|
||||
year_month_day tp;
|
||||
in >> parse("%F", tp);
|
||||
assert(!in.fail());
|
||||
assert(!in.bad());
|
||||
assert(tp == 2016_y/12/13);
|
||||
@ -400,11 +416,17 @@ test_H()
|
||||
{
|
||||
std::istringstream in{"2016-12-11 15"};
|
||||
sys_time<hours> tp;
|
||||
parse(in, "%F %H", tp);
|
||||
in >> parse("%F %H", tp);
|
||||
assert(!in.fail());
|
||||
assert(!in.bad());
|
||||
assert(tp == sys_days{2016_y/12/11} + hours{15});
|
||||
}
|
||||
{
|
||||
std::istringstream in{"2016-12-11 24"};
|
||||
sys_time<hours> tp;
|
||||
in >> parse("%F %H", tp);
|
||||
assert(in.fail());
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
@ -415,7 +437,7 @@ test_Ip()
|
||||
{
|
||||
std::istringstream in{"2016-12-11 1 pm"};
|
||||
sys_time<hours> tp;
|
||||
parse(in, "%F %I %p", tp);
|
||||
in >> parse("%F %I %p", tp);
|
||||
assert(!in.fail());
|
||||
assert(!in.bad());
|
||||
assert(tp == sys_days{2016_y/12/11} + hours{13});
|
||||
@ -423,11 +445,17 @@ test_Ip()
|
||||
{
|
||||
std::istringstream in{"2016-12-11 1 am"};
|
||||
sys_time<hours> tp;
|
||||
parse(in, "%F %I %p", tp);
|
||||
in >> parse("%F %I %p", tp);
|
||||
assert(!in.fail());
|
||||
assert(!in.bad());
|
||||
assert(tp == sys_days{2016_y/12/11} + hours{1});
|
||||
}
|
||||
{
|
||||
std::istringstream in{"2016-12-11 13 am"};
|
||||
sys_time<hours> tp;
|
||||
in >> parse("%F %I %p", tp);
|
||||
assert(in.fail());
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
@ -438,7 +466,7 @@ test_j()
|
||||
{
|
||||
std::istringstream in{"2016 361"};
|
||||
sys_days tp;
|
||||
parse(in, "%Y %j", tp);
|
||||
in >> parse("%Y %j", tp);
|
||||
assert(!in.fail());
|
||||
assert(!in.bad());
|
||||
assert(tp == sys_days{2016_y/12/26});
|
||||
@ -453,7 +481,7 @@ test_m()
|
||||
{
|
||||
std::istringstream in{"2016 12 09"};
|
||||
sys_days tp;
|
||||
parse(in, "%Y %d %m", tp);
|
||||
in >> parse("%Y %d %m", tp);
|
||||
assert(!in.fail());
|
||||
assert(!in.bad());
|
||||
assert(tp == 2016_y/9/12);
|
||||
@ -461,11 +489,17 @@ test_m()
|
||||
{
|
||||
std::istringstream in{"2016 12 9"};
|
||||
sys_days tp;
|
||||
parse(in, "%Y %d %m", tp);
|
||||
in >> parse("%Y %d %m", tp);
|
||||
assert(!in.fail());
|
||||
assert(!in.bad());
|
||||
assert(tp == 2016_y/9/12);
|
||||
}
|
||||
{
|
||||
std::istringstream in{"2016 12 13"};
|
||||
sys_days tp;
|
||||
in >> parse("%Y %d %m", tp);
|
||||
assert(in.fail());
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
@ -476,11 +510,17 @@ test_M()
|
||||
{
|
||||
std::istringstream in{"2016-12-11 15"};
|
||||
sys_time<minutes> tp;
|
||||
parse(in, "%F %M", tp);
|
||||
in >> parse("%F %M", tp);
|
||||
assert(!in.fail());
|
||||
assert(!in.bad());
|
||||
assert(tp == sys_days{2016_y/12/11} + minutes{15});
|
||||
}
|
||||
{
|
||||
std::istringstream in{"2016-12-11 65"};
|
||||
sys_time<minutes> tp;
|
||||
in >> parse("%F %M", tp);
|
||||
assert(in.fail());
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
@ -491,7 +531,7 @@ test_S()
|
||||
{
|
||||
std::istringstream in{"2016-12-11 15"};
|
||||
sys_seconds tp;
|
||||
parse(in, "%F %S", tp);
|
||||
in >> parse("%F %S", tp);
|
||||
assert(!in.fail());
|
||||
assert(!in.bad());
|
||||
assert(tp == sys_days{2016_y/12/11} + seconds{15});
|
||||
@ -499,11 +539,17 @@ test_S()
|
||||
{
|
||||
std::istringstream in{"2016-12-11 15.001"};
|
||||
sys_time<milliseconds> tp;
|
||||
parse(in, "%F %S", tp);
|
||||
in >> parse("%F %S", tp);
|
||||
assert(!in.fail());
|
||||
assert(!in.bad());
|
||||
assert(tp == sys_days{2016_y/12/11} + seconds{15} + milliseconds{1});
|
||||
}
|
||||
{
|
||||
std::istringstream in{"2016-12-11 60"};
|
||||
sys_seconds tp;
|
||||
in >> parse("%F %S", tp);
|
||||
assert(in.fail());
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
@ -514,7 +560,7 @@ test_T()
|
||||
{
|
||||
std::istringstream in{"2016-12-11 15:43:22"};
|
||||
sys_seconds tp;
|
||||
parse(in, "%F %T", tp);
|
||||
in >> parse("%F %T", tp);
|
||||
assert(!in.fail());
|
||||
assert(!in.bad());
|
||||
assert(tp == sys_days{2016_y/12/11} + hours{15} + minutes{43} + seconds{22});
|
||||
@ -522,7 +568,7 @@ test_T()
|
||||
{
|
||||
std::istringstream in{"2016-12-11 15:43:22.001"};
|
||||
sys_time<milliseconds> tp;
|
||||
parse(in, "%F %T", tp);
|
||||
in >> parse("%F %T", tp);
|
||||
assert(!in.fail());
|
||||
assert(!in.bad());
|
||||
assert(tp == sys_days{2016_y/12/11} + hours{15} + minutes{43} + seconds{22} +
|
||||
@ -531,11 +577,37 @@ test_T()
|
||||
{
|
||||
std::istringstream in{"2016-12-11 15:43:22"};
|
||||
sys_time<milliseconds> tp;
|
||||
parse(in, "%F %T", tp);
|
||||
in >> parse("%F %T", tp);
|
||||
assert(!in.fail());
|
||||
assert(!in.bad());
|
||||
assert(tp == sys_days{2016_y/12/11} + hours{15} + minutes{43} + seconds{22});
|
||||
}
|
||||
{
|
||||
std::istringstream in{"15:43:22.001"};
|
||||
milliseconds d;
|
||||
in >> parse("%T", d);
|
||||
assert(!in.fail());
|
||||
assert(!in.bad());
|
||||
assert(d == hours{15} + minutes{43} + seconds{22} + milliseconds{1});
|
||||
}
|
||||
{
|
||||
std::istringstream in{"2016-12-11 24:43:22"};
|
||||
sys_seconds tp;
|
||||
in >> parse("%F %T", tp);
|
||||
assert(in.fail());
|
||||
}
|
||||
{
|
||||
std::istringstream in{"2016-12-11 15:60:22"};
|
||||
sys_seconds tp;
|
||||
in >> parse("%F %T", tp);
|
||||
assert(in.fail());
|
||||
}
|
||||
{
|
||||
std::istringstream in{"2016-12-11 15:43:60"};
|
||||
sys_seconds tp;
|
||||
in >> parse("%F %T", tp);
|
||||
assert(in.fail());
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
@ -546,7 +618,7 @@ test_p()
|
||||
{
|
||||
std::istringstream in{"2016-12-11 11pm"};
|
||||
sys_time<hours> tp;
|
||||
parse(in, "%F %I%p", tp);
|
||||
in >> parse("%F %I%p", tp);
|
||||
assert(!in.fail());
|
||||
assert(!in.bad());
|
||||
assert(tp == sys_days{2016_y/12/11} + hours{23});
|
||||
@ -561,7 +633,7 @@ test_r()
|
||||
{
|
||||
std::istringstream in{"2016-12-26 1:36:57 pm"};
|
||||
sys_seconds tp;
|
||||
parse(in, "%F %r", tp);
|
||||
in >> parse("%F %r", tp);
|
||||
assert(!in.fail());
|
||||
assert(!in.bad());
|
||||
assert(tp == sys_days{2016_y/12/26} + hours{13} + minutes{36} + seconds{57});
|
||||
@ -576,7 +648,7 @@ test_R()
|
||||
{
|
||||
std::istringstream in{"2016-12-26 13:36"};
|
||||
sys_seconds tp;
|
||||
parse(in, "%F %R", tp);
|
||||
in >> parse("%F %R", tp);
|
||||
assert(!in.fail());
|
||||
assert(!in.bad());
|
||||
assert(tp == sys_days{2016_y/12/26} + hours{13} + minutes{36});
|
||||
@ -591,7 +663,7 @@ test_U()
|
||||
{
|
||||
std::istringstream in{"2016-52-1"};
|
||||
sys_days tp;
|
||||
parse(in, "%Y-%U-%w", tp);
|
||||
in >> parse("%Y-%U-%w", tp);
|
||||
assert(!in.fail());
|
||||
assert(!in.bad());
|
||||
assert(tp == sys_days{2016_y/12/26});
|
||||
@ -606,7 +678,7 @@ test_W()
|
||||
{
|
||||
std::istringstream in{"2016-52-1"};
|
||||
sys_days tp;
|
||||
parse(in, "%Y-%W-%w", tp);
|
||||
in >> parse("%Y-%W-%w", tp);
|
||||
assert(!in.fail());
|
||||
assert(!in.bad());
|
||||
assert(tp == sys_days{2016_y/12/26});
|
||||
@ -621,7 +693,7 @@ test_GV()
|
||||
{
|
||||
std::istringstream in{"2016-52-1"};
|
||||
sys_days tp;
|
||||
parse(in, "%G-%V-%w", tp);
|
||||
in >> parse("%G-%V-%w", tp);
|
||||
assert(!in.fail());
|
||||
assert(!in.bad());
|
||||
assert(tp == sys_days{2016_y/12/26});
|
||||
@ -629,7 +701,7 @@ test_GV()
|
||||
{
|
||||
std::istringstream in{"2016-52-1"};
|
||||
sys_days tp;
|
||||
parse(in, "%G-%V-%w", tp);
|
||||
in >> parse("%G-%V-%w", tp);
|
||||
assert(!in.fail());
|
||||
assert(!in.bad());
|
||||
assert(tp == sys_days{2016_y/12/26});
|
||||
@ -637,7 +709,7 @@ test_GV()
|
||||
{
|
||||
std::istringstream in{"20 16-52-1"};
|
||||
sys_days tp;
|
||||
parse(in, "%C %g-%V-%w", tp);
|
||||
in >> parse("%C %g-%V-%w", tp);
|
||||
assert(!in.fail());
|
||||
assert(!in.bad());
|
||||
assert(tp == sys_days{2016_y/12/26});
|
||||
@ -645,7 +717,7 @@ test_GV()
|
||||
{
|
||||
std::istringstream in{"20 16-52-1"};
|
||||
sys_days tp;
|
||||
parse(in, "%C %g-%V-%u", tp);
|
||||
in >> parse("%C %g-%V-%u", tp);
|
||||
assert(!in.fail());
|
||||
assert(!in.bad());
|
||||
assert(tp == sys_days{2016_y/12/26});
|
||||
@ -660,7 +732,7 @@ test_z()
|
||||
{
|
||||
std::istringstream in{"2016-12-26 15:53:22 -0500"};
|
||||
sys_seconds tp;
|
||||
parse(in, "%F %T %z", tp);
|
||||
in >> parse("%F %T %z", tp);
|
||||
assert(!in.fail());
|
||||
assert(!in.bad());
|
||||
assert(tp == sys_days{2016_y/12/26} + hours{20} + minutes{53} + seconds{22});
|
||||
@ -668,7 +740,7 @@ test_z()
|
||||
{
|
||||
std::istringstream in{"2016-12-26 15:53:22 -0500"};
|
||||
local_seconds tp;
|
||||
parse(in, "%F %T %z", tp);
|
||||
in >> parse("%F %T %z", tp);
|
||||
assert(!in.fail());
|
||||
assert(!in.bad());
|
||||
assert(tp == local_days{2016_y/12/26} + hours{15} + minutes{53} + seconds{22});
|
||||
@ -676,7 +748,7 @@ test_z()
|
||||
{
|
||||
std::istringstream in{"2016-12-26 15:53:22 -05:00"};
|
||||
sys_seconds tp;
|
||||
parse(in, "%F %T %Ez", tp);
|
||||
in >> parse("%F %T %Ez", tp);
|
||||
assert(!in.fail());
|
||||
assert(!in.bad());
|
||||
assert(tp == sys_days{2016_y/12/26} + hours{20} + minutes{53} + seconds{22});
|
||||
@ -692,7 +764,7 @@ test_Z()
|
||||
std::string a;
|
||||
std::istringstream in{"2016-12-26 15:53:22 word"};
|
||||
local_seconds tp;
|
||||
parse(in, "%F %T %Z", tp, a);
|
||||
in >> parse("%F %T %Z", tp, a);
|
||||
assert(!in.fail());
|
||||
assert(!in.bad());
|
||||
assert(tp == local_days{2016_y/12/26} + hours{15} + minutes{53} + seconds{22});
|
||||
@ -700,6 +772,105 @@ test_Z()
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
test_trailing_Z()
|
||||
{
|
||||
std::string format = "%FT%TZ";
|
||||
std::string datetime = "2017-2-15T13:13:13";
|
||||
std::istringstream input(datetime);
|
||||
date::sys_seconds tp;
|
||||
input >> date::parse(format, tp);
|
||||
assert(input.fail());
|
||||
assert(input.eof());
|
||||
}
|
||||
|
||||
void
|
||||
test_leading_ws()
|
||||
{
|
||||
using namespace std;
|
||||
using namespace date;
|
||||
istringstream in{"05/04/17 5/4/17"};
|
||||
year_month_day d1, d2;
|
||||
in >> parse("%D", d1) >> parse("%n%D", d2);
|
||||
assert(d1 == may/4/2017);
|
||||
assert(d2 == may/4/2017);
|
||||
}
|
||||
|
||||
void
|
||||
test_space()
|
||||
{
|
||||
using namespace std;
|
||||
using namespace date;
|
||||
{
|
||||
istringstream in{"05/04/17"};
|
||||
year_month_day d1;
|
||||
in >> parse(" %D", d1);
|
||||
assert(d1 == may/4/2017);
|
||||
}
|
||||
{
|
||||
istringstream in{" 05/04/17"};
|
||||
year_month_day d1;
|
||||
in >> parse(" %D", d1);
|
||||
assert(d1 == may/4/2017);
|
||||
}
|
||||
{
|
||||
istringstream in{" 05/04/17"};
|
||||
year_month_day d1;
|
||||
in >> parse(" %D", d1);
|
||||
assert(d1 == may/4/2017);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
test_n()
|
||||
{
|
||||
using namespace std;
|
||||
using namespace date;
|
||||
{
|
||||
istringstream in{"05/04/17"};
|
||||
year_month_day d1;
|
||||
in >> parse("%n%D", d1);
|
||||
assert(in.fail());
|
||||
}
|
||||
{
|
||||
istringstream in{" 05/04/17"};
|
||||
year_month_day d1;
|
||||
in >> parse("%n%D", d1);
|
||||
assert(d1 == may/4/2017);
|
||||
}
|
||||
{
|
||||
istringstream in{" 05/04/17"};
|
||||
year_month_day d1;
|
||||
in >> parse("%n%D", d1);
|
||||
assert(in.fail());
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
test_t()
|
||||
{
|
||||
using namespace std;
|
||||
using namespace date;
|
||||
{
|
||||
istringstream in{"05/04/17"};
|
||||
year_month_day d1;
|
||||
in >> parse("%t%D", d1);
|
||||
assert(d1 == may/4/2017);
|
||||
}
|
||||
{
|
||||
istringstream in{" 05/04/17"};
|
||||
year_month_day d1;
|
||||
in >> parse("%t%D", d1);
|
||||
assert(d1 == may/4/2017);
|
||||
}
|
||||
{
|
||||
istringstream in{" 05/04/17"};
|
||||
year_month_day d1;
|
||||
in >> parse("%t%D", d1);
|
||||
assert(in.fail());
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
main()
|
||||
{
|
||||
@ -727,4 +898,9 @@ main()
|
||||
test_X();
|
||||
test_z();
|
||||
test_Z();
|
||||
test_trailing_Z();
|
||||
test_leading_ws();
|
||||
test_space();
|
||||
test_n();
|
||||
test_t();
|
||||
}
|
||||
|
@ -57,10 +57,10 @@ main()
|
||||
|
||||
using tod = time_of_day<hours>;
|
||||
|
||||
static_assert(is_same<tod::precision, hours>{}, "");
|
||||
static_assert(is_same<tod::precision::period, seconds::period>{}, "");
|
||||
|
||||
static_assert( is_trivially_destructible<tod>{}, "");
|
||||
static_assert(!is_default_constructible<tod>{}, "");
|
||||
static_assert( is_default_constructible<tod>{}, "");
|
||||
static_assert( is_trivially_copy_constructible<tod>{}, "");
|
||||
static_assert( is_trivially_copy_assignable<tod>{}, "");
|
||||
static_assert( is_trivially_move_constructible<tod>{}, "");
|
||||
@ -68,14 +68,12 @@ main()
|
||||
|
||||
static_assert(is_nothrow_constructible<tod, hours>{}, "");
|
||||
static_assert(!is_convertible<hours, tod>{}, "");
|
||||
static_assert(is_nothrow_constructible<tod, hours, unsigned>{}, "");
|
||||
|
||||
static_assert(is_nothrow_constructible<tod::precision, tod>{}, "");
|
||||
static_assert(!is_convertible<tod, tod::precision>{}, "");
|
||||
|
||||
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}, "");
|
||||
@ -83,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()));
|
||||
}
|
||||
|
111
test/date_test/time_of_day_microfortnights.pass.cpp
Normal file
111
test/date_test/time_of_day_microfortnights.pass.cpp
Normal file
@ -0,0 +1,111 @@
|
||||
// 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.
|
||||
|
||||
// enum {am = 1, pm};
|
||||
|
||||
// template <class Rep, class Period>
|
||||
// class time_of_day<std::chrono::duration<Rep, Period>>
|
||||
// {
|
||||
// public:
|
||||
// using precision = std::chrono::std::chrono::duration<Rep, Period>;
|
||||
//
|
||||
// constexpr explicit time_of_day(precision since_midnight) noexcept;
|
||||
// constexpr time_of_day(std::chrono::hours h, std::chrono::minutes m,
|
||||
// std::chrono::seconds s, precision sub_s,
|
||||
// unsigned md) noexcept;
|
||||
//
|
||||
// constexpr std::chrono::hours hours() const noexcept;
|
||||
// constexpr std::chrono::minutes minutes() const noexcept;
|
||||
// constexpr std::chrono::seconds seconds() const noexcept;
|
||||
// constexpr precision subseconds() const noexcept;
|
||||
// constexpr unsigned mode() const noexcept;
|
||||
//
|
||||
// constexpr explicit operator precision() const noexcept;
|
||||
// constexpr precision to_duration() const noexcept;
|
||||
//
|
||||
// void make24() noexcept;
|
||||
// void make12() noexcept;
|
||||
// };
|
||||
|
||||
// template <class Rep, class Period>
|
||||
// std::ostream&
|
||||
// operator<<(std::ostream& os, const time_of_day<std::chrono::duration<Rep, Period>>& t);
|
||||
|
||||
#include "date.h"
|
||||
|
||||
#include <cassert>
|
||||
#include <sstream>
|
||||
#include <type_traits>
|
||||
|
||||
using fortnights = std::chrono::duration<date::weeks::rep,
|
||||
date::detail::ratio_multiply<std::ratio<2>,
|
||||
date::weeks::period>>;
|
||||
|
||||
using microfortnights = std::chrono::duration<std::int64_t,
|
||||
date::detail::ratio_multiply<fortnights::period,
|
||||
std::micro>>;
|
||||
|
||||
int
|
||||
main()
|
||||
{
|
||||
using namespace date;
|
||||
using namespace std;
|
||||
using namespace std::chrono;
|
||||
|
||||
using tod = time_of_day<typename common_type<hours, minutes, microfortnights>::type>;
|
||||
|
||||
static_assert(is_same<tod::precision::period, ratio<1, 10000>>{}, "");
|
||||
|
||||
static_assert( is_trivially_destructible<tod>{}, "");
|
||||
static_assert( is_default_constructible<tod>{}, "");
|
||||
static_assert( is_trivially_copy_constructible<tod>{}, "");
|
||||
static_assert( is_trivially_copy_assignable<tod>{}, "");
|
||||
static_assert( is_trivially_move_constructible<tod>{}, "");
|
||||
static_assert( is_trivially_move_assignable<tod>{}, "");
|
||||
|
||||
static_assert(is_constructible<tod, microfortnights>{}, "");
|
||||
static_assert(!is_convertible<microfortnights, tod>{}, "");
|
||||
|
||||
static_assert(is_nothrow_constructible<tod::precision, tod>{}, "");
|
||||
static_assert(!is_convertible<tod, tod::precision>{}, "");
|
||||
|
||||
constexpr tod t1 = tod{hours{13} + minutes{7} + microfortnights{5}};
|
||||
static_assert(t1.hours() == hours{13}, "");
|
||||
static_assert(t1.minutes() == minutes{7}, "");
|
||||
static_assert(t1.seconds() == seconds{6}, "");
|
||||
static_assert(t1.subseconds() == tod::precision{480}, "");
|
||||
#if __cplusplus >= 201402
|
||||
static_assert(static_cast<tod::precision>(t1) == hours{13} + minutes{7}
|
||||
+ microfortnights{5}, "");
|
||||
static_assert(t1.to_duration() == hours{13} + minutes{7} + microfortnights{5}, "");
|
||||
#endif
|
||||
|
||||
auto t2 = t1;
|
||||
assert(t2.hours() == t1.hours());
|
||||
assert(t2.minutes() == t1.minutes());
|
||||
assert(t2.seconds() == t1.seconds());
|
||||
assert(t2.subseconds() == t1.subseconds());
|
||||
assert(t2.to_duration() == t1.to_duration());
|
||||
ostringstream os;
|
||||
os << t2;
|
||||
assert(os.str() == "13:07:06.0480");
|
||||
}
|
@ -65,10 +65,10 @@ main()
|
||||
|
||||
using tod = time_of_day<milliseconds>;
|
||||
|
||||
static_assert(is_same<tod::precision, milliseconds>{}, "");
|
||||
static_assert(is_same<tod::precision::period, milliseconds::period>{}, "");
|
||||
|
||||
static_assert( is_trivially_destructible<tod>{}, "");
|
||||
static_assert(!is_default_constructible<tod>{}, "");
|
||||
static_assert( is_default_constructible<tod>{}, "");
|
||||
static_assert( is_trivially_copy_constructible<tod>{}, "");
|
||||
static_assert( is_trivially_copy_assignable<tod>{}, "");
|
||||
static_assert( is_trivially_move_constructible<tod>{}, "");
|
||||
@ -76,8 +76,6 @@ main()
|
||||
|
||||
static_assert(is_nothrow_constructible<tod, milliseconds>{}, "");
|
||||
static_assert(!is_convertible<milliseconds, tod>{}, "");
|
||||
static_assert(is_nothrow_constructible<tod, hours, minutes, seconds, milliseconds,
|
||||
unsigned>{}, "");
|
||||
|
||||
static_assert(is_nothrow_constructible<tod::precision, tod>{}, "");
|
||||
static_assert(!is_convertible<tod, tod::precision>{}, "");
|
||||
@ -87,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}, "");
|
||||
@ -100,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,10 +59,10 @@ main()
|
||||
|
||||
using tod = time_of_day<minutes>;
|
||||
|
||||
static_assert(is_same<tod::precision, minutes>{}, "");
|
||||
static_assert(is_same<tod::precision::period, seconds::period>{}, "");
|
||||
|
||||
static_assert( is_trivially_destructible<tod>{}, "");
|
||||
static_assert(!is_default_constructible<tod>{}, "");
|
||||
static_assert( is_default_constructible<tod>{}, "");
|
||||
static_assert( is_trivially_copy_constructible<tod>{}, "");
|
||||
static_assert( is_trivially_copy_assignable<tod>{}, "");
|
||||
static_assert( is_trivially_move_constructible<tod>{}, "");
|
||||
@ -70,7 +70,6 @@ main()
|
||||
|
||||
static_assert(is_nothrow_constructible<tod, minutes>{}, "");
|
||||
static_assert(!is_convertible<minutes, tod>{}, "");
|
||||
static_assert(is_nothrow_constructible<tod, hours, minutes, unsigned>{}, "");
|
||||
|
||||
static_assert(is_nothrow_constructible<tod::precision, tod>{}, "");
|
||||
static_assert(!is_convertible<tod, tod::precision>{}, "");
|
||||
@ -78,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}, "");
|
||||
@ -87,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");
|
||||
}
|
||||
|
@ -65,10 +65,10 @@ main()
|
||||
|
||||
using tod = time_of_day<nanoseconds>;
|
||||
|
||||
static_assert(is_same<tod::precision, nanoseconds>{}, "");
|
||||
static_assert(is_same<tod::precision::period, nanoseconds::period>{}, "");
|
||||
|
||||
static_assert( is_trivially_destructible<tod>{}, "");
|
||||
static_assert(!is_default_constructible<tod>{}, "");
|
||||
static_assert( is_default_constructible<tod>{}, "");
|
||||
static_assert( is_trivially_copy_constructible<tod>{}, "");
|
||||
static_assert( is_trivially_copy_assignable<tod>{}, "");
|
||||
static_assert( is_trivially_move_constructible<tod>{}, "");
|
||||
@ -76,8 +76,6 @@ main()
|
||||
|
||||
static_assert(is_nothrow_constructible<tod, nanoseconds>{}, "");
|
||||
static_assert(!is_convertible<nanoseconds, tod>{}, "");
|
||||
static_assert(is_nothrow_constructible<tod, hours, minutes, seconds, nanoseconds,
|
||||
unsigned>{}, "");
|
||||
|
||||
static_assert(is_nothrow_constructible<tod::precision, tod>{}, "");
|
||||
static_assert(!is_convertible<tod, tod::precision>{}, "");
|
||||
@ -87,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}, "");
|
||||
@ -100,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");
|
||||
}
|
||||
|
@ -60,10 +60,10 @@ main()
|
||||
|
||||
using tod = time_of_day<seconds>;
|
||||
|
||||
static_assert(is_same<tod::precision, seconds>{}, "");
|
||||
static_assert(is_same<tod::precision::period, seconds::period>{}, "");
|
||||
|
||||
static_assert( is_trivially_destructible<tod>{}, "");
|
||||
static_assert(!is_default_constructible<tod>{}, "");
|
||||
static_assert( is_default_constructible<tod>{}, "");
|
||||
static_assert( is_trivially_copy_constructible<tod>{}, "");
|
||||
static_assert( is_trivially_copy_assignable<tod>{}, "");
|
||||
static_assert( is_trivially_move_constructible<tod>{}, "");
|
||||
@ -71,7 +71,6 @@ main()
|
||||
|
||||
static_assert(is_nothrow_constructible<tod, seconds>{}, "");
|
||||
static_assert(!is_convertible<seconds, tod>{}, "");
|
||||
static_assert(is_nothrow_constructible<tod, hours, minutes, seconds, unsigned>{}, "");
|
||||
|
||||
static_assert(is_nothrow_constructible<tod::precision, tod>{}, "");
|
||||
static_assert(!is_convertible<tod, tod::precision>{}, "");
|
||||
@ -80,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}, "");
|
||||
@ -91,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()
|
||||
|
@ -23,6 +23,7 @@
|
||||
// class weekday_indexed
|
||||
// {
|
||||
// public:
|
||||
// weekday_indexed() = default;
|
||||
// constexpr weekday_indexed(const date::weekday& wd, unsigned index) noexcept;
|
||||
//
|
||||
// constexpr date::weekday weekday() const noexcept;
|
||||
@ -42,7 +43,7 @@
|
||||
#include <type_traits>
|
||||
|
||||
static_assert( std::is_trivially_destructible<date::weekday_indexed>{}, "");
|
||||
static_assert(!std::is_default_constructible<date::weekday_indexed>{}, "");
|
||||
static_assert( std::is_default_constructible<date::weekday_indexed>{}, "");
|
||||
static_assert( std::is_trivially_copy_constructible<date::weekday_indexed>{}, "");
|
||||
static_assert( std::is_trivially_copy_assignable<date::weekday_indexed>{}, "");
|
||||
static_assert( std::is_trivially_move_constructible<date::weekday_indexed>{}, "");
|
||||
|
@ -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;
|
||||
|
@ -105,7 +105,7 @@ test_arithmetic()
|
||||
|
||||
for (int y1 = 2010; y1 <= 2015; ++y1)
|
||||
{
|
||||
for (unsigned m1 = 1; m1 <= 12; ++m1)
|
||||
for (int m1 = 1; m1 <= 12; ++m1)
|
||||
{
|
||||
auto ymd1 = last/m1/y1;;
|
||||
auto ymd2 = ymd1 + months(24);
|
||||
|
@ -23,6 +23,7 @@
|
||||
// class year_month_weekday
|
||||
// {
|
||||
// public:
|
||||
// year_month_weekday() = default;
|
||||
// constexpr year_month_weekday(const date::year& y, const date::month& m,
|
||||
// const date::weekday_indexed& wdi) noexcept;
|
||||
// constexpr year_month_weekday(const sys_days& dp) noexcept;
|
||||
@ -83,7 +84,7 @@
|
||||
#include <type_traits>
|
||||
|
||||
static_assert( std::is_trivially_destructible<date::year_month_weekday>{}, "");
|
||||
static_assert(!std::is_default_constructible<date::year_month_weekday>{}, "");
|
||||
static_assert( std::is_default_constructible<date::year_month_weekday>{}, "");
|
||||
static_assert( std::is_trivially_copy_constructible<date::year_month_weekday>{}, "");
|
||||
static_assert( std::is_trivially_copy_assignable<date::year_month_weekday>{}, "");
|
||||
static_assert( std::is_trivially_move_constructible<date::year_month_weekday>{}, "");
|
||||
@ -106,7 +107,7 @@ test_arithmetic()
|
||||
|
||||
for (int y1 = 2010; y1 <= 2015; ++y1)
|
||||
{
|
||||
for (unsigned m1 = 1; m1 <= 12; ++m1)
|
||||
for (int m1 = 1; m1 <= 12; ++m1)
|
||||
{
|
||||
auto ymd1 = mon[2]/m1/y1;;
|
||||
auto ymd2 = ymd1 + months(24);
|
||||
|
@ -101,7 +101,7 @@ test_arithmetic()
|
||||
|
||||
for (int y1 = 2010; y1 <= 2015; ++y1)
|
||||
{
|
||||
for (unsigned m1 = 1; m1 <= 12; ++m1)
|
||||
for (int m1 = 1; m1 <= 12; ++m1)
|
||||
{
|
||||
auto ymd1 = mon[last]/m1/y1;;
|
||||
auto ymd2 = ymd1 + months(24);
|
||||
|
@ -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, "");
|
||||
}
|
||||
|
@ -115,4 +115,15 @@ main()
|
||||
std::ostringstream os;
|
||||
os << x0;
|
||||
assert(os.str() == "2015-W last-Tue");
|
||||
|
||||
for (auto y = 1950_y; y <= 2050_y; ++y)
|
||||
{
|
||||
auto wd = mon;
|
||||
do
|
||||
{
|
||||
auto x = y/last/wd;
|
||||
assert(date::year_month_day{x} == date::year_month_day{year_weeknum_weekday{x}});
|
||||
++wd;
|
||||
} while (wd != mon);
|
||||
}
|
||||
}
|
||||
|
@ -48,7 +48,10 @@ if [ -z "$CXX_LANG" ]
|
||||
then
|
||||
CXX_LANG=c++14
|
||||
fi
|
||||
OPTIONS="-std=${CXX_LANG} $OPTIONS -I$ROOT -Wall"
|
||||
OPTIONS="-std=${CXX_LANG} $OPTIONS -I$ROOT -Wall $ROOT/src/tz.cpp -lcurl"
|
||||
|
||||
echo $ROOT
|
||||
HEADER_INCLUDE="-I$ROOT/include -I$ROOT/include/date"
|
||||
|
||||
case $TRIPLE in
|
||||
*-*-mingw* | *-*-cygwin* | *-*-win*)
|
||||
|
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
|
38
test/tz_test/OffsetZone.pass.cpp
Normal file
38
test/tz_test/OffsetZone.pass.cpp
Normal file
@ -0,0 +1,38 @@
|
||||
// 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"
|
||||
#include "OffsetZone.h"
|
||||
#include <cassert>
|
||||
|
||||
int
|
||||
main()
|
||||
{
|
||||
using namespace date;
|
||||
using namespace std::chrono;
|
||||
auto now = system_clock::now();
|
||||
auto offset = hours{-4};
|
||||
zoned_time<system_clock::duration, OffsetZone> zt{OffsetZone{offset}, now};
|
||||
assert(zt.get_local_time().time_since_epoch() == now.time_since_epoch() + offset);
|
||||
}
|
@ -1,21 +1,15 @@
|
||||
To test: * Install tz.cpp by downloading the IANA timezone database
|
||||
at: http://www.iana.org/time-zones You only need the data, not the
|
||||
code.
|
||||
# TZ Test
|
||||
|
||||
* Change the string `install` in tz.cpp to point to your downloaded
|
||||
IANA database.
|
||||
## How to Test
|
||||
|
||||
* Install tz.cpp by downloading the IANA timezone database at: http://www.iana.org/time-zones You only need the data, not the code.
|
||||
* Change the string `install` in tz.cpp to point to your downloaded IANA database.
|
||||
* Compile validate.cpp along with tz.cpp.
|
||||
|
||||
* Run the binary and direct the terminal output to a temporary file.
|
||||
* Unzip the tzdata file that has the version corresponding to the IANA database you downloaded (e.g. tzdata2015f.txt.zip).
|
||||
* Compare the unzipped txt file with the output of your validate test program. If they are identical, the test passes, else it fails.
|
||||
|
||||
* Unzip the tzdata file that has the version corresponding to the IANA
|
||||
database you downloaded (e.g. tzdata2015f.txt.zip).
|
||||
|
||||
* Compare the unzipped txt file with the output of your validate test
|
||||
program. If they are identical, the test passes, else it fails.
|
||||
|
||||
Miscellaneous:
|
||||
## Miscellaneous
|
||||
|
||||
You can also compare one version of the tzdatabase with another using
|
||||
these uncompressed text files. The text files contain for each
|
||||
@ -25,4 +19,4 @@ versions change, minor updates to the set of these transitions are
|
||||
typically made, typically due to changes in government policies.
|
||||
|
||||
The tests in this section will run much faster with optimizations
|
||||
cranked up.
|
||||
cranked up.
|
||||
|
@ -1,4 +1,4 @@
|
||||
#include "tz.h"
|
||||
#include "date/tz.h"
|
||||
#include <iostream>
|
||||
|
||||
void
|
||||
@ -89,12 +89,18 @@ tzmain()
|
||||
using namespace std::chrono;
|
||||
auto& db = get_tzdb();
|
||||
std::vector<std::string> names;
|
||||
#if USE_OS_TZDB
|
||||
names.reserve(db.zones.size());
|
||||
for (auto& zone : db.zones)
|
||||
names.push_back(zone.name());
|
||||
#else // !USE_OS_TZDB
|
||||
names.reserve(db.zones.size() + db.links.size());
|
||||
for (auto& zone : db.zones)
|
||||
names.push_back(zone.name());
|
||||
for (auto& link : db.links)
|
||||
names.push_back(link.name());
|
||||
std::sort(names.begin(), names.end());
|
||||
#endif // !USE_OS_TZDB
|
||||
std::cout << db.version << "\n\n";
|
||||
for (auto const& name : names)
|
||||
{
|
||||
|
@ -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>
|
||||
|
||||
|
464
test/tz_test/zoned_time.pass.cpp
Normal file
464
test/tz_test/zoned_time.pass.cpp
Normal file
@ -0,0 +1,464 @@
|
||||
// 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 <class Duration>
|
||||
// class zoned_time
|
||||
// {
|
||||
// public:
|
||||
// using duration = typename std::common_type<Duration, std::chrono::seconds>::type;
|
||||
//
|
||||
// zoned_time();
|
||||
// zoned_time(const sys_time<Duration>& st);
|
||||
// explicit zoned_time(const time_zone* z);
|
||||
// explicit zoned_time(std::string_view name);
|
||||
//
|
||||
// template <class Duration2,
|
||||
// class = typename std::enable_if
|
||||
// <
|
||||
// std::is_convertible<sys_time<Duration2>,
|
||||
// sys_time<Duration>>::value
|
||||
// >::type>
|
||||
// zoned_time(const zoned_time<Duration2>& zt) NOEXCEPT;
|
||||
//
|
||||
// zoned_time(const time_zone* z, const local_time<Duration>& tp);
|
||||
// zoned_time(std::string_view name, const local_time<Duration>& tp);
|
||||
// zoned_time(const time_zone* z, const local_time<Duration>& tp, choose c);
|
||||
// zoned_time(std::string_view name, const local_time<Duration>& tp, choose c);
|
||||
//
|
||||
// zoned_time(const time_zone* z, const zoned_time<Duration>& zt);
|
||||
// zoned_time(std::string_view name, const zoned_time<Duration>& zt);
|
||||
// zoned_time(const time_zone* z, const zoned_time<Duration>& zt, choose);
|
||||
// zoned_time(std::string_view name, const zoned_time<Duration>& zt, choose);
|
||||
//
|
||||
// zoned_time(const time_zone* z, const sys_time<Duration>& st);
|
||||
// zoned_time(std::string_view name, const sys_time<Duration>& st);
|
||||
//
|
||||
// zoned_time& operator=(const sys_time<Duration>& st);
|
||||
// zoned_time& operator=(const local_time<Duration>& ut);
|
||||
//
|
||||
// explicit operator sys_time<duration>() const;
|
||||
// explicit operator local_time<duration>() const;
|
||||
//
|
||||
// const time_zone* get_time_zone() const;
|
||||
// local_time<duration> get_local_time() const;
|
||||
// sys_time<duration> get_sys_time() const;
|
||||
// sys_info get_info() const;
|
||||
//
|
||||
// template <class Duration1, class Duration2>
|
||||
// friend
|
||||
// bool
|
||||
// operator==(const zoned_time<Duration1>& x, const zoned_time<Duration2>& y);
|
||||
//
|
||||
// template <class CharT, class Traits, class Duration1>
|
||||
// friend
|
||||
// std::basic_ostream<CharT, Traits>&
|
||||
// operator<<(std::basic_ostream<CharT, Traits>& os, const zoned_time<Duration1>& t);
|
||||
// };
|
||||
//
|
||||
// using zoned_seconds = zoned_time<std::chrono::seconds>;
|
||||
//
|
||||
// template <class Duration1, class Duration2>
|
||||
// inline
|
||||
// bool
|
||||
// operator!=(const zoned_time<Duration1>& x, const zoned_time<Duration2>& y);
|
||||
//
|
||||
// template <class Duration>
|
||||
// zoned_time(sys_time<Duration>)
|
||||
// -> zoned_time<std::common_type_t<Duration, std::chrono::seconds>>;
|
||||
//
|
||||
// template <class Zone, class Duration>
|
||||
// zoned_time(Zone, sys_time<Duration>)
|
||||
// -> zoned_time<std::common_type_t<Duration, std::chrono::seconds>>;
|
||||
//
|
||||
// template <class Zone, class Duration>
|
||||
// zoned_time(Zone, local_time<Duration>, choose = choose::earliest)
|
||||
// -> zoned_time<std::common_type_t<Duration, std::chrono::seconds>>;
|
||||
//
|
||||
// template <class Zone, class Duration>
|
||||
// zoned_time(Zone, zoned_time<Duration>, choose = choose::earliest)
|
||||
// -> zoned_time<std::common_type_t<Duration, std::chrono::seconds>>;
|
||||
|
||||
#include "tz.h"
|
||||
#include <cassert>
|
||||
#include <sstream>
|
||||
#include <type_traits>
|
||||
|
||||
int
|
||||
main()
|
||||
{
|
||||
using namespace std;
|
||||
using namespace std::chrono;
|
||||
using namespace date;
|
||||
static_assert( is_nothrow_destructible<zoned_seconds>{}, "");
|
||||
static_assert( is_default_constructible<zoned_seconds>{}, "");
|
||||
static_assert( is_nothrow_copy_constructible<zoned_seconds>{}, "");
|
||||
static_assert( is_nothrow_copy_assignable<zoned_seconds>{}, "");
|
||||
static_assert( is_nothrow_move_constructible<zoned_seconds>{}, "");
|
||||
static_assert( is_nothrow_move_assignable<zoned_seconds>{}, "");
|
||||
|
||||
static_assert(is_same<zoned_time<minutes>::duration, seconds>{}, "");
|
||||
static_assert(is_same<zoned_seconds::duration, seconds>{}, "");
|
||||
static_assert(is_same<zoned_time<milliseconds>::duration, milliseconds>{}, "");
|
||||
|
||||
// zoned_time();
|
||||
{
|
||||
zoned_seconds zt;
|
||||
assert(zt.get_sys_time() == sys_seconds{});
|
||||
assert(zt.get_time_zone()->name() == "Etc/UTC");
|
||||
}
|
||||
|
||||
// zoned_time(const sys_time<Duration>& st);
|
||||
{
|
||||
static_assert(!is_convertible<sys_days, zoned_seconds>{}, "");
|
||||
static_assert( is_constructible<zoned_seconds, sys_days>{}, "");
|
||||
static_assert( is_convertible<sys_seconds, zoned_seconds>{}, "");
|
||||
static_assert(!is_convertible<sys_time<milliseconds>, zoned_seconds>{}, "");
|
||||
static_assert(!is_constructible<zoned_seconds, sys_time<milliseconds>>{}, "");
|
||||
|
||||
auto now = floor<seconds>(system_clock::now());
|
||||
zoned_seconds zt = now;
|
||||
assert(zt.get_sys_time() == now);
|
||||
assert(zt.get_time_zone()->name() == "Etc/UTC");
|
||||
}
|
||||
|
||||
// explicit zoned_time(const time_zone* z);
|
||||
{
|
||||
static_assert(!is_convertible<const time_zone*, zoned_seconds>{}, "");
|
||||
static_assert( is_constructible<zoned_seconds, const time_zone*>{}, "");
|
||||
zoned_seconds zt{locate_zone("America/New_York")};
|
||||
assert(zt.get_sys_time() == sys_seconds{});
|
||||
assert(zt.get_time_zone()->name() == "America/New_York");
|
||||
}
|
||||
|
||||
// explicit zoned_time(std::string_view name);
|
||||
{
|
||||
static_assert(!is_convertible<std::string, zoned_seconds>{}, "");
|
||||
static_assert( is_constructible<zoned_seconds, std::string>{}, "");
|
||||
static_assert( is_constructible<zoned_seconds, const char*>{}, "");
|
||||
static_assert( is_constructible<zoned_seconds, const char[3]>{}, "");
|
||||
zoned_seconds zt{"America/New_York"};
|
||||
assert(zt.get_sys_time() == sys_seconds{});
|
||||
assert(zt.get_time_zone()->name() == "America/New_York");
|
||||
}
|
||||
|
||||
// template <class Duration2,
|
||||
// class = typename std::enable_if
|
||||
// <
|
||||
// std::is_convertible<sys_time<Duration2>,
|
||||
// sys_time<Duration>>::value
|
||||
// >::type>
|
||||
// zoned_time(const zoned_time<Duration2>& zt) NOEXCEPT;
|
||||
{
|
||||
static_assert( is_convertible<zoned_time<days>, zoned_seconds>{}, "");
|
||||
static_assert(!is_constructible<zoned_time<days>, zoned_seconds>{}, "");
|
||||
zoned_time<days> zt1{"America/New_York", sys_days{2017_y/jul/5}};
|
||||
zoned_seconds zt2 = zt1;
|
||||
assert(zt2.get_sys_time() == sys_days{2017_y/jul/5});
|
||||
assert(zt2.get_time_zone()->name() == "America/New_York");
|
||||
}
|
||||
|
||||
// zoned_time(const time_zone* z, const local_time<Duration>& tp);
|
||||
{
|
||||
static_assert( is_constructible<zoned_seconds, const time_zone*, local_days>{}, "");
|
||||
zoned_seconds zt = {locate_zone("America/New_York"), local_days{2017_y/jul/5}};
|
||||
assert(zt.get_local_time() == local_days{2017_y/jul/5});
|
||||
assert(zt.get_time_zone()->name() == "America/New_York");
|
||||
try
|
||||
{
|
||||
zoned_seconds zt1 = {locate_zone("America/New_York"),
|
||||
local_days{2017_y/mar/sun[2]} + hours{2} + minutes{15}};
|
||||
assert(false);
|
||||
}
|
||||
catch(const nonexistent_local_time&)
|
||||
{
|
||||
}
|
||||
try
|
||||
{
|
||||
zoned_seconds zt1 = {locate_zone("America/New_York"),
|
||||
local_days{2017_y/nov/sun[1]} + hours{1} + minutes{15}};
|
||||
assert(false);
|
||||
}
|
||||
catch(const ambiguous_local_time&)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
// zoned_time(std::string_view name, const local_time<Duration>& tp);
|
||||
{
|
||||
static_assert( is_constructible<zoned_seconds, std::string, local_days>{}, "");
|
||||
static_assert( is_constructible<zoned_seconds, const char*, local_days>{}, "");
|
||||
zoned_seconds zt = {"America/New_York", local_days{2017_y/jul/5}};
|
||||
assert(zt.get_local_time() == local_days{2017_y/jul/5});
|
||||
assert(zt.get_time_zone()->name() == "America/New_York");
|
||||
try
|
||||
{
|
||||
zoned_seconds zt1 = {"America/New_York",
|
||||
local_days{2017_y/mar/sun[2]} + hours{2} + minutes{15}};
|
||||
assert(false);
|
||||
}
|
||||
catch(const nonexistent_local_time&)
|
||||
{
|
||||
}
|
||||
try
|
||||
{
|
||||
zoned_seconds zt1 = {"America/New_York",
|
||||
local_days{2017_y/nov/sun[1]} + hours{1} + minutes{15}};
|
||||
assert(false);
|
||||
}
|
||||
catch(const ambiguous_local_time&)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
// zoned_time(const time_zone* z, const local_time<Duration>& tp, choose c);
|
||||
{
|
||||
static_assert( is_constructible<zoned_seconds, const time_zone*, local_days, choose>{}, "");
|
||||
zoned_seconds zt = {locate_zone("America/New_York"),
|
||||
local_days{2017_y/jul/5} + hours{2} + minutes{15},
|
||||
choose::earliest};
|
||||
assert(zt.get_sys_time() == sys_days{2017_y/jul/5} + hours{6} + minutes{15});
|
||||
assert(zt.get_time_zone()->name() == "America/New_York");
|
||||
|
||||
zt = {locate_zone("America/New_York"),
|
||||
local_days{2017_y/jul/5} + hours{2} + minutes{15},
|
||||
choose::latest};
|
||||
assert(zt.get_sys_time() == sys_days{2017_y/jul/5} + hours{6} + minutes{15});
|
||||
assert(zt.get_time_zone()->name() == "America/New_York");
|
||||
|
||||
static_assert( is_constructible<zoned_seconds, const time_zone*, local_days, choose>{}, "");
|
||||
zoned_seconds zt1 = {locate_zone("America/New_York"),
|
||||
local_days{2017_y/mar/sun[2]} + hours{2} + minutes{15},
|
||||
choose::earliest};
|
||||
assert(zt1.get_sys_time() == sys_days{2017_y/mar/12} + hours{7});
|
||||
assert(zt1.get_time_zone()->name() == "America/New_York");
|
||||
|
||||
zoned_seconds zt2 = {locate_zone("America/New_York"),
|
||||
local_days{2017_y/mar/sun[2]} + hours{2} + minutes{15},
|
||||
choose::latest};
|
||||
assert(zt2.get_sys_time() == sys_days{2017_y/mar/12} + hours{7});
|
||||
assert(zt2.get_time_zone()->name() == "America/New_York");
|
||||
|
||||
zoned_seconds zt3 = {locate_zone("America/New_York"),
|
||||
local_days{2017_y/nov/sun[1]} + hours{1} + minutes{15},
|
||||
choose::earliest};
|
||||
assert(zt3.get_sys_time() == sys_days{2017_y/nov/5} + hours{5} + minutes{15});
|
||||
assert(zt3.get_time_zone()->name() == "America/New_York");
|
||||
|
||||
zoned_seconds zt4 = {locate_zone("America/New_York"),
|
||||
local_days{2017_y/nov/sun[1]} + hours{1} + minutes{15},
|
||||
choose::latest};
|
||||
assert(zt4.get_sys_time() == sys_days{2017_y/nov/5} + hours{6} + minutes{15});
|
||||
assert(zt4.get_time_zone()->name() == "America/New_York");
|
||||
}
|
||||
|
||||
// zoned_time(std::string_view name, const local_time<Duration>& tp, choose c);
|
||||
{
|
||||
static_assert( is_constructible<zoned_seconds, std::string, local_days, choose>{}, "");
|
||||
static_assert( is_constructible<zoned_seconds, const char*, local_days, choose>{}, "");
|
||||
zoned_seconds zt = {"America/New_York",
|
||||
local_days{2017_y/jul/5} + hours{2} + minutes{15},
|
||||
choose::earliest};
|
||||
assert(zt.get_sys_time() == sys_days{2017_y/jul/5} + hours{6} + minutes{15});
|
||||
assert(zt.get_time_zone()->name() == "America/New_York");
|
||||
|
||||
zt = {"America/New_York",
|
||||
local_days{2017_y/jul/5} + hours{2} + minutes{15},
|
||||
choose::latest};
|
||||
assert(zt.get_sys_time() == sys_days{2017_y/jul/5} + hours{6} + minutes{15});
|
||||
assert(zt.get_time_zone()->name() == "America/New_York");
|
||||
|
||||
static_assert( is_constructible<zoned_seconds, const time_zone*, local_days, choose>{}, "");
|
||||
zoned_seconds zt1 = {"America/New_York",
|
||||
local_days{2017_y/mar/sun[2]} + hours{2} + minutes{15},
|
||||
choose::earliest};
|
||||
assert(zt1.get_sys_time() == sys_days{2017_y/mar/12} + hours{7});
|
||||
assert(zt1.get_time_zone()->name() == "America/New_York");
|
||||
|
||||
zoned_seconds zt2 = {"America/New_York",
|
||||
local_days{2017_y/mar/sun[2]} + hours{2} + minutes{15},
|
||||
choose::latest};
|
||||
assert(zt2.get_sys_time() == sys_days{2017_y/mar/12} + hours{7});
|
||||
assert(zt2.get_time_zone()->name() == "America/New_York");
|
||||
|
||||
zoned_seconds zt3 = {"America/New_York",
|
||||
local_days{2017_y/nov/sun[1]} + hours{1} + minutes{15},
|
||||
choose::earliest};
|
||||
assert(zt3.get_sys_time() == sys_days{2017_y/nov/5} + hours{5} + minutes{15});
|
||||
assert(zt3.get_time_zone()->name() == "America/New_York");
|
||||
|
||||
zoned_seconds zt4 = {"America/New_York",
|
||||
local_days{2017_y/nov/sun[1]} + hours{1} + minutes{15},
|
||||
choose::latest};
|
||||
assert(zt4.get_sys_time() == sys_days{2017_y/nov/5} + hours{6} + minutes{15});
|
||||
assert(zt4.get_time_zone()->name() == "America/New_York");
|
||||
}
|
||||
|
||||
// zoned_time(const time_zone* z, const sys_time<Duration>& st);
|
||||
{
|
||||
static_assert( is_constructible<zoned_seconds, const time_zone*, sys_days>{}, "");
|
||||
|
||||
zoned_seconds zt = {locate_zone("America/New_York"),
|
||||
sys_days{2017_y/jul/5} + hours{2} + minutes{15}};
|
||||
assert(zt.get_sys_time() == sys_days{2017_y/jul/5} + hours{2} + minutes{15});
|
||||
assert(zt.get_time_zone()->name() == "America/New_York");
|
||||
}
|
||||
|
||||
// zoned_time(std::string_view name, const sys_time<Duration>& st);
|
||||
{
|
||||
static_assert( is_constructible<zoned_seconds, std::string, sys_days>{}, "");
|
||||
static_assert( is_constructible<zoned_seconds, const char*, sys_days>{}, "");
|
||||
|
||||
zoned_seconds zt = {"America/New_York",
|
||||
sys_days{2017_y/jul/5} + hours{2} + minutes{15}};
|
||||
assert(zt.get_sys_time() == sys_days{2017_y/jul/5} + hours{2} + minutes{15});
|
||||
assert(zt.get_time_zone()->name() == "America/New_York");
|
||||
}
|
||||
|
||||
// zoned_time& operator=(const sys_time<Duration>& st);
|
||||
{
|
||||
static_assert( is_assignable<zoned_seconds, const sys_days&>{}, "");
|
||||
|
||||
zoned_seconds zt{"America/New_York"};
|
||||
zt = sys_days{2017_y/jul/5};
|
||||
assert(zt.get_sys_time() == sys_days{2017_y/jul/5});
|
||||
assert(zt.get_time_zone()->name() == "America/New_York");
|
||||
}
|
||||
|
||||
// zoned_time& operator=(const local_time<Duration>& st);
|
||||
{
|
||||
static_assert( is_assignable<zoned_seconds, const local_days&>{}, "");
|
||||
|
||||
zoned_seconds zt{"America/New_York"};
|
||||
zt = local_days{2017_y/jul/5};
|
||||
assert(zt.get_local_time() == local_days{2017_y/jul/5});
|
||||
assert(zt.get_time_zone()->name() == "America/New_York");
|
||||
try
|
||||
{
|
||||
zt = {"America/New_York",
|
||||
local_days{2017_y/mar/sun[2]} + hours{2} + minutes{15}};
|
||||
assert(false);
|
||||
}
|
||||
catch(const nonexistent_local_time&)
|
||||
{
|
||||
assert(zt.get_local_time() == local_days{2017_y/jul/5});
|
||||
assert(zt.get_time_zone()->name() == "America/New_York");
|
||||
}
|
||||
try
|
||||
{
|
||||
zt = {"America/New_York",
|
||||
local_days{2017_y/nov/sun[1]} + hours{1} + minutes{15}};
|
||||
assert(false);
|
||||
}
|
||||
catch(const ambiguous_local_time&)
|
||||
{
|
||||
assert(zt.get_local_time() == local_days{2017_y/jul/5});
|
||||
assert(zt.get_time_zone()->name() == "America/New_York");
|
||||
}
|
||||
}
|
||||
|
||||
// explicit operator sys_time<duration>() const;
|
||||
{
|
||||
static_assert(!is_convertible<zoned_seconds, sys_seconds>{}, "");
|
||||
static_assert( is_constructible<sys_seconds, zoned_seconds>{}, "");
|
||||
auto now = floor<seconds>(system_clock::now());
|
||||
const zoned_seconds zt = {"America/New_York", now};
|
||||
assert(sys_seconds{zt} == now);
|
||||
}
|
||||
|
||||
// explicit operator local_time<duration>() const;
|
||||
{
|
||||
static_assert(!is_convertible<zoned_seconds, local_seconds>{}, "");
|
||||
static_assert( is_constructible<local_seconds, zoned_seconds>{}, "");
|
||||
auto now = local_days{2017_y/jul/5} + hours{23} + minutes{1} + seconds{48};
|
||||
const zoned_seconds zt = {"America/New_York", now};
|
||||
assert(local_seconds{zt} == now);
|
||||
}
|
||||
|
||||
// const time_zone* get_time_zone() const;
|
||||
{
|
||||
const zoned_seconds zt{"America/New_York"};
|
||||
assert(zt.get_time_zone() == locate_zone("America/New_York"));
|
||||
}
|
||||
|
||||
// local_time<duration> get_local_time() const;
|
||||
{
|
||||
const zoned_seconds zt{"America/New_York", sys_days{2017_y/jul/6} +
|
||||
hours{3} + minutes{7} + seconds{9}};
|
||||
assert(zt.get_local_time() == local_days{2017_y/jul/5} +
|
||||
hours{23} + minutes{7} + seconds{9});
|
||||
}
|
||||
|
||||
// sys_time<duration> get_sys_time() const;
|
||||
{
|
||||
const zoned_seconds zt{"America/New_York", sys_days{2017_y/jul/6} +
|
||||
hours{3} + minutes{7} + seconds{9}};
|
||||
assert(zt.get_sys_time() == sys_days{2017_y/jul/6} +
|
||||
hours{3} + minutes{7} + seconds{9});
|
||||
}
|
||||
|
||||
// sys_info get_info() const;
|
||||
{
|
||||
const zoned_seconds zt{"America/New_York", sys_days{2017_y/jul/6} +
|
||||
hours{3} + minutes{7} + seconds{9}};
|
||||
auto info = zt.get_info();
|
||||
assert(info.begin == sys_days{2017_y/mar/12} + hours{7});
|
||||
assert(info.end == sys_days{2017_y/nov/5} + hours{6});
|
||||
assert(info.offset == hours{-4});
|
||||
assert(info.save != minutes{0});
|
||||
assert(info.abbrev == "EDT");
|
||||
}
|
||||
|
||||
// template <class Duration1, class Duration2>
|
||||
// bool
|
||||
// operator==(const zoned_time<Duration1>& x, const zoned_time<Duration2>& y);
|
||||
{
|
||||
const zoned_seconds zt{"America/New_York", sys_days{2017_y/jul/6} +
|
||||
hours{3} + minutes{7} + seconds{9}};
|
||||
const zoned_seconds zt1{"America/New_York", sys_days{2017_y/jul/6} +
|
||||
hours{3} + minutes{7} + seconds{10}};
|
||||
assert(zt == zt);
|
||||
assert(!(zt == zt1));
|
||||
}
|
||||
|
||||
// template <class Duration1, class Duration2>
|
||||
// bool
|
||||
// operator!=(const zoned_time<Duration1>& x, const zoned_time<Duration2>& y);
|
||||
{
|
||||
const zoned_seconds zt{"America/New_York", sys_days{2017_y/jul/6} +
|
||||
hours{3} + minutes{7} + seconds{9}};
|
||||
const zoned_seconds zt1{"America/New_York", sys_days{2017_y/jul/6} +
|
||||
hours{3} + minutes{7} + seconds{10}};
|
||||
assert(!(zt != zt));
|
||||
assert(zt != zt1);
|
||||
}
|
||||
|
||||
// template <class CharT, class Traits, class Duration1>
|
||||
// std::basic_ostream<CharT, Traits>&
|
||||
// operator<<(std::basic_ostream<CharT, Traits>& os, const zoned_time<Duration1>& t);
|
||||
{
|
||||
const zoned_seconds zt{"America/New_York", sys_days{2017_y/jul/6} +
|
||||
hours{3} + minutes{7} + seconds{9}};
|
||||
std::ostringstream test;
|
||||
test << zt;
|
||||
assert(test.str() == "2017-07-05 23:07:09 EDT");
|
||||
}
|
||||
}
|
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
|
||||
}
|
10
test_fail.sh
Executable file
10
test_fail.sh
Executable file
@ -0,0 +1,10 @@
|
||||
#!/bin/bash
|
||||
|
||||
echo $1
|
||||
eval $1
|
||||
|
||||
if [ $? -eq 0 ]; then
|
||||
exit 0;
|
||||
fi
|
||||
exit 1;
|
||||
|
Reference in New Issue
Block a user