mirror of
https://github.com/HowardHinnant/date.git
synced 2025-06-30 11:31:04 +02:00
Compare commits
137 Commits
Author | SHA1 | Date | |
---|---|---|---|
229c6876c6 | |||
0a1b72bf9d | |||
6d7739e7e8 | |||
f94b8f36c6 | |||
a45ea7c17b | |||
0b336657b1 | |||
32ecb2ad24 | |||
d18e8b1653 | |||
b8d166b4b0 | |||
ca5727855b | |||
d0424a2518 | |||
8a1102fd08 | |||
632af88e80 | |||
28b7b23252 | |||
f079e3568c | |||
1a4f424659 | |||
5bdb7e6f31 | |||
e396108ee3 | |||
deec054564 | |||
dd8affc6de | |||
510a05429f | |||
361352673d | |||
447f5a30b9 | |||
fca69e308d | |||
7657ad7855 | |||
bbe2f51bc0 | |||
3e43210885 | |||
ac0c58d5da | |||
ab1dc3a5eb | |||
7c151cdb6a | |||
3286289bf6 | |||
cf8f25b183 | |||
dc9d161607 | |||
d2ddc5ea1e | |||
6219dd7e4d | |||
939031c38c | |||
51ce7e1310 | |||
155c6b9e76 | |||
1ead6715de | |||
f986299fbb | |||
706b1286e8 | |||
8a93211679 | |||
6b1c1b8b3a | |||
8f8336f42b | |||
cd3c57932f | |||
575fc23c3c | |||
0e65940a7f | |||
88a3b15126 | |||
5d225951ff | |||
ab37c362e3 | |||
0ef86f1ced | |||
cc4685a21e | |||
50acf3ffd8 | |||
15e0c84e42 | |||
28972d72b4 | |||
5f8c904231 | |||
c9169ea310 | |||
22ceabf205 | |||
c82b776f28 | |||
2c035f8def | |||
e6f4aed4d1 | |||
9ea5654c12 | |||
9d9161c978 | |||
3776e0f185 | |||
9e830536a0 | |||
655b249b8f | |||
529a09267f | |||
d9049ee697 | |||
2709deddd3 | |||
2e19c006e2 | |||
28b5106d4c | |||
e1aa4837e0 | |||
1ff7208036 | |||
b0adc54677 | |||
d57d764707 | |||
383214dea6 | |||
fb2554a7e0 | |||
8c126525cc | |||
8f95c598c9 | |||
417402ad35 | |||
38267fa1ef | |||
ebb5719cd7 | |||
2f4411312b | |||
e23c15bb36 | |||
052eebaf00 | |||
b49a7575eb | |||
6e921e1b1d | |||
39b4edf279 | |||
2ef74cb41a | |||
ac6ca2a095 | |||
ae017078c9 | |||
156e0a786e | |||
9a9a42db74 | |||
b5b765f928 | |||
77bd6b92a4 | |||
654b97091f | |||
b899774303 | |||
0e08b942c8 | |||
811be52e1c | |||
1c285d6545 | |||
bf79dd5a81 | |||
26fc2bd372 | |||
97246a638a | |||
432bab81f9 | |||
215cacff56 | |||
3cbfa4318f | |||
115dd428cf | |||
7848566815 | |||
393b52f21b | |||
0b72599bd4 | |||
ba99134b8a | |||
5e18488899 | |||
313189b0a8 | |||
057b441ceb | |||
d7a0bf1fa7 | |||
8140d979cd | |||
7990eae740 | |||
1ec2ea0295 | |||
658a3b9495 | |||
e7969c32e8 | |||
569b2d6785 | |||
abe3ada04f | |||
9537addfc4 | |||
6952fb50a6 | |||
fe2f9c7eac | |||
a6243ce56f | |||
a55f1a103b | |||
d544e5af25 | |||
cac99da8dc | |||
a088baf9a5 | |||
e6adff6754 | |||
d784766640 | |||
9343e31599 | |||
f43c39fcf1 | |||
e12095f26f | |||
7d811743e0 | |||
a2fdba1adc |
4
.gitattributes
vendored
Normal file
4
.gitattributes
vendored
Normal file
@ -0,0 +1,4 @@
|
||||
# Normalize EOL for all files that Git considers text files.
|
||||
* text=auto eol=lf
|
||||
*zip -text -diff
|
||||
|
2
.gitignore
vendored
2
.gitignore
vendored
@ -135,7 +135,7 @@ publish/
|
||||
# Publish Web Output
|
||||
*.[Pp]ublish.xml
|
||||
*.azurePubxml
|
||||
# TODO: Comment the next line if you want to checkin your web deploy settings
|
||||
# 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
|
||||
|
219
CMakeLists.txt
219
CMakeLists.txt
@ -7,7 +7,7 @@
|
||||
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
|
||||
GIT_TAG v3.0.1 # adjust tag/branch/commit as needed
|
||||
)
|
||||
FetchContent_MakeAvailable(date_src)
|
||||
...
|
||||
@ -17,12 +17,16 @@
|
||||
|
||||
cmake_minimum_required( VERSION 3.7 )
|
||||
|
||||
project( date VERSION 2.4.1 )
|
||||
|
||||
include( GNUInstallDirs )
|
||||
project( date VERSION 3.0.4 )
|
||||
set(ABI_VERSION 3) # used as SOVERSION, increment when ABI changes
|
||||
|
||||
get_directory_property( has_parent PARENT_DIRECTORY )
|
||||
|
||||
if (POLICY CMP0077)
|
||||
# Allow CMake 3.13+ to override options when using FetchContent / add_subdirectory.
|
||||
cmake_policy(SET CMP0077 NEW)
|
||||
endif ()
|
||||
|
||||
# Override by setting on CMake command line.
|
||||
set( CMAKE_CXX_STANDARD 17 CACHE STRING "The C++ standard whose features are requested." )
|
||||
|
||||
@ -34,12 +38,17 @@ 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 )
|
||||
option( ENABLE_DATE_INSTALL "Enable install" ON )
|
||||
|
||||
if( ENABLE_DATE_TESTING AND NOT BUILD_TZ_LIB )
|
||||
message(WARNING "Testing requested, bug BUILD_TZ_LIB not ON - forcing the latter")
|
||||
message(WARNING "Testing requested, but BUILD_TZ_LIB not ON - forcing the latter")
|
||||
set (BUILD_TZ_LIB ON CACHE BOOL "required for testing" FORCE)
|
||||
endif( )
|
||||
|
||||
if( ENABLE_DATE_INSTALL )
|
||||
include( GNUInstallDirs )
|
||||
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 "" )
|
||||
@ -62,116 +71,166 @@ 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> )
|
||||
$<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}> )
|
||||
# adding header sources just helps IDEs
|
||||
target_sources( date INTERFACE
|
||||
$<BUILD_INTERFACE:${CMAKE_CURRENT_LIST_DIR}/include>$<INSTALL_INTERFACE:include>/date/date.h
|
||||
# the rest of these are not currently part of the public interface of the library:
|
||||
$<BUILD_INTERFACE:${CMAKE_CURRENT_LIST_DIR}/include/date/solar_hijri.h>
|
||||
$<BUILD_INTERFACE:${CMAKE_CURRENT_LIST_DIR}/include/date/islamic.h>
|
||||
$<BUILD_INTERFACE:${CMAKE_CURRENT_LIST_DIR}/include/date/iso_week.h>
|
||||
$<BUILD_INTERFACE:${CMAKE_CURRENT_LIST_DIR}/include/date/julian.h>
|
||||
$<BUILD_INTERFACE:${CMAKE_CURRENT_LIST_DIR}/include>$<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>/date/date.h
|
||||
$<BUILD_INTERFACE:${CMAKE_CURRENT_LIST_DIR}/include>$<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>/date/solar_hijri.h
|
||||
$<BUILD_INTERFACE:${CMAKE_CURRENT_LIST_DIR}/include>$<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>/date/islamic.h
|
||||
$<BUILD_INTERFACE:${CMAKE_CURRENT_LIST_DIR}/include>$<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>/date/iso_week.h
|
||||
$<BUILD_INTERFACE:${CMAKE_CURRENT_LIST_DIR}/include>$<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>/date/julian.h
|
||||
)
|
||||
|
||||
set( APPLE_MOBILE_PLATFORM FALSE )
|
||||
if ( IOS
|
||||
OR CMAKE_SYSTEM_NAME STREQUAL "iOS"
|
||||
OR CMAKE_SYSTEM_NAME STREQUAL "visionOS"
|
||||
OR CMAKE_SYSTEM_NAME STREQUAL "watchOS"
|
||||
OR CMAKE_SYSTEM_NAME STREQUAL "tvOS"
|
||||
)
|
||||
set( APPLE_MOBILE_PLATFORM TRUE )
|
||||
endif()
|
||||
|
||||
set(TARGET_HEADERS
|
||||
include/date/date.h
|
||||
include/date/solar_hijri.h
|
||||
include/date/islamic.h
|
||||
include/date/iso_week.h
|
||||
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 )
|
||||
set_target_properties( date PROPERTIES PUBLIC_HEADER "${TARGET_HEADERS}" )
|
||||
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> )
|
||||
|
||||
# These used to be set with generator expressions,
|
||||
#
|
||||
# ONLY_C_LOCALE=$<IF:$<BOOL:${COMPILE_WITH_C_LOCALE}>,1,0>
|
||||
#
|
||||
# which expand in the output target file to, e.g.
|
||||
#
|
||||
# ONLY_C_LOCALE=$<IF:$<BOOL:FALSE>,1,0>
|
||||
#
|
||||
# This string is then (somtimes?) not correctly interpreted.
|
||||
if ( COMPILE_WITH_C_LOCALE )
|
||||
# To workaround libstdc++ issue https://github.com/HowardHinnant/date/issues/388
|
||||
target_compile_definitions( date INTERFACE ONLY_C_LOCALE=1 )
|
||||
else()
|
||||
target_compile_definitions( date INTERFACE ONLY_C_LOCALE=0 )
|
||||
endif()
|
||||
if ( DISABLE_STRING_VIEW )
|
||||
target_compile_definitions( date INTERFACE HAS_STRING_VIEW=0 -DHAS_DEDUCTION_GUIDES=0 )
|
||||
else()
|
||||
target_compile_definitions( date INTERFACE HAS_STRING_VIEW=1 )
|
||||
endif()
|
||||
|
||||
#[===================================================================[
|
||||
tz (compiled) library
|
||||
#]===================================================================]
|
||||
if( BUILD_TZ_LIB )
|
||||
add_library( tz )
|
||||
target_sources( tz
|
||||
add_library( date-tz )
|
||||
target_compile_definitions( date-tz PRIVATE BUILD_TZ_LIB=1 )
|
||||
target_sources( date-tz
|
||||
PUBLIC
|
||||
$<BUILD_INTERFACE:${CMAKE_CURRENT_LIST_DIR}/include>$<INSTALL_INTERFACE:include>/date/tz.h
|
||||
$<$<BOOL:${IOS}>:$<BUILD_INTERFACE:${CMAKE_CURRENT_LIST_DIR}/include>$<INSTALL_INTERFACE:include>/date/ios.h>
|
||||
$<BUILD_INTERFACE:${CMAKE_CURRENT_LIST_DIR}/include>$<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>/date/tz.h
|
||||
PRIVATE
|
||||
include/date/tz_private.h
|
||||
$<$<BOOL:${IOS}>:src/ios.mm>
|
||||
src/tz.cpp )
|
||||
add_library( date::tz ALIAS tz )
|
||||
target_link_libraries( tz PUBLIC date )
|
||||
target_include_directories( tz PUBLIC
|
||||
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>
|
||||
$<INSTALL_INTERFACE:include> )
|
||||
target_compile_definitions( tz
|
||||
PRIVATE
|
||||
AUTO_DOWNLOAD=$<IF:$<OR:$<BOOL:${USE_SYSTEM_TZ_DB}>,$<BOOL:${MANUAL_TZ_DB}>>,0,1>
|
||||
HAS_REMOTE_API=$<IF:$<OR:$<BOOL:${USE_SYSTEM_TZ_DB}>,$<BOOL:${MANUAL_TZ_DB}>>,0,1>
|
||||
$<$<AND:$<BOOL:${WIN32}>,$<BOOL:${BUILD_SHARED_LIBS}>>:DATE_BUILD_DLL=1>
|
||||
$<$<BOOL:${USE_TZ_DB_IN_DOT}>:INSTALL=.>
|
||||
if ( APPLE_MOBILE_PLATFORM )
|
||||
target_sources( date-tz
|
||||
PUBLIC
|
||||
USE_OS_TZDB=$<IF:$<AND:$<BOOL:${USE_SYSTEM_TZ_DB}>,$<NOT:$<BOOL:${WIN32}>>,$<NOT:$<BOOL:${MANUAL_TZ_DB}>>>,1,0>
|
||||
INTERFACE
|
||||
$<$<AND:$<BOOL:${WIN32}>,$<BOOL:${BUILD_SHARED_LIBS}>>:DATE_USE_DLL=1> )
|
||||
$<BUILD_INTERFACE:${CMAKE_CURRENT_LIST_DIR}/include>$<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>/date/ios.h
|
||||
PRIVATE
|
||||
src/ios.mm )
|
||||
endif()
|
||||
add_library( date::date-tz ALIAS date-tz )
|
||||
target_link_libraries( date-tz PUBLIC date )
|
||||
target_include_directories( date-tz PUBLIC
|
||||
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>
|
||||
$<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}> )
|
||||
|
||||
if ( USE_SYSTEM_TZ_DB OR MANUAL_TZ_DB )
|
||||
target_compile_definitions( date-tz PRIVATE AUTO_DOWNLOAD=0 HAS_REMOTE_API=0 )
|
||||
else()
|
||||
target_compile_definitions( date-tz PRIVATE AUTO_DOWNLOAD=1 HAS_REMOTE_API=1 )
|
||||
endif()
|
||||
|
||||
if ( USE_SYSTEM_TZ_DB AND NOT WIN32 AND NOT MANUAL_TZ_DB )
|
||||
target_compile_definitions( date-tz PRIVATE INSTALL=. PUBLIC USE_OS_TZDB=1 )
|
||||
else()
|
||||
target_compile_definitions( date-tz PUBLIC USE_OS_TZDB=0 )
|
||||
endif()
|
||||
|
||||
if ( WIN32 AND BUILD_SHARED_LIBS )
|
||||
target_compile_definitions( date-tz PUBLIC DATE_BUILD_DLL=1 )
|
||||
endif()
|
||||
|
||||
set(TZ_HEADERS include/date/tz.h)
|
||||
if( IOS )
|
||||
|
||||
if( APPLE_MOBILE_PLATFORM )
|
||||
list(APPEND TZ_HEADERS include/date/ios.h)
|
||||
endif( )
|
||||
set_target_properties( tz PROPERTIES
|
||||
set_target_properties( date-tz PROPERTIES
|
||||
POSITION_INDEPENDENT_CODE ON
|
||||
PUBLIC_HEADER "${TZ_HEADERS}"
|
||||
VERSION "${PROJECT_VERSION}"
|
||||
SOVERSION "${PROJECT_VERSION}" )
|
||||
SOVERSION "${ABI_VERSION}" )
|
||||
if( NOT MSVC )
|
||||
find_package( Threads )
|
||||
target_link_libraries( tz PUBLIC Threads::Threads )
|
||||
target_link_libraries( date-tz PUBLIC Threads::Threads )
|
||||
endif( )
|
||||
if( NOT USE_SYSTEM_TZ_DB AND NOT MANUAL_TZ_DB )
|
||||
find_package( CURL REQUIRED )
|
||||
target_include_directories( tz SYSTEM PRIVATE ${CURL_INCLUDE_DIRS} )
|
||||
target_link_libraries( tz PRIVATE ${CURL_LIBRARIES} )
|
||||
target_link_libraries( date-tz PRIVATE CURL::libcurl )
|
||||
endif( )
|
||||
endif( )
|
||||
|
||||
#[===================================================================[
|
||||
installation
|
||||
#]===================================================================]
|
||||
set( version_config "${CMAKE_CURRENT_BINARY_DIR}/dateConfigVersion.cmake" )
|
||||
if( ENABLE_DATE_INSTALL )
|
||||
set( version_config "${CMAKE_CURRENT_BINARY_DIR}/dateConfigVersion.cmake" )
|
||||
|
||||
include( CMakePackageConfigHelpers )
|
||||
write_basic_package_version_file( "${version_config}"
|
||||
VERSION ${PROJECT_VERSION}
|
||||
COMPATIBILITY SameMajorVersion )
|
||||
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 ()
|
||||
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 ${TARGET_HEADERS}
|
||||
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 )
|
||||
if( BUILD_TZ_LIB )
|
||||
install( TARGETS date-tz
|
||||
EXPORT dateConfig
|
||||
PUBLIC_HEADER DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/date
|
||||
ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}
|
||||
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
|
||||
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} ) # This is for Windows
|
||||
export( TARGETS date-tz NAMESPACE date:: APPEND FILE dateTargets.cmake )
|
||||
endif( )
|
||||
|
||||
if( WIN32 AND NOT CYGWIN)
|
||||
set( CONFIG_LOC CMake )
|
||||
else( )
|
||||
set( CONFIG_LOC "${CMAKE_INSTALL_LIBDIR}/cmake/date" )
|
||||
endif( )
|
||||
install( EXPORT dateConfig
|
||||
FILE dateTargets.cmake
|
||||
NAMESPACE date::
|
||||
DESTINATION ${CONFIG_LOC} )
|
||||
install (
|
||||
FILES cmake/dateConfig.cmake "${version_config}"
|
||||
DESTINATION ${CONFIG_LOC})
|
||||
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
|
||||
#]===================================================================]
|
||||
@ -179,7 +238,7 @@ if( ENABLE_DATE_TESTING )
|
||||
enable_testing( )
|
||||
|
||||
add_custom_target( testit COMMAND ${CMAKE_CTEST_COMMAND} )
|
||||
add_dependencies( testit tz )
|
||||
add_dependencies( testit date-tz )
|
||||
|
||||
function( add_pass_tests TEST_GLOB TEST_PREFIX )
|
||||
file( GLOB_RECURSE FILENAMES ${TEST_GLOB} )
|
||||
@ -193,7 +252,7 @@ if( ENABLE_DATE_TESTING )
|
||||
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 )
|
||||
target_link_libraries( ${BIN_NAME} date-tz )
|
||||
# HACK: because the test files don't use FQ includes:
|
||||
target_include_directories( ${BIN_NAME} PRIVATE include/date )
|
||||
add_dependencies( testit ${BIN_NAME} )
|
||||
@ -222,7 +281,7 @@ if( ENABLE_DATE_TESTING )
|
||||
${CMAKE_CXX_COMPILER}
|
||||
-std=c++14
|
||||
-L${CMAKE_BINARY_DIR}/
|
||||
-ltz
|
||||
-ldate-tz
|
||||
-I${PROJECT_SOURCE_DIR}/include
|
||||
-I${PROJECT_SOURCE_DIR}/include/date
|
||||
-o ${BIN_NAME}
|
||||
|
18
README.md
18
README.md
@ -5,7 +5,7 @@
|
||||
|
||||
---
|
||||
|
||||
**[Try it out on wandbox!](https://wandbox.org/permlink/L8MwjzSSC3fXXrMd)**
|
||||
**[Try it out on wandbox!](https://wandbox.org/permlink/oyXjibyF680HHoyS)**
|
||||
|
||||
## Summary
|
||||
|
||||
@ -43,6 +43,14 @@ Slightly modified versions of `"date.h"` and `"tz.h"` were voted into the C++20
|
||||
|
||||
## Build & Test
|
||||
|
||||
The recommended way to use any of these libraries besides `"tz.h"` is to just include it. These are header-only libraries (except `"tz.h"`).
|
||||
|
||||
To use `"tz.h"`, there is a single source file (`src/tz.cpp`) that needs to be compiled. Here are the recommended directions: https://howardhinnant.github.io/date/tz.html#Installation.
|
||||
|
||||
One can run tests by cd'ing into the `test` subdirectory and running `testit`. There are known failures on all platforms except for macOS. And even on macOS if C++11 is used. If any of these failures present problems for you, there exist workarounds.
|
||||
|
||||
Additionally there is _unsupported_ support for [vcpkg](https://github.com/Microsoft/vcpkg) and [CMake](https://cmake.org/). I don't personally use or maintain these systems as for me they cause more problems than they solve (for this small project). If you would like to contribute to these build systems please feel free to file a PR.
|
||||
|
||||
You can download and install Date using the [vcpkg](https://github.com/Microsoft/vcpkg) dependency manager:
|
||||
|
||||
git clone https://github.com/Microsoft/vcpkg.git
|
||||
@ -58,7 +66,7 @@ You can optionally build using [CMake](https://cmake.org/). Here is a guide of h
|
||||
```bash
|
||||
mkdir build
|
||||
cd build
|
||||
cmake ../
|
||||
cmake -DENABLE_DATE_TESTING=ON -DBUILD_TZ_LIB=ON ../
|
||||
cmake --build . --target testit # Consider '-- -j4' for multithreading
|
||||
```
|
||||
## Projects using this library
|
||||
@ -68,5 +76,11 @@ cmake --build . --target testit # Consider '-- -j4' for multithreading
|
||||
* https://github.com/ViewTouch/viewtouch
|
||||
* https://routinghub.com
|
||||
* https://github.com/valhalla
|
||||
* https://github.com/siodb/siodb
|
||||
* https://github.com/KomodoPlatform/atomicDEX-Pro
|
||||
* https://github.com/Kotlin/kotlinx-datetime
|
||||
* https://github.com/royalbee/jewish_date
|
||||
* https://github.com/apache/arrow/
|
||||
* https://lottopark.com
|
||||
|
||||
If you would like your project (or product) on this list, just let me know.
|
||||
|
@ -1,8 +1,8 @@
|
||||
include( CMakeFindDependencyMacro )
|
||||
include( "${CMAKE_CURRENT_LIST_DIR}/dateTargets.cmake" )
|
||||
if( NOT MSVC AND TARGET date::tz )
|
||||
if( NOT MSVC AND TARGET date::date-tz )
|
||||
find_dependency( Threads REQUIRED)
|
||||
get_target_property( _tzill date::tz INTERFACE_LINK_LIBRARIES )
|
||||
get_target_property( _tzill date::date-tz INTERFACE_LINK_LIBRARIES )
|
||||
if( _tzill AND "${_tzill}" MATCHES "libcurl" )
|
||||
find_dependency( CURL )
|
||||
endif( )
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -36,10 +36,10 @@
|
||||
{
|
||||
namespace iOSUtils
|
||||
{
|
||||
|
||||
|
||||
std::string get_tzdata_path();
|
||||
std::string get_current_timezone();
|
||||
|
||||
|
||||
} // namespace iOSUtils
|
||||
} // namespace date
|
||||
|
||||
|
@ -758,8 +758,8 @@ operator<<(std::basic_ostream<CharT, Traits>& os, const year_month_weekday_last&
|
||||
inline namespace literals
|
||||
{
|
||||
|
||||
CONSTCD11 islamic::day operator "" _d(unsigned long long d) NOEXCEPT;
|
||||
CONSTCD11 islamic::year operator "" _y(unsigned long long y) NOEXCEPT;
|
||||
CONSTCD11 islamic::day operator ""_d(unsigned long long d) NOEXCEPT;
|
||||
CONSTCD11 islamic::year operator ""_y(unsigned long long y) NOEXCEPT;
|
||||
|
||||
} // inline namespace literals
|
||||
#endif // !defined(_MSC_VER) || (_MSC_VER >= 1900)
|
||||
@ -1339,7 +1339,7 @@ inline namespace literals
|
||||
CONSTCD11
|
||||
inline
|
||||
islamic::day
|
||||
operator "" _d(unsigned long long d) NOEXCEPT
|
||||
operator ""_d(unsigned long long d) NOEXCEPT
|
||||
{
|
||||
return islamic::day{static_cast<unsigned>(d)};
|
||||
}
|
||||
@ -1347,7 +1347,7 @@ operator "" _d(unsigned long long d) NOEXCEPT
|
||||
CONSTCD11
|
||||
inline
|
||||
islamic::year
|
||||
operator "" _y(unsigned long long y) NOEXCEPT
|
||||
operator ""_y(unsigned long long y) NOEXCEPT
|
||||
{
|
||||
return islamic::year(static_cast<int>(y));
|
||||
}
|
||||
|
@ -148,6 +148,8 @@ public:
|
||||
year& operator+=(const years& y) NOEXCEPT;
|
||||
year& operator-=(const years& y) NOEXCEPT;
|
||||
|
||||
CONSTCD14 bool is_leap() const NOEXCEPT;
|
||||
|
||||
CONSTCD11 explicit operator int() const NOEXCEPT;
|
||||
CONSTCD11 bool ok() const NOEXCEPT;
|
||||
|
||||
@ -599,6 +601,17 @@ inline year year::operator--(int) NOEXCEPT {auto tmp(*this); --(*this); return t
|
||||
inline year& year::operator+=(const years& y) NOEXCEPT {*this = *this + y; return *this;}
|
||||
inline year& year::operator-=(const years& y) NOEXCEPT {*this = *this - y; return *this;}
|
||||
|
||||
CONSTCD14
|
||||
inline
|
||||
bool
|
||||
year::is_leap() 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 s1-s0 != days{7*52};
|
||||
}
|
||||
|
||||
CONSTCD11 inline year::operator int() const NOEXCEPT {return y_;}
|
||||
CONSTCD11 inline bool year::ok() const NOEXCEPT {return min() <= *this && *this <= max();}
|
||||
|
||||
@ -734,7 +747,7 @@ inline namespace literals
|
||||
CONSTCD11
|
||||
inline
|
||||
iso_week::year
|
||||
operator "" _y(unsigned long long y) NOEXCEPT
|
||||
operator ""_y(unsigned long long y) NOEXCEPT
|
||||
{
|
||||
return iso_week::year(static_cast<int>(y));
|
||||
}
|
||||
@ -742,7 +755,7 @@ operator "" _y(unsigned long long y) NOEXCEPT
|
||||
CONSTCD11
|
||||
inline
|
||||
iso_week::weeknum
|
||||
operator "" _w(unsigned long long wn) NOEXCEPT
|
||||
operator ""_w(unsigned long long wn) NOEXCEPT
|
||||
{
|
||||
return iso_week::weeknum(static_cast<unsigned>(wn));
|
||||
}
|
||||
@ -1020,10 +1033,7 @@ inline
|
||||
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(static_cast<unsigned>(date::trunc<weeks>(s1-s0).count()));
|
||||
return iso_week::weeknum(y_.is_leap() ? 53u : 52u);
|
||||
}
|
||||
|
||||
CONSTCD11 inline bool year_lastweek::ok() const NOEXCEPT {return y_.ok();}
|
||||
|
@ -758,8 +758,8 @@ operator<<(std::basic_ostream<CharT, Traits>& os, const year_month_weekday_last&
|
||||
inline namespace literals
|
||||
{
|
||||
|
||||
CONSTCD11 julian::day operator "" _d(unsigned long long d) NOEXCEPT;
|
||||
CONSTCD11 julian::year operator "" _y(unsigned long long y) NOEXCEPT;
|
||||
CONSTCD11 julian::day operator ""_d(unsigned long long d) NOEXCEPT;
|
||||
CONSTCD11 julian::year operator ""_y(unsigned long long y) NOEXCEPT;
|
||||
|
||||
// CONSTDATA julian::month jan{1};
|
||||
// CONSTDATA julian::month feb{2};
|
||||
@ -1333,7 +1333,7 @@ inline namespace literals
|
||||
CONSTCD11
|
||||
inline
|
||||
julian::day
|
||||
operator "" _d(unsigned long long d) NOEXCEPT
|
||||
operator ""_d(unsigned long long d) NOEXCEPT
|
||||
{
|
||||
return julian::day{static_cast<unsigned>(d)};
|
||||
}
|
||||
@ -1341,7 +1341,7 @@ operator "" _d(unsigned long long d) NOEXCEPT
|
||||
CONSTCD11
|
||||
inline
|
||||
julian::year
|
||||
operator "" _y(unsigned long long y) NOEXCEPT
|
||||
operator ""_y(unsigned long long y) NOEXCEPT
|
||||
{
|
||||
return julian::year(static_cast<int>(y));
|
||||
}
|
||||
@ -1655,9 +1655,12 @@ inline
|
||||
bool
|
||||
month_day::ok() const NOEXCEPT
|
||||
{
|
||||
CONSTDATA julian::day d[] =
|
||||
{31_d, 29_d, 31_d, 30_d, 31_d, 30_d, 31_d, 31_d, 30_d, 31_d, 30_d, 31_d};
|
||||
return m_.ok() && 1_d <= d_ && d_ <= d[static_cast<unsigned>(m_)-1];
|
||||
CONSTDATA julian::day d[] = {
|
||||
julian::day(31), julian::day(29), julian::day(31), julian::day(30),
|
||||
julian::day(31), julian::day(30), julian::day(31), julian::day(31),
|
||||
julian::day(30), julian::day(31), julian::day(30), julian::day(31)
|
||||
};
|
||||
return m_.ok() && julian::day(1) <= d_ && d_ <= d[static_cast<unsigned>(m_)-1];
|
||||
}
|
||||
|
||||
CONSTCD11
|
||||
@ -1946,9 +1949,12 @@ inline
|
||||
day
|
||||
year_month_day_last::day() const NOEXCEPT
|
||||
{
|
||||
CONSTDATA julian::day d[] =
|
||||
{31_d, 28_d, 31_d, 30_d, 31_d, 30_d, 31_d, 31_d, 30_d, 31_d, 30_d, 31_d};
|
||||
return month() != feb || !y_.is_leap() ? d[static_cast<unsigned>(month())-1] : 29_d;
|
||||
CONSTDATA julian::day d[] = {
|
||||
julian::day(31), julian::day(28), julian::day(31), julian::day(30),
|
||||
julian::day(31), julian::day(30), julian::day(31), julian::day(31),
|
||||
julian::day(30), julian::day(31), julian::day(30), julian::day(31)
|
||||
};
|
||||
return month() != feb || !y_.is_leap() ? d[static_cast<unsigned>(month())-1] : julian::day(29);
|
||||
}
|
||||
|
||||
CONSTCD14
|
||||
@ -2190,7 +2196,7 @@ year_month_day::ok() const NOEXCEPT
|
||||
{
|
||||
if (!(y_.ok() && m_.ok()))
|
||||
return false;
|
||||
return 1_d <= d_ && d_ <= (y_/m_/last).day();
|
||||
return julian::day(1) <= d_ && d_ <= (y_/m_/last).day();
|
||||
}
|
||||
|
||||
CONSTCD11
|
||||
|
@ -36,17 +36,55 @@
|
||||
// Posix::time_zone tz{"EST5EDT,M3.2.0,M11.1.0"};
|
||||
// zoned_time<system_clock::duration, Posix::time_zone> zt{tz, system_clock::now()};
|
||||
//
|
||||
// In C++17 CTAD simplifies this to:
|
||||
//
|
||||
// Posix::time_zone tz{"EST5EDT,M3.2.0,M11.1.0"};
|
||||
// zoned_time zt{tz, system_clock::now()};
|
||||
//
|
||||
// Extension to the Posix rules to allow a constant daylight saving offset:
|
||||
//
|
||||
// If the rule set is missing (everything starting with ','), then
|
||||
// there must be exactly one abbreviation (std or daylight) with
|
||||
// length 3 or greater, and that will be used as the constant offset. If
|
||||
// there are two, the std abbreviation is silently set to "", and the
|
||||
// result is constant daylight saving. If there are zero abbreviations
|
||||
// with no rule set, an exception is thrown.
|
||||
//
|
||||
// Example:
|
||||
// "EST5" yields a constant offset of -5h with 0h save and "EST abbreviation.
|
||||
// "5EDT" yields a constant offset of -4h with 1h save and "EDT" abbreviation.
|
||||
// "EST5EDT" and "5EDT4" are both equal to "5EDT".
|
||||
//
|
||||
// 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 <algorithm>
|
||||
#include <cassert>
|
||||
#include <cctype>
|
||||
#include <chrono>
|
||||
#include <ostream>
|
||||
#include <string>
|
||||
|
||||
#ifndef HAS_CHRONO_20
|
||||
# if defined(_LIBCPP_VERSION) && _LIBCPP_VERSION <= 200100
|
||||
# define HAS_CHRONO_20 0
|
||||
# else
|
||||
# define HAS_CHRONO_20 1
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#if HAS_CHRONO_20
|
||||
namespace chr = std::chrono;
|
||||
# define HAS_STRING_VIEW 1
|
||||
# include <format>
|
||||
#else
|
||||
# include "date/tz.h"
|
||||
namespace chr = date;
|
||||
#endif
|
||||
|
||||
namespace Posix
|
||||
{
|
||||
|
||||
@ -70,14 +108,15 @@ unsigned read_date(const string_t& s, unsigned i, rule& r);
|
||||
unsigned read_name(const string_t& s, unsigned i, std::string& name);
|
||||
unsigned read_signed_time(const string_t& s, unsigned i, std::chrono::seconds& t);
|
||||
unsigned read_unsigned_time(const string_t& s, unsigned i, std::chrono::seconds& t);
|
||||
unsigned read_unsigned(const string_t& s, unsigned i, unsigned limit, unsigned& u);
|
||||
unsigned read_unsigned(const string_t& s, unsigned i, unsigned limit, unsigned& u,
|
||||
const string_t& message = string_t{});
|
||||
|
||||
class rule
|
||||
{
|
||||
enum {off, J, M, N};
|
||||
|
||||
date::month m_;
|
||||
date::weekday wd_;
|
||||
chr::month m_;
|
||||
chr::weekday wd_;
|
||||
unsigned short n_ : 14;
|
||||
unsigned short mode_ : 2;
|
||||
std::chrono::duration<std::int32_t> time_ = std::chrono::hours{2};
|
||||
@ -86,22 +125,49 @@ public:
|
||||
rule() : mode_(off) {}
|
||||
|
||||
bool ok() const {return mode_ != off;}
|
||||
date::local_seconds operator()(date::year y) const;
|
||||
chr::local_seconds operator()(chr::year y) const;
|
||||
std::string to_string() const;
|
||||
|
||||
friend std::ostream& operator<<(std::ostream& os, const rule& r);
|
||||
friend unsigned read_date(const string_t& s, unsigned i, rule& r);
|
||||
friend bool operator==(const rule& x, const rule& y);
|
||||
};
|
||||
|
||||
inline
|
||||
date::local_seconds
|
||||
rule::operator()(date::year y) const
|
||||
bool
|
||||
operator==(const rule& x, const rule& y)
|
||||
{
|
||||
using date::local_days;
|
||||
using date::January;
|
||||
using date::days;
|
||||
using date::last;
|
||||
if (x.mode_ != y.mode_)
|
||||
return false;
|
||||
switch (x.mode_)
|
||||
{
|
||||
case rule::J:
|
||||
case rule::N:
|
||||
return x.n_ == y.n_;
|
||||
case rule::M:
|
||||
return x.m_ == y.m_ && x.n_ == y.n_ && x.wd_ == y.wd_;
|
||||
default:
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
inline
|
||||
bool
|
||||
operator!=(const rule& x, const rule& y)
|
||||
{
|
||||
return !(x == y);
|
||||
}
|
||||
|
||||
inline
|
||||
chr::local_seconds
|
||||
rule::operator()(chr::year y) const
|
||||
{
|
||||
using chr::local_days;
|
||||
using chr::January;
|
||||
using chr::days;
|
||||
using chr::last;
|
||||
using sec = std::chrono::seconds;
|
||||
date::local_seconds t;
|
||||
chr::local_seconds t;
|
||||
switch (mode_)
|
||||
{
|
||||
case J:
|
||||
@ -119,6 +185,62 @@ rule::operator()(date::year y) const
|
||||
return t;
|
||||
}
|
||||
|
||||
inline
|
||||
std::string
|
||||
rule::to_string() const
|
||||
{
|
||||
using namespace std::chrono;
|
||||
auto print_offset = [](seconds off)
|
||||
{
|
||||
std::string nm;
|
||||
if (off != hours{2})
|
||||
{
|
||||
chr::hh_mm_ss<seconds> offset{off};
|
||||
nm = '/';
|
||||
nm += std::to_string(offset.hours().count());
|
||||
if (offset.minutes() != minutes{0} || offset.seconds() != seconds{0})
|
||||
{
|
||||
nm += ':';
|
||||
if (offset.minutes() < minutes{10})
|
||||
nm += '0';
|
||||
nm += std::to_string(offset.minutes().count());
|
||||
if (offset.seconds() != seconds{0})
|
||||
{
|
||||
nm += ':';
|
||||
if (offset.seconds() < seconds{10})
|
||||
nm += '0';
|
||||
nm += std::to_string(offset.seconds().count());
|
||||
}
|
||||
}
|
||||
}
|
||||
return nm;
|
||||
};
|
||||
|
||||
std::string nm;
|
||||
switch (mode_)
|
||||
{
|
||||
case rule::J:
|
||||
nm = 'J';
|
||||
nm += std::to_string(n_);
|
||||
break;
|
||||
case rule::M:
|
||||
nm = 'M';
|
||||
nm += std::to_string(static_cast<unsigned>(m_));
|
||||
nm += '.';
|
||||
nm += std::to_string(n_);
|
||||
nm += '.';
|
||||
nm += std::to_string(wd_.c_encoding());
|
||||
break;
|
||||
case rule::N:
|
||||
nm = std::to_string(n_);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
nm += print_offset(time_);
|
||||
return nm;
|
||||
}
|
||||
|
||||
inline
|
||||
std::ostream&
|
||||
operator<<(std::ostream& os, const rule& r)
|
||||
@ -126,17 +248,29 @@ operator<<(std::ostream& os, const rule& r)
|
||||
switch (r.mode_)
|
||||
{
|
||||
case rule::J:
|
||||
#if HAS_CHRONO_20
|
||||
os << "J " << r.n_ << std::format("{:%T}", r.time_);
|
||||
#else
|
||||
os << 'J' << r.n_ << date::format(" %T", r.time_);
|
||||
#endif
|
||||
break;
|
||||
case rule::M:
|
||||
if (r.n_ == 5)
|
||||
os << r.m_/r.wd_[date::last];
|
||||
os << r.m_/r.wd_[chr::last];
|
||||
else
|
||||
os << r.m_/r.wd_[r.n_];
|
||||
os << date::format(" %T", r.time_);
|
||||
#if HAS_CHRONO_20
|
||||
os << ' ' << std::format("{:%T}", r.time_);
|
||||
#else
|
||||
os << date::format(" %T", r.time_);
|
||||
#endif
|
||||
break;
|
||||
case rule::N:
|
||||
#if HAS_CHRONO_20
|
||||
os << r.n_ << ' ' << std::format("{:%T}", r.time_);
|
||||
#else
|
||||
os << r.n_ << date::format(" %T", r.time_);
|
||||
#endif
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
@ -159,27 +293,112 @@ public:
|
||||
explicit time_zone(const detail::string_t& name);
|
||||
|
||||
template <class Duration>
|
||||
date::sys_info get_info(date::sys_time<Duration> st) const;
|
||||
chr::sys_info get_info(chr::sys_time<Duration> st) const;
|
||||
template <class Duration>
|
||||
date::local_info get_info(date::local_time<Duration> tp) const;
|
||||
chr::local_info get_info(chr::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;
|
||||
chr::sys_time<typename std::common_type<Duration, std::chrono::seconds>::type>
|
||||
to_sys(chr::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;
|
||||
chr::sys_time<typename std::common_type<Duration, std::chrono::seconds>::type>
|
||||
to_sys(chr::local_time<Duration> tp, chr::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;
|
||||
chr::local_time<typename std::common_type<Duration, std::chrono::seconds>::type>
|
||||
to_local(chr::sys_time<Duration> tp) const;
|
||||
|
||||
friend std::ostream& operator<<(std::ostream& os, const time_zone& z);
|
||||
|
||||
const time_zone* operator->() const {return this;}
|
||||
|
||||
std::string name() const;
|
||||
|
||||
friend bool operator==(const time_zone& x, const time_zone& y);
|
||||
|
||||
private:
|
||||
chr::sys_seconds get_start(chr::year y) const;
|
||||
chr::sys_seconds get_prev_start(chr::year y) const;
|
||||
chr::sys_seconds get_next_start(chr::year y) const;
|
||||
chr::sys_seconds get_end(chr::year y) const;
|
||||
chr::sys_seconds get_prev_end(chr::year y) const;
|
||||
chr::sys_seconds get_next_end(chr::year y) const;
|
||||
chr::sys_info contant_offset() const;
|
||||
};
|
||||
|
||||
inline
|
||||
chr::sys_seconds
|
||||
time_zone::get_start(chr::year y) const
|
||||
{
|
||||
return chr::sys_seconds{(start_rule_(y) - offset_).time_since_epoch()};
|
||||
}
|
||||
|
||||
inline
|
||||
chr::sys_seconds
|
||||
time_zone::get_prev_start(chr::year y) const
|
||||
{
|
||||
return chr::sys_seconds{(start_rule_(--y) - offset_).time_since_epoch()};
|
||||
}
|
||||
|
||||
inline
|
||||
chr::sys_seconds
|
||||
time_zone::get_next_start(chr::year y) const
|
||||
{
|
||||
return chr::sys_seconds{(start_rule_(++y) - offset_).time_since_epoch()};
|
||||
}
|
||||
|
||||
inline
|
||||
chr::sys_seconds
|
||||
time_zone::get_end(chr::year y) const
|
||||
{
|
||||
return chr::sys_seconds{(end_rule_(y) - (offset_ + save_)).time_since_epoch()};
|
||||
}
|
||||
|
||||
inline
|
||||
chr::sys_seconds
|
||||
time_zone::get_prev_end(chr::year y) const
|
||||
{
|
||||
return chr::sys_seconds{(end_rule_(--y) - (offset_ + save_)).time_since_epoch()};
|
||||
}
|
||||
|
||||
inline
|
||||
chr::sys_seconds
|
||||
time_zone::get_next_end(chr::year y) const
|
||||
{
|
||||
return chr::sys_seconds{(end_rule_(++y) - (offset_ + save_)).time_since_epoch()};
|
||||
}
|
||||
|
||||
inline
|
||||
chr::sys_info
|
||||
time_zone::contant_offset() const
|
||||
{
|
||||
using chr::year;
|
||||
using chr::sys_info;
|
||||
using chr::sys_days;
|
||||
using chr::January;
|
||||
using chr::December;
|
||||
using chr::last;
|
||||
using chr::days;
|
||||
using std::chrono::minutes;
|
||||
sys_info r;
|
||||
r.begin = sys_days{year::min()/January/1};
|
||||
r.end = sys_days{year::max()/December/last} + days{1} - std::chrono::seconds{1};
|
||||
if (std_abbrev_.size() > 0)
|
||||
{
|
||||
r.abbrev = std_abbrev_;
|
||||
r.offset = offset_;
|
||||
r.save = {};
|
||||
}
|
||||
else
|
||||
{
|
||||
r.abbrev = dst_abbrev_;
|
||||
r.offset = offset_ + save_;
|
||||
r.save = chr::ceil<minutes>(save_);
|
||||
}
|
||||
return r;
|
||||
}
|
||||
|
||||
inline
|
||||
time_zone::time_zone(const detail::string_t& s)
|
||||
{
|
||||
@ -187,15 +406,21 @@ time_zone::time_zone(const detail::string_t& s)
|
||||
using detail::read_signed_time;
|
||||
using detail::throw_invalid;
|
||||
auto i = read_name(s, 0, std_abbrev_);
|
||||
auto std_name_i = i;
|
||||
auto abbrev_name_i = i;
|
||||
i = read_signed_time(s, i, offset_);
|
||||
offset_ = -offset_;
|
||||
if (i != s.size())
|
||||
{
|
||||
i = read_name(s, i, dst_abbrev_);
|
||||
abbrev_name_i = i;
|
||||
if (i != s.size())
|
||||
{
|
||||
if (s[i] != ',')
|
||||
{
|
||||
i = read_signed_time(s, i, save_);
|
||||
save_ = -save_ - offset_;
|
||||
}
|
||||
if (i != s.size())
|
||||
{
|
||||
if (s[i] != ',')
|
||||
@ -211,98 +436,156 @@ time_zone::time_zone(const detail::string_t& s)
|
||||
}
|
||||
}
|
||||
}
|
||||
if (start_rule_.ok())
|
||||
{
|
||||
if (std_abbrev_.size() < 3)
|
||||
throw_invalid(s, std_name_i, "Zone with rules must have a std"
|
||||
" abbreviation of length 3 or greater");
|
||||
if (dst_abbrev_.size() < 3)
|
||||
throw_invalid(s, abbrev_name_i, "Zone with rules must have a daylight"
|
||||
" abbreviation of length 3 or greater");
|
||||
}
|
||||
else
|
||||
{
|
||||
if (dst_abbrev_.size() >= 3)
|
||||
{
|
||||
std_abbrev_.clear();
|
||||
}
|
||||
else if (std_abbrev_.size() < 3)
|
||||
{
|
||||
throw_invalid(s, std_name_i, "Zone must have at least one abbreviation"
|
||||
" of length 3 or greater");
|
||||
}
|
||||
else
|
||||
{
|
||||
dst_abbrev_.clear();
|
||||
save_ = {};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template <class Duration>
|
||||
date::sys_info
|
||||
time_zone::get_info(date::sys_time<Duration> st) const
|
||||
chr::sys_info
|
||||
time_zone::get_info(chr::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 chr::sys_info;
|
||||
using chr::year_month_day;
|
||||
using chr::sys_days;
|
||||
using chr::floor;
|
||||
using chr::ceil;
|
||||
using chr::days;
|
||||
using chr::year;
|
||||
using chr::January;
|
||||
using chr::December;
|
||||
using chr::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)
|
||||
if (st >= get_next_start(y))
|
||||
++y;
|
||||
else if (st < get_prev_end(y))
|
||||
--y;
|
||||
auto start = get_start(y);
|
||||
auto end = get_end(y);
|
||||
if (start <= end) // (northern hemisphere)
|
||||
{
|
||||
r.begin = start;
|
||||
r.end = end;
|
||||
r.offset += save_;
|
||||
r.save = ceil<minutes>(save_);
|
||||
r.abbrev = dst_abbrev_;
|
||||
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 = get_prev_end(y);
|
||||
r.end = start;
|
||||
r.abbrev = std_abbrev_;
|
||||
}
|
||||
else // st >= end
|
||||
{
|
||||
r.begin = end;
|
||||
r.end = get_next_start(y);
|
||||
r.abbrev = std_abbrev_;
|
||||
}
|
||||
}
|
||||
else if (st < start)
|
||||
else // end < start (southern hemisphere)
|
||||
{
|
||||
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_;
|
||||
if (end <= st && st < start)
|
||||
{
|
||||
r.begin = end;
|
||||
r.end = start;
|
||||
r.abbrev = std_abbrev_;
|
||||
}
|
||||
else if (st < end)
|
||||
{
|
||||
r.begin = get_prev_start(y);
|
||||
r.end = end;
|
||||
r.offset += save_;
|
||||
r.save = ceil<minutes>(save_);
|
||||
r.abbrev = dst_abbrev_;
|
||||
}
|
||||
else // st >= start
|
||||
{
|
||||
r.begin = start;
|
||||
r.end = get_next_end(y);
|
||||
r.offset += save_;
|
||||
r.save = ceil<minutes>(save_);
|
||||
r.abbrev = dst_abbrev_;
|
||||
}
|
||||
}
|
||||
}
|
||||
else // constant offset
|
||||
{
|
||||
r.begin = sys_days{year::min()/January/1};
|
||||
r.end = sys_days{year::max()/December/last};
|
||||
r.abbrev = std_abbrev_;
|
||||
}
|
||||
else
|
||||
r = contant_offset();
|
||||
using seconds = std::chrono::seconds;
|
||||
assert(r.begin <= floor<seconds>(st) && floor<seconds>(st) <= r.end);
|
||||
return r;
|
||||
}
|
||||
|
||||
template <class Duration>
|
||||
date::local_info
|
||||
time_zone::get_info(date::local_time<Duration> tp) const
|
||||
chr::local_info
|
||||
time_zone::get_info(chr::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 chr::local_info;
|
||||
using chr::year_month_day;
|
||||
using chr::days;
|
||||
using chr::sys_days;
|
||||
using chr::sys_seconds;
|
||||
using chr::year;
|
||||
using chr::ceil;
|
||||
using chr::January;
|
||||
using chr::December;
|
||||
using chr::last;
|
||||
using std::chrono::seconds;
|
||||
using std::chrono::minutes;
|
||||
local_info r{};
|
||||
using date::floor;
|
||||
using chr::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 start = get_start(y);
|
||||
auto end = get_end(y);
|
||||
auto utcs = sys_seconds{floor<seconds>(tp - offset_).time_since_epoch()};
|
||||
auto utcd = sys_seconds{floor<seconds>(tp - (offset_ + save_)).time_since_epoch()};
|
||||
auto northern = start <= end;
|
||||
if ((utcs < start) != (utcd < start))
|
||||
{
|
||||
r.first.begin = sys_seconds{(end_rule_(y-years{1}) -
|
||||
(offset_ + save_)).time_since_epoch()};
|
||||
if (northern)
|
||||
r.first.begin = get_prev_end(y);
|
||||
else
|
||||
r.first.begin = end;
|
||||
r.first.end = start;
|
||||
r.first.offset = offset_;
|
||||
r.first.abbrev = std_abbrev_;
|
||||
r.second.begin = start;
|
||||
r.second.end = end;
|
||||
if (northern)
|
||||
r.second.end = end;
|
||||
else
|
||||
r.second.end = get_next_end(y);
|
||||
r.second.abbrev = dst_abbrev_;
|
||||
r.second.offset = offset_ + save_;
|
||||
r.second.save = ceil<minutes>(save_);
|
||||
@ -311,61 +594,40 @@ time_zone::get_info(date::local_time<Duration> tp) const
|
||||
}
|
||||
else if ((utcs < end) != (utcd < end))
|
||||
{
|
||||
r.first.begin = start;
|
||||
if (northern)
|
||||
r.first.begin = start;
|
||||
else
|
||||
r.first.begin = get_prev_start(y);
|
||||
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()};
|
||||
if (northern)
|
||||
r.second.end = get_next_start(y);
|
||||
else
|
||||
r.second.end = start;
|
||||
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_;
|
||||
r.first = get_info(utcs);
|
||||
}
|
||||
else
|
||||
r.first = contant_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
|
||||
chr::sys_time<typename std::common_type<Duration, std::chrono::seconds>::type>
|
||||
time_zone::to_sys(chr::local_time<Duration> tp) const
|
||||
{
|
||||
using date::local_info;
|
||||
using date::sys_time;
|
||||
using date::ambiguous_local_time;
|
||||
using chr::local_info;
|
||||
using chr::sys_time;
|
||||
using chr::ambiguous_local_time;
|
||||
using chr::nonexistent_local_time;
|
||||
auto i = get_info(tp);
|
||||
if (i.result == local_info::nonexistent)
|
||||
throw nonexistent_local_time(tp, i);
|
||||
@ -375,12 +637,12 @@ time_zone::to_sys(date::local_time<Duration> tp) const
|
||||
}
|
||||
|
||||
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
|
||||
chr::sys_time<typename std::common_type<Duration, std::chrono::seconds>::type>
|
||||
time_zone::to_sys(chr::local_time<Duration> tp, chr::choose z) const
|
||||
{
|
||||
using date::local_info;
|
||||
using date::sys_time;
|
||||
using date::choose;
|
||||
using chr::local_info;
|
||||
using chr::sys_time;
|
||||
using chr::choose;
|
||||
auto i = get_info(tp);
|
||||
if (i.result == local_info::nonexistent)
|
||||
{
|
||||
@ -395,10 +657,10 @@ time_zone::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>
|
||||
time_zone::to_local(date::sys_time<Duration> tp) const
|
||||
chr::local_time<typename std::common_type<Duration, std::chrono::seconds>::type>
|
||||
time_zone::to_local(chr::sys_time<Duration> tp) const
|
||||
{
|
||||
using date::local_time;
|
||||
using chr::local_time;
|
||||
using std::chrono::seconds;
|
||||
using LT = local_time<typename std::common_type<Duration, seconds>::type>;
|
||||
auto i = get_info(tp);
|
||||
@ -409,13 +671,96 @@ inline
|
||||
std::ostream&
|
||||
operator<<(std::ostream& os, const time_zone& z)
|
||||
{
|
||||
using date::operator<<;
|
||||
using chr::operator<<;
|
||||
os << '{';
|
||||
#if HAS_CHRONO_20
|
||||
os << z.std_abbrev_ << ", " << z.dst_abbrev_ << ", " << std::format("{:%T, }", z.offset_)
|
||||
<< std::format("{:%T, [}", z.save_) << z.start_rule_ << ", " << z.end_rule_ << ")}";
|
||||
#else
|
||||
os << z.std_abbrev_ << ", " << z.dst_abbrev_ << date::format(", %T, ", z.offset_)
|
||||
<< date::format("%T, [", z.save_) << z.start_rule_ << ", " << z.end_rule_ << ")}";
|
||||
#endif
|
||||
return os;
|
||||
}
|
||||
|
||||
inline
|
||||
std::string
|
||||
time_zone::name() const
|
||||
{
|
||||
using namespace chr;
|
||||
using namespace std::chrono;
|
||||
auto print_abbrev = [](std::string const& nm)
|
||||
{
|
||||
if (std::any_of(nm.begin(), nm.end(),
|
||||
[](char c)
|
||||
{
|
||||
return !std::isalpha(c);
|
||||
}))
|
||||
{
|
||||
return '<' + nm + '>';
|
||||
}
|
||||
return nm;
|
||||
};
|
||||
auto print_offset = [](seconds off)
|
||||
{
|
||||
std::string nm;
|
||||
chr::hh_mm_ss<seconds> offset{-off};
|
||||
if (offset.is_negative())
|
||||
nm += '-';
|
||||
nm += std::to_string(offset.hours().count());
|
||||
if (offset.minutes() != minutes{0} || offset.seconds() != seconds{0})
|
||||
{
|
||||
nm += ':';
|
||||
if (offset.minutes() < minutes{10})
|
||||
nm += '0';
|
||||
nm += std::to_string(offset.minutes().count());
|
||||
if (offset.seconds() != seconds{0})
|
||||
{
|
||||
nm += ':';
|
||||
if (offset.seconds() < seconds{10})
|
||||
nm += '0';
|
||||
nm += std::to_string(offset.seconds().count());
|
||||
}
|
||||
}
|
||||
return nm;
|
||||
};
|
||||
auto nm = print_abbrev(std_abbrev_);
|
||||
nm += print_offset(offset_);
|
||||
if (!dst_abbrev_.empty())
|
||||
{
|
||||
nm += print_abbrev(dst_abbrev_);
|
||||
if (save_ != hours{1})
|
||||
nm += print_offset(offset_+save_);
|
||||
if (start_rule_.ok())
|
||||
{
|
||||
nm += ',';
|
||||
nm += start_rule_.to_string();
|
||||
nm += ',';
|
||||
nm += end_rule_.to_string();
|
||||
}
|
||||
}
|
||||
return nm;
|
||||
}
|
||||
|
||||
inline
|
||||
bool
|
||||
operator==(const time_zone& x, const time_zone& y)
|
||||
{
|
||||
return x.std_abbrev_ == y.std_abbrev_ &&
|
||||
x.dst_abbrev_ == y. dst_abbrev_ &&
|
||||
x.offset_ == y.offset_ &&
|
||||
x.save_ == y.save_ &&
|
||||
x.start_rule_ == y.start_rule_ &&
|
||||
x.end_rule_ == y.end_rule_;
|
||||
}
|
||||
|
||||
inline
|
||||
bool
|
||||
operator!=(const time_zone& x, const time_zone& y)
|
||||
{
|
||||
return !(x == y);
|
||||
}
|
||||
|
||||
namespace detail
|
||||
{
|
||||
|
||||
@ -428,7 +773,7 @@ throw_invalid(const string_t& s, unsigned i, const string_t& message)
|
||||
std::string(s) + '\n' +
|
||||
"\x1b[1;32m" +
|
||||
std::string(i, '~') + '^' +
|
||||
std::string(s.size()-i-1, '~') +
|
||||
std::string(i < s.size() ? s.size()-i-1 : 0, '~') +
|
||||
"\x1b[0m");
|
||||
}
|
||||
|
||||
@ -436,15 +781,17 @@ inline
|
||||
unsigned
|
||||
read_date(const string_t& s, unsigned i, rule& r)
|
||||
{
|
||||
using date::month;
|
||||
using date::weekday;
|
||||
using chr::month;
|
||||
using chr::weekday;
|
||||
if (i == s.size())
|
||||
throw_invalid(s, i, "Expected rule but found end of string");
|
||||
if (s[i] == 'J')
|
||||
{
|
||||
++i;
|
||||
unsigned n;
|
||||
i = read_unsigned(s, i, 3, n);
|
||||
i = read_unsigned(s, i, 3, n, "Expected to find the Julian day [1, 365]");
|
||||
if (!(1 <= n && n <= 365))
|
||||
throw_invalid(s, i-1, "Expected Julian day to be in the range [1, 365]");
|
||||
r.mode_ = rule::J;
|
||||
r.n_ = n;
|
||||
}
|
||||
@ -452,17 +799,23 @@ read_date(const string_t& s, unsigned i, rule& r)
|
||||
{
|
||||
++i;
|
||||
unsigned m;
|
||||
i = read_unsigned(s, i, 2, m);
|
||||
i = read_unsigned(s, i, 2, m, "Expected to find month [1, 12]");
|
||||
if (!(1 <= m && m <= 12))
|
||||
throw_invalid(s, i-1, "Expected month to be in the range [1, 12]");
|
||||
if (i == s.size() || s[i] != '.')
|
||||
throw_invalid(s, i, "Expected '.' after month");
|
||||
++i;
|
||||
unsigned n;
|
||||
i = read_unsigned(s, i, 1, n);
|
||||
i = read_unsigned(s, i, 1, n, "Expected to find week number [1, 5]");
|
||||
if (!(1 <= n && n <= 5))
|
||||
throw_invalid(s, i-1, "Expected week number to be in the range [1, 5]");
|
||||
if (i == s.size() || s[i] != '.')
|
||||
throw_invalid(s, i, "Expected '.' after weekday index");
|
||||
++i;
|
||||
unsigned wd;
|
||||
i = read_unsigned(s, i, 1, wd);
|
||||
i = read_unsigned(s, i, 1, wd, "Expected to find day of week [0, 6]");
|
||||
if (wd > 6)
|
||||
throw_invalid(s, i-1, "Expected day of week to be in the range [0, 6]");
|
||||
r.mode_ = rule::M;
|
||||
r.m_ = month{m};
|
||||
r.wd_ = weekday{wd};
|
||||
@ -472,6 +825,8 @@ read_date(const string_t& s, unsigned i, rule& r)
|
||||
{
|
||||
unsigned n;
|
||||
i = read_unsigned(s, i, 3, n);
|
||||
if (n > 365)
|
||||
throw_invalid(s, i-1, "Expected Julian day to be in the range [0, 365]");
|
||||
r.mode_ = rule::N;
|
||||
r.n_ = n;
|
||||
}
|
||||
@ -516,8 +871,6 @@ read_name(const string_t& s, unsigned i, std::string& name)
|
||||
++i;
|
||||
}
|
||||
}
|
||||
if (name.size() < 3)
|
||||
throw_invalid(s, i, "Found name to be shorter than 3 characters");
|
||||
return i;
|
||||
}
|
||||
|
||||
@ -552,17 +905,23 @@ read_unsigned_time(const string_t& s, unsigned i, std::chrono::seconds& t)
|
||||
if (i == s.size())
|
||||
throw_invalid(s, i, "Expected to read unsigned time, but found end of string");
|
||||
unsigned x;
|
||||
i = read_unsigned(s, i, 2, x);
|
||||
i = read_unsigned(s, i, 2, x, "Expected to find hours [0, 24]");
|
||||
if (x > 24)
|
||||
throw_invalid(s, i-1, "Expected hours to be in the range [0, 24]");
|
||||
t = hours{x};
|
||||
if (i != s.size() && s[i] == ':')
|
||||
{
|
||||
++i;
|
||||
i = read_unsigned(s, i, 2, x);
|
||||
i = read_unsigned(s, i, 2, x, "Expected to find minutes [0, 59]");
|
||||
if (x > 59)
|
||||
throw_invalid(s, i-1, "Expected minutes to be in the range [0, 59]");
|
||||
t += minutes{x};
|
||||
if (i != s.size() && s[i] == ':')
|
||||
{
|
||||
++i;
|
||||
i = read_unsigned(s, i, 2, x);
|
||||
i = read_unsigned(s, i, 2, x, "Expected to find seconds [0, 59]");
|
||||
if (x > 59)
|
||||
throw_invalid(s, i-1, "Expected seconds to be in the range [0, 59]");
|
||||
t += seconds{x};
|
||||
}
|
||||
}
|
||||
@ -571,10 +930,11 @@ read_unsigned_time(const string_t& s, unsigned i, std::chrono::seconds& t)
|
||||
|
||||
inline
|
||||
unsigned
|
||||
read_unsigned(const string_t& s, unsigned i, unsigned limit, unsigned& u)
|
||||
read_unsigned(const string_t& s, unsigned i, unsigned limit, unsigned& u,
|
||||
const string_t& message)
|
||||
{
|
||||
if (i == s.size() || !std::isdigit(s[i]))
|
||||
throw_invalid(s, i, "Expected to find a decimal digit");
|
||||
throw_invalid(s, i, message);
|
||||
u = static_cast<unsigned>(s[i] - '0');
|
||||
unsigned count = 1;
|
||||
for (++i; count < limit && i != s.size() && std::isdigit(s[i]); ++i, ++count)
|
||||
@ -586,7 +946,11 @@ read_unsigned(const string_t& s, unsigned i, unsigned limit, unsigned& u)
|
||||
|
||||
} // namespace Posix
|
||||
|
||||
#if HAS_CHRONO_20
|
||||
namespace std::chrono
|
||||
#else
|
||||
namespace date
|
||||
#endif
|
||||
{
|
||||
|
||||
template <>
|
||||
@ -622,6 +986,6 @@ struct zoned_traits<Posix::time_zone>
|
||||
|
||||
};
|
||||
|
||||
} // namespace date
|
||||
} // namespace chr
|
||||
|
||||
#endif // PTZ_H
|
||||
|
@ -792,8 +792,8 @@ operator<<(std::basic_ostream<CharT, Traits>& os, const year_month_weekday_last&
|
||||
inline namespace literals
|
||||
{
|
||||
|
||||
CONSTCD11 solar_hijri::day operator "" _d(unsigned long long d) NOEXCEPT;
|
||||
CONSTCD11 solar_hijri::year operator "" _y(unsigned long long y) NOEXCEPT;
|
||||
CONSTCD11 solar_hijri::day operator ""_d(unsigned long long d) NOEXCEPT;
|
||||
CONSTCD11 solar_hijri::year operator ""_y(unsigned long long y) NOEXCEPT;
|
||||
|
||||
} // inline namespace literals
|
||||
#endif // !defined(_MSC_VER) || (_MSC_VER >= 1900)
|
||||
@ -1364,7 +1364,7 @@ inline namespace literals
|
||||
CONSTCD11
|
||||
inline
|
||||
solar_hijri::day
|
||||
operator "" _d(unsigned long long d) NOEXCEPT
|
||||
operator ""_d(unsigned long long d) NOEXCEPT
|
||||
{
|
||||
return solar_hijri::day{static_cast<unsigned>(d)};
|
||||
}
|
||||
@ -1372,7 +1372,7 @@ operator "" _d(unsigned long long d) NOEXCEPT
|
||||
CONSTCD11
|
||||
inline
|
||||
solar_hijri::year
|
||||
operator "" _y(unsigned long long y) NOEXCEPT
|
||||
operator ""_y(unsigned long long y) NOEXCEPT
|
||||
{
|
||||
return solar_hijri::year(static_cast<int>(y));
|
||||
}
|
||||
@ -1707,9 +1707,13 @@ inline
|
||||
bool
|
||||
month_day::ok() const NOEXCEPT
|
||||
{
|
||||
CONSTDATA solar_hijri::day d[] =
|
||||
{31_d, 31_d, 31_d, 31_d, 31_d, 31_d, 30_d, 30_d, 30_d, 30_d, 30_d, 30_d};
|
||||
return m_.ok() && 1_d <= d_ && d_ <= d[static_cast<unsigned>(m_)-1];
|
||||
CONSTDATA solar_hijri::day d[] = {
|
||||
solar_hijri::day(31), solar_hijri::day(31), solar_hijri::day(31),
|
||||
solar_hijri::day(31), solar_hijri::day(31), solar_hijri::day(31),
|
||||
solar_hijri::day(30), solar_hijri::day(30), solar_hijri::day(30),
|
||||
solar_hijri::day(30), solar_hijri::day(30), solar_hijri::day(30)
|
||||
};
|
||||
return m_.ok() && solar_hijri::day(1) <= d_ && d_ <= d[static_cast<unsigned>(m_)-1];
|
||||
}
|
||||
|
||||
CONSTCD11
|
||||
@ -1998,10 +2002,14 @@ inline
|
||||
day
|
||||
year_month_day_last::day() const NOEXCEPT
|
||||
{
|
||||
CONSTDATA solar_hijri::day d[] =
|
||||
{31_d, 31_d, 31_d, 31_d, 31_d, 31_d, 30_d, 30_d, 30_d, 30_d, 30_d, 29_d};
|
||||
CONSTDATA solar_hijri::day d[] = {
|
||||
solar_hijri::day(31), solar_hijri::day(31), solar_hijri::day(31),
|
||||
solar_hijri::day(31), solar_hijri::day(31), solar_hijri::day(31),
|
||||
solar_hijri::day(30), solar_hijri::day(30), solar_hijri::day(30),
|
||||
solar_hijri::day(30), solar_hijri::day(30), solar_hijri::day(29)
|
||||
};
|
||||
return month() != esf || !y_.is_leap() ?
|
||||
d[static_cast<unsigned>(month())-1] : 30_d;
|
||||
d[static_cast<unsigned>(month()) - 1] : solar_hijri::day(30);
|
||||
}
|
||||
|
||||
CONSTCD14
|
||||
@ -2260,7 +2268,7 @@ year_month_day::ok() const NOEXCEPT
|
||||
{
|
||||
if (!(y_.ok() && m_.ok()))
|
||||
return false;
|
||||
return 1_d <= d_ && d_ <= (y_/m_/last).day();
|
||||
return solar_hijri::day(1) <= d_ && d_ <= (y_/m_/last).day();
|
||||
}
|
||||
|
||||
CONSTCD11
|
||||
|
@ -49,12 +49,12 @@
|
||||
|
||||
#ifndef HAS_REMOTE_API
|
||||
# if USE_OS_TZDB == 0
|
||||
# ifdef _WIN32
|
||||
# if defined _WIN32 || defined __ANDROID__
|
||||
# define HAS_REMOTE_API 0
|
||||
# else
|
||||
# define HAS_REMOTE_API 1
|
||||
# endif
|
||||
# else // HAS_REMOTE_API makes no since when using the OS timezone database
|
||||
# else // HAS_REMOTE_API makes no sense when using the OS timezone database
|
||||
# define HAS_REMOTE_API 0
|
||||
# endif
|
||||
#endif
|
||||
@ -86,15 +86,6 @@ static_assert(HAS_REMOTE_API == 0 ? AUTO_DOWNLOAD == 0 : true,
|
||||
# ifdef _WIN32
|
||||
# error "USE_OS_TZDB can not be used on Windows"
|
||||
# endif
|
||||
# ifndef MISSING_LEAP_SECONDS
|
||||
# ifdef __APPLE__
|
||||
# define MISSING_LEAP_SECONDS 1
|
||||
# else
|
||||
# define MISSING_LEAP_SECONDS 0
|
||||
# endif
|
||||
# endif
|
||||
#else
|
||||
# define MISSING_LEAP_SECONDS 0
|
||||
#endif
|
||||
|
||||
#ifndef HAS_DEDUCTION_GUIDES
|
||||
@ -148,6 +139,13 @@ namespace date
|
||||
|
||||
enum class choose {earliest, latest};
|
||||
|
||||
#if defined(BUILD_TZ_LIB)
|
||||
# if defined(ANDROID) || defined(__ANDROID__)
|
||||
struct tzdb;
|
||||
static std::unique_ptr<tzdb> init_tzdb();
|
||||
# endif // defined(ANDROID) || defined(__ANDROID__)
|
||||
#endif // defined(BUILD_TZ_LIB)
|
||||
|
||||
namespace detail
|
||||
{
|
||||
struct undocumented;
|
||||
@ -240,8 +238,8 @@ nonexistent_local_time::make_msg(local_time<Duration> tp, const local_info& i)
|
||||
<< i.first.abbrev << " and\n"
|
||||
<< local_seconds{i.second.begin.time_since_epoch()} + i.second.offset << ' '
|
||||
<< i.second.abbrev
|
||||
<< " which are both equivalent to\n"
|
||||
<< i.first.end << " UTC";
|
||||
<< " which are both equivalent to\n";
|
||||
date::operator<<(os, i.first.end) << " UTC";
|
||||
return os.str();
|
||||
}
|
||||
|
||||
@ -703,6 +701,11 @@ public:
|
||||
|
||||
private:
|
||||
template <class D, class T> friend class zoned_time;
|
||||
|
||||
template <class TimeZonePtr2>
|
||||
static
|
||||
TimeZonePtr2&&
|
||||
check(TimeZonePtr2&& p);
|
||||
};
|
||||
|
||||
using zoned_seconds = zoned_time<std::chrono::seconds>;
|
||||
@ -825,6 +828,12 @@ public:
|
||||
|
||||
#if !USE_OS_TZDB
|
||||
DATE_API void add(const std::string& s);
|
||||
#else
|
||||
# if defined(BUILD_TZ_LIB)
|
||||
# if defined(ANDROID) || defined(__ANDROID__)
|
||||
friend std::unique_ptr<tzdb> init_tzdb();
|
||||
# endif // defined(ANDROID) || defined(__ANDROID__)
|
||||
# endif // defined(BUILD_TZ_LIB)
|
||||
#endif // !USE_OS_TZDB
|
||||
|
||||
private:
|
||||
@ -848,8 +857,11 @@ private:
|
||||
DATE_API void
|
||||
load_data(std::istream& inf, std::int32_t tzh_leapcnt, std::int32_t tzh_timecnt,
|
||||
std::int32_t tzh_typecnt, std::int32_t tzh_charcnt);
|
||||
# if defined(ANDROID) || defined(__ANDROID__)
|
||||
void parse_from_android_tzdata(std::ifstream& inf, const std::size_t off);
|
||||
# endif // defined(ANDROID) || defined(__ANDROID__)
|
||||
#else // !USE_OS_TZDB
|
||||
DATE_API sys_info get_info_impl(sys_seconds tp, int timezone) const;
|
||||
DATE_API sys_info get_info_impl(sys_seconds tp, int tz_int) const;
|
||||
DATE_API void adjust_infos(const std::vector<detail::Rule>& rules);
|
||||
DATE_API void parse_info(std::istream& in);
|
||||
#endif // !USE_OS_TZDB
|
||||
@ -990,8 +1002,6 @@ inline bool operator>=(const time_zone_link& x, const time_zone_link& y) {return
|
||||
|
||||
#endif // !USE_OS_TZDB
|
||||
|
||||
#if !MISSING_LEAP_SECONDS
|
||||
|
||||
class leap_second
|
||||
{
|
||||
private:
|
||||
@ -1115,8 +1125,6 @@ operator>=(const sys_time<Duration>& x, const leap_second& y)
|
||||
|
||||
using leap = leap_second;
|
||||
|
||||
#endif // !MISSING_LEAP_SECONDS
|
||||
|
||||
#ifdef _WIN32
|
||||
|
||||
namespace detail
|
||||
@ -1162,9 +1170,7 @@ struct tzdb
|
||||
#if !USE_OS_TZDB
|
||||
std::vector<time_zone_link> links;
|
||||
#endif
|
||||
#if !MISSING_LEAP_SECONDS
|
||||
std::vector<leap_second> leap_seconds;
|
||||
#endif
|
||||
#if !USE_OS_TZDB
|
||||
std::vector<detail::Rule> rules;
|
||||
#endif
|
||||
@ -1200,11 +1206,11 @@ struct tzdb
|
||||
#endif // defined(_MSC_VER) && (_MSC_VER < 1900)
|
||||
|
||||
#if HAS_STRING_VIEW
|
||||
const time_zone* locate_zone(std::string_view tz_name) const;
|
||||
DATE_API const time_zone* locate_zone(std::string_view tz_name) const;
|
||||
#else
|
||||
const time_zone* locate_zone(const std::string& tz_name) const;
|
||||
DATE_API const time_zone* locate_zone(const std::string& tz_name) const;
|
||||
#endif
|
||||
const time_zone* current_zone() const;
|
||||
DATE_API const time_zone* current_zone() const;
|
||||
};
|
||||
|
||||
using TZ_DB = tzdb;
|
||||
@ -1219,33 +1225,33 @@ class tzdb_list
|
||||
std::atomic<tzdb*> head_{nullptr};
|
||||
|
||||
public:
|
||||
~tzdb_list();
|
||||
DATE_API ~tzdb_list();
|
||||
tzdb_list() = default;
|
||||
tzdb_list(tzdb_list&& x) noexcept;
|
||||
DATE_API tzdb_list(tzdb_list&& x) NOEXCEPT;
|
||||
|
||||
const tzdb& front() const noexcept {return *head_;}
|
||||
tzdb& front() noexcept {return *head_;}
|
||||
const tzdb& front() const NOEXCEPT {return *head_;}
|
||||
tzdb& front() NOEXCEPT {return *head_;}
|
||||
|
||||
class const_iterator;
|
||||
|
||||
const_iterator begin() const noexcept;
|
||||
const_iterator end() const noexcept;
|
||||
const_iterator begin() const NOEXCEPT;
|
||||
const_iterator end() const NOEXCEPT;
|
||||
|
||||
const_iterator cbegin() const noexcept;
|
||||
const_iterator cend() const noexcept;
|
||||
const_iterator cbegin() const NOEXCEPT;
|
||||
const_iterator cend() const NOEXCEPT;
|
||||
|
||||
const_iterator erase_after(const_iterator p) noexcept;
|
||||
DATE_API const_iterator erase_after(const_iterator p) NOEXCEPT;
|
||||
|
||||
struct undocumented_helper;
|
||||
private:
|
||||
void push_front(tzdb* tzdb) noexcept;
|
||||
void push_front(tzdb* tzdb) NOEXCEPT;
|
||||
};
|
||||
|
||||
class tzdb_list::const_iterator
|
||||
{
|
||||
tzdb* p_ = nullptr;
|
||||
|
||||
explicit const_iterator(tzdb* p) noexcept : p_{p} {}
|
||||
explicit const_iterator(tzdb* p) NOEXCEPT : p_{p} {}
|
||||
public:
|
||||
const_iterator() = default;
|
||||
|
||||
@ -1255,20 +1261,20 @@ public:
|
||||
using pointer = const value_type*;
|
||||
using difference_type = std::ptrdiff_t;
|
||||
|
||||
reference operator*() const noexcept {return *p_;}
|
||||
pointer operator->() const noexcept {return p_;}
|
||||
reference operator*() const NOEXCEPT {return *p_;}
|
||||
pointer operator->() const NOEXCEPT {return p_;}
|
||||
|
||||
const_iterator& operator++() noexcept {p_ = p_->next; return *this;}
|
||||
const_iterator operator++(int) noexcept {auto t = *this; ++(*this); return t;}
|
||||
const_iterator& operator++() NOEXCEPT {p_ = p_->next; return *this;}
|
||||
const_iterator operator++(int) NOEXCEPT {auto t = *this; ++(*this); return t;}
|
||||
|
||||
friend
|
||||
bool
|
||||
operator==(const const_iterator& x, const const_iterator& y) noexcept
|
||||
operator==(const const_iterator& x, const const_iterator& y) NOEXCEPT
|
||||
{return x.p_ == y.p_;}
|
||||
|
||||
friend
|
||||
bool
|
||||
operator!=(const const_iterator& x, const const_iterator& y) noexcept
|
||||
operator!=(const const_iterator& x, const const_iterator& y) NOEXCEPT
|
||||
{return !(x == y);}
|
||||
|
||||
friend class tzdb_list;
|
||||
@ -1276,28 +1282,28 @@ public:
|
||||
|
||||
inline
|
||||
tzdb_list::const_iterator
|
||||
tzdb_list::begin() const noexcept
|
||||
tzdb_list::begin() const NOEXCEPT
|
||||
{
|
||||
return const_iterator{head_};
|
||||
}
|
||||
|
||||
inline
|
||||
tzdb_list::const_iterator
|
||||
tzdb_list::end() const noexcept
|
||||
tzdb_list::end() const NOEXCEPT
|
||||
{
|
||||
return const_iterator{nullptr};
|
||||
}
|
||||
|
||||
inline
|
||||
tzdb_list::const_iterator
|
||||
tzdb_list::cbegin() const noexcept
|
||||
tzdb_list::cbegin() const NOEXCEPT
|
||||
{
|
||||
return begin();
|
||||
}
|
||||
|
||||
inline
|
||||
tzdb_list::const_iterator
|
||||
tzdb_list::cend() const noexcept
|
||||
tzdb_list::cend() const NOEXCEPT
|
||||
{
|
||||
return end();
|
||||
}
|
||||
@ -1328,7 +1334,7 @@ namespace detail
|
||||
template <class T>
|
||||
inline
|
||||
T*
|
||||
to_raw_pointer(T* p) noexcept
|
||||
to_raw_pointer(T* p) NOEXCEPT
|
||||
{
|
||||
return p;
|
||||
}
|
||||
@ -1336,7 +1342,7 @@ to_raw_pointer(T* p) noexcept
|
||||
template <class Pointer>
|
||||
inline
|
||||
auto
|
||||
to_raw_pointer(Pointer p) noexcept
|
||||
to_raw_pointer(Pointer p) NOEXCEPT
|
||||
-> decltype(detail::to_raw_pointer(p.operator->()))
|
||||
{
|
||||
return detail::to_raw_pointer(p.operator->());
|
||||
@ -1344,13 +1350,25 @@ to_raw_pointer(Pointer p) noexcept
|
||||
|
||||
} // namespace detail
|
||||
|
||||
template <class Duration, class TimeZonePtr>
|
||||
template <class TimeZonePtr2>
|
||||
inline
|
||||
TimeZonePtr2&&
|
||||
zoned_time<Duration, TimeZonePtr>::check(TimeZonePtr2&& p)
|
||||
{
|
||||
if (detail::to_raw_pointer(p) == nullptr)
|
||||
throw std::runtime_error(
|
||||
"zoned_time constructed with a time zone pointer == nullptr");
|
||||
return std::forward<TimeZonePtr2>(p);
|
||||
}
|
||||
|
||||
template <class Duration, class TimeZonePtr>
|
||||
#if !defined(_MSC_VER) || (_MSC_VER > 1916)
|
||||
template <class T, class>
|
||||
#endif
|
||||
inline
|
||||
zoned_time<Duration, TimeZonePtr>::zoned_time()
|
||||
: zone_(zoned_traits<TimeZonePtr>::default_zone())
|
||||
: zone_(check(zoned_traits<TimeZonePtr>::default_zone()))
|
||||
{}
|
||||
|
||||
template <class Duration, class TimeZonePtr>
|
||||
@ -1359,15 +1377,15 @@ template <class T, class>
|
||||
#endif
|
||||
inline
|
||||
zoned_time<Duration, TimeZonePtr>::zoned_time(const sys_time<Duration>& st)
|
||||
: zone_(zoned_traits<TimeZonePtr>::default_zone())
|
||||
: zone_(check(zoned_traits<TimeZonePtr>::default_zone()))
|
||||
, tp_(st)
|
||||
{}
|
||||
|
||||
template <class Duration, class TimeZonePtr>
|
||||
inline
|
||||
zoned_time<Duration, TimeZonePtr>::zoned_time(TimeZonePtr z)
|
||||
: zone_(std::move(z))
|
||||
{assert(detail::to_raw_pointer(zone_) != nullptr);}
|
||||
: zone_(check(std::move(z)))
|
||||
{}
|
||||
|
||||
#if HAS_STRING_VIEW
|
||||
|
||||
@ -1402,7 +1420,7 @@ zoned_time<Duration, TimeZonePtr>::zoned_time(const zoned_time<Duration2, TimeZo
|
||||
template <class Duration, class TimeZonePtr>
|
||||
inline
|
||||
zoned_time<Duration, TimeZonePtr>::zoned_time(TimeZonePtr z, const sys_time<Duration>& st)
|
||||
: zone_(std::move(z))
|
||||
: zone_(check(std::move(z)))
|
||||
, tp_(st)
|
||||
{}
|
||||
|
||||
@ -1412,7 +1430,7 @@ template <class T, class>
|
||||
#endif
|
||||
inline
|
||||
zoned_time<Duration, TimeZonePtr>::zoned_time(TimeZonePtr z, const local_time<Duration>& t)
|
||||
: zone_(std::move(z))
|
||||
: zone_(check(std::move(z)))
|
||||
, tp_(zone_->to_sys(t))
|
||||
{}
|
||||
|
||||
@ -1423,7 +1441,7 @@ template <class T, class>
|
||||
inline
|
||||
zoned_time<Duration, TimeZonePtr>::zoned_time(TimeZonePtr z, const local_time<Duration>& t,
|
||||
choose c)
|
||||
: zone_(std::move(z))
|
||||
: zone_(check(std::move(z)))
|
||||
, tp_(zone_->to_sys(t, c))
|
||||
{}
|
||||
|
||||
@ -1432,7 +1450,7 @@ template <class Duration2, class TimeZonePtr2, class>
|
||||
inline
|
||||
zoned_time<Duration, TimeZonePtr>::zoned_time(TimeZonePtr z,
|
||||
const zoned_time<Duration2, TimeZonePtr2>& zt)
|
||||
: zone_(std::move(z))
|
||||
: zone_(check(std::move(z)))
|
||||
, tp_(zt.tp_)
|
||||
{}
|
||||
|
||||
@ -1847,8 +1865,6 @@ operator<<(std::basic_ostream<CharT, Traits>& os, const zoned_time<Duration, Tim
|
||||
return to_stream(os, fmt, t);
|
||||
}
|
||||
|
||||
#if !MISSING_LEAP_SECONDS
|
||||
|
||||
class utc_clock
|
||||
{
|
||||
public:
|
||||
@ -2787,8 +2803,6 @@ to_gps_time(const tai_time<Duration>& t)
|
||||
return gps_clock::from_utc(tai_clock::to_utc(t));
|
||||
}
|
||||
|
||||
#endif // !MISSING_LEAP_SECONDS
|
||||
|
||||
} // namespace date
|
||||
|
||||
#endif // TZ_H
|
||||
|
@ -95,9 +95,9 @@ private:
|
||||
U& operator=(const pair& x);
|
||||
} u;
|
||||
|
||||
std::chrono::hours h_{};
|
||||
std::chrono::minutes m_{};
|
||||
std::chrono::seconds s_{};
|
||||
std::chrono::hours h_{0};
|
||||
std::chrono::minutes m_{0};
|
||||
std::chrono::seconds s_{0};
|
||||
tz zone_{tz::local};
|
||||
|
||||
public:
|
||||
@ -245,7 +245,7 @@ struct zonelet
|
||||
sys_seconds until_utc_;
|
||||
local_seconds until_std_;
|
||||
local_seconds until_loc_;
|
||||
std::chrono::minutes initial_save_{};
|
||||
std::chrono::minutes initial_save_{0};
|
||||
std::string initial_abbrev_;
|
||||
std::pair<const Rule*, date::year> first_rule_{nullptr, date::year::min()};
|
||||
std::pair<const Rule*, date::year> last_rule_{nullptr, date::year::max()};
|
||||
@ -289,8 +289,7 @@ struct transition
|
||||
std::ostream&
|
||||
operator<<(std::ostream& os, const transition& t)
|
||||
{
|
||||
using date::operator<<;
|
||||
os << t.timepoint << "Z ";
|
||||
date::operator<<(os, t.timepoint) << "Z ";
|
||||
if (t.info->offset >= std::chrono::seconds{0})
|
||||
os << '+';
|
||||
os << make_time(t.info->offset);
|
||||
|
110
src/ios.mm
110
src/ios.mm
@ -51,7 +51,7 @@ namespace date
|
||||
{
|
||||
namespace iOSUtils
|
||||
{
|
||||
|
||||
|
||||
struct TarInfo
|
||||
{
|
||||
char objType;
|
||||
@ -60,14 +60,14 @@ namespace date
|
||||
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()
|
||||
{
|
||||
@ -75,18 +75,18 @@ namespace date
|
||||
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()
|
||||
{
|
||||
@ -96,7 +96,7 @@ namespace date
|
||||
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
|
||||
@ -104,34 +104,34 @@ namespace date
|
||||
#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)
|
||||
{
|
||||
@ -142,55 +142,55 @@ namespace date
|
||||
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);
|
||||
@ -214,21 +214,21 @@ namespace date
|
||||
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);
|
||||
@ -239,20 +239,20 @@ namespace date
|
||||
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
|
||||
@ -266,17 +266,17 @@ namespace date
|
||||
#endif
|
||||
writeFile(tzdataPath, info.objName, obj, info.realContentSize);
|
||||
location += info.blocksContentSize;
|
||||
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
remove(tarPath.c_str());
|
||||
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
TarInfo
|
||||
getTarObjectInfo(std::ifstream &readStream)
|
||||
{
|
||||
@ -285,22 +285,22 @@ namespace date
|
||||
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)
|
||||
{
|
||||
@ -308,29 +308,29 @@ namespace date
|
||||
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
|
||||
|
||||
|
807
src/tz.cpp
807
src/tz.cpp
File diff suppressed because it is too large
Load Diff
@ -28,6 +28,7 @@ main()
|
||||
{
|
||||
using namespace date;
|
||||
using namespace std::chrono;
|
||||
using date::local_days, date::local_t, date::January, date::July, date::Sunday;
|
||||
|
||||
// self
|
||||
{
|
||||
|
@ -191,6 +191,7 @@ main()
|
||||
using namespace date;
|
||||
using namespace std::chrono;
|
||||
using sys_clock = std::chrono::system_clock;
|
||||
using local_t = date::local_t;
|
||||
|
||||
//steady_clock (must be different that sys_clock)
|
||||
static_assert(is_clock_castable<steady_clock, steady_clock>::value, "steady_clock -> steady_clock");
|
||||
|
@ -33,15 +33,15 @@
|
||||
// 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>&
|
||||
|
@ -46,19 +46,19 @@ int
|
||||
main()
|
||||
{
|
||||
using namespace date::detail;
|
||||
static_assert(width<0>::value == 0, "");
|
||||
static_assert(width<1>::value == 0, "");
|
||||
static_assert(width<2>::value == 1, "");
|
||||
static_assert(width<3>::value == 19, "");
|
||||
static_assert(width<4>::value == 2, "");
|
||||
static_assert(width<5>::value == 1, "");
|
||||
static_assert(width<6>::value == 19, "");
|
||||
static_assert(width<7>::value == 19, "");
|
||||
static_assert(width<8>::value == 3, "");
|
||||
static_assert(width<9>::value == 19, "");
|
||||
static_assert(width<10>::value == 1, "");
|
||||
static_assert(width<100>::value == 2, "");
|
||||
static_assert(width<1000>::value == 3, "");
|
||||
static_assert(width<10000>::value == 4, "");
|
||||
static_assert(width<625>::value == 4, "");
|
||||
static_assert(width<0, 1>::value == 0, "");
|
||||
static_assert(width<1, 1>::value == 0, "");
|
||||
static_assert(width<1, 2>::value == 1, "");
|
||||
static_assert(width<1, 3>::value == 19, "");
|
||||
static_assert(width<1, 4>::value == 2, "");
|
||||
static_assert(width<1, 5>::value == 1, "");
|
||||
static_assert(width<1, 6>::value == 19, "");
|
||||
static_assert(width<1, 7>::value == 19, "");
|
||||
static_assert(width<1, 8>::value == 3, "");
|
||||
static_assert(width<1, 9>::value == 19, "");
|
||||
static_assert(width<1, 10>::value == 1, "");
|
||||
static_assert(width<1, 100>::value == 2, "");
|
||||
static_assert(width<1, 1000>::value == 3, "");
|
||||
static_assert(width<1, 10000>::value == 4, "");
|
||||
static_assert(width<756, 625>::value == 4, "");
|
||||
}
|
||||
|
@ -36,7 +36,7 @@ void test_SI()
|
||||
// atto
|
||||
{
|
||||
duration<int, std::atto> d(13);
|
||||
os << d;
|
||||
date::operator<<(os, d);
|
||||
assert(os.str() == "13as");
|
||||
os.str("");
|
||||
}
|
||||
@ -44,7 +44,7 @@ void test_SI()
|
||||
// femto
|
||||
{
|
||||
duration<int, std::femto> d(13);
|
||||
os << d;
|
||||
date::operator<<(os, d);
|
||||
assert(os.str() == "13fs");
|
||||
os.str("");
|
||||
}
|
||||
@ -52,7 +52,7 @@ void test_SI()
|
||||
// pico
|
||||
{
|
||||
duration<int, std::pico> d(13);
|
||||
os << d;
|
||||
date::operator<<(os, d);
|
||||
assert(os.str() == "13ps");
|
||||
os.str("");
|
||||
}
|
||||
@ -60,7 +60,7 @@ void test_SI()
|
||||
// nano
|
||||
{
|
||||
duration<int, std::nano> d(13);
|
||||
os << d;
|
||||
date::operator<<(os, d);
|
||||
assert(os.str() == "13ns");
|
||||
os.str("");
|
||||
}
|
||||
@ -68,7 +68,7 @@ void test_SI()
|
||||
// mikro
|
||||
{
|
||||
duration<int, std::micro> d(13);
|
||||
os << d;
|
||||
date::operator<<(os, d);
|
||||
assert(os.str() == "13\xC2\xB5s");
|
||||
os.str("");
|
||||
}
|
||||
@ -76,7 +76,7 @@ void test_SI()
|
||||
// milli
|
||||
{
|
||||
duration<int, std::milli> d(13);
|
||||
os << d;
|
||||
date::operator<<(os, d);
|
||||
assert(os.str() == "13ms");
|
||||
os.str("");
|
||||
}
|
||||
@ -84,7 +84,7 @@ void test_SI()
|
||||
// centi
|
||||
{
|
||||
duration<int, std::centi> d(13);
|
||||
os << d;
|
||||
date::operator<<(os, d);
|
||||
assert(os.str() == "13cs");
|
||||
os.str("");
|
||||
}
|
||||
@ -92,7 +92,7 @@ void test_SI()
|
||||
// deci
|
||||
{
|
||||
duration<int, std::deci> d(13);
|
||||
os << d;
|
||||
date::operator<<(os, d);
|
||||
assert(os.str() == "13ds");
|
||||
os.str("");
|
||||
}
|
||||
@ -100,7 +100,7 @@ void test_SI()
|
||||
// seconds
|
||||
{
|
||||
duration<int> d(13);
|
||||
os << d;
|
||||
date::operator<<(os, d);
|
||||
assert(os.str() == "13s");
|
||||
os.str("");
|
||||
}
|
||||
@ -108,7 +108,7 @@ void test_SI()
|
||||
// deca
|
||||
{
|
||||
duration<int, std::deca> d(13);
|
||||
os << d;
|
||||
date::operator<<(os, d);
|
||||
assert(os.str() == "13das");
|
||||
os.str("");
|
||||
}
|
||||
@ -116,7 +116,7 @@ void test_SI()
|
||||
// hecto
|
||||
{
|
||||
duration<int, std::hecto> d(13);
|
||||
os << d;
|
||||
date::operator<<(os, d);
|
||||
assert(os.str() == "13hs");
|
||||
os.str("");
|
||||
}
|
||||
@ -124,7 +124,7 @@ void test_SI()
|
||||
// kilo
|
||||
{
|
||||
duration<int, std::kilo> d(13);
|
||||
os << d;
|
||||
date::operator<<(os, d);
|
||||
assert(os.str() == "13ks");
|
||||
os.str("");
|
||||
}
|
||||
@ -132,7 +132,7 @@ void test_SI()
|
||||
// mega
|
||||
{
|
||||
duration<int, std::mega> d(13);
|
||||
os << d;
|
||||
date::operator<<(os, d);
|
||||
assert(os.str() == "13Ms");
|
||||
os.str("");
|
||||
}
|
||||
@ -140,7 +140,7 @@ void test_SI()
|
||||
// giga
|
||||
{
|
||||
duration<int, std::giga> d(13);
|
||||
os << d;
|
||||
date::operator<<(os, d);
|
||||
assert(os.str() == "13Gs");
|
||||
os.str("");
|
||||
}
|
||||
@ -148,7 +148,7 @@ void test_SI()
|
||||
// tera
|
||||
{
|
||||
duration<int, std::tera> d(13);
|
||||
os << d;
|
||||
date::operator<<(os, d);
|
||||
assert(os.str() == "13Ts");
|
||||
os.str("");
|
||||
}
|
||||
@ -156,7 +156,7 @@ void test_SI()
|
||||
// peta
|
||||
{
|
||||
duration<int, std::peta> d(13);
|
||||
os << d;
|
||||
date::operator<<(os, d);
|
||||
assert(os.str() == "13Ps");
|
||||
os.str("");
|
||||
}
|
||||
@ -164,7 +164,7 @@ void test_SI()
|
||||
// femto
|
||||
{
|
||||
duration<int, std::exa> d(13);
|
||||
os << d;
|
||||
date::operator<<(os, d);
|
||||
assert(os.str() == "13Es");
|
||||
os.str("");
|
||||
}
|
||||
@ -180,7 +180,7 @@ void test_calendar()
|
||||
// minutes
|
||||
{
|
||||
minutes d(13);
|
||||
os << d;
|
||||
date::operator<<(os, d);
|
||||
assert(os.str() == "13min");
|
||||
os.str("");
|
||||
}
|
||||
@ -188,7 +188,7 @@ void test_calendar()
|
||||
// hours
|
||||
{
|
||||
hours d(13);
|
||||
os << d;
|
||||
date::operator<<(os, d);
|
||||
assert(os.str() == "13h");
|
||||
os.str("");
|
||||
}
|
||||
@ -196,7 +196,7 @@ void test_calendar()
|
||||
// days
|
||||
{
|
||||
days d(13);
|
||||
os << d;
|
||||
date::operator<<(os, d);
|
||||
assert(os.str() == "13d");
|
||||
os.str("");
|
||||
}
|
||||
@ -212,7 +212,7 @@ void test_integral_scale()
|
||||
// ratio 123 / 1
|
||||
{
|
||||
duration<int, std::ratio<123, 1>> d(13);
|
||||
os << d;
|
||||
date::operator<<(os, d);
|
||||
assert(os.str() == "13[123]s");
|
||||
os.str("");
|
||||
}
|
||||
@ -220,7 +220,7 @@ void test_integral_scale()
|
||||
// ratio 100 / 4 = ratio 25 / 1
|
||||
{
|
||||
duration<int, std::ratio<25, 1>> d(13);
|
||||
os << d;
|
||||
date::operator<<(os, d);
|
||||
assert(os.str() == "13[25]s");
|
||||
os.str("");
|
||||
}
|
||||
@ -228,7 +228,7 @@ void test_integral_scale()
|
||||
// weeks = ratio 7 * 24 * 60 * 60 / 1 = ratio 604800 / 1
|
||||
{
|
||||
weeks d(13);
|
||||
os << d;
|
||||
date::operator<<(os, d);
|
||||
assert(os.str() == "13[604800]s");
|
||||
os.str("");
|
||||
}
|
||||
@ -236,7 +236,7 @@ void test_integral_scale()
|
||||
// years = 146097/400 days = ratio 146097/400 * 24 * 60 * 60 = ratio 31556952 / 1
|
||||
{
|
||||
years d(13);
|
||||
os << d;
|
||||
date::operator<<(os, d);
|
||||
assert(os.str() == "13[31556952]s");
|
||||
os.str("");
|
||||
}
|
||||
@ -244,7 +244,7 @@ void test_integral_scale()
|
||||
// months = 1/12 years = ratio 1/12 * 31556952 = ratio 2629746 / 1
|
||||
{
|
||||
months d(13);
|
||||
os << d;
|
||||
date::operator<<(os, d);
|
||||
assert(os.str() == "13[2629746]s");
|
||||
os.str("");
|
||||
}
|
||||
@ -260,7 +260,7 @@ void test_ratio_scale()
|
||||
// ratio 1 / 2
|
||||
{
|
||||
duration<int, std::ratio<1, 2>> d(13);
|
||||
os << d;
|
||||
date::operator<<(os, d);
|
||||
assert(os.str() == "13[1/2]s");
|
||||
os.str("");
|
||||
}
|
||||
@ -268,7 +268,7 @@ void test_ratio_scale()
|
||||
// ratio 100 / 3
|
||||
{
|
||||
duration<int, std::ratio<100, 3>> d(13);
|
||||
os << d;
|
||||
date::operator<<(os, d);
|
||||
assert(os.str() == "13[100/3]s");
|
||||
os.str("");
|
||||
}
|
||||
@ -276,7 +276,7 @@ void test_ratio_scale()
|
||||
// ratio 100 / 6 = ratio 50 / 3
|
||||
{
|
||||
duration<int, std::ratio<100, 6>> d(13);
|
||||
os << d;
|
||||
date::operator<<(os, d);
|
||||
assert(os.str() == "13[50/3]s");
|
||||
os.str("");
|
||||
}
|
||||
|
@ -32,86 +32,86 @@ main()
|
||||
using namespace date;
|
||||
using namespace std::chrono;
|
||||
std::ostringstream os;
|
||||
os << format("%C", sys_days{jun/1/20001});
|
||||
os << date::format("%C", sys_days{jun/1/20001});
|
||||
assert(os.str() == "200");
|
||||
|
||||
os.str("");
|
||||
os << format("%C", sys_days{jun/1/20000});
|
||||
os << date::format("%C", sys_days{jun/1/20000});
|
||||
assert(os.str() == "200");
|
||||
|
||||
os.str("");
|
||||
os << format("%C", sys_days{jun/1/19999});
|
||||
os << date::format("%C", sys_days{jun/1/19999});
|
||||
assert(os.str() == "199");
|
||||
|
||||
os.str("");
|
||||
os << format("%C", sys_days{jun/1/2001});
|
||||
os << date::format("%C", sys_days{jun/1/2001});
|
||||
assert(os.str() == "20");
|
||||
|
||||
os.str("");
|
||||
os << format("%C", sys_days{jun/1/2000});
|
||||
os << date::format("%C", sys_days{jun/1/2000});
|
||||
assert(os.str() == "20");
|
||||
|
||||
os.str("");
|
||||
os << format("%C", sys_days{jun/1/1999});
|
||||
os << date::format("%C", sys_days{jun/1/1999});
|
||||
assert(os.str() == "19");
|
||||
|
||||
os.str("");
|
||||
os << format("%C", sys_days{jun/1/101});
|
||||
os << date::format("%C", sys_days{jun/1/101});
|
||||
assert(os.str() == "01");
|
||||
|
||||
os.str("");
|
||||
os << format("%C", sys_days{jun/1/100});
|
||||
os << date::format("%C", sys_days{jun/1/100});
|
||||
assert(os.str() == "01");
|
||||
|
||||
os.str("");
|
||||
os << format("%C", sys_days{jun/1/99});
|
||||
os << date::format("%C", sys_days{jun/1/99});
|
||||
assert(os.str() == "00");
|
||||
|
||||
os.str("");
|
||||
os << format("%C", sys_days{jun/1/1});
|
||||
os << date::format("%C", sys_days{jun/1/1});
|
||||
assert(os.str() == "00");
|
||||
|
||||
os.str("");
|
||||
os << format("%C", sys_days{jun/1/0});
|
||||
os << date::format("%C", sys_days{jun/1/0});
|
||||
assert(os.str() == "00");
|
||||
|
||||
os.str("");
|
||||
os << format("%C", sys_days{jun/1/-1});
|
||||
os << date::format("%C", sys_days{jun/1/-1});
|
||||
assert(os.str() == "-01");
|
||||
|
||||
os.str("");
|
||||
os << format("%C", sys_days{jun/1/-99});
|
||||
os << date::format("%C", sys_days{jun/1/-99});
|
||||
assert(os.str() == "-01");
|
||||
|
||||
os.str("");
|
||||
os << format("%C", sys_days{jun/1/-100});
|
||||
os << date::format("%C", sys_days{jun/1/-100});
|
||||
assert(os.str() == "-01");
|
||||
|
||||
os.str("");
|
||||
os << format("%C", sys_days{jun/1/-101});
|
||||
os << date::format("%C", sys_days{jun/1/-101});
|
||||
assert(os.str() == "-02");
|
||||
|
||||
os.str("");
|
||||
os << format("%C", sys_days{jun/1/-1999});
|
||||
os << date::format("%C", sys_days{jun/1/-1999});
|
||||
assert(os.str() == "-20");
|
||||
|
||||
os.str("");
|
||||
os << format("%C", sys_days{jun/1/-2000});
|
||||
os << date::format("%C", sys_days{jun/1/-2000});
|
||||
assert(os.str() == "-20");
|
||||
|
||||
os.str("");
|
||||
os << format("%C", sys_days{jun/1/-2001});
|
||||
os << date::format("%C", sys_days{jun/1/-2001});
|
||||
assert(os.str() == "-21");
|
||||
|
||||
os.str("");
|
||||
os << format("%C", sys_days{jun/1/-19999});
|
||||
os << date::format("%C", sys_days{jun/1/-19999});
|
||||
assert(os.str() == "-200");
|
||||
|
||||
os.str("");
|
||||
os << format("%C", sys_days{jun/1/-20000});
|
||||
os << date::format("%C", sys_days{jun/1/-20000});
|
||||
assert(os.str() == "-200");
|
||||
|
||||
os.str("");
|
||||
os << format("%C", sys_days{jun/1/-20001});
|
||||
os << date::format("%C", sys_days{jun/1/-20001});
|
||||
assert(os.str() == "-201");
|
||||
}
|
||||
|
@ -29,12 +29,11 @@ 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);
|
||||
auto s = date::format(out_fmt, t);
|
||||
assert(s == output);
|
||||
}
|
||||
|
||||
|
@ -40,39 +40,41 @@ main()
|
||||
using namespace date;
|
||||
using namespace std::chrono;
|
||||
std::ostringstream os;
|
||||
os << format("%F %T", sys_days{jan/1/year::min()});
|
||||
using date::year, date::last;
|
||||
|
||||
os << date::format("%F %T", sys_days{jan/1/year::min()});
|
||||
assert(os.str() == "-32767-01-01 00:00:00");
|
||||
os.str("");
|
||||
os << format("%F %T", sys_days{dec/last/year::max()});
|
||||
os << date::format("%F %T", sys_days{dec/last/year::max()});
|
||||
assert(os.str() == "32767-12-31 00:00:00");
|
||||
os.str("");
|
||||
os << format("%F %T", sys_days{dec/last/year::max()} + hours{23} + minutes{59} +
|
||||
os << date::format("%F %T", sys_days{dec/last/year::max()} + hours{23} + minutes{59} +
|
||||
seconds{59} + microseconds{999999});
|
||||
assert(os.str() == "32767-12-31 23:59:59.999999");
|
||||
os.str("");
|
||||
|
||||
os << format("%Y-%m-%d %H:%M:%S", sys_days{jan/1/year::min()});
|
||||
os << date::format("%Y-%m-%d %H:%M:%S", sys_days{jan/1/year::min()});
|
||||
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()});
|
||||
os << date::format("%Y-%m-%d %H:%M:%S", sys_days{dec/last/year::max()});
|
||||
assert(os.str() == "32767-12-31 00:00:00");
|
||||
os.str("");
|
||||
os << format("%Y-%m-%d %H:%M:%S", sys_days{dec/last/year::max()} + hours{23} +
|
||||
os << date::format("%Y-%m-%d %H:%M:%S", sys_days{dec/last/year::max()} + hours{23} +
|
||||
minutes{59} + seconds{59} + microseconds{999999});
|
||||
assert(os.str() == "32767-12-31 23:59:59.999999");
|
||||
os.str("");
|
||||
|
||||
os << format("%F %T", sys_days{jan/1/year::min()} + microfortnights{1});
|
||||
os << date::format("%F %T", sys_days{jan/1/year::min()} + microfortnights{1});
|
||||
assert(os.str() == "-32767-01-01 00:00:01.2096");
|
||||
os.str("");
|
||||
os << format("%F %T", sys_days{dec/last/year::max()} + microfortnights{1});
|
||||
os << date::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());
|
||||
os << date::format("%F", jan/1/year::min());
|
||||
assert(os.str() == "-32767-01-01");
|
||||
os.str("");
|
||||
os << format("%F", dec/last/year::max());
|
||||
os << date::format("%F", dec/last/year::max());
|
||||
assert(os.str() == "32767-12-31");
|
||||
os.str("");
|
||||
}
|
||||
|
@ -32,90 +32,90 @@ main()
|
||||
using namespace date;
|
||||
using namespace std::chrono;
|
||||
std::ostringstream os;
|
||||
os << format("%y", sys_days{jun/1/20001});
|
||||
os << date::format("%y", sys_days{jun/1/20001});
|
||||
assert(os.str() == "01");
|
||||
|
||||
os.str("");
|
||||
os << format("%y", sys_days{jun/1/20000});
|
||||
os << date::format("%y", sys_days{jun/1/20000});
|
||||
assert(os.str() == "00");
|
||||
|
||||
os.str("");
|
||||
os << format("%y", sys_days{jun/1/19999});
|
||||
os << date::format("%y", sys_days{jun/1/19999});
|
||||
assert(os.str() == "99");
|
||||
|
||||
os.str("");
|
||||
os << format("%y", sys_days{jun/1/2001});
|
||||
os << date::format("%y", sys_days{jun/1/2001});
|
||||
assert(os.str() == "01");
|
||||
|
||||
os.str("");
|
||||
os << format("%y", sys_days{jun/1/2000});
|
||||
os << date::format("%y", sys_days{jun/1/2000});
|
||||
assert(os.str() == "00");
|
||||
|
||||
os.str("");
|
||||
os << format("%y", sys_days{jun/1/1999});
|
||||
os << date::format("%y", sys_days{jun/1/1999});
|
||||
assert(os.str() == "99");
|
||||
|
||||
os.str("");
|
||||
os << format("%y", sys_days{jun/1/101});
|
||||
os << date::format("%y", sys_days{jun/1/101});
|
||||
assert(os.str() == "01");
|
||||
|
||||
os.str("");
|
||||
os << format("%y", sys_days{jun/1/100});
|
||||
os << date::format("%y", sys_days{jun/1/100});
|
||||
assert(os.str() == "00");
|
||||
|
||||
os.str("");
|
||||
os << format("%y", sys_days{jun/1/99});
|
||||
os << date::format("%y", sys_days{jun/1/99});
|
||||
assert(os.str() == "99");
|
||||
|
||||
os.str("");
|
||||
os << format("%y", sys_days{jun/1/1});
|
||||
os << date::format("%y", sys_days{jun/1/1});
|
||||
assert(os.str() == "01");
|
||||
|
||||
os.str("");
|
||||
os << format("%y", sys_days{jun/1/0});
|
||||
os << date::format("%y", sys_days{jun/1/0});
|
||||
assert(os.str() == "00");
|
||||
|
||||
os.str("");
|
||||
os << format("%y", sys_days{jun/1/-1});
|
||||
os << date::format("%y", sys_days{jun/1/-1});
|
||||
assert(os.str() == "01");
|
||||
|
||||
os.str("");
|
||||
os << format("%y", sys_days{jun/1/-99});
|
||||
os << date::format("%y", sys_days{jun/1/-99});
|
||||
assert(os.str() == "99");
|
||||
|
||||
os.str("");
|
||||
os << format("%y", sys_days{jun/1/-100});
|
||||
os << date::format("%y", sys_days{jun/1/-100});
|
||||
assert(os.str() == "00");
|
||||
|
||||
os.str("");
|
||||
os << format("%y", sys_days{jun/1/-101});
|
||||
os << date::format("%y", sys_days{jun/1/-101});
|
||||
assert(os.str() == "01");
|
||||
|
||||
os.str("");
|
||||
os << format("%y", sys_days{jun/1/-1999});
|
||||
os << date::format("%y", sys_days{jun/1/-1999});
|
||||
assert(os.str() == "99");
|
||||
|
||||
os.str("");
|
||||
os << format("%y", sys_days{jun/1/-2000});
|
||||
os << date::format("%y", sys_days{jun/1/-2000});
|
||||
assert(os.str() == "00");
|
||||
|
||||
os.str("");
|
||||
os << format("%y", sys_days{jun/1/-2001});
|
||||
os << date::format("%y", sys_days{jun/1/-2001});
|
||||
assert(os.str() == "01");
|
||||
|
||||
os.str("");
|
||||
os << format("%y", sys_days{jun/1/-19999});
|
||||
os << date::format("%y", sys_days{jun/1/-19999});
|
||||
assert(os.str() == "99");
|
||||
|
||||
os.str("");
|
||||
os << format("%y", sys_days{jun/1/-20000});
|
||||
os << date::format("%y", sys_days{jun/1/-20000});
|
||||
assert(os.str() == "00");
|
||||
|
||||
os.str("");
|
||||
os << format("%y", sys_days{jun/1/-20001});
|
||||
os << date::format("%y", sys_days{jun/1/-20001});
|
||||
assert(os.str() == "01");
|
||||
|
||||
os.str("");
|
||||
os << format("%y", sys_days{jun/1/year::min()});
|
||||
os << date::format("%y", sys_days{jun/1/date::year::min()});
|
||||
assert(os.str() == "67");
|
||||
}
|
||||
|
@ -83,10 +83,11 @@ main()
|
||||
constexpr ConvertibleToMonths custom_month;
|
||||
constexpr ConvertibleToYears custom_year;
|
||||
constexpr ConvertibleToYearsAndMonths prefer_year;
|
||||
|
||||
|
||||
using date::last;
|
||||
|
||||
{
|
||||
constexpr year_month ym = 2001_y/feb;
|
||||
constexpr date::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);
|
||||
@ -97,7 +98,7 @@ main()
|
||||
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);
|
||||
@ -141,7 +142,7 @@ main()
|
||||
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);
|
||||
@ -166,7 +167,7 @@ main()
|
||||
}
|
||||
|
||||
{
|
||||
constexpr year_month_day ym = 2001_y/feb/10;
|
||||
constexpr date::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);
|
||||
@ -177,7 +178,7 @@ main()
|
||||
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);
|
||||
@ -221,7 +222,7 @@ main()
|
||||
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);
|
||||
@ -246,7 +247,7 @@ main()
|
||||
}
|
||||
|
||||
{
|
||||
constexpr year_month_day_last ym = 2001_y/feb/last;
|
||||
constexpr date::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);
|
||||
@ -257,7 +258,7 @@ main()
|
||||
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);
|
||||
@ -301,7 +302,7 @@ main()
|
||||
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);
|
||||
@ -326,7 +327,7 @@ main()
|
||||
}
|
||||
|
||||
{
|
||||
constexpr year_month_weekday ym = 2001_y/feb/fri[4];
|
||||
constexpr date::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]);
|
||||
@ -337,7 +338,7 @@ main()
|
||||
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]);
|
||||
@ -381,7 +382,7 @@ main()
|
||||
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]);
|
||||
@ -406,7 +407,7 @@ main()
|
||||
}
|
||||
|
||||
{
|
||||
constexpr year_month_weekday_last ym = 2001_y/feb/fri[last];
|
||||
constexpr date::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]);
|
||||
@ -417,7 +418,7 @@ main()
|
||||
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]);
|
||||
@ -461,7 +462,7 @@ main()
|
||||
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]);
|
||||
|
@ -204,6 +204,13 @@ test_c()
|
||||
assert(!in.bad());
|
||||
assert(tp == sys_days{2016_y/12/11} + hours{14} + minutes{2} + seconds{43});
|
||||
}
|
||||
{
|
||||
// can't parse negative years with "%c" directly
|
||||
std::istringstream in{"Sun Dec 11 14:02:43 -2016"};
|
||||
sys_seconds tp;
|
||||
in >> parse("%c", tp);
|
||||
assert(in.fail());
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
@ -362,6 +369,30 @@ test_d()
|
||||
assert(!in.bad());
|
||||
assert(tp == 2016_y/12/9);
|
||||
}
|
||||
{
|
||||
std::istringstream in{"2016 +9 12"};
|
||||
sys_days tp;
|
||||
in >> parse("%Y %d %m", tp);
|
||||
assert(in.fail());
|
||||
}
|
||||
{
|
||||
std::istringstream in{"2016 +9 12"};
|
||||
sys_days tp;
|
||||
in >> parse("%Y %e %m", tp);
|
||||
assert(in.fail());
|
||||
}
|
||||
{
|
||||
std::istringstream in{"2016 -9 12"};
|
||||
sys_days tp;
|
||||
in >> parse("%Y %d %m", tp);
|
||||
assert(in.fail());
|
||||
}
|
||||
{
|
||||
std::istringstream in{"2016 -9 12"};
|
||||
sys_days tp;
|
||||
in >> parse("%Y %e %m", tp);
|
||||
assert(in.fail());
|
||||
}
|
||||
{
|
||||
std::istringstream in{"2016 31 11"};
|
||||
sys_days tp;
|
||||
@ -390,6 +421,7 @@ test_F()
|
||||
{
|
||||
using namespace date;
|
||||
using namespace std::chrono;
|
||||
using date::year_month_day;
|
||||
{
|
||||
std::istringstream in{"2016-12-13"};
|
||||
sys_days tp;
|
||||
@ -400,7 +432,7 @@ test_F()
|
||||
}
|
||||
{
|
||||
std::istringstream in{"2016-12-13"};
|
||||
year_month_day tp;
|
||||
year_month_day tp{};
|
||||
in >> parse("%F", tp);
|
||||
assert(!in.fail());
|
||||
assert(!in.bad());
|
||||
@ -413,6 +445,7 @@ test_H()
|
||||
{
|
||||
using namespace date;
|
||||
using namespace std::chrono;
|
||||
using date::sys_time;
|
||||
{
|
||||
std::istringstream in{"2016-12-11 15"};
|
||||
sys_time<hours> tp;
|
||||
@ -434,6 +467,7 @@ test_Ip()
|
||||
{
|
||||
using namespace date;
|
||||
using namespace std::chrono;
|
||||
using date::sys_time;
|
||||
{
|
||||
std::istringstream in{"2016-12-11 1 pm"};
|
||||
sys_time<hours> tp;
|
||||
@ -456,6 +490,12 @@ test_Ip()
|
||||
in >> parse("%F %I %p", tp);
|
||||
assert(in.fail());
|
||||
}
|
||||
{
|
||||
std::istringstream in{"2016-12-11 +1 pm"};
|
||||
sys_time<hours> tp;
|
||||
in >> parse("%F %I %p", tp);
|
||||
assert(in.fail());
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
@ -500,6 +540,12 @@ test_m()
|
||||
in >> parse("%Y %d %m", tp);
|
||||
assert(in.fail());
|
||||
}
|
||||
{
|
||||
std::istringstream in{"2016-12-+3"};
|
||||
sys_days tp;
|
||||
in >> parse("%Y-%d-%m", tp);
|
||||
assert(in.fail());
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
@ -507,6 +553,7 @@ test_M()
|
||||
{
|
||||
using namespace date;
|
||||
using namespace std::chrono;
|
||||
using date::sys_time;
|
||||
{
|
||||
std::istringstream in{"2016-12-11 15"};
|
||||
sys_time<minutes> tp;
|
||||
@ -528,6 +575,7 @@ test_S()
|
||||
{
|
||||
using namespace date;
|
||||
using namespace std::chrono;
|
||||
using date::sys_time;
|
||||
{
|
||||
std::istringstream in{"2016-12-11 15"};
|
||||
sys_seconds tp;
|
||||
@ -557,6 +605,7 @@ test_T()
|
||||
{
|
||||
using namespace date;
|
||||
using namespace std::chrono;
|
||||
using date::sys_time;
|
||||
{
|
||||
std::istringstream in{"2016-12-11 15:43:22"};
|
||||
sys_seconds tp;
|
||||
@ -615,6 +664,7 @@ test_p()
|
||||
{
|
||||
using namespace date;
|
||||
using namespace std::chrono;
|
||||
using date::sys_time;
|
||||
{
|
||||
std::istringstream in{"2016-12-11 11pm"};
|
||||
sys_time<hours> tp;
|
||||
@ -623,6 +673,21 @@ test_p()
|
||||
assert(!in.bad());
|
||||
assert(tp == sys_days{2016_y/12/11} + hours{23});
|
||||
}
|
||||
{
|
||||
std::istringstream in{"1986-12-01 01:01:01 pm"};
|
||||
sys_time<seconds> tp;
|
||||
in >> parse("%Y-%m-%d %I:%M:%S %p", tp);
|
||||
assert(!in.fail());
|
||||
assert(!in.bad());
|
||||
assert(tp == sys_days{1986_y/12/01} + hours{13} + minutes{01} + seconds{01});
|
||||
}
|
||||
{
|
||||
std::istringstream in{"1986-12-01 01:01:01"};
|
||||
sys_time<seconds> tp;
|
||||
in >> parse("%Y-%m-%d %I:%M:%S", tp);
|
||||
// The test will fail because %I needs the %p option to shows if it is AM or PM
|
||||
assert(in.fail());
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
@ -729,6 +794,7 @@ test_z()
|
||||
{
|
||||
using namespace date;
|
||||
using namespace std::chrono;
|
||||
using date::local_seconds, date::local_days;
|
||||
{
|
||||
std::istringstream in{"2016-12-26 15:53:22 -0500"};
|
||||
sys_seconds tp;
|
||||
@ -753,6 +819,30 @@ test_z()
|
||||
assert(!in.bad());
|
||||
assert(tp == sys_days{2016_y/12/26} + hours{20} + minutes{53} + seconds{22});
|
||||
}
|
||||
{
|
||||
std::istringstream in{"2016-12-26 15:53:22 -+500"};
|
||||
sys_seconds tp;
|
||||
in >> parse("%F %T %z", tp);
|
||||
assert(in.fail());
|
||||
}
|
||||
{
|
||||
std::istringstream in{"2016-12-26 15:53:22 -+500"};
|
||||
sys_seconds tp;
|
||||
in >> parse("%F %T %Ez", tp);
|
||||
assert(in.fail());
|
||||
}
|
||||
{
|
||||
std::istringstream in{"2016-12-26 15:53:22 --500"};
|
||||
sys_seconds tp;
|
||||
in >> parse("%F %T %z", tp);
|
||||
assert(in.fail());
|
||||
}
|
||||
{
|
||||
std::istringstream in{"2016-12-26 15:53:22 --500"};
|
||||
sys_seconds tp;
|
||||
in >> parse("%F %T %Ez", tp);
|
||||
assert(in.fail());
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
@ -760,6 +850,7 @@ test_Z()
|
||||
{
|
||||
using namespace date;
|
||||
using namespace std::chrono;
|
||||
using date::local_seconds, date::local_days;
|
||||
{
|
||||
std::string a;
|
||||
std::istringstream in{"2016-12-26 15:53:22 word"};
|
||||
|
@ -79,16 +79,16 @@ main()
|
||||
static_assert(t1.to_duration() == hours{13}, "");
|
||||
#endif
|
||||
|
||||
auto t2 = t1;
|
||||
const auto t2 = t1;
|
||||
assert(t2.hours() == t1.hours());
|
||||
assert(t2.to_duration() == t1.to_duration());
|
||||
ostringstream os;
|
||||
os << t2;
|
||||
assert(os.str() == "13:00:00");
|
||||
auto h = make12(t2.hours());
|
||||
auto h = date::make12(t2.hours());
|
||||
os.str("");
|
||||
assert(h == hours{1});
|
||||
assert(t2.to_duration() == t1.to_duration());
|
||||
assert(!is_am(t2.hours()));
|
||||
assert(is_pm(t2.hours()));
|
||||
assert(!date::is_am(t2.hours()));
|
||||
assert(date::is_pm(t2.hours()));
|
||||
}
|
||||
|
@ -90,6 +90,7 @@ main()
|
||||
{
|
||||
using namespace date;
|
||||
using namespace std::chrono;
|
||||
using date::year;
|
||||
|
||||
static_assert(year{2015} == 2015_y, "");
|
||||
static_assert(year{2015} != 2016_y, "");
|
||||
|
@ -75,6 +75,9 @@ test_arithmetic()
|
||||
{
|
||||
using namespace date;
|
||||
using namespace std::chrono;
|
||||
using date::year_month;
|
||||
using date::year;
|
||||
using date::month;
|
||||
|
||||
for (int y1 = 2010; y1 <= 2015; ++y1)
|
||||
{
|
||||
@ -114,6 +117,7 @@ void test_arithemtic_not_ok()
|
||||
{
|
||||
using namespace date;
|
||||
using namespace std::chrono;
|
||||
using date::year_month, date::month;
|
||||
|
||||
year_month ym{2018_y, month{14}};
|
||||
|
||||
@ -123,7 +127,7 @@ void test_arithemtic_not_ok()
|
||||
assert(ym - months{0} == ym2);
|
||||
assert(ym - ym2 == months{0});
|
||||
assert(ym2 - ym == months{0});
|
||||
|
||||
|
||||
auto ymc = ym;
|
||||
ymc += months{0};
|
||||
assert(ymc.ok());
|
||||
|
@ -56,7 +56,6 @@ static_assert( std::is_trivially_move_assignable<iso_week::lastweek_weekday>{},
|
||||
|
||||
static_assert(std::is_trivially_copyable<iso_week::lastweek_weekday>{}, "");
|
||||
static_assert(std::is_standard_layout<iso_week::lastweek_weekday>{}, "");
|
||||
static_assert(std::is_literal_type<iso_week::lastweek_weekday>{}, "");
|
||||
|
||||
static_assert( std::is_nothrow_constructible<iso_week::lastweek_weekday,
|
||||
iso_week::weekday>{}, "");
|
||||
|
@ -82,7 +82,6 @@ static_assert( std::is_trivially_move_assignable<iso_week::weekday>{}, "");
|
||||
|
||||
static_assert(std::is_trivially_copyable<iso_week::weekday>{}, "");
|
||||
static_assert(std::is_standard_layout<iso_week::weekday>{}, "");
|
||||
static_assert(std::is_literal_type<iso_week::weekday>{}, "");
|
||||
|
||||
static_assert( std::is_nothrow_constructible<iso_week::weekday, unsigned>{}, "");
|
||||
static_assert( std::is_nothrow_constructible<iso_week::weekday, iso_week::sys_days>{}, "");
|
||||
|
@ -70,7 +70,6 @@ static_assert( std::is_trivially_move_assignable<iso_week::weeknum>{}, "");
|
||||
|
||||
static_assert(std::is_trivially_copyable<iso_week::weeknum>{}, "");
|
||||
static_assert(std::is_standard_layout<iso_week::weeknum>{}, "");
|
||||
static_assert(std::is_literal_type<iso_week::weeknum>{}, "");
|
||||
|
||||
static_assert( std::is_nothrow_constructible<iso_week::weeknum, unsigned>{}, "");
|
||||
static_assert(!std::is_convertible<unsigned, iso_week::weeknum>{}, "");
|
||||
|
@ -59,7 +59,6 @@ static_assert( std::is_trivially_move_assignable<iso_week::weeknum_weekday>{}, "
|
||||
|
||||
static_assert(std::is_trivially_copyable<iso_week::weeknum_weekday>{}, "");
|
||||
static_assert(std::is_standard_layout<iso_week::weeknum_weekday>{}, "");
|
||||
static_assert(std::is_literal_type<iso_week::weeknum_weekday>{}, "");
|
||||
|
||||
static_assert( std::is_nothrow_constructible<iso_week::weeknum_weekday,
|
||||
iso_week::weeknum,
|
||||
|
@ -72,7 +72,6 @@ static_assert( std::is_trivially_move_assignable<iso_week::year>{}, "");
|
||||
|
||||
static_assert(std::is_trivially_copyable<iso_week::year>{}, "");
|
||||
static_assert(std::is_standard_layout<iso_week::year>{}, "");
|
||||
static_assert(std::is_literal_type<iso_week::year>{}, "");
|
||||
|
||||
static_assert( std::is_nothrow_constructible<iso_week::year, int>{}, "");
|
||||
static_assert(!std::is_convertible<int, iso_week::year>{}, "");
|
||||
@ -84,6 +83,7 @@ int
|
||||
main()
|
||||
{
|
||||
using namespace iso_week;
|
||||
using iso_week::year;
|
||||
|
||||
static_assert(year{2015} == 2015_y, "");
|
||||
static_assert(int{year{2015}} == 2015, "");
|
||||
@ -93,6 +93,9 @@ main()
|
||||
static_assert(year{2015} <= 2015_y, "");
|
||||
static_assert(year{2016} >= 2015_y, "");
|
||||
|
||||
static_assert(year{2015}.is_leap(), "");
|
||||
static_assert(!year{2016}.is_leap(), "");
|
||||
|
||||
auto y = year{2014};
|
||||
assert(++y == year{2015});
|
||||
assert(y == year{2015});
|
||||
|
@ -64,7 +64,6 @@ static_assert( std::is_trivially_move_assignable<iso_week::year_lastweek>{}, "")
|
||||
|
||||
static_assert(std::is_trivially_copyable<iso_week::year_lastweek>{}, "");
|
||||
static_assert(std::is_standard_layout<iso_week::year_lastweek>{}, "");
|
||||
static_assert(std::is_literal_type<iso_week::year_lastweek>{}, "");
|
||||
|
||||
static_assert(std::is_nothrow_constructible<iso_week::year_lastweek,
|
||||
iso_week::year>{}, "");
|
||||
|
@ -65,7 +65,6 @@ static_assert( std::is_trivially_move_assignable<iso_week::year_lastweek_weekday
|
||||
|
||||
static_assert(std::is_trivially_copyable<iso_week::year_lastweek_weekday>{}, "");
|
||||
static_assert(std::is_standard_layout<iso_week::year_lastweek_weekday>{}, "");
|
||||
static_assert(std::is_literal_type<iso_week::year_lastweek_weekday>{}, "");
|
||||
|
||||
static_assert( std::is_nothrow_constructible<iso_week::year_lastweek_weekday,
|
||||
iso_week::year, iso_week::weekday>{}, "");
|
||||
|
@ -65,7 +65,6 @@ static_assert( std::is_trivially_move_assignable<iso_week::year_weeknum>{}, "");
|
||||
|
||||
static_assert(std::is_trivially_copyable<iso_week::year_weeknum>{}, "");
|
||||
static_assert(std::is_standard_layout<iso_week::year_weeknum>{}, "");
|
||||
static_assert(std::is_literal_type<iso_week::year_weeknum>{}, "");
|
||||
|
||||
static_assert( std::is_nothrow_constructible<iso_week::year_weeknum,
|
||||
iso_week::year,
|
||||
|
@ -69,7 +69,6 @@ static_assert( std::is_trivially_move_assignable<iso_week::year_weeknum_weekday>
|
||||
|
||||
static_assert(std::is_trivially_copyable<iso_week::year_weeknum_weekday>{}, "");
|
||||
static_assert(std::is_standard_layout<iso_week::year_weeknum_weekday>{}, "");
|
||||
static_assert(std::is_literal_type<iso_week::year_weeknum_weekday>{}, "");
|
||||
|
||||
static_assert( std::is_nothrow_constructible<iso_week::year_weeknum_weekday,
|
||||
iso_week::year, iso_week::weeknum,
|
||||
|
110
test/posix/ptz.pass.cpp
Normal file
110
test/posix/ptz.pass.cpp
Normal file
@ -0,0 +1,110 @@
|
||||
// The MIT License (MIT)
|
||||
//
|
||||
// Copyright (c) 2021 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 Posix::time_zone
|
||||
|
||||
#include "tz.h"
|
||||
#include "ptz.h"
|
||||
#include <cassert>
|
||||
|
||||
bool
|
||||
is_equal(date::sys_info const& x, date::sys_info const& y)
|
||||
{
|
||||
using namespace std::chrono;
|
||||
return x.begin == y.begin &&
|
||||
x.end == y.end &&
|
||||
x.offset == y.offset &&
|
||||
(x.save == minutes{0}) == (y.save == minutes{0}) &&
|
||||
x.abbrev == y.abbrev;
|
||||
}
|
||||
|
||||
bool
|
||||
is_equal(date::local_info const& x, date::local_info const& y)
|
||||
{
|
||||
return x.result == y.result && is_equal(x.first, y.first)
|
||||
&& is_equal(x.second, y.second);
|
||||
}
|
||||
|
||||
int
|
||||
main()
|
||||
{
|
||||
using namespace date;
|
||||
using namespace std;
|
||||
using namespace std::chrono;
|
||||
using date::local_days, date::Sunday, date::last;
|
||||
|
||||
auto tzi = locate_zone("Australia/Sydney");
|
||||
Posix::time_zone tzp{"AEST-10AEDT,M10.1.0,M4.1.0/3"};
|
||||
auto tp = local_days{2021_y/1/1} + 0s;
|
||||
assert(tzp.get_info(tp).result == local_info::unique);
|
||||
assert(is_equal(tzi->get_info(tp), tzp.get_info(tp)));
|
||||
|
||||
tp = local_days{2021_y/10/Sunday[1]} + 2h + 30min;
|
||||
assert(tzp.get_info(tp).result == local_info::nonexistent);
|
||||
assert(is_equal(tzi->get_info(tp), tzp.get_info(tp)));
|
||||
|
||||
tp = local_days{2021_y/4/Sunday[1]} + 2h + 30min;
|
||||
assert(tzp.get_info(tp).result == local_info::ambiguous);
|
||||
assert(is_equal(tzi->get_info(tp), tzp.get_info(tp)));
|
||||
|
||||
tp = local_days{2021_y/7/1};
|
||||
assert(tzp.get_info(tp).result == local_info::unique);
|
||||
assert(is_equal(tzi->get_info(tp), tzp.get_info(tp)));
|
||||
|
||||
|
||||
tzi = locate_zone("America/New_York");
|
||||
tzp = Posix::time_zone{"EST5EDT,M3.2.0,M11.1.0"};
|
||||
tp = local_days{2021_y/1/1};
|
||||
assert(tzp.get_info(tp).result == local_info::unique);
|
||||
assert(is_equal(tzi->get_info(tp), tzp.get_info(tp)));
|
||||
|
||||
tp = local_days{2021_y/3/Sunday[2]} + 2h + 30min;
|
||||
assert(tzp.get_info(tp).result == local_info::nonexistent);
|
||||
assert(is_equal(tzi->get_info(tp), tzp.get_info(tp)));
|
||||
|
||||
tp = local_days{2021_y/11/Sunday[1]} + 1h + 30min;
|
||||
assert(tzp.get_info(tp).result == local_info::ambiguous);
|
||||
assert(is_equal(tzi->get_info(tp), tzp.get_info(tp)));
|
||||
|
||||
tp = local_days{2021_y/7/1};
|
||||
assert(tzp.get_info(tp).result == local_info::unique);
|
||||
assert(is_equal(tzi->get_info(tp), tzp.get_info(tp)));
|
||||
|
||||
|
||||
tzi = locate_zone("Europe/Dublin");
|
||||
tzp = Posix::time_zone{"IST-1GMT0,M10.5.0,M3.5.0/1"};
|
||||
tp = local_days{2021_y/1/1};
|
||||
assert(tzp.get_info(tp).result == local_info::unique);
|
||||
assert(is_equal(tzi->get_info(tp), tzp.get_info(tp)));
|
||||
|
||||
tp = local_days{2021_y/3/Sunday[last]} + 1h + 30min;
|
||||
assert(tzp.get_info(tp).result == local_info::nonexistent);
|
||||
assert(is_equal(tzi->get_info(tp), tzp.get_info(tp)));
|
||||
|
||||
tp = local_days{2021_y/10/Sunday[last]} + 1h + 30min;
|
||||
assert(tzp.get_info(tp).result == local_info::ambiguous);
|
||||
assert(is_equal(tzi->get_info(tp), tzp.get_info(tp)));
|
||||
|
||||
tp = local_days{2021_y/7/1};
|
||||
assert(tzp.get_info(tp).result == local_info::unique);
|
||||
assert(is_equal(tzi->get_info(tp), tzp.get_info(tp)));
|
||||
}
|
@ -215,7 +215,7 @@ test_g() {
|
||||
static_assert(sizeof(ymdd)/sizeof(ymdd[0]) == sizeof(ymdh)/sizeof(ymdh[0]), "");
|
||||
static_assert(sizeof(ymdd)/sizeof(ymdd[0]) == sizeof(leaps)/sizeof(leaps[0]), "");
|
||||
|
||||
for (auto i = 0; i < sizeof(ymdd)/sizeof(ymdd[0]); ++i)
|
||||
for (auto i = 0u; i < sizeof(ymdd)/sizeof(ymdd[0]); ++i)
|
||||
{
|
||||
assert(solar_hijri::year_month_day{ymdd[i]} == ymdh[i]);
|
||||
assert(ymdd[i] == date::year_month_day{ymdh[i]});
|
||||
|
@ -46,8 +46,14 @@ fi
|
||||
|
||||
if [ -z "$CXX_LANG" ]
|
||||
then
|
||||
CXX_LANG=c++14
|
||||
CXX_LANG=c++17
|
||||
fi
|
||||
|
||||
if expr "$CXX" : ".*g++" >/dev/null
|
||||
then
|
||||
OPTIONS="$OPTIONS -pthread"
|
||||
fi
|
||||
|
||||
OPTIONS="-std=${CXX_LANG} $OPTIONS -I$ROOT -Wall $ROOT/src/tz.cpp -lcurl"
|
||||
|
||||
echo $ROOT
|
||||
|
@ -42,7 +42,7 @@ public:
|
||||
{
|
||||
using namespace date;
|
||||
using namespace std::chrono;
|
||||
using LT = local_time<std::common_type_t<Duration, minutes>>;
|
||||
using LT = date::local_time<std::common_type_t<Duration, minutes>>;
|
||||
return LT{(tp + offset_).time_since_epoch()};
|
||||
}
|
||||
|
||||
@ -52,7 +52,7 @@ public:
|
||||
{
|
||||
using namespace date;
|
||||
using namespace std::chrono;
|
||||
using ST = sys_time<std::common_type_t<Duration, minutes>>;
|
||||
using ST = date::sys_time<std::common_type_t<Duration, minutes>>;
|
||||
return ST{(tp - offset_).time_since_epoch()};
|
||||
}
|
||||
|
||||
|
36
test/tz_test/tzdb_list.pass.cpp
Normal file
36
test/tz_test/tzdb_list.pass.cpp
Normal file
@ -0,0 +1,36 @@
|
||||
// The MIT License (MIT)
|
||||
//
|
||||
// Copyright (c) 2020 Howard Hinnant
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in all
|
||||
// copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
// SOFTWARE.
|
||||
|
||||
#include "tz.h"
|
||||
#include <type_traits>
|
||||
|
||||
int
|
||||
main()
|
||||
{
|
||||
using namespace date;
|
||||
static_assert( std::is_nothrow_destructible<tzdb_list>{}, "");
|
||||
static_assert( std::is_nothrow_default_constructible<tzdb_list>{}, "");
|
||||
static_assert(!std::is_copy_constructible<tzdb_list>{}, "");
|
||||
static_assert(!std::is_copy_assignable<tzdb_list>{}, "");
|
||||
static_assert( std::is_nothrow_move_constructible<tzdb_list>{}, "");
|
||||
static_assert(!std::is_move_assignable<tzdb_list>{}, "");
|
||||
}
|
@ -9,7 +9,7 @@ test_info(const date::time_zone* zone, const date::sys_info& info)
|
||||
auto begin = info.begin;
|
||||
auto end = info.end - microseconds{1};
|
||||
auto mid = begin + (end - begin) /2;
|
||||
using sys_microseconds = sys_time<microseconds>;
|
||||
using sys_microseconds = date::sys_time<microseconds>;
|
||||
using zoned_microseconds = zoned_time<microseconds>;
|
||||
zoned_microseconds local{zone};
|
||||
|
||||
@ -106,7 +106,7 @@ tzmain()
|
||||
{
|
||||
std::cout << name << '\n';
|
||||
auto z = locate_zone(name);
|
||||
auto begin = sys_days(jan/1/year::min()) + seconds{0};
|
||||
auto begin = sys_days(jan/1/date::year::min()) + seconds{0};
|
||||
auto end = sys_days(jan/1/2035) + seconds{0};
|
||||
auto info = z->get_info(begin);
|
||||
std::cout << "Initially: ";
|
||||
@ -130,7 +130,7 @@ tzmain()
|
||||
info.save == prev_save)
|
||||
continue;
|
||||
auto dp = floor<days>(begin);
|
||||
auto ymd = year_month_day(dp);
|
||||
auto ymd = date::year_month_day(dp);
|
||||
auto time = make_time(begin - dp);
|
||||
std::cout << ymd << ' ' << time << "Z ";
|
||||
if (info.offset >= seconds{0})
|
||||
|
@ -25,12 +25,12 @@
|
||||
// {
|
||||
// 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
|
||||
// <
|
||||
@ -38,36 +38,36 @@
|
||||
// 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>&
|
||||
@ -108,6 +108,7 @@ main()
|
||||
using namespace std;
|
||||
using namespace std::chrono;
|
||||
using namespace date;
|
||||
using date::sys_time, date::local_days, date::local_seconds;
|
||||
static_assert( is_nothrow_destructible<zoned_seconds>{}, "");
|
||||
static_assert( is_default_constructible<zoned_seconds>{}, "");
|
||||
static_assert( is_nothrow_copy_constructible<zoned_seconds>{}, "");
|
||||
|
@ -34,6 +34,7 @@ void testDeductionFrom(Source&& s)
|
||||
{
|
||||
using namespace date;
|
||||
using namespace std::chrono;
|
||||
using date::sys_time, date::local_days, date::local_time;
|
||||
|
||||
// No time point
|
||||
{
|
||||
@ -148,13 +149,14 @@ main()
|
||||
{
|
||||
using namespace date;
|
||||
using namespace std::chrono;
|
||||
using date::sys_time, date::local_days, date::local_time;
|
||||
|
||||
#if HAS_DEDUCTION_GUIDES
|
||||
// no arguments
|
||||
{
|
||||
zoned_time zt{};
|
||||
static_assert(std::is_same<decltype(zt), zoned_time<seconds>>::value, "");
|
||||
}
|
||||
}
|
||||
|
||||
// zoned_time
|
||||
{
|
||||
|
12
test_fail.sh
12
test_fail.sh
@ -1,10 +1,6 @@
|
||||
#!/bin/bash
|
||||
#!/bin/sh
|
||||
|
||||
# show what is to be run
|
||||
echo $1
|
||||
eval $1
|
||||
|
||||
if [ $? -eq 0 ]; then
|
||||
exit 0;
|
||||
fi
|
||||
exit 1;
|
||||
|
||||
# run the command
|
||||
eval $1 || exit 1 # if fails, return 1
|
||||
|
Reference in New Issue
Block a user