506 Commits

Author SHA1 Message Date
1658637448 C++23 enable in CMakeLists.txt 2023-04-27 14:26:47 +02:00
4bbbffdf4c Merge pull request #1 from zaporozhets/feature/add_linux_build_support
Add linux build support
2023-04-25 14:13:35 +02:00
8ec7f3a36d Add linux build support 2023-04-13 19:03:31 +02:00
b1a75847d5 Added qmake helper file to use this library easily with Qt 2021-02-14 23:24:22 +01:00
49d78d1837 Silenced warning 2021-02-09 18:32:44 +01:00
a32ff4f07e esp-idf fixes 2021-02-09 17:46:44 +01:00
3be6b76d70 Added library.json 2021-02-09 17:46:44 +01:00
bf79dd5a81 Update README.md 2021-01-11 20:05:18 -05:00
26fc2bd372 Fix read_long_double with respect to decimal_point:
*  Respect locale settings when ONLY_C_LOCALE=0
*  Do not respect locale settings when ONLY_C_LOCALE=1
Fixes #637
2021-01-05 21:14:41 -05:00
97246a638a Silence lossy conversion warning
Fixes #620
2020-11-10 08:41:30 -05:00
432bab81f9 Skip "version" file and USE_OS_TZDB to return "unknown" if no version found (#616)
In commit commit 0b72599bd4 there
was a change to read "version" in addition to "+VERSION", so that
file shold also be ignored when scanning/reading zonefiles.

Also before the above mentioed commit get_version() would return
"unknown" if not on __APPLE__ and the version file was not found.
Put back that behaviour, for all USE_OS_TZDB users.

This last change changes the behaviour for __APPLE__ from throwing
an exception to returning "unknown".

Co-authored-by: Lars Gullik Bjønnes <lbjonnes@cisco.com>
2020-10-27 10:08:30 -04:00
215cacff56 Change all uses of round to detail::round_i
Fixes #613

detail::round_i is the same as round when the To::rep
is integral, and is just an implicit conversion when
To::rep is floating point.
2020-10-25 20:16:07 -04:00
3cbfa4318f Put back handling DISABLE_STRING_VIEW (#609)
* Put back handling DISABLE_STRING_VIEW
* Add HAS_DEDUCTION_GUIDES to interface library target
2020-10-08 19:22:15 -04:00
115dd428cf Proposed fix for issue #161
Header include should follow the same preprocessor rules as function definition.
2020-10-08 11:47:09 +03:00
7848566815 Fix a parse error for Visual Studio 2020-10-02 12:53:16 -04:00
393b52f21b Update README.md 2020-09-19 10:15:51 -04:00
0b72599bd4 For USE_OS_TZDB, look for version number in the files
version and +VERSION
2020-09-11 16:00:18 -04:00
ba99134b8a For USE_OS_TZDB, look for leap seconds in the files
leapseconds and leap-seconds.list
2020-09-11 15:53:07 -04:00
5e18488899 Fix subtle bug in fractional_width 2020-09-05 16:34:04 -04:00
313189b0a8 Correct lingering references to bare "tz" libname: (#600)
Fixes: #599
2020-08-25 16:57:00 -04:00
057b441ceb Use LLONG_MAX instead of std::numeric_limits<long long>::max() when constexpr is absent 2020-08-21 17:09:51 -04:00
d7a0bf1fa7 replace noexcept with NOEXCEPT macro 2020-08-21 17:09:51 -04:00
8140d979cd fix brace value initialization for msvc 18 2020-08-21 17:09:51 -04:00
7990eae740 fix user defined literals for compatibility with msvc 18 2020-08-21 17:09:47 -04:00
1ec2ea0295 Add test/tz_test/tzdb_list.pass.cpp 2020-08-17 21:34:20 -04:00
658a3b9495 Fix crasher for early local times and USE_OS_TZDB=1 2020-08-17 21:34:20 -04:00
e7969c32e8 Add Kotlin's datetime library to the list of projects using this (#593) 2020-08-14 09:53:14 -04:00
569b2d6785 Improve error message while parsing posix timezone string 2020-08-02 10:56:37 -04:00
abe3ada04f Update README.md 2020-07-28 17:00:00 -04:00
9537addfc4 fix ONLY_C_LOCALE export from cmake (#590)
* fix ONLY_C_LOCALE export from cmake

* add some comments

* remove all generator expressions for target output

* cmake: fewer variables, make it easier to read
2020-07-22 19:03:42 -04:00
6952fb50a6 Correct the value for not_a_year 2020-07-08 14:20:31 -04:00
fe2f9c7eac Change constexpr to CONSTDATA 2020-07-07 15:01:45 -04:00
a6243ce56f set cmake proj ver to 3.0: (#584)
FIXES: #583
2020-06-22 11:48:09 -04:00
a55f1a103b Update README.md 2020-06-15 15:18:20 -04:00
d544e5af25 Throw exception if zoned_time is constructed with nullptr 2020-06-14 19:30:23 -04:00
cac99da8dc For traits in constexpr context use ::value
* Fixes #542
2020-06-02 21:08:57 -04:00
a088baf9a5 Update README.md 2020-05-26 11:47:28 -04:00
e6adff6754 [cmake] Rename tz library to date-tz:
Fixes: #426
2020-05-24 21:31:18 -04:00
d784766640 iOS Simulator support 2020-05-24 21:31:18 -04:00
9343e31599 Give Posix::time_zone equality comparison 2020-05-24 21:31:18 -04:00
f43c39fcf1 Add member function name() const to Posix::time_zone
* Returns the minimal string that uniquely identifies this
  time_zone.  That is, it takes advantage of all defaults.
2020-05-06 22:12:15 -04:00
e12095f26f Revert change for floating point reps in decimal_format_seconds 2020-04-18 09:24:53 -04:00
7d811743e0 Fix parse of second offset in posix time zone 2020-04-18 09:24:22 -04:00
a2fdba1adc __GNUC_MINOR -> __GNUC_MINOR__
* Fixes #560
2020-03-30 12:50:37 -04:00
4c1968b8f0 Fix constexpr overflow problems on gcc-7-9 2020-03-08 21:58:56 -04:00
9cc3a7bca1 Adding Persian/Jalali/Solar-Hijri calendar 2020-03-08 20:18:45 -04:00
9a0ee25428 Do a runtime test for realpath vs readlink
* Ubuntu needs to use readlink under current_zone
  and most everyone else needs realpath.  Attempting
  to make everyone happy with this commit.
2020-01-25 10:05:26 -05:00
c8d311f6f1 fixes #534 (#535) 2020-01-16 18:16:58 -05:00
fe63f0bb5f Add MANUAL_TZ_DB configure option: (#527)
* Add MANUAL_TZ_DB configure option:

FIXES: #458

* [fold] address review feedback
2020-01-15 22:08:15 -05:00
9502bc27a3 Update Date.h (#529)
* Remove arithmetic overflow: 

Using operator '-' on a 4 byte value and then casting the result to a 8 byte value. Casting the value to the wider type before calling operator '-' to avoid overflow.
2020-01-11 15:24:10 -05:00
66a5aa482e Add constexpr for clock_cast. 2020-01-11 14:44:06 -05:00
b9cd9c3fde Fixed a typo in CMakeLists.txt: USE_AUTOLOAD => AUTO_DOWNLOAD (#523)
USE_AUTOLOAD wasn't used anywhere else in date's sources. AUTO_DOWNLOAD
is used in .cpp/.h files while never mentioned in CMakeLists.txt.
Must have been a typo.
2020-01-03 20:15:29 -05:00
a184309786 Fix unwanted localization of integral grouping
* Fixes #525
2020-01-01 11:12:14 -05:00
fc4cf092f9 Fix cmake install for 3.14 or earlier (3.7 min) (#522)
* Fix cmake install for 3.14 or earlier (3.7 min)

Fixes: #504, #505

* Add find_dependency to config file

FIXES: #514
2019-12-29 14:51:04 -05:00
48433b9892 Update date.h (#518)
using decltype in day constructor to be consistent with month and year
2019-12-05 14:00:16 -05:00
4c95165298 Constrain make_zoned for icc16
Build fails with Intel Compiler v16:

<source>(1698): error: expression must have a constant value
  std::is_class<typename std::decay<decltype(*std::declval<TimeZonePtr&>())>::type>{}
                                                                                    ^
2019-11-29 19:45:59 -05:00
940f4a5ceb Support Curl Error Buffer
Allow user to get error message when download fails
2019-11-29 19:38:40 -05:00
018a50bcd0 Work around for a NVCC compiler bug
The NVCC compiler fails to compile the date library due
to a compiler bug which causes it to emit an error when
directly using std::ratio_{multiply,divide} in the template
instantiations for std::duration. This PR works around the
issue by introducing custom ratio_{multiply,divide} which
delegate to the standard library templates
2019-11-29 19:27:36 -05:00
3e376be2e9 Rename link to time_zone_link
* At the request of LEWG
2019-11-08 19:36:09 +00:00
224c71a899 Rename leap to leap_second and leaps to leap_seconds
* At the request of LEWG
2019-11-08 19:24:03 +00:00
67e272a54e change the order in hh_mm_ss::to_duration() to have correct result on Windows for cases when h is 2147483647 hours and m and s are all 0 (#501) 2019-10-24 09:57:36 -04:00
d399e10cba Bump zoned_time fixes for MSVC from 1900 to 1916 2019-10-22 13:28:48 -04:00
96ffe23f72 Replace INTMAX_MAX with numeric_limits 2019-10-21 22:22:50 -04:00
48f1455cd2 CMake refactor for easier subdirectory inclusion 2019-10-18 14:59:37 -04:00
e3186e36c2 typo (#498) 2019-10-18 14:47:38 -04:00
3f0f9b3cbe Search for '/' after "zoneinfo" in current_zone() 2019-10-14 15:54:32 -04:00
23fa1bb86d Add vcpkg installation instructions (#495) 2019-09-27 09:46:58 -04:00
4481c75192 Improve current_zone().
Fixes #454
2019-09-23 22:09:13 -04:00
e6d2c08159 Honor symbol visibility settings (#464) 2019-09-23 22:08:07 -04:00
a5c4b4ebf8 Protect is_am and make12 from ADL 2019-09-17 15:48:15 -04:00
44344000f0 Fix MSVC C++ version detection 2019-09-12 19:58:05 -04:00
6d5ff9b958 Point travis badge to upstream master 2019-09-11 14:00:11 -04:00
375579eac1 Remove point release verison from descriptions 2019-09-11 14:00:11 -04:00
2ced83ceff Add clang 6 and clang 7 builds 2019-09-11 14:00:11 -04:00
718cbe3f9b Add gcc 8 build for bionic 2019-09-11 14:00:11 -04:00
961bf06c32 Add nice names to build matrix 2019-09-11 14:00:11 -04:00
fe491eff1c Add travis ci configuration file 2019-09-10 09:36:13 -04:00
c56f915cc3 fixed shared library support 2019-09-09 11:47:47 -04:00
5e57a19abe renamed targets to date and tz 2019-09-09 11:47:47 -04:00
9454aeda2b set library version to 2.4.1
Update CMakeLists.txt to set library version to 2.4.1
2019-09-06 17:32:15 -04:00
3a343adf6a Improve main CMake file
Rename target date_interface to interface and tz to timezone.
Export targets date::interface and date::timezone from cmake.
2019-09-06 10:29:30 -04:00
d21333f636 Fixes #484 2019-09-03 23:17:43 -04:00
cb4bf26fc7 Fix compilation error with GCC 5
GCC 5 complains that `operator-=` and `operator+=` are not constexpr.  The `-` and `+` operator appear seem to be fine.
2019-09-03 22:59:04 -04:00
b87eb970c1 Implemented test for checking addition with classes converible to years/months
To work this specific test require current implementation
strategy (template with unspecified argument).
2019-09-03 22:52:31 -04:00
5a0057587d Correct behavior for classes for which only lvalue is convertible to string_view.
Added OnlyLValueString test case that shows the problem with
current impl. Implemented the change, that accept TimeZonePtrOrName
by forwarding reference (to preserve value category), and
merged time_zone selection into one trait.
2019-09-01 14:43:50 -04:00
5345d135b7 Implemented custom time zone deduction test.
Implemented test for deduction from the custom time zone ptr.
Used OffsetZone extracted for that purpose.
2019-09-01 14:43:50 -04:00
7c020642fb Fixed deduction guides for GCC 8.
The GCC 8 was correctly preffering the deduction guide
syntezied from the std::string_view constructor which is more
specialized than deduction guide. Changed the constructor
so the Duration cannot be deduced from it.
2019-09-01 14:43:50 -04:00
1d721d9afd Implemented set of basic deduction test.
Implemented test for deduction from string, string_view,
time_zone ptr and other zoned_time.
2019-09-01 14:43:50 -04:00
141ba85614 Fix space-matches 0 spaces at end of format string 2019-08-23 15:51:18 -04:00
dca8ddc659 Replace computed value with standard macro 2019-07-21 23:43:29 -04:00
1f5c192f4a Resolve GCC 9.1.0 noexcept warning 2019-07-21 23:31:29 -04:00
46ccd69c9c Resolve GCC 9.1.0 unused-function warning 2019-07-21 23:18:54 -04:00
c0e7b4e2f7 Make date.h compatible with g++-4.7 2019-07-21 21:48:51 -04:00
09d90a8b5e Fix operator<< for years with non C locale
Fix the issue https://github.com/HowardHinnant/date/issues/392
2019-07-21 21:20:49 -04:00
6f0b645df1 #388 add comment on unit test failure (#442) 2019-07-21 20:47:33 -04:00
7ef1a55143 tz.cpp: Cast conversions to/from size_t
These cause warnings with -Wsign-conversion.
2019-07-21 20:46:01 -04:00
27d1e1e54e Removed undefined behavioir from year_mont_day_last::day (#456)
This is done to make the result of calling day() on
year_month_day_last object that is !ok() unspecified.
Checked only months, are there are needed to avoid UB.
2019-05-28 09:01:14 -04:00
7817ebf45a Update date.h (#451)
endf -> endif
2019-05-20 09:44:20 -04:00
a029f1105d Conditionally set _SILENCE_CXX17_UNCAUGHT_EXCEPTION_DEPRECATION_WARNING 2019-05-19 22:46:35 -04:00
44215f6781 Eschew using directives in headers, even at function scope.
* There is still an impact on user code, though I'm not sure
  if by specification or compiler bug.
* Prefer using declarations instead.
2019-05-19 21:53:29 -04:00
ed0368fc75 The URL for windowsZones.xml changed to (#447)
https://raw.githubusercontent.com/unicode-org/cldr/master/common/supplemental/windowsZones.xml
2019-05-15 12:08:24 -04:00
429d9ba739 Add User-Agent curl option in download_to_string function. [#438] 2019-04-19 09:07:03 -04:00
081e9af55b Migrate ptz.h from jan to January 2019-04-05 22:36:21 -04:00
8a563041fa Adjust HAS_STRING_VIEW for VS
Fixes #330
2019-04-05 09:19:54 -04:00
9dc96fd9b5 Silence warning
Fixes #337
2019-03-26 18:13:39 -04:00
8b69087d35 Fix up constexpr of changed weekday_from_days 2019-03-21 12:23:38 -04:00
d5e96f0991 Suppress VS-15 warning about concerning conditional expression is constant
Thanks to https://github.com/ujos for the report.
2019-03-20 21:24:01 -04:00
5ba1c1ad85 HAS_UNCAUGHT_EXCEPTIONS definition.
Added some flexibility for usage of std::uncaught_exceptions().
Xcode 10 uses clang and perfectly compiles C++17, but
std::uncaught_exceptions() is available only on iOS 10+ devices. When
application supports iOS 9 devices and uses C++17 there is no way to
build it, except drop iOS 9 support or remove C++17 code. Using this
define we could configure should date.h use std::uncaught_exceptions()
or not.
2019-03-20 20:43:43 -04:00
10ab6ae9e5 Fix warnings from Clang (#421)
Clang 9 (in Visual Studio) complains about a mixed signed-unsigned comparison and an unused function.
Replace the naked `int` constant -1 by `std::size_t(-1)` with the same codegen as before (no curlies to avoid narrowing).
Guard the definition of `get_download_folder()` by the same condition as its call-site.

Signed-off-by: Daniela Engert <dani@ngrt.de>
2019-03-19 20:25:59 -04:00
e31daf8093 Unit tests for !year_month::ok() arithmetic. (#425) 2019-03-19 20:22:23 -04:00
cb7ca96f68 Protect weekday_from_days from signed overflow
Found by static analyzer.
This change makes weekday_from_days slightly more efficient.
2019-03-19 19:51:32 -04:00
b5d025ea2f Align time_of_day with hh_mm_ss
Per committee review
2019-03-19 19:50:30 -04:00
f782ae98f0 Fix type-o again 2019-02-20 15:27:44 -10:00
d6c5d02068 Fix type-o in get_leap_second_info_t 2019-02-20 15:25:50 -10:00
16077472af Rename is_leap_second to get_leap_second_info 2019-02-20 15:19:54 -10:00
5a62c405e0 Remove unneeded make_precision 2019-02-03 23:21:36 -05:00
09a19a09f4 Further consolidate time_of_day logic
Adjust how it works for floating point durations.
2019-02-03 16:14:56 -05:00
9cb0013aef Update time_of_day to be more consistent ...
the needs of formatting.
2019-02-02 14:06:12 -05:00
f1326968af Make compatible with const-only string.data() spec 2019-01-31 19:23:17 -05:00
61c3d35634 Fix problem with wchar_t* to std::string conversion. (#419)
VS2019 correctly points out that a conversion from a wide NTCS to std::string requires narrowing. This may result in an undesired string value. Implement the string conversion properly.

Signed-off-by: Daniela Engert <dani@ngrt.de>
2019-01-27 17:08:01 -05:00
4e7e76b981 add c_encoding and iso_encoding weekday functions (#380)
- c_encoding satisfies ctime wday encoding: days since Sunday, range
  [0,6]
- iso_encoding satisfies ISO 8601 weekday:
  a digit d from 1 through 7, beginning with Monday and ending with Sunday
2019-01-19 14:46:21 -05:00
90d0440884 Introduce %q and %Q to_stream formatting flags
* These flags format a duration.
* %Q specifies the duration's numeric value.
* %q specifies the duration's SI abbreviation.
* Example: format("%Q %q", 45ms) == "45 ms"
2019-01-19 14:30:19 -05:00
2cb4c34009 Ignore tzdata.zi and leapseconds tzdb files on Linux when loading time zones (#411) 2018-12-18 12:15:00 -05:00
7231a182a4 Revert 5f34c40 and 23b1f00 in preparation of a better solution.
Signed-off-by: Daniela Engert <dani@ngrt.de>
2018-12-16 15:29:17 -05:00
0e85704e47 Don't write to ~/Downloads if not installing there 2018-12-14 20:12:55 -05:00
5f34c40523 More patches for VS-2017 compatiblity 2018-11-25 17:04:27 -05:00
23b1f007fe Patch for VS-2017 compatiblity 2018-11-25 14:38:54 -05:00
a22125ca40 Remove constexpr from islamic::year::isleap for C++11 2018-11-20 09:00:12 -05:00
8f91ef27ed Revert "Model the TAI-UTC difference between 1961 and 1972"
This reverts commit 1eed461d06.
2018-11-08 13:56:23 -08:00
4b46deb4f9 Update README.md
Add  Valhalla (Open Source Routing Library/Service)
2018-11-01 15:19:35 -04:00
54e8516af2 Update README with more accurate CMake info 2018-10-23 11:12:05 -04:00
1eed461d06 Model the TAI-UTC difference between 1961 and 1972 2018-10-03 17:51:55 -04:00
591f572b67 Allow %j to parse and format durations 2018-09-26 14:35:03 -07:00
F
69e9cd612f Prefer using std::string that using namespace std and unqualified string (#386)
'using namespace std;' in header files can conflict with custom
namespace names. For example 'string' is used without 'std::'
qualification. If tz.h is included in a file where string is a
namespace, it cannot be compiled anymore. The same happens with date.h
if ONLY_C_LOCALE=1.
2018-09-26 17:31:56 -04:00
6b51ca8271 Add routinghub to README 2018-09-12 20:42:25 -04:00
3e82a52d66 Add ViewTouch to list of project using this library 2018-08-27 19:33:16 -04:00
6a4d93a0bd Silence more shadow warnings 2018-07-01 23:00:33 -04:00
39d6730665 Silence shadow warnings 2018-07-01 22:37:25 -04:00
de6a03d337 Set _SILENCE_CXX17_UNCAUGHT_EXCEPTION_DEPRECATION_WARNING for VS 2018-06-27 09:21:19 -04:00
e86edc3820 Added missing license to unit test files (#356) 2018-06-23 10:39:00 -04:00
1b32e316db Workaround MSVC 19.14.26431 parsing bug (#355) 2018-06-21 10:08:59 -04:00
f46885e632 Suffix d for days duration (#354) 2018-06-20 11:39:48 -04:00
2d282e35fa Use string_literal for C++11 when possible 2018-06-19 19:37:02 -04:00
d50970b32a Some backwards compatibility fixes for VS-2013 2018-06-12 18:13:24 -04:00
af2b2b70b3 Remove usage of octal literals in tests (#350)
* Remove usage of octal literals

* Fixed July
2018-06-12 13:18:18 -04:00
3933a0122d Add option to disable string_view
Also add -fPIC flag when compiling the shared version of the library.
2018-06-11 17:01:51 -04:00
07876e4433 Character classification functions (isspace, isalnum) are undefined for signed chars
Convert them to int using char_traits or static_cast to unsigned char
2018-06-11 17:00:45 -04:00
0197889505 Update to Sunday constants 2018-06-11 15:14:44 -04:00
b86def339e Test for utc during leap second insertion 2018-06-11 10:45:41 -04:00
aa0494b980 custom clock and noncastable tests 2018-06-11 10:45:41 -04:00
df31560701 Moved test to clock_cast_test dir 2018-06-11 10:45:41 -04:00
4b687f4c04 Test is now C++11 compatible 2018-06-11 10:45:41 -04:00
db60c5eb8e Unit test and typo fix 2018-06-11 10:45:41 -04:00
9f1c4b0110 Implemented clock_cast for local_time.
Implemented clock_time_conversion<D, local_t> calling D::from_local
and clock_time_conversion<locat_t, S> calling S::to_local.

To avoid ambiguities addes:
* clock_time_conversion<local_t, local_t> - idenitity
* clock_time_conversion<local_t, utc_clock> - same as default (utc_clock::to_local)
* clock_time_conversion<utc_clock, local_t> - same as default (utc_clock::from_local)

In addition, as std::chrono::system_clock cannot be edited, added:
* clock_time_conversion<local_t, std::chrono::system_clock> - assumes same epoch
* clock_time_conversion<std::chrono::system_clock, local_t> - assumes same epoch
They will be required to resolve amibiguity anyway.
2018-06-11 10:45:41 -04:00
da15227f6c Implemented to/from_local functions for utc/tai/gps.
Implemented to_local and from_local functions for utc_clock,
tai_clock and gps_clock. For the tai/gps clock used this function
for defining the io - we delegate to serializing/parsing local
time.

The drwaback is that the local_time cannot properly represent
leap second in the UTC time, so separate serialization is needed.
2018-06-11 10:45:41 -04:00
d4fb7eb76d Put unspecified_month_disambiguator in namespace detail 2018-06-10 16:22:21 -04:00
0e3e84fd56 Used suggested Tim Song implementation 2018-06-10 16:22:21 -04:00
3eac2d376e Revert "Fixed addition of multi-year duration to year_month."
This reverts commit 328cecaa56.
2018-06-10 16:22:21 -04:00
f5f4d76936 Replace save_stream with save_ostream
* In islamic.h and julian.h
2018-06-10 15:44:43 -04:00
c7b69d949a Change the encoding for an invalid weekday from 7 to 8 2018-06-08 09:50:40 -04:00
48baa942fc Use uncaught_exceptions in C++17 2018-06-06 13:52:23 -04:00
af415701ba Update wandbox link 2018-06-06 13:31:03 -04:00
be2ec2310b Emphasize Sunday over sun in the implementation
*  Keep the three letter lower case spellings for backwards
   compatibility purposes.
2018-06-03 13:55:00 -04:00
40b83654b6 [API BREAKING] Remove conversion from weekday to unsigned
* There has been a great deal of anguish over the encoding of
  weekdays:  whether [0, 6] maps to [Sunday, Saturday] or
  [1, 7] maps to [Monday, Sunday].  This commit attempts
  to address that issue, but will break a small amount of
  code at compile-time.  See below on how to fix that.

* The weekday constructor used to accept [0, 6] to represent
  [Sunday, Saturday].  It now accepts [0, 7] to represent
  [Sunday, Saturday] with both 0 and 7 mapping to Sunday.

* The conversion from weekday to unsigned has been removed.

* To convert a weekday to unsigned replace:

      auto u = unsigned{wd};

  with:

      auto u = (wd - Sunday).count();

  This maps [Sunday, Saturday] to [0, 6], which is the
  C/POSIX mapping.  If you prefer the ISO mapping
  ([Monday, Sunday] -> [1, 7]), then do:

      auto u = (wd - Monday).count() + 1;
2018-06-02 22:56:10 -04:00
6c4d333026 fixed build in WinRT mode, where some API are not available 2018-06-02 16:14:18 -04:00
1fdda81a30 fixed build with latest VS2017 v15.7.1; toolset MSVC 14.14 2018-06-02 16:14:18 -04:00
apo
f33e179936 Eliminate use of uninitialized offset. 2018-05-25 09:56:34 -04:00
328cecaa56 Fixed addition of multi-year duration to year_month.
* Added new overloads for operator+/- between year_month and duration
  that is convertible to years, so it is better candidate for operands
  that are convertible to both years and months. To preserve
  functionality, this operator is conditionally noexcept.

* Reworked year_month_day, year_month_day_last, year_month_weekday,
  and year_month_weekday_last.

* Added tests for this new functionality.
2018-05-12 18:21:24 -04:00
5d15157bbb Fix bug for parsing negative offsets of less than 1h 2018-05-05 12:01:56 -04:00
a91ceefb4e Allow %H %M and %S to deal with negative durations 2018-04-23 20:31:28 -04:00
88c661e9f3 Fix zoned_time deduction guides 2018-04-23 20:30:58 -04:00
c665992a6e Allow heterogeneous zoned_time constructors
taking {string_view, zoned_time}
2018-04-21 17:45:52 -04:00
9d0bcdb63f Fix deduction error in parse where only offset is requested 2018-04-18 21:56:11 -04:00
973bd393bc Respect and minimize tie/flush in from/to_stream
* Save/restore tie, setting it to nullptr during the operation
* On construction tie_->flush()
* For ostreams only, flush if unitbuf
2018-04-18 21:47:15 -04:00
d53db7a1cb And yet more fixes to allow duplicate flags on parse 2018-04-15 15:32:24 -04:00
e5c69d84ab Fix constexpr issue for VS2015 2018-04-09 11:01:58 -04:00
b48a18a1d9 More fixes to allow duplicate parsing 2018-04-08 15:49:06 -04:00
cdb4b276d9 Allow duplicate parsing into the same fields
* as long as all duplicates produce consistent results.
2018-04-07 21:42:00 -04:00
1d9e49ea21 to_stream sets failbit if unable to format
*  If a formatting flag requests data that is not available in
   the Streamable object, or if the Streamable object answers !ok(),
   failbit is set.
2018-04-06 11:19:44 -04:00
0125d330ab Correct to_stream/from_stream handling of stream data
* to_stream and from_stream now reset the stream formatting state to
  default settings on entry, and restore the stream state on exit.

* to_stream and from_stream now correctly handle mis-modified flags.

* Fix %h to be equivalent to %b instead of %B.

* This addresses issues 319, 320 and 321.
2018-03-31 13:06:57 -04:00
e7e1482087 Remove BUILD_TZ_STATIC and replace with BUILD_SHARED_LIBS
* This is more standard CMake
* See https://cmake.org/cmake/help/v3.1/command/add_library.html
2018-03-19 18:04:34 +00:00
d6b95dc301 Remove TZ_CXX_STANDARD and instead use CMAKE_CXX_STANDARD
* See https://cmake.org/cmake/help/v3.1/variable/CMAKE_CXX_STANDARD.html?highlight=cmake_cxx_standard
2018-03-19 17:59:36 +00:00
700489e475 Introduced full weekday and month names
* The standardized version of this library has std::chrono::January
  and std::chrono::Sunday in place of std::chrono_literals::jan and
  std::chrono_literals::sun.  Compatible names added to namespace
  date to ease transition from this lib to std::chrono.  The old
  names are retained for backwards compatibility.
2018-03-18 18:27:04 -04:00
e6941697eb Validate TZdata failed with OS TZdata 2018-03-18 18:17:27 -04:00
c311db2f1a Clean up tz_test README 2018-03-18 18:14:40 -04:00
fffa52ac0e Cleanup and add to README.md 2018-03-18 18:14:40 -04:00
f105595f04 Use proper lib directory when installing on UNIX
Linux distributions use lib, lib32, and lib64 directories for library files,
symlinking them where needed. Let's follow distirbution rules by
utilising CMake module GNUInstallDirs.
2018-03-18 17:55:08 -04:00
20f0595b32 Update standardization progress 2018-03-17 10:57:45 -04:00
674a9e6953 Update README.md 2018-03-16 15:42:13 -04:00
bc8cf368e5 Update readme link to d0355r6 2018-03-14 22:50:18 -04:00
1e8ab50f82 Test modifications for standardization 2018-03-14 22:49:04 -04:00
38c5ca38bb Typo fixes in comment text 2018-03-04 18:26:07 -05:00
0bde4ba8c8 Make the parsing of minutes optional under the flag %z 2018-03-03 11:57:03 -05:00
afe61df277 Fix case of generated dateConfig so it will work on a case sensitive filesystem 2018-03-02 16:37:32 -05:00
43d8a4eab0 Range check minutes under parse 2018-03-02 09:03:41 -05:00
mwu
ca4036a4b0 Explicitly qualify std::string. Having a global scope string type shall not break the compilation anymore. 2018-02-23 21:17:26 -05:00
a1ceec19fe Workaround for MSVC 2018-02-20 11:51:28 -05:00
5524dd1ae8 Update README.md 2018-02-15 18:49:37 -05:00
4ada98d247 Enable testing in CMakeLists.txt
* Per instructions by @SlavSlavov in https://github.com/HowardHinnant/date/pull/278
2018-01-29 08:39:58 -05:00
040eed838b Augment path to ios.h 2018-01-26 19:53:51 -05:00
2acf403bcd Dont include ios.h unconditionally.
The include in tz.cpp was changed to only include the ios.h header
when compiling on apple platforms, as the documentation states that
only the four files date.h, tz.h, tz_private.h, and tz.cpp should be
required to use the time zone library.

Additionally, the ios.mm file was moved to src/ since it contains
C++ source code.
2018-01-24 20:24:10 -05:00
637e5d8007 Use target_compile_definitions
It's generally preferred to use [`target_compile_definitions`](https://floooh.github.io/2016/01/12/cmake-dependency-juggling.html) over `add_definitions`.
2018-01-21 12:33:42 -05:00
362cd8f27e Account for WIN32 2018-01-21 12:29:13 -05:00
a4ce4bc2d3 Use correct target
Also, fix the formatting in the generator expressions. For some reason, the previous
formatting caused this error:

  Target "date_interface" INTERFACE_INCLUDE_DIRECTORIES property contains
  path:

  ...

  which is prefixed in the source directory.
2018-01-21 12:29:13 -05:00
3e5a57467a Export a CMake config file
This will allow users to import the project via CMake methods, i.e `find_package` rather than doing it manually.
2018-01-21 12:29:13 -05:00
3b8372f4fa Avoid use of undeclared to_utc_time.
* Fixes https://github.com/HowardHinnant/date/issues/289
2018-01-18 15:55:58 -05:00
6941691de4 implement current_zone() for iOS using native API from iOSUtils 2018-01-12 14:59:01 -05:00
09b78ba92c bump msvc define to fix compile issue on MSVC 15.6 2018-01-12 10:51:05 -05:00
28c1c61ac2 Advertise that this works in C++17 2018-01-08 09:54:42 -05:00
55289f0d73 Make tz_dir a function-local static
* This solves initialization order issues detailed
  in https://github.com/HowardHinnant/date/issues/275
2018-01-05 19:26:44 -05:00
b7e58e193f Set standard or default to C++17
Changed cmake to default to c++17 unless TZ_CXX_STANDARD is set(e.g. to 11,14 or 17)
2018-01-05 18:45:29 -05:00
2b6ee6378c minutes fix 2018-01-05 18:42:48 -05:00
7d80d89a44 Allow specifying cxx standard to target
Not everyone can use C++17 even with compilers that support it
2017-12-31 16:42:29 -05:00
d9052cffa2 rename and mark-as-advanced the following cmake-variable used in function print_option:
CURR_${OPT} -> PRINT_OPTION_CURR_${OPT}
so that the date-project now has the following advanced cmake-variables:
 PRINT_OPTION_CURR_BUILD_TZ_STATIC
 PRINT_OPTION_CURR_USE_SYSTEM_TZ_DB
 PRINT_OPTION_CURR_USE_TZ_DB_IN_DOT
2017-12-26 21:00:29 +01:00
447687870f - Interface library name changed from date to date_interface
- Print state of set options
- cleanup on duplicate ${CMAKE_THREAD_LIBS_INIT}
2017-12-26 13:39:55 -05:00
dbd6e6e388 cmake: remove include_directories() command that is missing directory 2017-12-26 13:35:25 -05:00
9178193ad2 cmake: date as INTERFACE target, to enable automatic include_directory
(for cases where just date.h, but not "tz.h and its lib" are needed)
2017-12-26 13:35:25 -05:00
44c2515280 Use the highest possible C++ standard (#18) 2017-12-26 11:12:11 +02:00
0af7654764 Fix iOS build 2017-12-11 05:45:27 -06:00
1eeb4cd652 Prepare for the new definition of IST
* Irish Standard Time has a -1h save in the winter instead
  of a +1h save in the summer.
2017-12-08 13:08:40 -05:00
b49bdc3ca7 Add missing include <memory> for unique_ptr 2017-12-06 10:12:49 -05:00
c7e5a4d08e Add posix-style time zone example: ptz.h 2017-12-03 14:40:01 -05:00
5653e9e3a9 Fixes CURLE_SSL_CACERT (60) when downloading tzdata2017c.tar.gz 2017-12-01 12:14:41 -05:00
d3b8d4af8d use target_include_directories instead of include_directories 2017-12-01 11:18:59 -05:00
c2e139ef53 Replace realpath with readlink
* Appears to be more modern and Debian Stretch requires it.
2017-11-30 17:17:28 -05:00
a3e8f399c4 ifdef out clock_cast for VC-2017 and earlier
* Clients report it can't handle the C++11
* Triggered to be enabled on VC-number-next
* Deprecated API (to_xxx_time) rewritten to be independent of
  clock_cast.
* Whitespace changes to bring column length down to 90.
2017-11-30 15:40:37 -05:00
443a29df53 Improve range check on year
* The previous fix broke parsing of sub-date quantities such as
  durations.
2017-11-30 12:06:51 -05:00
1902b8e8fb Range check year on parse 2017-11-30 10:45:30 -05:00
c513a20691 Fix off-by-one bug in iso_week::year_lastweek_weekday
* The conversion from year_lastweek_weekday to sys_days
  and local_days had an off by one error.
* Added test for this case.
2017-11-30 10:28:14 -05:00
87ed7f83cf Correct IANA data download URL 2017-11-27 12:44:57 -05:00
f8cc62c396 Changed naming
so that it is parent folder name _pass or _fail (e.g.)
date_test_fail_<test_name>
and date_test_pass_<test_name>
As this should be easier to sort
2017-11-27 10:20:14 -05:00
2d2b65906a Set so that the pass tests are all tests that do not end in .fail.cpp 2017-11-27 10:20:14 -05:00
53629fa30c No longer hardwiring subfolders of test
Hid build errors on should fail tests
2017-11-27 10:20:14 -05:00
748a1fd5a9 Updated testing so that failures of the should fail tests will compile
but will return 1 in testing if they actually built
2017-11-26 23:22:29 -05:00
524517b369 Added scripts to do fail testing 2017-11-26 23:11:58 -05:00
98ae1e5241 part 1 of merge request 2017-11-26 23:09:46 -05:00
9b88763dbf Remove noexcept from tai_clock::now() and gps_clock::now()
*  These functions may try to initialize the tzdb which
   could fail.
2017-11-26 21:24:45 -05:00
f3741d68ff Removed OpenSSL requirement. Curl, if it supports SSL, will pull it in.
Tested on Ubuntu so far
2017-11-26 16:56:41 -05:00
080df4988f excluded testit from Windows 2017-11-26 16:56:41 -05:00
1f27fb7d42 Cannot set USE_OS_TZDB=1 on Windows 2017-11-26 16:56:41 -05:00
3e47883c41 Added compile option BUILD_STATIC that defaults to ON to build static
libraries.  Set to off to build shared
2017-11-26 16:56:41 -05:00
3a33cdca7d Fixed WORKING_DIR path on testit target to use project root as base 2017-11-26 16:56:41 -05:00
3c4f0b5ada Changed testing approach and added gitignore 2017-11-26 16:56:41 -05:00
c0a3e528a3 Typo 2017-11-26 16:56:41 -05:00
9c67d94f2f Started adding test building 2017-11-26 16:56:41 -05:00
9c39772731 Create CMakeList.txt
This is an implementation of cmake config relating to #18
2017-11-26 16:56:41 -05:00
15a63ec819 Updated on behalf of schmidt9 2017-11-26 14:41:40 -05:00
543315b700 Reversed order of arguments to clock_time_conversion.
Now the order of argument matches the clock_cast function.
The test only is_clock_castable trait still matches is_convertible
order of arguments.
2017-11-26 13:50:21 -05:00
7c69f1570d Changed invocation to match specification
Slight difference between invocation on lvalue of clock_time_conversion
object and prvalue.
2017-11-25 22:01:12 +01:00
dd91be668e Added deprecated functions test for real 2017-11-24 23:42:18 +01:00
b13c859ff1 Restored deprecated to_clock_time function.
Fixed the to_utc_time(const gps_time<Duration>& t) function
to correctly use clock_cast<utc_time>.

Added test to deprecated functions.
2017-11-24 23:37:32 +01:00
d4592bd497 Maked clock_time_conversion as const and used alias.
Marked operator() of all supplied clock_time_conversion overload
as const.
Changed input type to sys_time/utc_time alias when possible.
Used consitient nomencalture: st for sys_time, ut for utc_time
and tp for time in different clock.
2017-11-24 23:26:56 +01:00
9910f5fcc3 Moved clock_cast test to separate dir.
Fixed naqme of the to_sys_return_reference test, so it
is invoked.
2017-11-24 22:30:54 +01:00
58a4a9518a Mismatch in return type of converting function is now hard error.
Change the implementation, in the way that mismatch in return
type of the from/to_sys/utc functions (not returning time_point,
or returning time_point with inappropriate clock) leads to
hard error.

Added appropariate fail test for to_sys function, including:
* returning an int
* returning time_point of wrong clock
* reutrning reference to time_point
2017-11-24 22:23:50 +01:00
5a9b44a37a Implemented test for casting non-wall clocks and detecting that clocks cannot be casted.
Added test that detects if clock_cast<Dest>(Source) properly
SFINAEs if clock's are not castable, this includes test for
steady_clock that is not castable to any wall-clock.

Secondly added steady_based_clock based on steady_clock
(as name indicates), that clock_cast may be extended to clock
non-related to wall-time (sys/utc) using conversion traits.

Final example is pair of ambiguous clocks (amb1/amb2_clock) that can convert
to each other either using sys_clock or utc_clock.
Then the conversion from amb2 to amb1 is disambiguated
via trait specialization.
2017-11-24 18:08:00 +01:00
a9d2907fa1 Implemented test for custom clocks derived from sys_clock.
Created mil_clock and s2s_clock, that are both using to_sys/from_sys
function and are fully interoperable with existing clocks (including
ones based on utc).

Implemented an trait is used to provide direct conversion
from s2s_clock to mil_clock without converting to sys_clock
(conversion counter is used for this purpose).
2017-11-24 18:07:33 +01:00
bf5a4f3cd5 Implemented test for existing clocks.
Implemented test for conversions between existing clocks
(sys_clock, utc_clock, tai_clock, gps_clock) showing that
they can be used instead of to_clock_time functions.
2017-11-24 18:06:55 +01:00
e1099ef3ab Implemented clock_cast function.
Added an clock_time_conversion trait, that should be specialized
with SourceClock and DestClock respectively and provide an function
that convert time_point in SourceClock to equivalent time_point
in DestClock.

This function has following specializations:
1) <sys_clock, utc_clock> - convert sys_time to utc_time
2) <utc_clock, sys_clock> - convert utc_time to sys_time
3) <Clock, sys_clock>     - calls Clock::to_sys if it returns sys_time
4) <Clock, utc_clock>     - calls Clock::to_utc if it returns utc_time
5) <sys_clock, Clock>     - calls Clock::from_sys if it returns time_point<Clock>
5) <utc_clock, Clock>     - calls Clock::from_utc if it returns time_point<Clock>

Implemented an clock_cast<DestClock>(time_point<SourceClock, Dur> st), that
works as follow:
1) If DestClock is same as SourceClock, returns std
2) Otherwise, if clock_conversion<SourceClock, DestClock> available, uses it
3) Otherwise, if tries using clock_conversion<SourceClock, CommClock>
   and clock_conversion<CommClock, DestClock> for CommClock being utc_time
   or sys_time
4) Otherwise, tries using clock_conversion<SourceClock, utc_clock>
   and clock_conversion<sys_clock, DestinationClock> or reversed (firstly
   convert to sys_clock, then to utc_clock) to convert.
2017-11-24 17:55:15 +01:00
4614ebda4a Update to accomidate change of iana url #241 2017-11-23 20:25:00 -05:00
c286981b3b Fix improper application of GCC diagnostic suppression 2017-11-21 10:07:31 -05:00
9ca582d9da Silence GCC conversion warning for bitfields
* Used only in weekday_indexed.
2017-11-20 14:50:48 -05:00
f4b12ab023 Adjust HAS_CHRONO_ROUNDING macro for MSVC with v140_clang_c2 and LLVM-vs2014 2017-11-20 11:45:04 -05:00
bd51baf31e msvc token workaround 2017-11-19 18:52:56 -05:00
16439a8ce2 enhance tz_dir detection for buildroot with uclibc systems
* use /etc/TZ for timezone detection on buildroot with uclibc systems
2017-11-19 18:42:13 -05:00
d97bc984c7 Change default_zone from "UTC" to "Etc/UTC"
* zoned_traits<const time_zone*>::default_zone()
  should not depend on a Link, but on a Zone.
2017-11-19 18:17:09 -05:00
c9ef0a8f05 express reverse_bytes in an easy to optimize way
optimizes to single bswap instruction on gcc and clang
2017-11-19 17:52:17 -05:00
4832ea0ddb Move HAS_STRING_VIEW to date.h 2017-11-17 11:09:17 -05:00
ec514101a6 minor patches to build on Windows with MSVC v140_clang_c2 and LLVM-vs2014 2017-11-15 07:20:07 -05:00
517c0f2704 Update C++ standards proposal status 2017-11-12 06:27:50 -05:00
e12f7c66f0 Unconstrain make_zoned for VS-2015 2017-11-07 13:01:16 -07:00
3a5e8c9384 Silence clang warning 2017-10-30 13:48:09 -04:00
fa6529a2fc Allow zoned_time conversion among different TimeZonePtr types 2017-10-28 18:20:34 -04:00
4b73a42d02 Update README.md 2017-10-25 22:12:31 -04:00
25696b7fb3 Optimize to_stream for zoned_time
* Decrease the number of lookups in the database from 2 to 1.
2017-10-24 15:44:41 -04:00
9381e894a5 Specify exception constructors
* For nonexistent_local_time and ambiguous_local_time.
* Simplify the constructors.
* Make these exceptions usable for custom time zones.
2017-10-24 12:12:31 -04:00
5563d31b2e Update validation.cpp for new directory structure 2017-10-24 12:06:50 -04:00
202041e531 Add a workaround for a missing operator<< for gcc 5 on linux. See issue #205 for details. 2017-10-24 11:02:54 -04:00
0b7d9c6dbe Update README.md 2017-10-23 09:47:15 -04:00
66a97f907e to_stream sets failbit if required to supply a bad name:
* for an invalid month
* for an invalid weekday
2017-10-15 13:57:19 -04:00
94eb182256 Add wt to list of products using this library
Announced at CppCon-2017 by Roel Standaert.
2017-10-15 11:03:40 -04:00
f328d8c84a Have format set exceptions(failbit | badbit)
*  Be sure if something bad happens under the hood it is not silently
   swallowed.
2017-10-14 20:42:26 -04:00
8b9f0515b5 Replacing 0 with nullptr to avoid GCC warning
All the calls to `std::time_get::get` had `0` as end-of-range iterator.

E.g.

    auto& f = use_facet<time_get<CharT>>(is.getloc());
	// ...
    f.get(is, 0, is, err, &tm, command, fmt+1);
              ^

Using `nullptr` instead of `0` doesn't trigger the GCC 5.x warning:

> warning: zero as null pointer constant [-Wzero-as-null-pointer-constant]
2017-10-12 19:51:06 +02:00
ce975cadb0 Update Try-it-out link 2017-10-03 18:11:57 -04:00
2032fccbb7 Fix valgrind warning about uninitialized variable use in to_stream()
tm variable is not initialized in to_stream(), and valgrind warns about
"Conditional jump or move depends on uninitialised value(s)".

This is a false positive, as strftime always reads tm_hour, even if it
ends up never using it. To silence the warnings, initialize tm to zero.
2017-10-03 15:22:49 -04:00
2e213abb76 Silence clang static analyzer warnings 2017-10-03 12:45:09 -04:00
3acb299f3f Rename TZ_DB to tzdb
* Bring into alignment with proposal
* TZ_DB alias left behind for backwards compatibility
2017-09-30 14:48:25 -04:00
22a229af91 On macOS tz_dir is now discoverable at run time
* Apple changed the location of their IANA database in High Sierra,
  breaking current_zone().  Now on Apple the location of the IANA
  database is searched for at run time.
2017-09-26 09:47:24 -04:00
fc917fe303 Port testit to new directory structure 2017-09-25 19:28:04 -04:00
bff551b2a5 Convert Windows header file names to lower case 2017-09-23 19:55:56 -04:00
9f6c8d8c10 Update include paths for new directory structure 2017-09-22 20:10:58 -04:00
3c3ba68906 Proposal for an alternative directory structure 2017-09-22 20:03:16 -04:00
c5e58fd015 include <wordexp.h> is unnecessary when using USE_OS_TZDB 2017-09-10 13:50:51 -04:00
ef6d53595d Fix CHAR_BIT not found by including climits. 2017-09-09 19:05:54 -04:00
0f658db2cd Correct how width is counted for fractional seconds
* Include decimal point character in count.
2017-09-09 15:32:47 -04:00
481771ef5e Add support down to femtosecond precision
* Requires platform specific use of 128bit integral representation
  (e.g. std::chrono::duration<__int128_t, std::femto>).
2017-09-09 10:30:39 -04:00
5f01382e24 Enable current_zone() on FreeBSD 2017-09-08 20:47:38 -04:00
41563c46e8 Disabled some template constraints for vs since it does not work properly there 2017-09-07 19:41:47 -04:00
bba9aeafab Added shortened curl include path to support nuget package rmt_curl 2017-09-07 19:33:59 -04:00
4cb893c780 Enable DATE_BUILD_DLL for Linux and macOS 2017-09-05 20:07:13 -04:00
gm
c09d35534d Reformulate macros for static and shared linking on windows. 2017-09-05 19:59:57 -04:00
272d487b3d Add non-const front() to tzdb_list
* Needed when USE_OS_TZDB==1 && MISSING_LEAP_SECONDS==0
2017-08-31 17:45:42 -04:00
aad6010831 Add test for custom time zone support 2017-08-31 10:44:07 -04:00
gm
0707cc4932 NULL to nullptr change. 2017-08-27 21:13:47 -04:00
d3fcf00d55 Small exception safety improvement. 2017-08-27 21:13:47 -04:00
gm
2402a0bd25 undef somethings 2017-08-28 13:10:57 +12:00
873aa0515e Correct the fixes for VS-2017 that broke everyone else 2017-08-21 21:21:59 -04:00
49b50c43d9 Introduce the ONLY_C_LOCALE
*Eliminates dependance on on the time_get and time_put facets.
2017-08-18 22:56:03 -04:00
38c24b4090 Add fixes for VS-2017. 2017-08-18 22:55:31 -04:00
2515dfd1b5 Remove deleted weekday(int) constructor
* This was a failed experiment.
2017-08-15 13:44:16 -04:00
c3ab69ee0d Hard code year::min(), year::max() to [-32767, 32767]
* When year < 0, -year > 0 (always).
* These are the minimal limits C places on short.
* Reserving -32768 is useful in the implementation.
2017-08-15 12:42:27 -04:00
be871e6c85 Add is_clock 2017-08-13 22:57:36 -04:00
eced00fc1c Make tzdb_list::push_front private 2017-08-12 17:42:48 -04:00
859a50a70e Replace list<TZ_DB> with tzdb_list
* tzdb_list is a singly linked list with an atomic head
* push_front() and front() are thread safe.
2017-08-12 17:41:55 -04:00
80a142407a Add zoned_traits
* zoned_traits is SFINEA-friendly.

* zoned_traits is specialized on const time_zone*
  to call locate_zone.

* zoned_time accesses the database via zoned_traits<TimeZonePtr>.

* Clients with custom time zone databases can specialize zoned_traits.
2017-08-12 17:41:55 -04:00
d4d6eda861 Template zoned_time on TimeZonePtr
* TimeZonePtr defaults to const time_zone*.
* Adjust template deduction guides and make_zoned.
* Add HAS_STRING_VIEW
2017-08-12 17:41:55 -04:00
07ada69385 Expose a list<TZ_DB>
* Existing API always accesses the front of the list.
* Add locate_zone and current_zone member functions to TZ_DB.
* reload_tzdb() pushes a new database to the front of the list.
* get_tzdb_list() exposes the list<TZ_DB>&.
2017-08-12 17:41:55 -04:00
e7c3ca0e90 Fix compilation warnings for -DUSE_OS_TZDB.
tz.cpp:1617:24: error: unused parameter 't' [-Werror,-Wunused-parameter]
maybe_reverse_bytes(T& t, std::false_type)
                       ^
tz.cpp:2470:1: error: unused function 'get_version' [-Werror,-Wunused-function]
get_version()
^
tz.cpp: In lambda function:
tz.cpp:1922:84: error: declaration of ‘t’ shadows a previous local [-Werror=shadow]
                                        [](const sys_seconds& x, const transition& t)
                                                                                    ^
tz.cpp:1921:19: note: shadowed declaration is here
         for (auto t = std::upper_bound(transitions_.begin(), transitions_.end(), l,
                   ^
2017-08-12 16:59:23 -04:00
82de27d339 Fix bug in sys_time and local_time from_stream
* to handle microfortnights
2017-08-12 13:56:17 -04:00
922abf1299 Protect from Oracle sun macro 2017-08-06 00:30:27 -04:00
c4dcd5eb78 More Oracle fixes. 2017-08-05 20:27:15 -04:00
9c181a1440 Update tests for default constructible:
* weekday_indexed
* year_month_weekday
2017-08-05 16:31:18 -04:00
e2a38e600c Set constexpr rules to C++11 for Oracle 12.6 and earlier 2017-08-05 16:06:20 -04:00
4ae416f06a Add default constructor for weekday_indexed
* This enables the year_month_weekday default constructor.
2017-07-27 14:34:11 -04:00
5726b70bb7 Turn off constexpr when using clang + VS-2013 std::lib 2017-07-24 08:26:37 -04:00
e6b1e0fe58 Allow read_unsigned to read 0 digits
* Will allow reading "optional" integers.
2017-07-24 08:18:18 -04:00
170ebfd354 Another memory leaks fix 2017-07-22 12:00:52 -04:00
a5b77bb0fe add to copyright holder 2017-07-21 10:41:48 -04:00
5a53cb38a3 VS2013 doesn't accept exception specification for constructor default. Resolves #183 2017-07-21 10:41:48 -04:00
494fee4e1b User defined literals are not supported by VS2013, use explicit year constructor instead 2017-07-21 10:41:48 -04:00
a034eeed23 Have parse of %p set failbit if unsuccessful. 2017-07-19 15:26:29 -04:00
a1b19a2ed6 Silence some warnings. 2017-07-19 15:25:57 -04:00
496497d16e Fix memory leaks 2017-07-17 12:25:27 -04:00
a828109809 Suppress -Wunused-function warning 2017-07-13 09:49:38 -04:00
2129b813c9 Add www.safe.com to list of projects using date 2017-07-10 20:42:29 -04:00
c8d3cc14da Add zoned_time deduction guides 2017-07-06 20:49:53 -04:00
893cf51fd8 Add test for zoned_time 2017-07-06 20:49:28 -04:00
6067371127 Don't pass ill-formed strings to stold
* Avoid exceptions coming out of stold.
* from_stream should always set failbit instead of throw.
2017-07-06 11:54:55 -04:00
0c8b1f5967 Put expand_path back in when INSTALL is defined 2017-07-05 10:30:23 -04:00
16dd16e64e Silence warning on VS 2017-07-03 16:48:48 -04:00
ea0158c779 Move get_program_folder closer to where it is used 2017-07-03 16:45:11 -04:00
a0b8883763 Remove unused variables in load_timezone_mappings_from_xml_file 2017-07-03 16:43:01 -04:00
156bdf8bc6 Remove #ifdef in time_of_day
* Workaround for MSVC no longer needed.
2017-07-03 16:41:09 -04:00
2d1d8f2255 Put %Z back into default streaming for zoned_time
* It was removed by accident.
2017-07-01 23:00:34 -04:00
e0c962a8ce Silence unused variable warnings 2017-07-01 20:37:14 -04:00
7cbc4d8013 Also ignore leap-seconds.list
The tzdata package on Ubuntu includes /usr/share/zoneinfo/leap-
seconds.list. This is not a TZif file, so it should be ignored.
2017-06-29 10:07:35 -04:00
090b66beb8 Update README.md 2017-06-27 22:22:58 -04:00
791de2d9fc Update README.md 2017-06-27 22:22:09 -04:00
77a703afe2 Update to point to current standards proposal and R4 draft 2017-06-27 22:19:58 -04:00
bee4f27d4a Correct problems with load_timezone_mappings_from_xml_file
*  Move outside of HAS_REMOTE_API.

*  Ignore non-empty lines full of white space.
2017-06-26 22:03:01 -04:00
56cec17500 Add gratuitous zoned_time:: qualifier to operators
*  VS-2017 compatibility.
2017-06-26 21:33:34 -04:00
d359399090 Give zoned_time a default constructor 2017-06-26 21:19:29 -04:00
a003ad28fa Make wide string literals in to_stream 2017-06-17 13:18:40 -04:00
012f2c6135 Make to_stream and from_stream return a stream reference 2017-06-17 13:11:39 -04:00
edcd9bd9c1 define MISSING_LEAP_SECONDS 0 when !USE_OS_TZDB 2017-06-16 15:55:43 -04:00
9f0d511be6 Put up draft of D0355R3 2017-06-16 13:26:40 -04:00
ccd857ff6d Add Alloc parameter to basic_string in two places 2017-06-16 13:23:41 -04:00
88890939d5 Add zone1970.tab to the list of files
that should be ignored by init_tzdb() under USE_OS_TZDB.
2017-06-14 20:48:19 -04:00
1139c9b64f Allow zoned_time with coarser precision than seconds
*  This gives greater interoperability with the deduction for class
   templates language feature.

*  time_points output from zoned_time still have at least seconds
   precision.
2017-06-13 23:00:54 -04:00
ec412a1de0 Set failbit instead of throw within to_stream
* This is for consistency with other std streaming operations.
2017-06-12 21:01:58 -04:00
aa4dafcc46 Silence sign conversion warnings 2017-06-12 13:33:47 -04:00
cc81c9ea50 Fix minor problems for g++:
* Add missing #include <string>

* Explicitly convert sys_days to sys_seconds in conditional operator
2017-06-12 09:44:41 -04:00
a610f087c1 Add support for the zic-compiled OS-supplied time zone DB:
*  Avoids the need to download the IANA database.

*  Heavily based on contributions by Aaron Bishop.

*  Turn on with -DUSE_OS_TZDB, off by default.

*  Not supported on Windows.

*  Disables HAS_REMOTE_API.

*  get_tzdb().version only supported on Apple.  This string has
   the value "unknown" elsewhere.

*  Leap second support is missing on Apple, and may not be on your
   platform either (please report).  Leap second support is enabled,
   disabled with -DMISSING_LEAP_SECONDS.

   Without leap second support, utc_time, tai_time, and gps_time (and
   those clocks) are not available.

*  On Apple, time zone transitions are only supported in the range:

   1901-12-13 20:45:52 to 2038-01-19 03:14:07

*  On Linux, time zone transitions are only as far in the future as
   the OS-provided transitions go.  There is no support for POSIX-
   style transitions.
2017-06-04 21:04:53 -04:00
5132385454 Remove obsolete LAZY_INIT flag. 2017-06-04 20:32:37 -04:00
5c38ad84e8 Eliminate TIMEZONE_MAPPING by making it equivalent to _WIN32.
*  Clean up indenting and whitespace.
*  No functionality changes intended.
2017-06-04 20:32:37 -04:00
8b743db4b6 Reorganize readme 2017-05-31 20:49:51 -04:00
9c9ddeba37 Work around EDG 4.11 front end bug. 2017-05-21 13:41:31 -04:00
0fb3921e5b Fail if you need a valid year and don't parse one. 2017-05-20 23:04:49 -04:00
83c8b4d522 changes for compatibility with Clang with Microsoft CodeGen (v140_clang_c2):
- added date:: namespace to flloor() and abs() calls
- added IUnknown forward declaration before including Windows headers to prevent issue with objbase.h
- minor changes
2017-05-08 10:04:20 -04:00
f493bd67f2 Tweak white space parsing rules (again):
* White space matches zero or more white space characters.

  * %n matches one white space character.

  * %t matches zero or one white space characters.
2017-05-07 15:25:07 -04:00
cf0481b9af Reset command, width and modified for %n and %t in from_stream. 2017-05-04 21:03:48 -04:00
f57432d7b4 Don't skip white space by default in from_stream.
* Put a space at the beginning of your
  format string to recover this behavior.
2017-05-04 14:47:28 -04:00
e8f0dca452 Fix type-o in to_stream duration overload. 2017-05-04 10:04:17 -04:00
44f6dfc58e fix compile warning about unused get_download_gz_file()
get_download_gz_file() is not used when HAS_REMOTE_API=0, and causes:

warning: 'std::__cxx11::string date::get_download_gz_file(const string&)' defined but not used [-Wunused-function]

Wrap get_download_gz_file() inside #ifdef to remove the warning.

Signed-off-by: Tomi Valkeinen <tomi.valkeinen@iki.fi>
2017-05-02 20:10:44 -04:00
ec7db09085 Use system_error instead of strerror_r:
* Addresses portability issues.
2017-05-02 20:10:44 -04:00
cb83bc2501 Update README.md 2017-04-24 16:46:58 -04:00
faec35eaf1 Update README.md 2017-04-23 12:49:22 -04:00
20efec5b16 Update README.md 2017-04-23 12:48:06 -04:00
b2dc8b1f6e Tweak getTimeZoneKeyName():
* for systems that return "Coordinated Universal Time".
 * return "UTC" instead.
2017-04-18 20:48:28 -04:00
2f8997d3ed Make parse fail if fmt string is not completely consumed. 2017-04-18 12:02:21 -04:00
c64d69b1e1 Avoid getting localized time zone names from Windows OS.
* Use GetDynamicTimeZoneInformation to get .TimeZoneKeyName
  https://msdn.microsoft.com/en-us/library/windows/desktop/ms724318(v=vs.85).aspx
  > Retrieves the current time zone and dynamic daylight saving time settings.
  https://msdn.microsoft.com/en-us/library/windows/desktop/ms724253(v=vs.85).aspx
  > The name of the time zone registry key on the local computer.

* This avoids the need to map from StandardName to TimeZoneKeyName.

* Using .DynamicDaylightTimeDisabled = true forces the OS to return a
  non-daylight saving time result.

* Use of wcstombs is preferred over wstring_convert as the latter is now
  deprecated in C++17 because the implementors could not interpret the
  specification.
2017-04-17 19:06:58 -04:00
gm
885910375f Fix pragma warnings. Displayed at least by MSVC. 2017-04-16 23:53:37 +12:00
d15491103b Move chrono_io.h functionality into date.h. 2017-04-13 21:01:47 -04:00
05db422ca9 Respect width and padding in "chrono_io.h" 2017-04-13 18:02:26 -04:00
2c094f5559 Restrict parse of %Z to valid timezone names and abbrev. 2017-04-13 14:09:14 -04:00
096bad2622 Parse should fail if fmt string is not consumed. 2017-04-13 12:45:28 -04:00
fc3d4d97fe Silence unused variable 'leaps' warning 2017-04-13 12:44:21 -04:00
4f27361378 Add range checking for the time-of-day fields during parse.
*  Also refactor the leap-second logic used in utc_time.
2017-04-07 18:52:09 -04:00
a4eef8e20c Fix gcc -O -D_FORTIFY_SOURCE. 2017-04-03 20:46:36 -04:00
1fd0806757 Fix -Wshadow for gcc and clang. 2017-04-03 20:46:36 -04:00
3daf8c1ffe Minor tweaks. 2017-04-01 21:53:29 -04:00
c4c2550b29 Ignore GCC warnings.
* 4.9 missing initializer warnings
* pedantic for __int128 case
* Wrap diagnostic push and pop in tz.cpp and date.h.
2017-04-01 12:36:54 -04:00
f30450b4c5 Merge branch 'master' of github.com:HowardHinnant/date 2017-03-30 14:45:42 -04:00
d29cd4e343 Fix formatting bug for utc_time. 2017-03-30 14:44:42 -04:00
5afd241be6 Update README.md 2017-03-28 21:04:59 -04:00
f044cb0583 Update README.md 2017-03-28 21:02:32 -04:00
3495c513a1 Enable parse and format for more types:
* year
    * month
    * day
    * weekday
    * year_month
    * month_day
2017-03-25 17:46:17 -04:00
3ab6510cab Update copyright to 2017 2017-03-21 21:52:51 -04:00
5eff31acdd Update README.md 2017-03-21 10:41:05 -04:00
5e86f2c5ba Create downloads folder when it does not exist yet. 2017-03-20 18:25:19 -04:00
dbee0e7da4 Allow parsing %Ez to parse only 1 hour digit. 2017-03-17 20:18:06 -04:00
d110f07f59 Clean up time_of_day tests.
* Don't assume int64_t is the rep in the predefined chrono durations.
2017-03-14 11:05:33 -04:00
9e1120c676 Make time_of_day default constructor non-explicit.
Add zoned_time const char* overloaded constructor.
2017-03-12 15:18:53 -04:00
f4292e6aca Added Alloc argument to template parameters to support custom allocators in from_stream 2017-03-11 20:13:06 -05:00
a811a20748 Fixes minor typos in comments - no actual change to code 2017-03-08 11:28:35 -05:00
3df43424ac Add from_stream 2017-03-02 13:16:22 -10:00
1e7e7a214d Simplify the implementation of format and parse:
* For format, all a type must do is implement to_stream.

* For parse, each type X must specialize parse_manip<X,CharT,Traits>.
  Each specialization must include a public typedef to itself named
  type.

* Each parse_manip specialization must have a stream extraction
  operator.

* This commit depends on expression-SFINAE.  If this commit breaks
  your build, it is likely that your compiler/version does not
  support expression-SFINAE.  To fix this NO_EXPRESSION_SFINAE
  needs to be defined in the configuration area of date.h for
  that compiler/version.
2017-02-26 14:10:10 -05:00
ffc8cd0a3b Add format and parse to tai_time, gps_time, year_month_day 2017-02-26 09:28:15 -05:00
e9d36c6200 Rewrite format and parse in terms of detail::fields<Duration>
* Add format and parse to utc_time<Duration>.
* Added more tests.
2017-02-25 20:44:59 -05:00
3233cbaf9a Update link to latest proposal 2017-02-13 13:00:12 -05:00
3e906a2409 Remove a leftover output to std::cout 2017-02-13 12:17:11 -05:00
c7f2995d0b Remove outdated warning about the version change. 2017-02-11 11:04:14 -05:00
0d6de15043 Work around {} bug for older compilers
* iso_week.h
2017-02-08 14:44:37 -05:00
5c09ae73f2 Work around {} bug for older compilers 2017-02-08 11:32:33 -05:00
098223cf6d Second try at silencing "unused" warning for strerror_r 2017-02-07 17:31:14 -05:00
6a31edcb38 Silence "unused" warning for strerror_r 2017-02-06 10:18:40 -05:00
800ae143aa Correct the return type on two format overloads 2017-02-06 10:18:08 -05:00
c1034550d2 Exclude expand_path when INSTALL is not defined 2017-01-30 18:02:06 -05:00
3a9880999d Add format and parse overloads for durations 2017-01-28 16:21:21 -05:00
ce67ee0997 Add License file 2017-01-26 19:42:42 -05:00
2b8e6562ae Work around VS-2015 bug 2017-01-24 15:35:28 -05:00
186dbb2891 Enable CONSTCD14 for VS2017 2017-01-19 12:46:11 -05:00
49a59e5665 Add support for unsigned-based durations in time_of_day 2017-01-14 12:54:03 -05:00
095f66af28 resolve /etc/localtime by calling realpath 2017-01-14 07:46:05 -05:00
ea1717e8ab Define DATE_API empty when building static lib on Windows 2017-01-10 20:31:32 -05:00
659cdca5dc Only define get_windows_zones_install() under TIMEZONE_MAPPING 2017-01-09 21:01:39 -05:00
634b84eb60 Introduce set_install as suggested by PR 99
* Retain install variable as a function local static to maintain
  recent fixes to initialization order problems.
2017-01-07 18:27:40 -05:00
41093d05d8 Use CONSTDATA in function parse making compiler without constexpr support happy 2017-01-07 13:19:02 -05:00
c6f3dd2832 make the location of windowsZones.xml configurable 2017-01-05 20:28:12 -05:00
e203304afd Give DATE_API a default definition. 2017-01-05 20:24:46 -05:00
4e44539a59 export symbols on Windows 2017-01-04 20:48:34 -05:00
09537c4e19 Added missing #include <tuple> in tz.cpp
This is needed for std::tie. GCC and Clang are fine with it missing, but
my Visual Studio doesn't like it.
2017-01-03 10:23:38 -05:00
2935f80109 Have get_version check for the file named version first 2017-01-01 15:02:08 -05:00
4a1c49152f Enable previous fix for C++11 as well. 2017-01-01 14:51:10 -05:00
gm
07d9e8a0fe Enable the c++14 CONSTDATA code path for VS2017 and fix const const warning. 2017-01-01 18:01:20 +13:00
6889dc69fb Add missing #include 2016-12-26 18:34:40 -05:00
628404b87c Re-implement parse.
* Work with const CharT* format at the lowest level.
* Avoid dependence on std::lib except for locale-sensitive parsing.
* Add tests for parse.
2016-12-26 16:27:56 -05:00
2216bfbe44 Work around VS-2015 bug 2016-12-07 10:47:50 -05:00
64ea0a5bc3 move file scope static variables into functions to deal with static initialization order problem 2016-12-02 20:57:21 -05:00
8a3aeb566b Fix and test format %y 2016-11-27 15:30:01 -05:00
a5450e9d02 Fix and test format %C 2016-11-27 13:41:24 -05:00
2310435582 Add a format test stressing range 2016-11-26 16:15:08 -05:00
6b3ea4516a Fix bugs with formatting fractional seconds 2016-11-26 13:37:38 -05:00
298e9aff2d Add to_stream which avoids temporary streams and strings.
*  This is a low-level formatting facility which other functions
   such as format call into.
2016-11-25 20:37:51 -05:00
0cfa783b14 Unify and simplify fractional decimal seconds formatting
* Many of the ideas and some of the code herein is credited to
  Adrian Colomitchi

* Decouple fractional decimal seconds formatting from time_of_day
  formatting so that it can be more easily used elsewhere in the
  future.

* Include super-second durations such as nanocenturies and
  microfortnights in the class of durations that will get formatted
  with fractional decimal seconds.

* If a duration is exactly representable with fractional decimal
  seconds not exceeding 18 decimal fractional digits, format it
  exactly.  Otherwise format it to 6 fractional decimal digits
  (microseconds precision).  The number 18 is chosen as this is the
  limit of std::ratio using 64 bits (i.e. atto).

* The above bullet implies that durations with ratio<1, 4> will now
  be formatted with 2 fractional decimal digits instead of 1.
  ratio<1, 8> will be formatted with 3, and ratio<1, 3> with 6.

* Unify the implementation into one C++11 implementation that works
  equally well with C++14.

* Drive-by fix a couple formatting bugs dealing with negative
  durations.

* Deprecate the make_time functions taking unsigned md by removing
  their documentation.  Also deprecate the corresponding time_of_day
  constructors taking unsigned md.

* This change paves the way for future formatting improvements.
2016-11-24 19:53:39 -05:00
44e0480087 Fix formatting bug with %Ez 2016-11-12 18:21:21 -08:00
63e33bdf49 silence warnings in gcc 6.2 2016-11-12 15:19:46 +01:00
33f7cc6de4 Fix overflow bug in parse 2016-11-08 12:59:00 -08:00
27964fa642 Fix C++11 constexpr bug in year_lastweek_weekday::weeknum() 2016-11-02 14:21:26 -04:00
887d7574b1 Default USE_SHELL_API to 1 2016-10-23 18:58:00 -04:00
bae66f2bff Update README.md 2016-10-22 13:42:36 -04:00
1f7325ef7f Update README.md 2016-10-20 17:14:15 -04:00
9f7a438f7d Add unary operators + and - to year 2016-10-19 12:01:26 -04:00
9e25c2d74f Supply missing imbues in format 2016-10-18 11:52:07 -04:00
806c29fddc Lots of minor changes motivated by reviews of the draft proposal 2016-10-15 17:31:08 -04:00
501609bacf Make those time_point conversions which can be noexcept, noexcept 2016-10-12 19:48:45 -04:00
cfa55850c7 Fix dangling reference bug in parse 2016-10-11 10:34:59 -04:00
ff929570f9 Update readme with R1 draft proposal 2016-10-09 20:19:18 -04:00
fab89b205b Minor cleanups in the clocks 2016-10-09 20:11:11 -04:00
2ba541b684 Merge branch 'master' of github.com:HowardHinnant/date 2016-10-08 16:07:01 -04:00
81b5cc65f0 Remove static conversion functions from clocks
The free function converters are sufficient API.
2016-10-08 16:05:10 -04:00
381cbf9a7b Fix type-o in parse 2016-10-08 15:04:27 -04:00
f66af06870 Simplify implementation details of "chrono_io.h" 2016-10-08 15:03:33 -04:00
d02f762e32 Update README.md 2016-10-05 17:22:42 -04:00
3f0540cefd Update README concerning new IANA versioning 2016-09-28 18:17:26 -04:00
19c83e47ed Get local version from NEWS instead of Makefile 2016-09-28 18:08:50 -04:00
cedbe3c445 Update README.md 2016-09-23 18:44:23 -07:00
cb820f9090 Merge pull request #86 from saschazelzer/clang-fedora-support
Clang on Fedora needs <climits> for the CHAR_BIT definition.
2016-09-16 09:23:34 -04:00
69ec0bb134 Clang on Fedora needs <climits> for the CHAR_BIT definition. 2016-09-16 07:31:04 +02:00
3fb4d32922 Update tests for default constructible calendar types 2016-09-15 20:21:56 -04:00
641cd739c3 VS2013's std::vector does not support incomplete template types.
This commit works around this by exposing the zonelet class declaration
to the public tz.h header.
2016-09-15 20:10:04 -04:00
553affefa4 Work around a compiler bug in VS2013 with explicit conversion constructors. 2016-09-15 20:10:04 -04:00
570a1e699c Do not use user defined literals for VS2013 compatibility. 2016-09-15 20:10:04 -04:00
e107bcdef2 Use NOEXCEPT macro for VS2013 compatibility. 2016-09-15 20:10:04 -04:00
765d0e8f7a Add parse manipulators 2016-09-15 20:10:04 -04:00
86446a9fac format passes time_point by const& 2016-09-13 20:28:00 -04:00
b2df8cade5 Add trivial default constructors to most calendar types 2016-09-13 20:14:43 -04:00
845ce25bb7 Refine decision to use the std::chrono rounding modes 2016-09-10 11:57:52 -04:00
6cb8d59886 Update Try it out link 2016-09-09 21:23:28 -04:00
59d9cfa96d Update the availability of floor, ceil, round 2016-09-09 21:21:22 -04:00
a7b6adae62 Add %F to parse 2016-09-09 21:01:21 -04:00
3b3a27efe1 Fix for issue #79.
parse was not checking failbit aggressively enough.
2016-09-09 21:00:11 -04:00
ea9f664a06 Update README.md 2016-09-07 20:40:45 -04:00
32ca148d5c Work around uniform initialization bug for clang-3.6 2016-08-29 12:24:07 -04:00
17ba481e71 Work around [Bug c++/67631] New: brace initialization bug
https://gcc.gnu.org/ml/gcc-bugs/2015-09/msg01520.html
2016-08-28 18:30:12 -04:00
8e2de8587e Eliminate dependence on OS's gmtime_s / gmtime_r
When compiled with -arch i386, Apple's gmtime_s has a 32 bit bug meaning
it can't format dates earlier than 1901-12-13 20:45:52.
2016-08-28 14:52:41 -04:00
7816c3b48f Eliminate dependence on OS's timegm / _mkgmtime
Apple's OS timegm has a 32 bit bug meaning it can't parse dates earlier
than 1901-12-13 20:45:52.
2016-08-28 14:26:22 -04:00
3e25bd45f7 Clean up includes
Alphabetize and survey for missing and unneeded includes.
2016-08-27 14:18:46 -04:00
fcdca67c5b Switch to floor in format
Need to round towards negative infinity for dates prior to the epoch,
else the wrong answer gets formatted.
2016-08-27 13:22:27 -04:00
343e8299c7 Merge pull request #77 from gabm/FixFormating
Problem: time_points with a finer resolution than system_clock::duration cannot be formated
2016-08-26 07:43:31 -04:00
2fae542f6a Fix formating of time_points with a resolution finer than system_clock::duration 2016-08-26 10:55:05 +02:00
b3e3045211 Merge pull request #75 from gabm/FixMissingLocale
Problem: date::format(..) doesn't compile
2016-08-25 11:05:51 -04:00
ef57f27b38 Added #include <cctype> for windows std::isdigit 2016-08-25 15:41:49 +02:00
ef8bba9818 Fix missing standard locale 2016-08-25 08:23:19 +02:00
e8f8a1ffac Added missing sstream include 2016-08-25 08:20:14 +02:00
ebc20c139b Move formatting and parsing
Moved formatting and parsing of sys_time and local_time from tz.h to
date.h in order to make this functionality available to a wider
audience.  Existing code does not need to change.  But future code
can #include "date.h" instead of "tz.h" and need not compile tz.cpp nor
link to curl.

Formatting zoned_time remains in tz.h.
2016-08-24 20:54:24 -04:00
7e9d9075d9 Miscellaneous changes while enabling iOS support
Put all of the logic for discovering iOS in one place in ios.h.

Make TAR_DEBUG configurable and default it to 0.

Various whitespace style pickiness.
2016-08-23 20:55:13 -04:00
927fc619ef Namespaces, ios macro 2016-08-21 21:37:24 +03:00
952857e721 Correct type-o in error message 2016-08-14 20:35:22 -04:00
78025bf922 Add iOS support 2016-08-14 20:35:22 -04:00
4ee985fef3 Add link to Cppcon 2016 abstract. 2016-08-14 20:34:49 -04:00
0663b7aeb3 Allow only one decimal point to be read under "%Ez". 2016-08-09 23:23:55 -04:00
77435397cb Handle fractional seconds and offsets better. 2016-08-08 18:25:17 -04:00
137c317cc6 Add INSTALL configuration. 2016-08-06 14:57:47 -04:00
b4ca58d9a8 Revert "Remove support for using system() now other means proven."
This reverts commit ebf3b0776a.
2016-08-05 20:16:09 -04:00
67bdd6ac14 Merge pull request #68 from xaxousis/master
Fix c++11 msl and get_units overloads return expression
2016-08-04 10:26:39 -04:00
1ace59fc98 Fix c++11 msl overloads return expression
The implementation of these functions used the expression:

    return {1, 'x'};

This call the initializer list constructor of basic_string. Which lead
to two char strings.

This changes the expression to:

    return {'x'};
2016-08-03 14:41:13 +02:00
75 changed files with 19629 additions and 4791 deletions

194
.gitignore vendored Normal file
View File

@ -0,0 +1,194 @@
#ignore thumbnails created by windows
Thumbs.db
#Ignore files build by Visual Studio
*.obj
*.exe
*.pdb
*.user
*.aps
*.pch
*.vspscc
*_i.c
*_p.c
*.ncb
*.suo
*.tlb
*.tlh
*.bak
*.cache
*.ilk
*.log
[Bb]in
[Dd]ebug*/
*.lib
*.sbr
obj/
[Rr]elease*/
_ReSharper*/
[Tt]est[Rr]esult*
.idea/
*.opensdf
## Ignore Visual Studio temporary files, build results, and
## files generated by popular Visual Studio add-ons.
# User-specific files
*.suo
*.user
*.userosscache
*.sln.docstates
# User-specific folders
*.sln.ide/
# Build results
[Dd]ebug/
[Dd]ebugPublic/
[Rr]elease/
[Rr]eleases/
x64/
x86/
build/
bld/
[Bb]in/
[Oo]bj/
# Roslyn cache directories
*.ide/
# MSTest test Results
[Tt]est[Rr]esult*/
[Bb]uild[Ll]og.*
#NUNIT
*.VisualState.xml
TestResult.xml
# Build Results of an ATL Project
[Dd]ebugPS/
[Rr]eleasePS/
dlldata.c
*_i.c
*_p.c
*_i.h
*.ilk
*.meta
*.obj
*.pch
*.pdb
*.pgc
*.pgd
*.rsp
*.sbr
*.tlb
*.tli
*.tlh
*.tmp
*.tmp_proj
*.log
*.vspscc
*.vssscc
.builds
*.pidb
*.svclog
*.scc
# Chutzpah Test files
_Chutzpah*
# Visual C++ cache files
ipch/
*.aps
*.ncb
*.opensdf
*.sdf
*.cachefile
# Visual Studio profiler
*.psess
*.vsp
*.vspx
# TFS 2012 Local Workspace
$tf/
# Guidance Automation Toolkit
*.gpState
# ReSharper is a .NET coding add-in
_ReSharper*/
*.[Rr]e[Ss]harper
*.DotSettings.user
# JustCode is a .NET coding addin-in
.JustCode
# TeamCity is a build add-in
_TeamCity*
# DotCover is a Code Coverage Tool
*.dotCover
# NCrunch
_NCrunch_*
.*crunch*.local.xml
# MightyMoose
*.mm.*
AutoTest.Net/
# Web workbench (sass)
.sass-cache/
# Installshield output folder
[Ee]xpress/
# DocProject is a documentation generator add-in
DocProject/buildhelp/
DocProject/Help/*.HxT
DocProject/Help/*.HxC
DocProject/Help/*.hhc
DocProject/Help/*.hhk
DocProject/Help/*.hhp
DocProject/Help/Html2
DocProject/Help/html
# Click-Once directory
publish/
# Publish Web Output
*.[Pp]ublish.xml
*.azurePubxml
# TODO: Comment the next line if you want to checkin your web deploy settings
# but database connection strings (with potential passwords) will be unencrypted
*.pubxml
*.publishproj
# NuGet Packages
*.nupkg
# The packages folder can be ignored because of Package Restore
**/packages/*
# except build/, which is used as an MSBuild target.
!**/packages/build/
# If using the old MSBuild-Integrated Package Restore, uncomment this:
#!**/packages/repositories.config
# Windows Azure Build Output
csx/
*.build.csdef
# Windows Store app package directory
AppPackages/
# Others
sql/
*.Cache
ClientBin/
[Ss]tyle[Cc]op.*
~$*
*~
*.dbmdl
*.dbproj.schemaview
*.pfx
*.publishsettings
node_modules/
bower_components/
# RIA/Silverlight projects
Generated_Code/
# Backup & report files from converting an old project file
# to a newer Visual Studio version. Backup files are not needed,
# because we have git ;-)
_UpgradeReport_Files/
Backup*/
UpgradeLog*.XML
UpgradeLog*.htm
# SQL Server files
*.mdf
*.ldf
# Business Intelligence projects
*.rdl.data
*.bim.layout
*.bim_*.settings
# Microsoft Fakes
FakesAssemblies/
*.suo
*.vcxproj.filters
*.npp
CMakeFiles/*
nbproject/*
*.cd
*.cd
a.out
cmake-build-debug/*

147
.travis.yml Normal file
View File

@ -0,0 +1,147 @@
language: cpp
env:
global:
- CMAKE_EXTRA_CONF="-DCOMPILE_WITH_C_LOCALE=ON"
- CTEST_OUTPUT_ON_FAILURE=1
matrix:
include:
- name: "Ubuntu 16.04 LTS (Xenial Xerus) GCC 7"
os: linux
dist: xenial
addons:
apt:
sources:
- ubuntu-toolchain-r-test
packages:
- g++-7
env:
- MATRIX_EVAL="CC=gcc-7 && CXX=g++-7"
- name: "Ubuntu 16.04 LTS (Xenial Xerus) GCC 8"
os: linux
dist: xenial
addons:
apt:
sources:
- ubuntu-toolchain-r-test
packages:
- g++-8
env:
- MATRIX_EVAL="CC=gcc-8 && CXX=g++-8"
- name: "Ubuntu 16.04 LTS (Xenial Xerus) GCC 9"
os: linux
dist: xenial
addons:
apt:
sources:
- ubuntu-toolchain-r-test
packages:
- g++-9
env:
- MATRIX_EVAL="CC=gcc-9 && CXX=g++-9"
- name: "Ubuntu 18.04 LTS (Bionic Beaver) GCC 7"
os: linux
dist: bionic
addons:
apt:
sources:
- ubuntu-toolchain-r-test
packages:
- g++-7
env:
- MATRIX_EVAL="CC=gcc-7 && CXX=g++-7"
- name: "Ubuntu 18.04 LTS (Bionic Beaver) GCC 8"
os: linux
dist: bionic
addons:
apt:
sources:
- ubuntu-toolchain-r-test
packages:
- g++-8
env:
- MATRIX_EVAL="CC=gcc-8 && CXX=g++-8"
- name: "Ubuntu 18.04 LTS (Bionic Beaver) Clang 6"
os: linux
dist: bionic
addons:
apt:
sources:
- llvm-toolchain-bionic-6.0
packages:
- clang-6.0
env:
- MATRIX_EVAL="CC=clang-6.0 && CXX=clang++-6.0"
- name: "Ubuntu 18.04 LTS (Bionic Beaver) Clang 7"
os: linux
dist: bionic
addons:
apt:
sources:
- llvm-toolchain-bionic-7
packages:
- clang-7
env:
- MATRIX_EVAL="CC=clang-7 && CXX=clang++-7"
- name: "Ubuntu 18.04 LTS (Bionic Beaver) Clang 8"
os: linux
dist: bionic
addons:
apt:
sources:
- llvm-toolchain-bionic-8
packages:
- clang-8
env:
- MATRIX_EVAL="CC=clang-8 && CXX=clang++-8"
- &macos
name: xcode10
os: osx
osx_image: xcode10.2
env:
- CMAKE_EXTRA_CONF=""
addons:
homebrew:
packages:
- bash
- ninja
- <<: *macos
name: xcode9
# xcode 9 only works if we tell it to use c++14 explicitly
env:
- CMAKE_EXTRA_CONF="-DCMAKE_CXX_STANDARD=14"
osx_image: xcode9.4
- <<: *macos
osx_image: xcode11
name: xcode11
before_install:
- eval "${MATRIX_EVAL}"
- ci/install_cmake.sh 3.15.2
- export OPENSSL_ROOT=$(brew --prefix openssl@1.1)
- if [ "$(uname)" = "Darwin" ] ; then export PATH="$HOME/cmake/CMake.app/Contents/bin:${PATH}"; fi
- if [ "$(uname)" = "Linux" ] ; then export PATH="$HOME/cmake/bin:${PATH}"; fi
cache:
directories:
- $HOME/cmake
script:
- mkdir -p build
- cd build
- eval cmake -DENABLE_DATE_TESTING=ON -DBUILD_SHARED_LIBS=ON ${CMAKE_EXTRA_CONF} ..
- cmake --build . --parallel
- cmake --build . --parallel --target testit

23
CMakeLists.txt Normal file
View File

@ -0,0 +1,23 @@
if(DEFINED IDF_TARGET)
idf_component_register(INCLUDE_DIRS include)
set_property(TARGET ${COMPONENT_LIB} PROPERTY CXX_STANDARD 23)
target_compile_definitions(${COMPONENT_TARGET} INTERFACE HAS_UNCAUGHT_EXCEPTIONS=1)
else()
add_library(date
include/date/chrono_io.h
include/date/date.h
include/date/ios.h
include/date/islamic.h
include/date/iso_week.h
include/date/julian.h
include/date/ptz.h
include/date/solar_hijri.h
include/date/tz.h
include/date/tz_private.h
src/tz.cpp
)
target_include_directories(date PUBLIC
include/
)
endif()

31
LICENSE.txt Normal file
View File

@ -0,0 +1,31 @@
The source code in this project is released using the MIT License. There is no
global license for the project because each file is licensed individually with
different author names and/or dates.
If you contribute to this project, please add your name to the license of each
file you modify. If you have already contributed to this project and forgot to
add your name to the license, please feel free to submit a new P/R to add your
name to the license in each file you modified.
For convenience, here is a copy of the MIT license found in each file except
without author names or dates:
The MIT License (MIT)
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

View File

@ -1,23 +1,84 @@
# Date
[![Build Status](https://travis-ci.org/HowardHinnant/date.svg?branch=master)](https://travis-ci.org/HowardHinnant/date)
[![Join the chat at https://gitter.im/HowardHinnant/date](https://badges.gitter.im/HowardHinnant/date.svg)](https://gitter.im/HowardHinnant/date?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
This is actually several separate C++11/C++14 libraries:
---
1. `"date.h"` is a header-only library which builds upon `<chrono>`. It adds some new `duration` types, and new `time_point` types. It also adds "field" types such as `year_month_day` which is a struct `{year, month, day}`. And it provides convenient means to convert between the "field" types and the `time_point` types. See http://howardhinnant.github.io/date/date.html for more details.
**[Try it out on wandbox!](https://wandbox.org/permlink/oyXjibyF680HHoyS)**
Here is the Cppcon 2015 presentation on date.h: https://www.youtube.com/watch?v=tzyGjOm8AKo
## Summary
Here are the Cppcon 2015 slides on date.h: http://schd.ws/hosted_files/cppcon2015/43/hinnant_dates.pdf
This is actually several separate C++11/C++14/C++17 libraries:
2. `"tz.h"` / `"tz.cpp"` are a timezone library built on top of the `"date.h"` library. This timezone library is a complete parser of the IANA timezone database. It provides for an easy way to access all of the data in this database, using the types from `"date.h"` and `<chrono>`. The IANA database also includes data on leap seconds, and this library provides utilities to compute with that information as well. See http://howardhinnant.github.io/date/tz.html for more details.
1. `"date.h"` is a header-only library which builds upon `<chrono>`. It adds some new `duration` types, and new `time_point` types. It also adds "field" types such as `year_month_day` which is a struct `{year, month, day}`. And it provides convenient means to convert between the "field" types and the `time_point` types.
3. `"chrono_io.h"` is a header-only library for streaming out chrono durations. See http://howardhinnant.github.io/date/chrono_io.html for more details.
* Documentation: http://howardhinnant.github.io/date/date.html
* Video: https://www.youtube.com/watch?v=tzyGjOm8AKo
* Slides: http://schd.ws/hosted_files/cppcon2015/43/hinnant_dates.pdf
4. `"iso_week.h"` is a header-only library built on top of the `"date.h"` library which implements the ISO week date calendar. See http://howardhinnant.github.io/date/iso_week.html for more details.
1. `"tz.h"` / `"tz.cpp"` are a timezone library built on top of the `"date.h"` library. This timezone library is a complete parser of the IANA timezone database. It provides for an easy way to access all of the data in this database, using the types from `"date.h"` and `<chrono>`. The IANA database also includes data on leap seconds, and this library provides utilities to compute with that information as well.
5. `"julian.h"` is a header-only library built on top of the `"date.h"` library which implements a proleptic Julian calendar which is fully interoperable with everything above. See http://howardhinnant.github.io/date/julian.html for more details.
* Documentation: http://howardhinnant.github.io/date/tz.html
* Video: https://www.youtube.com/watch?v=Vwd3pduVGKY
* Slides: http://schd.ws/hosted_files/cppcon2016/0f/Welcome%20To%20The%20Time%20Zone%20-%20Howard%20Hinnant%20-%20CppCon%202016.pdf
6. `"islamic.h"` is a header-only library built on top of the `"date.h"` library which implements a proleptic Islamic calendar which is fully interoperable with everything above. See http://howardhinnant.github.io/date/islamic.html for more details.
1. `"iso_week.h"` is a header-only library built on top of the `"date.h"` library which implements the ISO week date calendar.
There has been a recent change in the library design. If you are trying to migrate from the previous design, rename `day_point` to `sys_days` everywhere, and that ought to bring the number of errors down to a small roar.
* Documentation: http://howardhinnant.github.io/date/iso_week.html
`"date.h"` and `"tz.h"` are now proposed for standardization here: http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2016/p0355r0.html
1. `"julian.h"` is a header-only library built on top of the `"date.h"` library which implements a proleptic Julian calendar which is fully interoperable with everything above.
* Documentation: http://howardhinnant.github.io/date/julian.html
1. `"islamic.h"` is a header-only library built on top of the `"date.h"` library which implements a proleptic Islamic calendar which is fully interoperable with everything above.
* Documentation: http://howardhinnant.github.io/date/islamic.html
## Standardization
Slightly modified versions of `"date.h"` and `"tz.h"` were voted into the C++20 working draft at the Jacksonville FL meeting on 2018-03-17:
* http://howardhinnant.github.io/date/d0355r7.html
## Build & Test
The recommended way to use any of these libraries besides `"tz.h"` is to just include it. These are header-only libraries (except `"tz.h"`).
To use `"tz.h"`, there is a single source file (`src/tz.cpp`) that needs to be compiled. Here are the recommended directions: https://howardhinnant.github.io/date/tz.html#Installation.
One can run tests by cd'ing into the `test` subdirectory and running `testit`. There are known failures on all platforms except for macOS. And even on macOS if C++11 is used. If any of these failures present problems for you, there exist workarounds.
Additionally there is unsupported support for [vcpkg](https://github.com/Microsoft/vcpkg) and [CMake](https://cmake.org/). I don't personally use or maintain these systems as for me they cause more problems than they solve (for this small project). If you would like to contribute to these build systems please feel free to file a PR.
You can download and install Date using the [vcpkg](https://github.com/Microsoft/vcpkg) dependency manager:
git clone https://github.com/Microsoft/vcpkg.git
cd vcpkg
./bootstrap-vcpkg.sh
./vcpkg integrate install
vcpkg install date
The Date port in vcpkg is updated by Microsoft team members and community contributors. If the version falls behind, please [create an issue or pull request](https://github.com/Microsoft/vcpkg) on the vcpkg repository.
You can optionally build using [CMake](https://cmake.org/). Here is a guide of how to build and test using the CMake Makefile generator.
```bash
mkdir build
cd build
cmake ../
cmake --build . --target testit # Consider '-- -j4' for multithreading
```
## Projects using this library
* www.safe.com
* www.webtoolkit.eu/wt
* https://github.com/ViewTouch/viewtouch
* https://routinghub.com
* https://github.com/valhalla
* https://github.com/siodb/siodb
* https://github.com/KomodoPlatform/atomicDEX-Pro
* https://github.com/Kotlin/kotlinx-datetime
* https://github.com/royalbee/jewish_date
If you would like your project (or product) on this list, just let me know.

View File

@ -1,668 +0,0 @@
#ifndef CHRONO_IO_H
#define CHRONO_IO_H
// The MIT License (MIT)
//
// Copyright (c) 2016 Howard Hinnant
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
//
// Our apologies. When the previous paragraph was written, lowercase had not yet
// been invented (that woud involve another several millennia of evolution).
// We did not mean to shout.
#include <chrono>
#include <cstddef>
#include <cstdint>
#include <iosfwd>
#include <ratio>
#include <string>
#include <type_traits>
namespace date
{
namespace detail
{
#if __cplusplus >= 201402
template <class CharT, std::size_t N>
class string_literal
{
CharT p_[N];
public:
using const_iterator = const CharT*;
string_literal(string_literal const&) = default;
string_literal& operator=(string_literal const&) = delete;
template <std::size_t N1 = 2,
class = std::enable_if_t<N1 == N>>
constexpr string_literal(CharT c) noexcept
: p_{c}
{
}
constexpr string_literal(const CharT(&a)[N]) noexcept
: p_{}
{
for (std::size_t i = 0; i < N; ++i)
p_[i] = a[i];
}
template <class U = CharT, class = std::enable_if_t<1 < sizeof(U)>>
constexpr string_literal(const char(&a)[N]) noexcept
: p_{}
{
for (std::size_t i = 0; i < N; ++i)
p_[i] = a[i];
}
template <class CharT2, class = std::enable_if_t<!std::is_same<CharT2, CharT>{}>>
constexpr string_literal(string_literal<CharT2, N> const& a) noexcept
: p_{}
{
for (std::size_t i = 0; i < N; ++i)
p_[i] = a[i];
}
template <std::size_t N1, std::size_t N2,
class = std::enable_if_t<N1 + N2 - 1 == N>>
constexpr string_literal(const string_literal<CharT, N1>& x,
const string_literal<CharT, N2>& y) noexcept
: p_{}
{
std::size_t i = 0;
for (; i < N1-1; ++i)
p_[i] = x[i];
for (std::size_t j = 0; j < N2; ++j, ++i)
p_[i] = y[j];
}
constexpr const CharT* data() const noexcept {return p_;}
constexpr std::size_t size() const noexcept {return N-1;}
constexpr const_iterator begin() const noexcept {return p_;}
constexpr const_iterator end() const noexcept {return p_ + N-1;}
constexpr CharT const& operator[](std::size_t n) const noexcept
{
return p_[n];
}
template <class Traits>
friend
std::basic_ostream<CharT, Traits>&
operator<<(std::basic_ostream<CharT, Traits>& os, const string_literal& s)
{
return os << s.p_;
}
};
template <class CharT1, class CharT2, std::size_t N1, std::size_t N2>
constexpr
inline
string_literal<std::conditional_t<sizeof(CharT2) <= sizeof(CharT1), CharT1, CharT2>,
N1 + N2 - 1>
operator+(const string_literal<CharT1, N1>& x, const string_literal<CharT2, N2>& y) noexcept
{
using CharT = std::conditional_t<sizeof(CharT2) <= sizeof(CharT1), CharT1, CharT2>;
return string_literal<CharT, N1 + N2 - 1>{string_literal<CharT, N1>{x},
string_literal<CharT, N2>{y}};
}
template <class CharT, std::size_t N>
constexpr
inline
string_literal<CharT, N>
msl(const CharT(&a)[N]) noexcept
{
return string_literal<CharT, N>{a};
}
template <class CharT,
class = std::enable_if_t<std::is_same<CharT, char>{} ||
std::is_same<CharT, wchar_t>{} ||
std::is_same<CharT, char16_t>{} ||
std::is_same<CharT, char32_t>{}>>
constexpr
inline
string_literal<CharT, 2>
msl(CharT c) noexcept
{
return string_literal<CharT, 2>{c};
}
constexpr
std::size_t
to_string_len(std::intmax_t i)
{
std::size_t r = 0;
do
{
i /= 10;
++r;
} while (i > 0);
return r;
}
template <std::intmax_t N>
constexpr
inline
std::enable_if_t
<
N < 10,
string_literal<char, to_string_len(N)+1>
>
msl() noexcept
{
return msl(char(N % 10 + '0'));
}
template <std::intmax_t N>
constexpr
inline
std::enable_if_t
<
10 <= N,
string_literal<char, to_string_len(N)+1>
>
msl() noexcept
{
return msl<N/10>() + msl(char(N % 10 + '0'));
}
template <class CharT, std::intmax_t N, std::intmax_t D>
constexpr
inline
std::enable_if_t
<
std::ratio<N, D>::type::den != 1,
string_literal<CharT, to_string_len(std::ratio<N, D>::type::num) +
to_string_len(std::ratio<N, D>::type::den) + 4>
>
msl(std::ratio<N, D>) noexcept
{
using R = typename std::ratio<N, D>::type;
return msl(CharT{'['}) + msl<R::num>() + msl(CharT{'/'}) +
msl<R::den>() + msl(CharT{']'});
}
template <class CharT, std::intmax_t N, std::intmax_t D>
constexpr
inline
std::enable_if_t
<
std::ratio<N, D>::type::den == 1,
string_literal<CharT, to_string_len(std::ratio<N, D>::type::num) + 3>
>
msl(std::ratio<N, D>) noexcept
{
using R = typename std::ratio<N, D>::type;
return msl(CharT{'['}) + msl<R::num>() + msl(CharT{']'});
}
template <class CharT>
constexpr
inline
auto
msl(std::atto) noexcept
{
return msl(CharT{'a'});
}
template <class CharT>
constexpr
inline
auto
msl(std::femto) noexcept
{
return msl(CharT{'f'});
}
template <class CharT>
constexpr
inline
auto
msl(std::pico) noexcept
{
return msl(CharT{'p'});
}
template <class CharT>
constexpr
inline
auto
msl(std::nano) noexcept
{
return msl(CharT{'n'});
}
template <class CharT>
constexpr
inline
std::enable_if_t
<
std::is_same<CharT, char>{},
string_literal<char, 3>
>
msl(std::micro) noexcept
{
return string_literal<char, 3>{"\xC2\xB5"};
}
template <class CharT>
constexpr
inline
std::enable_if_t
<
!std::is_same<CharT, char>{},
string_literal<CharT, 2>
>
msl(std::micro) noexcept
{
return string_literal<CharT, 2>{CharT{static_cast<unsigned char>('\xB5')}};
}
template <class CharT>
constexpr
inline
auto
msl(std::milli) noexcept
{
return msl(CharT{'m'});
}
template <class CharT>
constexpr
inline
auto
msl(std::centi) noexcept
{
return msl(CharT{'c'});
}
template <class CharT>
constexpr
inline
auto
msl(std::deci) noexcept
{
return msl(CharT{'d'});
}
template <class CharT>
constexpr
inline
auto
msl(std::deca) noexcept
{
return string_literal<CharT, 3>{"da"};
}
template <class CharT>
constexpr
inline
auto
msl(std::hecto) noexcept
{
return msl(CharT{'h'});
}
template <class CharT>
constexpr
inline
auto
msl(std::kilo) noexcept
{
return msl(CharT{'k'});
}
template <class CharT>
constexpr
inline
auto
msl(std::mega) noexcept
{
return msl(CharT{'M'});
}
template <class CharT>
constexpr
inline
auto
msl(std::giga) noexcept
{
return msl(CharT{'G'});
}
template <class CharT>
constexpr
inline
auto
msl(std::tera) noexcept
{
return msl(CharT{'T'});
}
template <class CharT>
constexpr
inline
auto
msl(std::peta) noexcept
{
return msl(CharT{'P'});
}
template <class CharT>
constexpr
inline
auto
msl(std::exa) noexcept
{
return msl(CharT{'E'});
}
template <class CharT, class Rep, class Period>
constexpr
auto
get_units(const std::chrono::duration<Rep, Period>&)
{
return msl<CharT>(Period{}) + string_literal<CharT, 2>{"s"};
}
template <class CharT, class Rep>
constexpr
auto
get_units(const std::chrono::duration<Rep, std::ratio<1>>&)
{
return string_literal<CharT, 2>{"s"};
}
template <class CharT, class Rep>
constexpr
auto
get_units(const std::chrono::duration<Rep, std::ratio<60>>&)
{
return string_literal<CharT, 4>{"min"};
}
template <class CharT, class Rep>
constexpr
auto
get_units(const std::chrono::duration<Rep, std::ratio<3600>>&)
{
return string_literal<CharT, 2>{"h"};
}
#else // __cplusplus < 201402
inline
std::string
to_string(std::uint64_t x)
{
return std::to_string(x);
}
template <class CharT>
std::basic_string<CharT>
to_string(std::uint64_t x)
{
auto y = std::to_string(x);
return std::basic_string<CharT>(y.begin(), y.end());
}
template <class CharT, std::intmax_t N, std::intmax_t D>
constexpr
inline
typename std::enable_if
<
std::ratio<N, D>::type::den != 1,
std::basic_string<CharT>
>::type
msl(std::ratio<N, D>) noexcept
{
using R = typename std::ratio<N, D>::type;
return std::basic_string<CharT>(1, '[') + to_string<CharT>(R::num) + CharT{'/'} +
to_string<CharT>(R::den) + CharT{']'};
}
template <class CharT, std::intmax_t N, std::intmax_t D>
constexpr
inline
typename std::enable_if
<
std::ratio<N, D>::type::den == 1,
std::basic_string<CharT>
>::type
msl(std::ratio<N, D>) noexcept
{
using R = typename std::ratio<N, D>::type;
return std::basic_string<CharT>(1, '[') + to_string<CharT>(R::num) + CharT{']'};
}
template <class CharT>
constexpr
inline
std::basic_string<CharT>
msl(std::atto) noexcept
{
return {1, 'a'};
}
template <class CharT>
constexpr
inline
std::basic_string<CharT>
msl(std::femto) noexcept
{
return {1, 'f'};
}
template <class CharT>
constexpr
inline
std::basic_string<CharT>
msl(std::pico) noexcept
{
return {1, 'p'};
}
template <class CharT>
constexpr
inline
std::basic_string<CharT>
msl(std::nano) noexcept
{
return {1, 'n'};
}
template <class CharT>
constexpr
inline
typename std::enable_if
<
std::is_same<CharT, char>::value,
std::string
>::type
msl(std::micro) noexcept
{
return "\xC2\xB5";
}
template <class CharT>
constexpr
inline
typename std::enable_if
<
!std::is_same<CharT, char>::value,
std::basic_string<CharT>
>::type
msl(std::micro) noexcept
{
return {1, CharT(static_cast<unsigned char>('\xB5'))};
}
template <class CharT>
constexpr
inline
std::basic_string<CharT>
msl(std::milli) noexcept
{
return {1, 'm'};
}
template <class CharT>
constexpr
inline
std::basic_string<CharT>
msl(std::centi) noexcept
{
return {1, 'c'};
}
template <class CharT>
constexpr
inline
std::basic_string<CharT>
msl(std::deci) noexcept
{
return {1, 'd'};
}
template <class CharT>
constexpr
inline
std::basic_string<CharT>
msl(std::deca) noexcept
{
return {'d', 'a'};
}
template <class CharT>
constexpr
inline
std::basic_string<CharT>
msl(std::hecto) noexcept
{
return {1, 'h'};
}
template <class CharT>
constexpr
inline
std::basic_string<CharT>
msl(std::kilo) noexcept
{
return {1, 'k'};
}
template <class CharT>
constexpr
inline
std::basic_string<CharT>
msl(std::mega) noexcept
{
return {1, 'M'};
}
template <class CharT>
constexpr
inline
std::basic_string<CharT>
msl(std::giga) noexcept
{
return {1, 'G'};
}
template <class CharT>
constexpr
inline
std::basic_string<CharT>
msl(std::tera) noexcept
{
return {1, 'T'};
}
template <class CharT>
constexpr
inline
std::basic_string<CharT>
msl(std::peta) noexcept
{
return {1, 'P'};
}
template <class CharT>
constexpr
inline
std::basic_string<CharT>
msl(std::exa) noexcept
{
return {1, 'E'};
}
template <class CharT, class Rep, class Period>
std::basic_string<CharT>
get_units(const std::chrono::duration<Rep, Period>&)
{
return msl<CharT>(Period{}) + CharT{'s'};
}
template <class CharT, class Rep>
std::basic_string<CharT>
get_units(const std::chrono::duration<Rep, std::ratio<1>>&)
{
return {1, 's'};
}
template <class CharT, class Rep>
std::basic_string<CharT>
get_units(const std::chrono::duration<Rep, std::ratio<60>>&)
{
return {'m', 'i', 'n'};
}
template <class CharT, class Rep>
std::basic_string<CharT>
get_units(const std::chrono::duration<Rep, std::ratio<3600>>&)
{
return {1, 'h'};
}
#endif // __cplusplus >= 201402
} // namespace detail
template <class CharT, class Traits, class Rep, class Period>
inline
std::basic_ostream<CharT, Traits>&
operator<<(std::basic_ostream<CharT, Traits>& os,
const std::chrono::duration<Rep, Period>& d)
{
using namespace std::chrono;
return os << d.count()
<< detail::get_units<CharT>(duration<Rep, typename Period::type>{});
}
} // namespace date
#endif // CHRONO_IO_H

34
ci/install_cmake.sh Executable file
View File

@ -0,0 +1,34 @@
#!/usr/bin/env bash
set -e
IFS=. read cm_maj cm_min cm_rel <<<"$1"
: ${cm_rel:-0}
CMAKE_ROOT=${2:-"${HOME}/cmake"}
function cmake_version ()
{
if [[ -d ${CMAKE_ROOT} ]] ; then
local perms=$(test $(uname) = "Linux" && echo "/111" || echo "+111")
local installed=$(find ${CMAKE_ROOT} -perm ${perms} -type f -name cmake)
if [[ "${installed}" != "" ]] ; then
echo "$(${installed} --version | head -1)"
fi
fi
}
installed=$(cmake_version)
if [[ "${installed}" != "" && ${installed} =~ ${cm_maj}.${cm_min}.${cm_rel} ]] ; then
echo "cmake already installed: ${installed}"
exit
fi
pkgname="cmake-${cm_maj}.${cm_min}.${cm_rel}-$(uname)-x86_64.tar.gz"
tmppkg="/tmp/cmake.tar.gz"
wget --quiet https://cmake.org/files/v${cm_maj}.${cm_min}/${pkgname} -O ${tmppkg}
mkdir -p ${CMAKE_ROOT}
cd ${CMAKE_ROOT}
tar --strip-components 1 -xf ${tmppkg}
rm -f ${tmppkg}
echo "installed: $(cmake_version)"

11
cmake/dateConfig.cmake Normal file
View File

@ -0,0 +1,11 @@
include( CMakeFindDependencyMacro )
include( "${CMAKE_CURRENT_LIST_DIR}/dateTargets.cmake" )
if( NOT MSVC AND TARGET date::date-tz )
find_dependency( Threads REQUIRED)
get_target_property( _tzill date::date-tz INTERFACE_LINK_LIBRARIES )
if( _tzill AND "${_tzill}" MATCHES "libcurl" )
find_dependency( CURL )
endif( )
endif( )

16
compile_fail.sh Executable file
View File

@ -0,0 +1,16 @@
#!/bin/bash
export TEST_BIN_NAME=$1
#echo "Building ${TEST_BIN_NAME}"
shift 1
export BUILD_COMMAND=$@
#echo "Build command: ${BUILD_COMMAND}"
eval ${BUILD_COMMAND} >/dev/null 2>/dev/null
if [ $? -eq 0 ]; then
echo -ne "#!/bin/bash\nexit 1;" > ${TEST_BIN_NAME}
else
echo -ne "#!/bin/bash\nexit 0;" > ${TEST_BIN_NAME}
fi
chmod u+x ${TEST_BIN_NAME}
exit 0;

1
date.pri Normal file
View File

@ -0,0 +1 @@
QMAKE_CXXFLAGS += -isystem $$PWD/include

34
include/date/chrono_io.h Normal file
View File

@ -0,0 +1,34 @@
#ifndef CHRONO_IO_H
#define CHRONO_IO_H
// The MIT License (MIT)
//
// Copyright (c) 2016, 2017 Howard Hinnant
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
//
// Our apologies. When the previous paragraph was written, lowercase had not yet
// been invented (that would involve another several millennia of evolution).
// We did not mean to shout.
// This functionality has moved to "date.h"
#include "date.h"
#endif // CHRONO_IO_H

8008
include/date/date.h Normal file

File diff suppressed because it is too large Load Diff

50
include/date/ios.h Normal file
View File

@ -0,0 +1,50 @@
//
// ios.h
// DateTimeLib
//
// The MIT License (MIT)
//
// Copyright (c) 2016 Alexander Kormanovsky
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
#ifndef ios_hpp
#define ios_hpp
#if __APPLE__
# include <TargetConditionals.h>
# if TARGET_OS_IPHONE
# include <string>
namespace date
{
namespace iOSUtils
{
std::string get_tzdata_path();
std::string get_current_timezone();
} // namespace iOSUtils
} // namespace date
# endif // TARGET_OS_IPHONE
#else // !__APPLE__
# define TARGET_OS_IPHONE 0
#endif // !__APPLE__
#endif // ios_hpp

View File

@ -24,7 +24,7 @@
// SOFTWARE.
//
// Our apologies. When the previous paragraph was written, lowercase had not yet
// been invented (that woud involve another several millennia of evolution).
// been invented (that would involve another several millennia of evolution).
// We did not mean to shout.
#include "date.h"
@ -39,10 +39,10 @@ using days = date::days;
using weeks = date::weeks;
using years = std::chrono::duration
<int, std::ratio_multiply<std::ratio<10631, 30>, days::period>>;
<int, date::detail::ratio_multiply<std::ratio<10631, 30>, days::period>>;
using months = std::chrono::duration
<int, std::ratio_divide<years::period, std::ratio<12>>>;
<int, date::detail::ratio_divide<years::period, std::ratio<12>>>;
// time_point
@ -253,7 +253,7 @@ public:
CONSTCD14 year& operator+=(const years& y) NOEXCEPT;
CONSTCD14 year& operator-=(const years& y) NOEXCEPT;
CONSTCD11 bool is_leap() const NOEXCEPT;
CONSTCD14 bool is_leap() const NOEXCEPT;
CONSTCD11 explicit operator int() const NOEXCEPT;
CONSTCD11 bool ok() const NOEXCEPT;
@ -866,7 +866,7 @@ inline
std::basic_ostream<CharT, Traits>&
operator<<(std::basic_ostream<CharT, Traits>& os, const day& d)
{
date::detail::save_stream<CharT, Traits> _(os);
date::detail::save_ostream<CharT, Traits> _(os);
os.fill('0');
os.flags(std::ios::dec | std::ios::right);
os.width(2);
@ -1046,7 +1046,7 @@ CONSTCD14 inline year year::operator--(int) NOEXCEPT {auto tmp(*this); --(*this)
CONSTCD14 inline year& year::operator+=(const years& y) NOEXCEPT {*this = *this + y; return *this;}
CONSTCD14 inline year& year::operator-=(const years& y) NOEXCEPT {*this = *this - y; return *this;}
CONSTCD11
CONSTCD14
inline
bool
year::is_leap() const NOEXCEPT
@ -1177,7 +1177,7 @@ inline
std::basic_ostream<CharT, Traits>&
operator<<(std::basic_ostream<CharT, Traits>& os, const year& y)
{
date::detail::save_stream<CharT, Traits> _(os);
date::detail::save_ostream<CharT, Traits> _(os);
os.fill('0');
os.flags(std::ios::dec | std::ios::internal);
os.width(4 + (y < year{0}));
@ -2236,7 +2236,7 @@ inline
std::basic_ostream<CharT, Traits>&
operator<<(std::basic_ostream<CharT, Traits>& os, const year_month_day& ymd)
{
date::detail::save_stream<CharT, Traits> _(os);
date::detail::save_ostream<CharT, Traits> _(os);
os.fill('0');
os.flags(std::ios::dec | std::ios::right);
os << ymd.year() << '-';

View File

@ -3,7 +3,7 @@
// The MIT License (MIT)
//
// Copyright (c) 2015, 2016 Howard Hinnant
// Copyright (c) 2015, 2016, 2017 Howard Hinnant
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
@ -25,6 +25,8 @@
#include "date.h"
#include <climits>
namespace iso_week
{
@ -341,7 +343,7 @@ public:
year_lastweek_weekday& operator-=(const years& y) NOEXCEPT;
CONSTCD11 iso_week::year year() const NOEXCEPT;
CONSTCD11 iso_week::weeknum weeknum() const NOEXCEPT;
CONSTCD14 iso_week::weeknum weeknum() const NOEXCEPT;
CONSTCD11 iso_week::weekday weekday() const NOEXCEPT;
CONSTCD14 operator sys_days() const NOEXCEPT;
@ -449,7 +451,7 @@ weekday::weekday(unsigned wd) NOEXCEPT
CONSTCD11
inline
weekday::weekday(date::weekday wd) NOEXCEPT
: wd_(to_iso_encoding(static_cast<unsigned>(wd)))
: wd_(wd.iso_encoding())
{}
CONSTCD11
@ -605,7 +607,10 @@ inline
year
year::min() NOEXCEPT
{
using namespace std::chrono;
using std::chrono::seconds;
using std::chrono::minutes;
using std::chrono::hours;
using std::chrono::duration_cast;
static_assert(sizeof(seconds)*CHAR_BIT >= 41, "seconds may overflow");
static_assert(sizeof(hours)*CHAR_BIT >= 30, "hours may overflow");
return sizeof(minutes)*CHAR_BIT < 34 ?
@ -618,7 +623,10 @@ inline
year
year::max() NOEXCEPT
{
using namespace std::chrono;
using std::chrono::seconds;
using std::chrono::minutes;
using std::chrono::hours;
using std::chrono::duration_cast;
static_assert(sizeof(seconds)*CHAR_BIT >= 41, "seconds may overflow");
static_assert(sizeof(hours)*CHAR_BIT >= 30, "hours may overflow");
return sizeof(minutes)*CHAR_BIT < 34 ?
@ -711,7 +719,7 @@ inline
std::basic_ostream<CharT, Traits>&
operator<<(std::basic_ostream<CharT, Traits>& os, const year& y)
{
date::detail::save_stream<CharT, Traits> _(os);
date::detail::save_ostream<CharT, Traits> _(os);
os.fill('0');
os.flags(std::ios::dec | std::ios::internal);
os.width(4 + (y < year{0}));
@ -873,7 +881,7 @@ inline
std::basic_ostream<CharT, Traits>&
operator<<(std::basic_ostream<CharT, Traits>& os, const weeknum& wn)
{
date::detail::save_stream<CharT, Traits> _(os);
date::detail::save_ostream<CharT, Traits> _(os);
os << 'W';
os.fill('0');
os.flags(std::ios::dec | std::ios::right);
@ -1013,9 +1021,9 @@ weeknum
year_lastweek::weeknum() const NOEXCEPT
{
const auto y = date::year{static_cast<int>(y_)};
const auto s0 = sys_days{(y-years{1})/12/date::thu[date::last]};
const auto s1 = sys_days{y/12/date::thu[date::last]};
return iso_week::weeknum(date::trunc<weeks>(s1-s0).count());
const auto s0 = sys_days((y-years{1})/12/date::thu[date::last]);
const auto s1 = sys_days(y/12/date::thu[date::last]);
return iso_week::weeknum(static_cast<unsigned>(date::trunc<weeks>(s1-s0).count()));
}
CONSTCD11 inline bool year_lastweek::ok() const NOEXCEPT {return y_.ok();}
@ -1297,7 +1305,7 @@ year_lastweek_weekday::operator-=(const years& y) NOEXCEPT
CONSTCD11 inline year year_lastweek_weekday::year() const NOEXCEPT {return y_;}
CONSTCD11
CONSTCD14
inline
weeknum
year_lastweek_weekday::weeknum() const NOEXCEPT
@ -1311,16 +1319,16 @@ CONSTCD14
inline
year_lastweek_weekday::operator sys_days() const NOEXCEPT
{
return sys_days{date::year{static_cast<int>(y_)}/date::dec/date::thu[date::last]}
+ (mon - thu) - (mon - wd_);
return sys_days(date::year{static_cast<int>(y_)}/date::dec/date::thu[date::last])
+ (sun - thu) - (sun - wd_);
}
CONSTCD14
inline
year_lastweek_weekday::operator local_days() const NOEXCEPT
{
return local_days{date::year{static_cast<int>(y_)}/date::dec/date::thu[date::last]}
+ (mon - thu) - (mon - wd_);
return local_days(date::year{static_cast<int>(y_)}/date::dec/date::thu[date::last])
+ (sun - thu) - (sun - wd_);
}
CONSTCD11
@ -1469,7 +1477,7 @@ CONSTCD14
inline
year_weeknum_weekday::operator sys_days() const NOEXCEPT
{
return sys_days{date::year{static_cast<int>(y_)-1}/date::dec/date::thu[date::last]}
return sys_days(date::year{static_cast<int>(y_)-1}/date::dec/date::thu[date::last])
+ (date::mon - date::thu) + weeks{static_cast<unsigned>(wn_)-1} + (wd_ - mon);
}
@ -1477,7 +1485,7 @@ CONSTCD14
inline
year_weeknum_weekday::operator local_days() const NOEXCEPT
{
return local_days{date::year{static_cast<int>(y_)-1}/date::dec/date::thu[date::last]}
return local_days(date::year{static_cast<int>(y_)-1}/date::dec/date::thu[date::last])
+ (date::mon - date::thu) + weeks{static_cast<unsigned>(wn_)-1} + (wd_ - mon);
}
@ -1497,13 +1505,14 @@ year_weeknum_weekday::from_days(days d) NOEXCEPT
const auto dp = sys_days{d};
const auto wd = iso_week::weekday{dp};
auto y = date::year_month_day{dp + days{3}}.year();
auto start = sys_days{(y - date::years{1})/date::dec/date::thu[date::last]} + (mon-thu);
auto start = sys_days((y - date::years{1})/date::dec/date::thu[date::last]) + (mon-thu);
if (dp < start)
{
--y;
start = sys_days{(y - date::years{1})/date::dec/date::thu[date::last]} + (mon-thu);
start = sys_days((y - date::years{1})/date::dec/date::thu[date::last]) + (mon-thu);
}
const auto wn = iso_week::weeknum(date::trunc<weeks>(dp - start).count() + 1);
const auto wn = iso_week::weeknum(
static_cast<unsigned>(date::trunc<weeks>(dp - start).count() + 1));
return {iso_week::year(static_cast<int>(y)), wn, wd};
}
@ -1606,7 +1615,7 @@ inline
year_weeknum
operator/(const year& y, int wn) NOEXCEPT
{
return y/weeknum(wn);
return y/weeknum(static_cast<unsigned>(wn));
}
CONSTCD11

View File

@ -24,7 +24,7 @@
// SOFTWARE.
//
// Our apologies. When the previous paragraph was written, lowercase had not yet
// been invented (that woud involve another several millennia of evolution).
// been invented (that would involve another several millennia of evolution).
// We did not mean to shout.
#include "date.h"
@ -39,10 +39,10 @@ using days = date::days;
using weeks = date::weeks;
using years = std::chrono::duration
<int, std::ratio_multiply<std::ratio<1461, 4>, days::period>>;
<int, date::detail::ratio_multiply<std::ratio<1461, 4>, days::period>>;
using months = std::chrono::duration
<int, std::ratio_divide<years::period, std::ratio<12>>>;
<int, date::detail::ratio_divide<years::period, std::ratio<12>>>;
// time_point
@ -879,7 +879,7 @@ inline
std::basic_ostream<CharT, Traits>&
operator<<(std::basic_ostream<CharT, Traits>& os, const day& d)
{
date::detail::save_stream<CharT, Traits> _(os);
date::detail::save_ostream<CharT, Traits> _(os);
os.fill('0');
os.flags(std::ios::dec | std::ios::right);
os.width(2);
@ -1171,7 +1171,7 @@ inline
std::basic_ostream<CharT, Traits>&
operator<<(std::basic_ostream<CharT, Traits>& os, const year& y)
{
date::detail::save_stream<CharT, Traits> _(os);
date::detail::save_ostream<CharT, Traits> _(os);
os.fill('0');
os.flags(std::ios::dec | std::ios::internal);
os.width(4 + (y < year{0}));
@ -1655,9 +1655,12 @@ inline
bool
month_day::ok() const NOEXCEPT
{
CONSTDATA julian::day d[] =
{31_d, 29_d, 31_d, 30_d, 31_d, 30_d, 31_d, 31_d, 30_d, 31_d, 30_d, 31_d};
return m_.ok() && 1_d <= d_ && d_ <= d[static_cast<unsigned>(m_)-1];
CONSTDATA julian::day d[] = {
julian::day(31), julian::day(29), julian::day(31), julian::day(30),
julian::day(31), julian::day(30), julian::day(31), julian::day(31),
julian::day(30), julian::day(31), julian::day(30), julian::day(31)
};
return m_.ok() && julian::day(1) <= d_ && d_ <= d[static_cast<unsigned>(m_)-1];
}
CONSTCD11
@ -1946,9 +1949,12 @@ inline
day
year_month_day_last::day() const NOEXCEPT
{
CONSTDATA julian::day d[] =
{31_d, 28_d, 31_d, 30_d, 31_d, 30_d, 31_d, 31_d, 30_d, 31_d, 30_d, 31_d};
return month() != feb || !y_.is_leap() ? d[static_cast<unsigned>(month())-1] : 29_d;
CONSTDATA julian::day d[] = {
julian::day(31), julian::day(28), julian::day(31), julian::day(30),
julian::day(31), julian::day(30), julian::day(31), julian::day(31),
julian::day(30), julian::day(31), julian::day(30), julian::day(31)
};
return month() != feb || !y_.is_leap() ? d[static_cast<unsigned>(month())-1] : julian::day(29);
}
CONSTCD14
@ -2190,7 +2196,7 @@ year_month_day::ok() const NOEXCEPT
{
if (!(y_.ok() && m_.ok()))
return false;
return 1_d <= d_ && d_ <= (y_/m_/last).day();
return julian::day(1) <= d_ && d_ <= (y_/m_/last).day();
}
CONSTCD11
@ -2250,7 +2256,7 @@ inline
std::basic_ostream<CharT, Traits>&
operator<<(std::basic_ostream<CharT, Traits>& os, const year_month_day& ymd)
{
date::detail::save_stream<CharT, Traits> _(os);
date::detail::save_ostream<CharT, Traits> _(os);
os.fill('0');
os.flags(std::ios::dec | std::ios::right);
os << ymd.year() << '-';

788
include/date/ptz.h Normal file
View File

@ -0,0 +1,788 @@
#ifndef PTZ_H
#define PTZ_H
// The MIT License (MIT)
//
// Copyright (c) 2017 Howard Hinnant
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
// This header allows Posix-style time zones as specified for TZ here:
// http://pubs.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap08.html#tag_08_03
//
// Posix::time_zone can be constructed with a posix-style string and then used in
// a zoned_time like so:
//
// zoned_time<system_clock::duration, Posix::time_zone> zt{"EST5EDT,M3.2.0,M11.1.0",
// system_clock::now()};
// or:
//
// Posix::time_zone tz{"EST5EDT,M3.2.0,M11.1.0"};
// zoned_time<system_clock::duration, Posix::time_zone> zt{tz, system_clock::now()};
//
// If the rule set is missing (everything starting with ','), then the rule is that the
// alternate offset is never enabled.
//
// Note, Posix-style time zones are not recommended for all of the reasons described here:
// https://stackoverflow.com/tags/timezone/info
//
// They are provided here as a non-trivial custom time zone example, and if you really
// have to have Posix time zones, you're welcome to use this one.
#include "date/tz.h"
#include <cctype>
#include <ostream>
#include <string>
namespace Posix
{
namespace detail
{
#if HAS_STRING_VIEW
using string_t = std::string_view;
#else // !HAS_STRING_VIEW
using string_t = std::string;
#endif // !HAS_STRING_VIEW
class rule;
void throw_invalid(const string_t& s, unsigned i, const string_t& message);
unsigned read_date(const string_t& s, unsigned i, rule& r);
unsigned read_name(const string_t& s, unsigned i, std::string& name);
unsigned read_signed_time(const string_t& s, unsigned i, std::chrono::seconds& t);
unsigned read_unsigned_time(const string_t& s, unsigned i, std::chrono::seconds& t);
unsigned read_unsigned(const string_t& s, unsigned i, unsigned limit, unsigned& u,
const string_t& message = string_t{});
class rule
{
enum {off, J, M, N};
date::month m_;
date::weekday wd_;
unsigned short n_ : 14;
unsigned short mode_ : 2;
std::chrono::duration<std::int32_t> time_ = std::chrono::hours{2};
public:
rule() : mode_(off) {}
bool ok() const {return mode_ != off;}
date::local_seconds operator()(date::year y) const;
std::string to_string() const;
friend std::ostream& operator<<(std::ostream& os, const rule& r);
friend unsigned read_date(const string_t& s, unsigned i, rule& r);
friend bool operator==(const rule& x, const rule& y);
};
inline
bool
operator==(const rule& x, const rule& y)
{
if (x.mode_ != y.mode_)
return false;
switch (x.mode_)
{
case rule::J:
case rule::N:
return x.n_ == y.n_;
case rule::M:
return x.m_ == y.m_ && x.n_ == y.n_ && x.wd_ == y.wd_;
default:
return true;
}
}
inline
bool
operator!=(const rule& x, const rule& y)
{
return !(x == y);
}
inline
date::local_seconds
rule::operator()(date::year y) const
{
using date::local_days;
using date::January;
using date::days;
using date::last;
using sec = std::chrono::seconds;
date::local_seconds t;
switch (mode_)
{
case J:
t = local_days{y/January/0} + days{n_ + (y.is_leap() && n_ > 59)} + sec{time_};
break;
case M:
t = (n_ == 5 ? local_days{y/m_/wd_[last]} : local_days{y/m_/wd_[n_]}) + sec{time_};
break;
case N:
t = local_days{y/January/1} + days{n_} + sec{time_};
break;
default:
assert(!"rule called with bad mode");
}
return t;
}
inline
std::string
rule::to_string() const
{
using namespace std::chrono;
auto print_offset = [](seconds off)
{
std::string nm;
if (off != hours{2})
{
date::hh_mm_ss<seconds> offset{off};
nm = '/';
nm += std::to_string(offset.hours().count());
if (offset.minutes() != minutes{0} || offset.seconds() != seconds{0})
{
nm += ':';
if (offset.minutes() < minutes{10})
nm += '0';
nm += std::to_string(offset.minutes().count());
if (offset.seconds() != seconds{0})
{
nm += ':';
if (offset.seconds() < seconds{10})
nm += '0';
nm += std::to_string(offset.seconds().count());
}
}
}
return nm;
};
std::string nm;
switch (mode_)
{
case rule::J:
nm = 'J';
nm += std::to_string(n_);
break;
case rule::M:
nm = 'M';
nm += std::to_string(static_cast<unsigned>(m_));
nm += '.';
nm += std::to_string(n_);
nm += '.';
nm += std::to_string(wd_.c_encoding());
break;
case rule::N:
nm = std::to_string(n_);
break;
default:
break;
}
nm += print_offset(time_);
return nm;
}
inline
std::ostream&
operator<<(std::ostream& os, const rule& r)
{
switch (r.mode_)
{
case rule::J:
os << 'J' << r.n_ << date::format(" %T", r.time_);
break;
case rule::M:
if (r.n_ == 5)
os << r.m_/r.wd_[date::last];
else
os << r.m_/r.wd_[r.n_];
os << date::format(" %T", r.time_);
break;
case rule::N:
os << r.n_ << date::format(" %T", r.time_);
break;
default:
break;
}
return os;
}
} // namespace detail
class time_zone
{
std::string std_abbrev_;
std::string dst_abbrev_ = {};
std::chrono::seconds offset_;
std::chrono::seconds save_ = std::chrono::hours{1};
detail::rule start_rule_;
detail::rule end_rule_;
public:
explicit time_zone(const detail::string_t& name);
template <class Duration>
date::sys_info get_info(date::sys_time<Duration> st) const;
template <class Duration>
date::local_info get_info(date::local_time<Duration> tp) const;
template <class Duration>
date::sys_time<typename std::common_type<Duration, std::chrono::seconds>::type>
to_sys(date::local_time<Duration> tp) const;
template <class Duration>
date::sys_time<typename std::common_type<Duration, std::chrono::seconds>::type>
to_sys(date::local_time<Duration> tp, date::choose z) const;
template <class Duration>
date::local_time<typename std::common_type<Duration, std::chrono::seconds>::type>
to_local(date::sys_time<Duration> tp) const;
friend std::ostream& operator<<(std::ostream& os, const time_zone& z);
const time_zone* operator->() const {return this;}
std::string name() const;
friend bool operator==(const time_zone& x, const time_zone& y);
};
inline
time_zone::time_zone(const detail::string_t& s)
{
using detail::read_name;
using detail::read_signed_time;
using detail::throw_invalid;
auto i = read_name(s, 0, std_abbrev_);
i = read_signed_time(s, i, offset_);
offset_ = -offset_;
if (i != s.size())
{
i = read_name(s, i, dst_abbrev_);
if (i != s.size())
{
if (s[i] != ',')
{
i = read_signed_time(s, i, save_);
save_ = -save_ - offset_;
}
if (i != s.size())
{
if (s[i] != ',')
throw_invalid(s, i, "Expecting end of string or ',' to start rule");
++i;
i = read_date(s, i, start_rule_);
if (i == s.size() || s[i] != ',')
throw_invalid(s, i, "Expecting ',' and then the ending rule");
++i;
i = read_date(s, i, end_rule_);
if (i != s.size())
throw_invalid(s, i, "Found unexpected trailing characters");
}
}
}
}
template <class Duration>
date::sys_info
time_zone::get_info(date::sys_time<Duration> st) const
{
using date::sys_info;
using date::year_month_day;
using date::sys_seconds;
using date::sys_days;
using date::floor;
using date::ceil;
using date::days;
using date::years;
using date::year;
using date::January;
using date::December;
using date::last;
using std::chrono::minutes;
sys_info r{};
r.offset = offset_;
if (start_rule_.ok())
{
auto y = year_month_day{floor<days>(st)}.year();
auto start = sys_seconds{(start_rule_(y) - offset_).time_since_epoch()};
auto end = sys_seconds{(end_rule_(y) - (offset_ + save_)).time_since_epoch()};
if (start <= st && st < end)
{
r.begin = start;
r.end = end;
r.offset += save_;
r.save = ceil<minutes>(save_);
r.abbrev = dst_abbrev_;
}
else if (st < start)
{
r.begin = sys_seconds{(end_rule_(y-years{1}) -
(offset_ + save_)).time_since_epoch()};
r.end = start;
r.abbrev = std_abbrev_;
}
else // st >= end
{
r.begin = end;
r.end = sys_seconds{(start_rule_(y+years{1}) - offset_).time_since_epoch()};
r.abbrev = std_abbrev_;
}
}
else // constant offset
{
r.begin = sys_days{year::min()/January/1};
r.end = sys_days{year::max()/December/last};
r.abbrev = std_abbrev_;
}
return r;
}
template <class Duration>
date::local_info
time_zone::get_info(date::local_time<Duration> tp) const
{
using date::local_info;
using date::year_month_day;
using date::days;
using date::sys_days;
using date::sys_seconds;
using date::years;
using date::year;
using date::ceil;
using date::January;
using date::December;
using date::last;
using std::chrono::seconds;
using std::chrono::minutes;
local_info r{};
using date::floor;
if (start_rule_.ok())
{
auto y = year_month_day{floor<days>(tp)}.year();
auto start = sys_seconds{(start_rule_(y) - offset_).time_since_epoch()};
auto end = sys_seconds{(end_rule_(y) - (offset_ + save_)).time_since_epoch()};
auto utcs = sys_seconds{floor<seconds>(tp - offset_).time_since_epoch()};
auto utcd = sys_seconds{floor<seconds>(tp - (offset_ + save_)).time_since_epoch()};
if ((utcs < start) != (utcd < start))
{
r.first.begin = sys_seconds{(end_rule_(y-years{1}) -
(offset_ + save_)).time_since_epoch()};
r.first.end = start;
r.first.offset = offset_;
r.first.abbrev = std_abbrev_;
r.second.begin = start;
r.second.end = end;
r.second.abbrev = dst_abbrev_;
r.second.offset = offset_ + save_;
r.second.save = ceil<minutes>(save_);
r.result = save_ > seconds{0} ? local_info::nonexistent
: local_info::ambiguous;
}
else if ((utcs < end) != (utcd < end))
{
r.first.begin = start;
r.first.end = end;
r.first.offset = offset_ + save_;
r.first.save = ceil<minutes>(save_);
r.first.abbrev = dst_abbrev_;
r.second.begin = end;
r.second.end = sys_seconds{(start_rule_(y+years{1}) -
offset_).time_since_epoch()};
r.second.abbrev = std_abbrev_;
r.second.offset = offset_;
r.result = save_ > seconds{0} ? local_info::ambiguous
: local_info::nonexistent;
}
else if (utcs < start)
{
r.first.begin = sys_seconds{(end_rule_(y-years{1}) -
(offset_ + save_)).time_since_epoch()};
r.first.end = start;
r.first.offset = offset_;
r.first.abbrev = std_abbrev_;
}
else if (utcs < end)
{
r.first.begin = start;
r.first.end = end;
r.first.offset = offset_ + save_;
r.first.save = ceil<minutes>(save_);
r.first.abbrev = dst_abbrev_;
}
else
{
r.first.begin = end;
r.first.end = sys_seconds{(start_rule_(y+years{1}) -
offset_).time_since_epoch()};
r.first.abbrev = std_abbrev_;
r.first.offset = offset_;
}
}
else // constant offset
{
r.first.begin = sys_days{year::min()/January/1};
r.first.end = sys_days{year::max()/December/last};
r.first.abbrev = std_abbrev_;
r.first.offset = offset_;
}
return r;
}
template <class Duration>
date::sys_time<typename std::common_type<Duration, std::chrono::seconds>::type>
time_zone::to_sys(date::local_time<Duration> tp) const
{
using date::local_info;
using date::sys_time;
using date::ambiguous_local_time;
auto i = get_info(tp);
if (i.result == local_info::nonexistent)
throw nonexistent_local_time(tp, i);
else if (i.result == local_info::ambiguous)
throw ambiguous_local_time(tp, i);
return sys_time<Duration>{tp.time_since_epoch()} - i.first.offset;
}
template <class Duration>
date::sys_time<typename std::common_type<Duration, std::chrono::seconds>::type>
time_zone::to_sys(date::local_time<Duration> tp, date::choose z) const
{
using date::local_info;
using date::sys_time;
using date::choose;
auto i = get_info(tp);
if (i.result == local_info::nonexistent)
{
return i.first.end;
}
else if (i.result == local_info::ambiguous)
{
if (z == choose::latest)
return sys_time<Duration>{tp.time_since_epoch()} - i.second.offset;
}
return sys_time<Duration>{tp.time_since_epoch()} - i.first.offset;
}
template <class Duration>
date::local_time<typename std::common_type<Duration, std::chrono::seconds>::type>
time_zone::to_local(date::sys_time<Duration> tp) const
{
using date::local_time;
using std::chrono::seconds;
using LT = local_time<typename std::common_type<Duration, seconds>::type>;
auto i = get_info(tp);
return LT{(tp + i.offset).time_since_epoch()};
}
inline
std::ostream&
operator<<(std::ostream& os, const time_zone& z)
{
using date::operator<<;
os << '{';
os << z.std_abbrev_ << ", " << z.dst_abbrev_ << date::format(", %T, ", z.offset_)
<< date::format("%T, [", z.save_) << z.start_rule_ << ", " << z.end_rule_ << ")}";
return os;
}
inline
std::string
time_zone::name() const
{
using namespace date;
using namespace std::chrono;
auto nm = std_abbrev_;
auto print_offset = [](seconds off)
{
std::string nm;
hh_mm_ss<seconds> offset{-off};
if (offset.is_negative())
nm += '-';
nm += std::to_string(offset.hours().count());
if (offset.minutes() != minutes{0} || offset.seconds() != seconds{0})
{
nm += ':';
if (offset.minutes() < minutes{10})
nm += '0';
nm += std::to_string(offset.minutes().count());
if (offset.seconds() != seconds{0})
{
nm += ':';
if (offset.seconds() < seconds{10})
nm += '0';
nm += std::to_string(offset.seconds().count());
}
}
return nm;
};
nm += print_offset(offset_);
if (!dst_abbrev_.empty())
{
nm += dst_abbrev_;
if (save_ != hours{1})
nm += print_offset(offset_+save_);
if (start_rule_.ok())
{
nm += ',';
nm += start_rule_.to_string();
nm += ',';
nm += end_rule_.to_string();
}
}
return nm;
}
inline
bool
operator==(const time_zone& x, const time_zone& y)
{
return x.std_abbrev_ == y.std_abbrev_ &&
x.dst_abbrev_ == y. dst_abbrev_ &&
x.offset_ == y.offset_ &&
x.save_ == y.save_ &&
x.start_rule_ == y.start_rule_ &&
x.end_rule_ == y.end_rule_;
}
inline
bool
operator!=(const time_zone& x, const time_zone& y)
{
return !(x == y);
}
namespace detail
{
inline
void
throw_invalid(const string_t& s, unsigned i, const string_t& message)
{
throw std::runtime_error(std::string("Invalid time_zone initializer.\n") +
std::string(message) + ":\n" +
std::string(s) + '\n' +
"\x1b[1;32m" +
std::string(i, '~') + '^' +
std::string(i < s.size() ? s.size()-i-1 : 0, '~') +
"\x1b[0m");
}
inline
unsigned
read_date(const string_t& s, unsigned i, rule& r)
{
using date::month;
using date::weekday;
if (i == s.size())
throw_invalid(s, i, "Expected rule but found end of string");
if (s[i] == 'J')
{
++i;
unsigned n;
i = read_unsigned(s, i, 3, n, "Expected to find the Julian day [1, 365]");
r.mode_ = rule::J;
r.n_ = n;
}
else if (s[i] == 'M')
{
++i;
unsigned m;
i = read_unsigned(s, i, 2, m, "Expected to find month [1, 12]");
if (i == s.size() || s[i] != '.')
throw_invalid(s, i, "Expected '.' after month");
++i;
unsigned n;
i = read_unsigned(s, i, 1, n, "Expected to find week number [1, 5]");
if (i == s.size() || s[i] != '.')
throw_invalid(s, i, "Expected '.' after weekday index");
++i;
unsigned wd;
i = read_unsigned(s, i, 1, wd, "Expected to find day of week [0, 6]");
r.mode_ = rule::M;
r.m_ = month{m};
r.wd_ = weekday{wd};
r.n_ = n;
}
else if (std::isdigit(s[i]))
{
unsigned n;
i = read_unsigned(s, i, 3, n);
r.mode_ = rule::N;
r.n_ = n;
}
else
throw_invalid(s, i, "Expected 'J', 'M', or a digit to start rule");
if (i != s.size() && s[i] == '/')
{
++i;
std::chrono::seconds t;
i = read_unsigned_time(s, i, t);
r.time_ = t;
}
return i;
}
inline
unsigned
read_name(const string_t& s, unsigned i, std::string& name)
{
if (i == s.size())
throw_invalid(s, i, "Expected a name but found end of string");
if (s[i] == '<')
{
++i;
while (true)
{
if (i == s.size())
throw_invalid(s, i,
"Expected to find closing '>', but found end of string");
if (s[i] == '>')
break;
name.push_back(s[i]);
++i;
}
++i;
}
else
{
while (i != s.size() && std::isalpha(s[i]))
{
name.push_back(s[i]);
++i;
}
}
if (name.size() < 3)
throw_invalid(s, i, "Found name to be shorter than 3 characters");
return i;
}
inline
unsigned
read_signed_time(const string_t& s, unsigned i,
std::chrono::seconds& t)
{
if (i == s.size())
throw_invalid(s, i, "Expected to read signed time, but found end of string");
bool negative = false;
if (s[i] == '-')
{
negative = true;
++i;
}
else if (s[i] == '+')
++i;
i = read_unsigned_time(s, i, t);
if (negative)
t = -t;
return i;
}
inline
unsigned
read_unsigned_time(const string_t& s, unsigned i, std::chrono::seconds& t)
{
using std::chrono::seconds;
using std::chrono::minutes;
using std::chrono::hours;
if (i == s.size())
throw_invalid(s, i, "Expected to read unsigned time, but found end of string");
unsigned x;
i = read_unsigned(s, i, 2, x, "Expected to find hours [0, 24]");
t = hours{x};
if (i != s.size() && s[i] == ':')
{
++i;
i = read_unsigned(s, i, 2, x, "Expected to find minutes [0, 59]");
t += minutes{x};
if (i != s.size() && s[i] == ':')
{
++i;
i = read_unsigned(s, i, 2, x, "Expected to find seconds [0, 59]");
t += seconds{x};
}
}
return i;
}
inline
unsigned
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, message);
u = static_cast<unsigned>(s[i] - '0');
unsigned count = 1;
for (++i; count < limit && i != s.size() && std::isdigit(s[i]); ++i, ++count)
u = u * 10 + static_cast<unsigned>(s[i] - '0');
return i;
}
} // namespace detail
} // namespace Posix
namespace date
{
template <>
struct zoned_traits<Posix::time_zone>
{
#if HAS_STRING_VIEW
static
Posix::time_zone
locate_zone(std::string_view name)
{
return Posix::time_zone{name};
}
#else // !HAS_STRING_VIEW
static
Posix::time_zone
locate_zone(const std::string& name)
{
return Posix::time_zone{name};
}
static
Posix::time_zone
locate_zone(const char* name)
{
return Posix::time_zone{name};
}
#endif // !HAS_STRING_VIEW
};
} // namespace date
#endif // PTZ_H

File diff suppressed because it is too large Load Diff

2792
include/date/tz.h Normal file

File diff suppressed because it is too large Load Diff

View File

@ -24,16 +24,32 @@
// SOFTWARE.
//
// Our apologies. When the previous paragraph was written, lowercase had not yet
// been invented (that woud involve another several millennia of evolution).
// been invented (that would involve another several millennia of evolution).
// We did not mean to shout.
#if !defined(_MSC_VER) || (_MSC_VER >= 1900)
#include "tz.h"
#else
#include "date.h"
#include <vector>
#endif
namespace date
{
namespace detail
{
#if !USE_OS_TZDB
enum class tz {utc, local, standard};
//forward declare to avoid warnings in gcc 6.2
class MonthDayTime;
std::istream& operator>>(std::istream& is, MonthDayTime& x);
std::ostream& operator<<(std::ostream& os, const MonthDayTime& x);
class MonthDayTime
{
private:
@ -110,11 +126,25 @@ public:
// A Rule specifies one or more set of datetimes without using an offset.
// Multiple dates are specified with multiple years. The years in effect
// go from starting_year_ to ending_year_, inclusive. starting_year_ <=
// ending_year_. save_ is ineffect for times from the specified time
// ending_year_. save_ is in effect for times from the specified time
// onward, including the specified time. When the specified time is
// local, it uses the save_ from the chronologically previous Rule, or if
// there is none, 0.
//forward declare to avoid warnings in gcc 6.2
class Rule;
bool operator==(const Rule& x, const Rule& y);
bool operator<(const Rule& x, const Rule& y);
bool operator==(const Rule& x, const date::year& y);
bool operator<(const Rule& x, const date::year& y);
bool operator==(const date::year& x, const Rule& y);
bool operator<(const date::year& x, const Rule& y);
bool operator==(const Rule& x, const std::string& y);
bool operator<(const Rule& x, const std::string& y);
bool operator==(const std::string& x, const Rule& y);
bool operator<(const std::string& x, const Rule& y);
std::ostream& operator<<(std::ostream& os, const Rule& r);
class Rule
{
private:
@ -187,7 +217,7 @@ inline bool operator> (const std::string& x, const Rule& y) {return y < x;}
inline bool operator<=(const std::string& x, const Rule& y) {return !(y < x);}
inline bool operator>=(const std::string& x, const Rule& y) {return !(x < y);}
struct time_zone::zonelet
struct zonelet
{
enum tag {has_rule, has_save, is_empty};
@ -215,7 +245,7 @@ struct time_zone::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()};
@ -226,6 +256,61 @@ struct time_zone::zonelet
zonelet& operator=(const zonelet&) = delete;
};
#else // USE_OS_TZDB
struct ttinfo
{
std::int32_t tt_gmtoff;
unsigned char tt_isdst;
unsigned char tt_abbrind;
unsigned char pad[2];
};
static_assert(sizeof(ttinfo) == 8, "");
struct expanded_ttinfo
{
std::chrono::seconds offset;
std::string abbrev;
bool is_dst;
};
struct transition
{
sys_seconds timepoint;
const expanded_ttinfo* info;
transition(sys_seconds tp, const expanded_ttinfo* i = nullptr)
: timepoint(tp)
, info(i)
{}
friend
std::ostream&
operator<<(std::ostream& os, const transition& t)
{
using date::operator<<;
os << t.timepoint << "Z ";
if (t.info->offset >= std::chrono::seconds{0})
os << '+';
os << make_time(t.info->offset);
if (t.info->is_dst > 0)
os << " daylight ";
else
os << " standard ";
os << t.info->abbrev;
return os;
}
};
#endif // USE_OS_TZDB
} // namespace detail
} // namespace date
#if defined(_MSC_VER) && (_MSC_VER < 1900)
#include "tz.h"
#endif
#endif // TZ_PRIVATE_H

11
library.json Normal file
View File

@ -0,0 +1,11 @@
{
"name": "date",
"version": "1.0.0",
"build": {
"includeDir": "include",
"srcFilter":
[
"+<->"
]
}
}

337
src/ios.mm Normal file
View File

@ -0,0 +1,337 @@
//
// The MIT License (MIT)
//
// Copyright (c) 2016 Alexander Kormanovsky
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
//
#include "date/ios.h"
#if TARGET_OS_IPHONE
#include <Foundation/Foundation.h>
#include <fstream>
#include <zlib.h>
#include <sys/stat.h>
#ifndef TAR_DEBUG
# define TAR_DEBUG 0
#endif
#define INTERNAL_DIR "Library"
#define TZDATA_DIR "tzdata"
#define TARGZ_EXTENSION "tar.gz"
#define TAR_BLOCK_SIZE 512
#define TAR_TYPE_POSITION 156
#define TAR_NAME_POSITION 0
#define TAR_NAME_SIZE 100
#define TAR_SIZE_POSITION 124
#define TAR_SIZE_SIZE 12
namespace date
{
namespace iOSUtils
{
struct TarInfo
{
char objType;
std::string objName;
size_t realContentSize; // writable size without padding zeroes
size_t blocksContentSize; // adjusted size to 512 bytes blocks
bool success;
};
std::string convertCFStringRefPathToCStringPath(CFStringRef ref);
bool extractTzdata(CFURLRef homeUrl, CFURLRef archiveUrl, std::string destPath);
TarInfo getTarObjectInfo(std::ifstream &readStream);
std::string getTarObject(std::ifstream &readStream, int64_t size);
bool writeFile(const std::string &tzdataPath, const std::string &fileName,
const std::string &data, size_t realContentSize);
std::string
get_current_timezone()
{
CFTimeZoneRef tzRef = CFTimeZoneCopySystem();
CFStringRef tzNameRef = CFTimeZoneGetName(tzRef);
CFIndex bufferSize = CFStringGetLength(tzNameRef) + 1;
char buffer[bufferSize];
if (CFStringGetCString(tzNameRef, buffer, bufferSize, kCFStringEncodingUTF8))
{
CFRelease(tzRef);
return std::string(buffer);
}
CFRelease(tzRef);
return "";
}
std::string
get_tzdata_path()
{
CFURLRef homeUrlRef = CFCopyHomeDirectoryURL();
CFStringRef homePath = CFURLCopyPath(homeUrlRef);
std::string path(std::string(convertCFStringRefPathToCStringPath(homePath)) +
INTERNAL_DIR + "/" + TZDATA_DIR);
std::string result_path(std::string(convertCFStringRefPathToCStringPath(homePath)) +
INTERNAL_DIR);
if (access(path.c_str(), F_OK) == 0)
{
#if TAR_DEBUG
printf("tzdata dir exists\n");
#endif
CFRelease(homeUrlRef);
CFRelease(homePath);
return result_path;
}
CFBundleRef mainBundle = CFBundleGetMainBundle();
CFArrayRef paths = CFBundleCopyResourceURLsOfType(mainBundle, CFSTR(TARGZ_EXTENSION),
NULL);
if (CFArrayGetCount(paths) != 0)
{
// get archive path, assume there is no other tar.gz in bundle
CFURLRef archiveUrl = static_cast<CFURLRef>(CFArrayGetValueAtIndex(paths, 0));
CFStringRef archiveName = CFURLCopyPath(archiveUrl);
archiveUrl = CFBundleCopyResourceURL(mainBundle, archiveName, NULL, NULL);
extractTzdata(homeUrlRef, archiveUrl, path);
CFRelease(archiveUrl);
CFRelease(archiveName);
}
CFRelease(homeUrlRef);
CFRelease(homePath);
CFRelease(paths);
return result_path;
}
std::string
convertCFStringRefPathToCStringPath(CFStringRef ref)
{
CFIndex bufferSize = CFStringGetMaximumSizeOfFileSystemRepresentation(ref);
char *buffer = new char[bufferSize];
CFStringGetFileSystemRepresentation(ref, buffer, bufferSize);
auto result = std::string(buffer);
delete[] buffer;
return result;
}
bool
extractTzdata(CFURLRef homeUrl, CFURLRef archiveUrl, std::string destPath)
{
std::string TAR_TMP_PATH = "/tmp.tar";
CFStringRef homeStringRef = CFURLCopyPath(homeUrl);
auto homePath = convertCFStringRefPathToCStringPath(homeStringRef);
CFRelease(homeStringRef);
CFStringRef archiveStringRef = CFURLCopyPath(archiveUrl);
auto archivePath = convertCFStringRefPathToCStringPath(archiveStringRef);
CFRelease(archiveStringRef);
// create Library path
auto libraryPath = homePath + INTERNAL_DIR;
// create tzdata path
auto tzdataPath = libraryPath + "/" + TZDATA_DIR;
// -- replace %20 with " "
const std::string search = "%20";
const std::string replacement = " ";
size_t pos = 0;
while ((pos = archivePath.find(search, pos)) != std::string::npos) {
archivePath.replace(pos, search.length(), replacement);
pos += replacement.length();
}
gzFile tarFile = gzopen(archivePath.c_str(), "rb");
// create tar unpacking path
auto tarPath = libraryPath + TAR_TMP_PATH;
// create tzdata directory
mkdir(destPath.c_str(), S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH);
// ======= extract tar ========
std::ofstream os(tarPath.c_str(), std::ofstream::out | std::ofstream::app);
unsigned int bufferLength = 1024 * 256; // 256Kb
unsigned char *buffer = (unsigned char *)malloc(bufferLength);
bool success = true;
while (true)
{
int readBytes = gzread(tarFile, buffer, bufferLength);
if (readBytes > 0)
{
os.write((char *) &buffer[0], readBytes);
}
else
if (readBytes == 0)
{
break;
}
else
if (readBytes == -1)
{
printf("decompression failed\n");
success = false;
break;
}
else
{
printf("unexpected zlib state\n");
success = false;
break;
}
}
os.close();
free(buffer);
gzclose(tarFile);
if (!success)
{
remove(tarPath.c_str());
return false;
}
// ======== extract files =========
uint64_t location = 0; // Position in the file
// get file size
struct stat stat_buf;
int res = stat(tarPath.c_str(), &stat_buf);
if (res != 0)
{
printf("error file size\n");
remove(tarPath.c_str());
return false;
}
int64_t tarSize = stat_buf.st_size;
// create read stream
std::ifstream is(tarPath.c_str(), std::ifstream::in | std::ifstream::binary);
// process files
while (location < tarSize)
{
TarInfo info = getTarObjectInfo(is);
if (!info.success || info.realContentSize == 0)
{
break; // something wrong or all files are read
}
switch (info.objType)
{
case '0': // file
case '\0': //
{
std::string obj = getTarObject(is, info.blocksContentSize);
#if TAR_DEBUG
size += info.realContentSize;
printf("#%i %s file size %lld written total %ld from %lld\n", ++count,
info.objName.c_str(), info.realContentSize, size, tarSize);
#endif
writeFile(tzdataPath, info.objName, obj, info.realContentSize);
location += info.blocksContentSize;
break;
}
}
}
remove(tarPath.c_str());
return true;
}
TarInfo
getTarObjectInfo(std::ifstream &readStream)
{
int64_t length = TAR_BLOCK_SIZE;
char buffer[length];
char type;
char name[TAR_NAME_SIZE + 1];
char sizeBuf[TAR_SIZE_SIZE + 1];
readStream.read(buffer, length);
memcpy(&type, &buffer[TAR_TYPE_POSITION], 1);
memset(&name, '\0', TAR_NAME_SIZE + 1);
memcpy(&name, &buffer[TAR_NAME_POSITION], TAR_NAME_SIZE);
memset(&sizeBuf, '\0', TAR_SIZE_SIZE + 1);
memcpy(&sizeBuf, &buffer[TAR_SIZE_POSITION], TAR_SIZE_SIZE);
size_t realSize = strtol(sizeBuf, NULL, 8);
size_t blocksSize = realSize + (TAR_BLOCK_SIZE - (realSize % TAR_BLOCK_SIZE));
return {type, std::string(name), realSize, blocksSize, true};
}
std::string
getTarObject(std::ifstream &readStream, int64_t size)
{
char buffer[size];
readStream.read(buffer, size);
return std::string(buffer);
}
bool
writeFile(const std::string &tzdataPath, const std::string &fileName, const std::string &data,
size_t realContentSize)
{
std::ofstream os(tzdataPath + "/" + fileName, std::ofstream::out | std::ofstream::binary);
if (!os) {
return false;
}
// trim empty space
char trimmedData[realContentSize + 1];
memset(&trimmedData, '\0', realContentSize);
memcpy(&trimmedData, data.c_str(), realContentSize);
// write
os.write(trimmedData, realContentSize);
os.close();
return true;
}
} // namespace iOSUtils
} // namespace date
#endif // TARGET_OS_IPHONE

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,75 @@
// The MIT License (MIT)
//
// Copyright (c) 2019 nanoric
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
#include "tz.h"
#include <cassert>
#include <type_traits>
struct const_clock {
using duration =
typename std::common_type<std::chrono::system_clock::duration,
date::days>::type;
using rep = duration::rep;
using period = duration::period;
using time_point = std::chrono::time_point<const_clock, duration>;
static constexpr date::sys_days epoch { date::days { 1000 } };
template <typename Duration>
static std::chrono::time_point<std::chrono::system_clock,
typename std::common_type<Duration, date::days>::type>
CONSTCD11 to_sys(std::chrono::time_point<const_clock, Duration> const& tp)
{
return epoch + tp.time_since_epoch();
}
template <typename Duration>
static std::chrono::time_point<const_clock,
typename std::common_type<Duration, date::days>::type>
CONSTCD11 from_sys(
std::chrono::time_point<std::chrono::system_clock, Duration> const&
tp)
{
using res = std::chrono::time_point<const_clock,
typename std::common_type<Duration, date::days>::type>;
return res(tp - epoch);
}
};
int main()
{
using namespace date;
using namespace std::chrono;
using const_days = time_point<const_clock, days>;
CONSTCD14 sys_days sys { days { 1024 } };
static_assert(sys.time_since_epoch().count() == 1024, "");
CONSTCD14 const_days c {clock_cast<const_clock>(sys)};
CONSTCD14 sys_days sys2 {clock_cast<system_clock>(c)};
CONSTCD14 sys_days sys3 { clock_cast<system_clock>(const_days(days(48))) };
#if __cplusplus >= 201402L
static_assert(c.time_since_epoch().count() == 24, "");
static_assert(sys2.time_since_epoch().count() == 1024, "");
static_assert(sys3.time_since_epoch().count() == 1048, "");
#endif
}

View File

@ -0,0 +1,213 @@
// The MIT License (MIT)
//
// Copyright (c) 2017, 2018 Tomasz Kamiński
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
#include "tz.h"
#include <cassert>
#include <type_traits>
//used to count number of conversion
int conversions = 0;
//to/from impl
struct mil_clock
{
using duration = typename std::common_type<std::chrono::system_clock::duration, date::days>::type;
using rep = duration::rep;
using period = duration::period;
using time_point = std::chrono::time_point<mil_clock, duration>;
static constexpr date::sys_days epoch{date::days{1000}};
template<typename Duration>
static
std::chrono::time_point<std::chrono::system_clock, typename std::common_type<Duration, date::days>::type>
to_sys(std::chrono::time_point<mil_clock, Duration> const& tp)
{
++conversions;
return epoch + tp.time_since_epoch();
}
template<typename Duration>
static
std::chrono::time_point<mil_clock, typename std::common_type<Duration, date::days>::type>
from_sys(std::chrono::time_point<std::chrono::system_clock, Duration> const& tp)
{
++conversions;
using res = std::chrono::time_point<mil_clock, typename std::common_type<Duration, date::days>::type>;
return res(tp - epoch);
}
template<typename Duration>
static
std::chrono::time_point<date::local_t, typename std::common_type<Duration, date::days>::type>
to_local(std::chrono::time_point<mil_clock, Duration> const& tp)
{
return date::clock_cast<date::local_t>(to_sys(tp));
}
template<typename Duration>
static
std::chrono::time_point<mil_clock, typename std::common_type<Duration, date::days>::type>
from_local(std::chrono::time_point<date::local_t, Duration> const& tp)
{
return from_sys(date::clock_cast<std::chrono::system_clock>(tp));
}
static time_point now()
{
return from_sys(std::chrono::system_clock::now());
}
};
date::sys_days const mil_clock::epoch;
// traits example
struct s2s_clock
{
using duration = std::chrono::system_clock::duration;
using rep = duration::rep;
using period = duration::period;
using time_point = std::chrono::time_point<s2s_clock, duration>;
template<typename Duration>
static
std::chrono::time_point<std::chrono::system_clock, Duration>
to_sys(std::chrono::time_point<s2s_clock, Duration> const& tp)
{
++conversions;
return std::chrono::time_point<std::chrono::system_clock, Duration>(tp.time_since_epoch());
}
template<typename Duration>
static
std::chrono::time_point<s2s_clock, Duration>
from_sys(std::chrono::time_point<std::chrono::system_clock, Duration> const& tp)
{
++conversions;
return std::chrono::time_point<s2s_clock, Duration>(tp.time_since_epoch());
}
static time_point now()
{
return from_sys(std::chrono::system_clock::now());
}
};
namespace date
{
template<>
struct clock_time_conversion<mil_clock, s2s_clock>
{
template<typename Duration>
std::chrono::time_point<mil_clock, typename std::common_type<Duration, date::days>::type>
operator()(std::chrono::time_point<s2s_clock, Duration> const& tp)
{
++conversions;
using res = std::chrono::time_point<mil_clock, typename std::common_type<Duration, date::days>::type>;
return res(tp.time_since_epoch() - mil_clock::epoch.time_since_epoch());
}
};
}
int
main()
{
using namespace date;
using sys_clock = std::chrono::system_clock;
// self
{
sys_days st(1997_y/dec/12);
auto mt = mil_clock::from_sys(st);
assert(clock_cast<mil_clock>(mt) == mt);
}
// mil <-> local
{
local_days lt(1997_y/dec/12);
auto mt = mil_clock::from_local(lt);
assert(clock_cast<mil_clock>(lt) == mt);
assert(clock_cast<local_t>(mt) == lt);
}
// mil <-> sys
{
sys_days st(1997_y/dec/12);
auto mt = mil_clock::from_sys(st);
assert(clock_cast<mil_clock>(st) == mt);
assert(clock_cast<sys_clock>(mt) == st);
}
// mil <-> utc
{
sys_days st(1997_y/dec/12);
auto mt = mil_clock::from_sys(st);
auto ut = utc_clock::from_sys(st);
assert(clock_cast<mil_clock>(ut) == mt);
assert(clock_cast<utc_clock>(mt) == ut);
}
// mil <-> tai
{
sys_days st(1997_y/dec/12);
auto mt = mil_clock::from_sys(st);
auto ut = utc_clock::from_sys(st);
auto tt = tai_clock::from_utc(ut);
assert(clock_cast<tai_clock>(mt) == tt);
assert(clock_cast<mil_clock>(tt) == mt);
}
// mil <-> gps
{
sys_days st(1997_y/dec/12);
auto mt = mil_clock::from_sys(st);
auto ut = utc_clock::from_sys(st);
auto gt = gps_clock::from_utc(ut);
assert(clock_cast<gps_clock>(mt) == gt);
assert(clock_cast<mil_clock>(gt) == mt);
}
// s2s -> mil
{
sys_days st(1997_y/dec/12);
auto mt = mil_clock::from_sys(st);
auto s2t = s2s_clock::from_sys(st);
//direct trait conversion
conversions = 0;
assert(clock_cast<mil_clock>(s2t) == mt);
assert(conversions == 1);
//uses sys_clock
conversions = 0;
assert(clock_cast<s2s_clock>(mt) == s2t);
assert(conversions == 2);
}
}

View File

@ -0,0 +1,90 @@
// The MIT License (MIT)
//
// Copyright (c) 2017 Tomasz Kamiński
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
#include "tz.h"
#include <cassert>
int
main()
{
using namespace date;
// sys <-> utc
{
sys_days st(1997_y/dec/12);
auto ut = utc_clock::from_sys(st);
assert(to_utc_time(st) == ut);
assert(to_sys_time(ut) == st);
}
// tai <-> utc
{
sys_days st(1997_y/dec/12);
auto ut = utc_clock::from_sys(st);
auto tt = tai_clock::from_utc(ut);
assert(to_tai_time(ut) == tt);
assert(to_utc_time(tt) == ut);
}
// tai <-> sys
{
sys_days st(1997_y/dec/12);
auto ut = utc_clock::from_sys(st);
auto tt = tai_clock::from_utc(ut);
assert(to_tai_time(st) == tt);
assert(to_sys_time(tt) == st);
}
// gps <-> utc
{
sys_days st(1997_y/dec/12);
auto ut = utc_clock::from_sys(st);
auto gt = gps_clock::from_utc(ut);
assert(to_gps_time(ut) == gt);
assert(to_utc_time(gt) == ut);
}
// gps <-> sys
{
sys_days st(1997_y/dec/12);
auto ut = utc_clock::from_sys(st);
auto gt = gps_clock::from_utc(ut);
assert(to_gps_time(st) == gt);
assert(to_sys_time(gt) == st);
}
// tai <-> gps
{
sys_days st(1997_y/dec/12);
auto ut = utc_clock::from_sys(st);
auto tt = tai_clock::from_utc(ut);
auto gt = gps_clock::from_utc(ut);
assert(to_gps_time(tt) == gt);
assert(to_tai_time(gt) == tt);
}
}

View File

@ -0,0 +1,132 @@
// The MIT License (MIT)
//
// Copyright (c) 2018 Tomasz Kamiński
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
#include <chrono>
#include "date/tz.h"
int
main()
{
using namespace date;
using namespace std::chrono;
// self
{
auto ls = local_days{1970_y/January/1_d};
assert(clock_cast<local_t>(ls) == ls);
}
/// sys epoch
{
auto ls = local_days{1970_y/January/1_d};
auto st = clock_cast<system_clock>(ls);
assert(clock_cast<local_t>(st) == ls);
assert(st.time_since_epoch() == seconds(0));
}
/// sys 2000 case
{
auto ls = local_days{2000_y/January/1_d};
auto st = clock_cast<system_clock>(ls);
assert(clock_cast<local_t>(st) == ls);
assert(st.time_since_epoch() == seconds(946684800));
}
/// utc epoch
{
auto lu = local_days{1970_y/January/1_d};
auto ut = clock_cast<utc_clock>(lu);
assert(clock_cast<local_t>(ut) == lu);
assert(ut.time_since_epoch() == seconds(0));
}
// utc leap second
{
auto lu = local_days{2015_y/July/1_d} - milliseconds(1);
auto ut = clock_cast<utc_clock>(lu) + milliseconds(50); //into leap second
assert(clock_cast<local_t>(ut) == lu);
}
/// utc paper example
{
auto lu = local_days{2000_y/January/1_d};
auto ut = clock_cast<utc_clock>(lu);
assert(clock_cast<local_t>(ut) == lu);
assert(ut.time_since_epoch() == seconds(946684822));
}
/// tai epoch
{
auto lt = local_days{1958_y/January/1_d};
auto tt = clock_cast<tai_clock>(lt);
assert(clock_cast<local_t>(tt) == lt);
assert(tt.time_since_epoch() == seconds(0));
auto lu = local_days{1958_y/January/1_d} - seconds(10);
auto ut = clock_cast<utc_clock>(lu);
assert(clock_cast<tai_clock>(ut) == tt);
}
// tai paper example
{
auto lt = local_days{2000_y/January/1_d} + seconds(32);
auto tt = clock_cast<tai_clock>(lt);
assert(clock_cast<local_t>(tt) == lt);
auto lu = local_days{2000_y/January/1_d};
auto ut = clock_cast<utc_clock>(lu);
assert(clock_cast<tai_clock>(ut) == tt);
}
/// gps epoch
{
auto lg = local_days{1980_y/January/Sunday[1]};
auto gt = clock_cast<gps_clock>(lg);
assert(clock_cast<local_t>(gt) == lg);
assert(gt.time_since_epoch() == seconds(0));
auto lu = local_days{1980_y/January/Sunday[1]};
auto ut = clock_cast<utc_clock>(lu);
assert(clock_cast<gps_clock>(ut) == gt);
auto lt = local_days{1980_y/January/Sunday[1]} + seconds(19);
auto tt = clock_cast<tai_clock>(lt);
assert(clock_cast<gps_clock>(tt) == gt);
}
// gps 2000 example
{
auto lg = local_days{2000_y/January/1_d};
auto gt = clock_cast<gps_clock>(lg);
assert(clock_cast<local_t>(gt) == lg);
auto lu = local_days{2000_y/January/1_d} - seconds(13);
auto ut = clock_cast<utc_clock>(lu);
assert(clock_cast<gps_clock>(ut) == gt);
auto lt = local_days{2000_y/January/1_d} + seconds(19);
auto tt = clock_cast<tai_clock>(lt);
assert(clock_cast<gps_clock>(tt) == gt);
}
}

View File

@ -0,0 +1,251 @@
// The MIT License (MIT)
//
// Copyright (c) 2017, 2018 Tomasz Kamiński
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
#include "tz.h"
#include <type_traits>
#include <cassert>
template<typename SourceClock, typename DestClock, typename = void>
struct is_clock_castable
: std::false_type
{};
template<typename SourceClock, typename DestClock>
struct is_clock_castable<SourceClock, DestClock, decltype(date::clock_cast<DestClock>(typename SourceClock::time_point()), void())>
: std::true_type
{};
//Clock based on steady clock, not related to wall time (sys_clock/utc_clock)
struct steady_based_clock
{
using duration = std::chrono::steady_clock::duration;
using rep = duration::rep;
using period = duration::period;
using time_point = std::chrono::time_point<steady_based_clock, duration>;
static time_point now()
{
return time_point(std::chrono::steady_clock::now().time_since_epoch());
}
};
//Traits that allow conversion between steady_clock and steady_based clock
//Does not use wall-time clocks as rally (sys/utc)
namespace date
{
template<>
struct clock_time_conversion<std::chrono::steady_clock, steady_based_clock>
{
template<typename Duration>
std::chrono::time_point<std::chrono::steady_clock, Duration>
operator()(std::chrono::time_point<steady_based_clock, Duration> const& tp) const
{
using res = std::chrono::time_point<std::chrono::steady_clock, Duration>;
return res(tp.time_since_epoch());
}
};
template<>
struct clock_time_conversion<steady_based_clock, std::chrono::steady_clock>
{
template<typename Duration>
std::chrono::time_point<steady_based_clock, Duration>
operator()(std::chrono::time_point<std::chrono::steady_clock, Duration> const& tp) const
{
using res = std::chrono::time_point<steady_based_clock, Duration>;
return res(tp.time_since_epoch());
}
};
}
//Ambigous clocks both providing to/from_sys and to/from_utc
//They are mock_ups just returning zero time_point
struct amb1_clock
{
using duration = std::chrono::seconds;
using rep = duration::rep;
using period = duration::period;
using time_point = std::chrono::time_point<amb1_clock>;
static time_point now()
{
return {};
}
template<typename Duration>
static
std::chrono::time_point<std::chrono::system_clock, Duration>
to_sys(std::chrono::time_point<amb1_clock, Duration> const&)
{
return {};
}
template<typename Duration>
static
std::chrono::time_point<amb1_clock, Duration>
from_sys(std::chrono::time_point<std::chrono::system_clock, Duration> const&)
{
return {};
}
template<typename Duration>
static
std::chrono::time_point<date::utc_clock, Duration>
to_utc(std::chrono::time_point<amb1_clock, Duration> const&)
{
return {};
}
template<typename Duration>
static
std::chrono::time_point<amb1_clock, Duration>
from_utc(std::chrono::time_point<date::utc_clock, Duration> const&)
{
return {};
}
};
struct amb2_clock
{
using duration = std::chrono::seconds;
using rep = duration::rep;
using period = duration::period;
using time_point = std::chrono::time_point<amb2_clock>;
static time_point now()
{
return {};
}
template<typename Duration>
static
std::chrono::time_point<std::chrono::system_clock, Duration>
to_sys(std::chrono::time_point<amb2_clock, Duration> const&)
{
return {};
}
template<typename Duration>
static
std::chrono::time_point<amb2_clock, Duration>
from_sys(std::chrono::time_point<std::chrono::system_clock, Duration> const&)
{
return {};
}
template<typename Duration>
static
std::chrono::time_point<date::utc_clock, Duration>
to_utc(std::chrono::time_point<amb2_clock, Duration> const&)
{
return {};
}
template<typename Duration>
static
std::chrono::time_point<amb2_clock, Duration>
from_utc(std::chrono::time_point<date::utc_clock, Duration> const&)
{
return {};
}
};
namespace date
{
//Disambiguates that sys_clock is preffered
template<>
struct clock_time_conversion<amb1_clock, amb2_clock>
{
template<typename Duration>
std::chrono::time_point<amb1_clock, Duration>
operator()(std::chrono::time_point<amb2_clock, Duration> const& tp) const
{
return amb1_clock::from_sys(amb2_clock::to_sys(tp));
}
};
}
int
main()
{
using namespace date;
using namespace std::chrono;
using sys_clock = std::chrono::system_clock;
//steady_clock (must be different that sys_clock)
static_assert(is_clock_castable<steady_clock, steady_clock>::value, "steady_clock -> steady_clock");
static_assert(!is_clock_castable<steady_clock, local_t>::value, "steady_clock -> local_t");
static_assert(!is_clock_castable<local_t, steady_clock>::value, "local_t -> steady_clock");
static_assert(!is_clock_castable<steady_clock, sys_clock>::value, "steady_clock -> sys_clock");
static_assert(!is_clock_castable<sys_clock, steady_clock>::value, "sys_clock -> steady_clock");
static_assert(!is_clock_castable<steady_clock, utc_clock>::value, "steady_clock -> utc_clock");
static_assert(!is_clock_castable<utc_clock, steady_clock>::value, "utc_clock -> steady_clock");
static_assert(!is_clock_castable<steady_clock, tai_clock>::value, "steady_clock -> tai_clock");
static_assert(!is_clock_castable<tai_clock, steady_clock>::value, "tai_clock -> steady_clock");
//steady_based_clock (unrelated to sys_clock and utc_clocks)
static_assert(is_clock_castable<steady_based_clock, steady_based_clock>::value, "steady_based_clock -> steady_based_clock");
static_assert(!is_clock_castable<steady_based_clock, local_t>::value, "steady_based_clock -> local_t");
static_assert(!is_clock_castable<local_t, steady_based_clock>::value, "local_t -> steady_based_clock");
static_assert(!is_clock_castable<steady_based_clock, sys_clock>::value, "steady_based_clock -> sys_clock");
static_assert(!is_clock_castable<sys_clock, steady_based_clock>::value, "sys_clock -> steady_based_clock");
static_assert(!is_clock_castable<steady_based_clock, utc_clock>::value, "steady_based_clock -> utc_clock");
static_assert(!is_clock_castable<utc_clock, steady_based_clock>::value, "utc_clock -> steady_based_clock");
static_assert(!is_clock_castable<steady_based_clock, tai_clock>::value, "steady_based_clock -> tai_clock");
static_assert(!is_clock_castable<tai_clock, steady_based_clock>::value, "tai_clock -> steady_based_clock");
//steady_based <-> steady_clock
{
auto s1 = steady_clock::time_point(steady_clock::duration(200));
auto s2 = steady_based_clock::time_point(steady_based_clock::duration(200));
assert(clock_cast<steady_based_clock>(s1) == s2);
assert(clock_cast<steady_clock>(s2) == s1);
}
//ambX <-> sys/utc works as one rally can be used in each case, or one lead to quicker conversione
static_assert(is_clock_castable<amb1_clock, amb1_clock>::value, "amb1_clock -> amb1_clock");
static_assert(is_clock_castable<amb1_clock, sys_clock>::value, "amb1_clock -> sys_clock");
static_assert(is_clock_castable<sys_clock, amb1_clock>::value, "sys_clock -> amb1_clock");
static_assert(is_clock_castable<amb1_clock, utc_clock>::value, "amb1_clock -> utc_clock");
static_assert(is_clock_castable<utc_clock, amb1_clock>::value, "utc_clock -> amb1_clock");
static_assert(is_clock_castable<amb1_clock, tai_clock>::value, "amb1_clock -> tai_clock");
static_assert(is_clock_castable<tai_clock, amb1_clock>::value, "tai_clock -> amb1_clock");
static_assert(is_clock_castable<amb1_clock, tai_clock>::value, "amb1_clock -> tai_clock");
static_assert(is_clock_castable<gps_clock, amb1_clock>::value, "gps_clock -> amb1_clock");
static_assert(is_clock_castable<amb2_clock, amb2_clock>::value, "amb2_clock -> amb2_clock");
static_assert(is_clock_castable<amb2_clock, sys_clock>::value, "amb2_clock -> sys_clock");
static_assert(is_clock_castable<sys_clock, amb2_clock>::value, "sys_clock -> amb2_clock");
static_assert(is_clock_castable<amb2_clock, utc_clock>::value, "amb2_clock -> utc_clock");
static_assert(is_clock_castable<utc_clock, amb2_clock>::value, "utc_clock -> amb2_clock");
static_assert(is_clock_castable<amb2_clock, tai_clock>::value, "amb2_clock -> tai_clock");
static_assert(is_clock_castable<tai_clock, amb2_clock>::value, "tai_clock -> amb2_clock");
static_assert(is_clock_castable<amb2_clock, tai_clock>::value, "amb2_clock -> tai_clock");
static_assert(is_clock_castable<gps_clock, amb2_clock>::value, "gps_clock -> amb2_clock");
//amb1 -> amb2: ambigous because can either go trough sys_clock or utc_clock
static_assert(!is_clock_castable<amb1_clock, amb2_clock>::value, "amb1_clock -> amb2_clock");
//amb2 -> amb1: disambiguated via trait specialization
static_assert(is_clock_castable<amb2_clock, amb1_clock>::value, "amb2_clock -> amb1_clock");
}

View File

@ -0,0 +1,102 @@
// The MIT License (MIT)
//
// Copyright (c) 2017 Tomasz Kamiński
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
#include "tz.h"
#include <cassert>
int
main()
{
using namespace date;
using sys_clock = std::chrono::system_clock;
// self
{
sys_days st(1997_y/dec/12);
auto ut = utc_clock::from_sys(st);
auto tt = tai_clock::from_utc(ut);
assert(clock_cast<sys_clock>(st) == st);
assert(clock_cast<utc_clock>(ut) == ut);
assert(clock_cast<tai_clock>(tt) == tt);
}
// sys <-> utc
{
sys_days st(1997_y/dec/12);
auto ut = utc_clock::from_sys(st);
assert(clock_cast<utc_clock>(st) == ut);
assert(clock_cast<sys_clock>(ut) == st);
}
// tai <-> utc
{
sys_days st(1997_y/dec/12);
auto ut = utc_clock::from_sys(st);
auto tt = tai_clock::from_utc(ut);
assert(clock_cast<tai_clock>(ut) == tt);
assert(clock_cast<utc_clock>(tt) == ut);
}
// tai <-> sys
{
sys_days st(1997_y/dec/12);
auto ut = utc_clock::from_sys(st);
auto tt = tai_clock::from_utc(ut);
assert(clock_cast<tai_clock>(st) == tt);
assert(clock_cast<sys_clock>(tt) == st);
}
// gps <-> utc
{
sys_days st(1997_y/dec/12);
auto ut = utc_clock::from_sys(st);
auto gt = gps_clock::from_utc(ut);
assert(clock_cast<gps_clock>(ut) == gt);
assert(clock_cast<utc_clock>(gt) == ut);
}
// gps <-> sys
{
sys_days st(1997_y/dec/12);
auto ut = utc_clock::from_sys(st);
auto gt = gps_clock::from_utc(ut);
assert(clock_cast<gps_clock>(st) == gt);
assert(clock_cast<sys_clock>(gt) == st);
}
// tai <-> gps
{
sys_days st(1997_y/dec/12);
auto ut = utc_clock::from_sys(st);
auto tt = tai_clock::from_utc(ut);
auto gt = gps_clock::from_utc(ut);
assert(clock_cast<gps_clock>(tt) == gt);
assert(clock_cast<tai_clock>(gt) == tt);
}
}

View File

@ -0,0 +1,49 @@
// The MIT License (MIT)
//
// Copyright (c) 2017 Tomasz Kamiński
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
#include "tz.h"
struct bad_clock
{
using duration = std::chrono::system_clock::duration;
using rep = duration::rep;
using period = duration::period;
using time_point = std::chrono::time_point<bad_clock, duration>;
template<typename Duration>
static
int
to_sys(std::chrono::time_point<bad_clock, Duration> const& tp)
{
return tp.time_since_epoch().count();
}
};
int
main()
{
using namespace date;
using sys_clock = std::chrono::system_clock;
auto bt = bad_clock::time_point();
clock_cast<sys_clock>(bt);
}

View File

@ -0,0 +1,51 @@
// The MIT License (MIT)
//
// Copyright (c) 2017 Tomasz Kamiński
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
#include "tz.h"
struct bad_clock
{
using duration = std::chrono::system_clock::duration;
using rep = duration::rep;
using period = duration::period;
using time_point = std::chrono::time_point<bad_clock, duration>;
template<typename Duration>
static
date::sys_time<Duration> const&
to_sys(std::chrono::time_point<bad_clock, Duration> const& tp)
{
static date::sys_time<Duration> val;
val = date::sys_time<Duration>(tp.time_since_epoch());
return val;
}
};
int
main()
{
using namespace date;
using sys_clock = std::chrono::system_clock;
auto bt = bad_clock::time_point();
clock_cast<sys_clock>(bt);
}

View File

@ -0,0 +1,49 @@
// The MIT License (MIT)
//
// Copyright (c) 2017, 2018 Tomasz Kamiński
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
#include "tz.h"
struct bad_clock
{
using duration = std::chrono::system_clock::duration;
using rep = duration::rep;
using period = duration::period;
using time_point = std::chrono::time_point<bad_clock, duration>;
template<typename Duration>
static
date::utc_time<Duration>
to_sys(std::chrono::time_point<bad_clock, Duration> const& tp)
{
return date::utc_time<Duration>(tp.time_since_epoch());
}
};
int
main()
{
using namespace date;
using sys_clock = std::chrono::system_clock;
auto bt = bad_clock::time_point();
clock_cast<sys_clock>(bt);
}

View File

@ -60,7 +60,7 @@
#include <type_traits>
static_assert( std::is_trivially_destructible<date::day>{}, "");
static_assert(!std::is_default_constructible<date::day>{}, "");
static_assert( std::is_default_constructible<date::day>{}, "");
static_assert( std::is_trivially_copy_constructible<date::day>{}, "");
static_assert( std::is_trivially_copy_assignable<date::day>{}, "");
static_assert( std::is_trivially_move_constructible<date::day>{}, "");

View File

@ -0,0 +1,141 @@
// The MIT License (MIT)
//
// Copyright (c) 2017 Howard Hinnant
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
// template <class Duration>
// class decimal_format_seconds
// {
// using CT = typename std::common_type<Duration, std::chrono::seconds>::type;
// using rep = typename CT::rep;
// public:
// static unsigned constexpr width = detail::width<CT::period::den>::value < 19 ?
// detail::width<CT::period::den>::value : 6u;
// using precision = std::chrono::duration<rep,
// std::ratio<1, static_pow10<width>::value>>;
// private:
// std::chrono::seconds s_;
// precision sub_s_;
//
// public:
// constexpr explicit decimal_format_seconds(const Duration& d) noexcept;
//
// constexpr std::chrono::seconds& seconds() noexcept;
// constexpr std::chrono::seconds seconds() const noexcept;
// constexpr precision subseconds() const noexcept;
// constexpr precision to_duration() const noexcept;
//
// template <class CharT, class Traits>
// friend
// std::basic_ostream<CharT, Traits>&
// operator<<(std::basic_ostream<CharT, Traits>& os, const decimal_format_seconds& x);
// };
#include "date.h"
#include <cassert>
#include <sstream>
#include <type_traits>
using fortnights = std::chrono::duration<date::weeks::rep,
date::detail::ratio_multiply<std::ratio<2>,
date::weeks::period>>;
using microfortnights = std::chrono::duration<std::int64_t,
date::detail::ratio_multiply<fortnights::period,
std::micro>>;
int
main()
{
using namespace date::detail;
using namespace std;
using namespace std::chrono;
{
using D = decimal_format_seconds<minutes>;
static_assert(is_same<D::precision, seconds>{}, "");
static_assert(D::width == 0, "");
D dfs{minutes{3}};
assert(dfs.seconds() == seconds{180});
assert(dfs.to_duration() == seconds{180});
ostringstream out;
out << dfs;
assert(out.str() == "180");
}
{
using D = decimal_format_seconds<seconds>;
static_assert(is_same<D::precision, seconds>{}, "");
static_assert(D::width == 0, "");
D dfs{seconds{3}};
assert(dfs.seconds() == seconds{3});
assert(dfs.to_duration() == seconds{3});
ostringstream out;
out << dfs;
assert(out.str() == "03");
}
{
using D = decimal_format_seconds<milliseconds>;
static_assert(D::width == 3, "");
D dfs{seconds{3}};
assert(dfs.seconds() == seconds{3});
assert(dfs.to_duration() == seconds{3});
assert(dfs.subseconds() == milliseconds{0});
ostringstream out;
out << dfs;
assert(out.str() == "03.000");
}
{
using D = decimal_format_seconds<milliseconds>;
static_assert(D::width == 3, "");
D dfs{milliseconds{3}};
assert(dfs.seconds() == seconds{0});
assert(dfs.to_duration() == milliseconds{3});
assert(dfs.subseconds() == milliseconds{3});
ostringstream out;
out << dfs;
assert(out.str() == "00.003");
}
{
using D = decimal_format_seconds<microfortnights>;
static_assert(D::width == 4, "");
D dfs{microfortnights{3}};
using S = D::precision;
assert(dfs.seconds() == seconds{3});
assert(dfs.to_duration() == S{36288});
assert(dfs.subseconds() == S{6288});
ostringstream out;
out << dfs;
assert(out.str() == "03.6288");
}
{
using CT = common_type<seconds, microfortnights>::type;
using D = decimal_format_seconds<CT>;
static_assert(D::width == 4, "");
D dfs{microfortnights{3}};
using S = D::precision;
assert(dfs.seconds() == seconds{3});
assert(dfs.to_duration() == S{36288});
assert(dfs.subseconds() == S{6288});
ostringstream out;
out << dfs;
assert(out.str() == "03.6288");
}
}

View File

@ -0,0 +1,50 @@
// The MIT License (MIT)
//
// Copyright (c) 2017 Howard Hinnant
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
// template <unsigned exp>
// struct static_pow10
// {
// static constepxr std::uint64_t value = ...;
// };
#include "date.h"
#include <cassert>
#include <sstream>
#include <type_traits>
int
main()
{
using namespace date::detail;
static_assert(static_pow10<0>::value == 1, "");
static_assert(static_pow10<1>::value == 10, "");
static_assert(static_pow10<2>::value == 100, "");
static_assert(static_pow10<3>::value == 1000, "");
static_assert(static_pow10<4>::value == 10000, "");
static_assert(static_pow10<5>::value == 100000, "");
static_assert(static_pow10<6>::value == 1000000, "");
static_assert(static_pow10<7>::value == 10000000, "");
static_assert(static_pow10<8>::value == 100000000, "");
static_assert(static_pow10<9>::value == 1000000000, "");
static_assert(static_pow10<10>::value == 10000000000, "");
}

View File

@ -0,0 +1,64 @@
// The MIT License (MIT)
//
// Copyright (c) 2017 Howard Hinnant
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
// width<n>::value is the number of fractional decimal digits in 1/n
// width<0>::value and width<1>::value are defined to be 0
// If 1/n takes more than 18 fractional decimal digits,
// the result is truncated to 19.
// Example: width<2>::value == 1
// Example: width<3>::value == 19
// Example: width<4>::value == 2
// Example: width<10>::value == 1
// Example: width<1000>::value == 3
// template <std::uint64_t n>
//
// struct width
// {
// static constexpr unsigned value = ...;
// };
#include "date.h"
#include <cassert>
#include <sstream>
#include <type_traits>
int
main()
{
using namespace date::detail;
static_assert(width<0, 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, "");
}

View File

@ -0,0 +1,328 @@
// The MIT License (MIT)
//
// Copyright (c) 2018 Tomasz Kamiński
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
#include "date.h"
#include <cassert>
#include <sstream>
void test_SI()
{
using namespace std::chrono;
using namespace date;
std::ostringstream os;
// atto
{
duration<int, std::atto> d(13);
os << d;
assert(os.str() == "13as");
os.str("");
}
// femto
{
duration<int, std::femto> d(13);
os << d;
assert(os.str() == "13fs");
os.str("");
}
// pico
{
duration<int, std::pico> d(13);
os << d;
assert(os.str() == "13ps");
os.str("");
}
// nano
{
duration<int, std::nano> d(13);
os << d;
assert(os.str() == "13ns");
os.str("");
}
// mikro
{
duration<int, std::micro> d(13);
os << d;
assert(os.str() == "13\xC2\xB5s");
os.str("");
}
// milli
{
duration<int, std::milli> d(13);
os << d;
assert(os.str() == "13ms");
os.str("");
}
// centi
{
duration<int, std::centi> d(13);
os << d;
assert(os.str() == "13cs");
os.str("");
}
// deci
{
duration<int, std::deci> d(13);
os << d;
assert(os.str() == "13ds");
os.str("");
}
// seconds
{
duration<int> d(13);
os << d;
assert(os.str() == "13s");
os.str("");
}
// deca
{
duration<int, std::deca> d(13);
os << d;
assert(os.str() == "13das");
os.str("");
}
// hecto
{
duration<int, std::hecto> d(13);
os << d;
assert(os.str() == "13hs");
os.str("");
}
// kilo
{
duration<int, std::kilo> d(13);
os << d;
assert(os.str() == "13ks");
os.str("");
}
// mega
{
duration<int, std::mega> d(13);
os << d;
assert(os.str() == "13Ms");
os.str("");
}
// giga
{
duration<int, std::giga> d(13);
os << d;
assert(os.str() == "13Gs");
os.str("");
}
// tera
{
duration<int, std::tera> d(13);
os << d;
assert(os.str() == "13Ts");
os.str("");
}
// peta
{
duration<int, std::peta> d(13);
os << d;
assert(os.str() == "13Ps");
os.str("");
}
// femto
{
duration<int, std::exa> d(13);
os << d;
assert(os.str() == "13Es");
os.str("");
}
}
void test_calendar()
{
using namespace std::chrono;
using namespace date;
std::ostringstream os;
// minutes
{
minutes d(13);
os << d;
assert(os.str() == "13min");
os.str("");
}
// hours
{
hours d(13);
os << d;
assert(os.str() == "13h");
os.str("");
}
// days
{
days d(13);
os << d;
assert(os.str() == "13d");
os.str("");
}
}
void test_integral_scale()
{
using namespace std::chrono;
using namespace date;
std::ostringstream os;
// ratio 123 / 1
{
duration<int, std::ratio<123, 1>> d(13);
os << d;
assert(os.str() == "13[123]s");
os.str("");
}
// ratio 100 / 4 = ratio 25 / 1
{
duration<int, std::ratio<25, 1>> d(13);
os << d;
assert(os.str() == "13[25]s");
os.str("");
}
// weeks = ratio 7 * 24 * 60 * 60 / 1 = ratio 604800 / 1
{
weeks d(13);
os << d;
assert(os.str() == "13[604800]s");
os.str("");
}
// years = 146097/400 days = ratio 146097/400 * 24 * 60 * 60 = ratio 31556952 / 1
{
years d(13);
os << d;
assert(os.str() == "13[31556952]s");
os.str("");
}
// months = 1/12 years = ratio 1/12 * 31556952 = ratio 2629746 / 1
{
months d(13);
os << d;
assert(os.str() == "13[2629746]s");
os.str("");
}
}
void test_ratio_scale()
{
using namespace std::chrono;
using namespace date;
std::ostringstream os;
// ratio 1 / 2
{
duration<int, std::ratio<1, 2>> d(13);
os << d;
assert(os.str() == "13[1/2]s");
os.str("");
}
// ratio 100 / 3
{
duration<int, std::ratio<100, 3>> d(13);
os << d;
assert(os.str() == "13[100/3]s");
os.str("");
}
// ratio 100 / 6 = ratio 50 / 3
{
duration<int, std::ratio<100, 6>> d(13);
os << d;
assert(os.str() == "13[50/3]s");
os.str("");
}
}
void test_constexpr()
{
using date::detail::get_units;
CONSTCD11 auto as = get_units<char>(std::atto{});
CONSTCD11 auto fs = get_units<char>(std::femto{});
CONSTCD11 auto ps = get_units<char>(std::pico{});
CONSTCD11 auto ns = get_units<char>(std::nano{});
CONSTCD11 auto us = get_units<char>(std::micro{});
CONSTCD11 auto usw = get_units<wchar_t>(std::micro{});
CONSTCD11 auto ms = get_units<char>(std::milli{});
CONSTCD11 auto cs = get_units<char>(std::centi{});
CONSTCD11 auto ds = get_units<char>(std::deci{});
CONSTCD11 auto s = get_units<char>(std::ratio<1>{});
CONSTCD11 auto das = get_units<char>(std::deca{});
CONSTCD11 auto hs = get_units<char>(std::hecto{});
CONSTCD11 auto ks = get_units<char>(std::kilo{});
CONSTCD11 auto Ms = get_units<char>(std::mega{});
CONSTCD11 auto Gs = get_units<char>(std::giga{});
CONSTCD11 auto Ts = get_units<char>(std::tera{});
CONSTCD11 auto Ps = get_units<char>(std::peta{});
CONSTCD11 auto Es = get_units<char>(std::exa{});
(void)as, (void)fs, (void)ps, (void)ns, (void)usw, (void)us,
(void)ms, (void)cs, (void)ds, (void)s, (void)das, (void)hs,
(void)ks, (void)Ms, (void)Gs, (void)Ts, (void)Ps, (void)Es;
CONSTCD11 auto min = get_units<char>(std::ratio<60>{});
CONSTCD11 auto h = get_units<char>(std::ratio<3600>{});
CONSTCD11 auto d = get_units<char>(std::ratio<86400>{});
(void)min, (void)h, (void)d;
CONSTCD14 auto integer = get_units<char>(std::ratio<123>{});
CONSTCD14 auto ratio = get_units<char>(std::ratio<123, 3>{});
(void)integer, (void)ratio;
}
int
main()
{
test_SI();
test_calendar();
test_integral_scale();
test_ratio_scale();
}

View File

@ -0,0 +1,117 @@
// The MIT License (MIT)
//
// Copyright (c) 2016 Howard Hinnant
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
#include "date.h"
#include <cassert>
#include <sstream>
#include <type_traits>
int
main()
{
using namespace date;
using namespace std::chrono;
std::ostringstream os;
os << format("%C", sys_days{jun/1/20001});
assert(os.str() == "200");
os.str("");
os << format("%C", sys_days{jun/1/20000});
assert(os.str() == "200");
os.str("");
os << format("%C", sys_days{jun/1/19999});
assert(os.str() == "199");
os.str("");
os << format("%C", sys_days{jun/1/2001});
assert(os.str() == "20");
os.str("");
os << format("%C", sys_days{jun/1/2000});
assert(os.str() == "20");
os.str("");
os << format("%C", sys_days{jun/1/1999});
assert(os.str() == "19");
os.str("");
os << format("%C", sys_days{jun/1/101});
assert(os.str() == "01");
os.str("");
os << format("%C", sys_days{jun/1/100});
assert(os.str() == "01");
os.str("");
os << format("%C", sys_days{jun/1/99});
assert(os.str() == "00");
os.str("");
os << format("%C", sys_days{jun/1/1});
assert(os.str() == "00");
os.str("");
os << format("%C", sys_days{jun/1/0});
assert(os.str() == "00");
os.str("");
os << format("%C", sys_days{jun/1/-1});
assert(os.str() == "-01");
os.str("");
os << format("%C", sys_days{jun/1/-99});
assert(os.str() == "-01");
os.str("");
os << format("%C", sys_days{jun/1/-100});
assert(os.str() == "-01");
os.str("");
os << format("%C", sys_days{jun/1/-101});
assert(os.str() == "-02");
os.str("");
os << format("%C", sys_days{jun/1/-1999});
assert(os.str() == "-20");
os.str("");
os << format("%C", sys_days{jun/1/-2000});
assert(os.str() == "-20");
os.str("");
os << format("%C", sys_days{jun/1/-2001});
assert(os.str() == "-21");
os.str("");
os << format("%C", sys_days{jun/1/-19999});
assert(os.str() == "-200");
os.str("");
os << format("%C", sys_days{jun/1/-20000});
assert(os.str() == "-200");
os.str("");
os << format("%C", sys_days{jun/1/-20001});
assert(os.str() == "-201");
}

View File

@ -0,0 +1,52 @@
// The MIT License (MIT)
//
// Copyright (c) 2016 Howard Hinnant
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
#include "date.h"
#include <cassert>
#include <sstream>
template <class T>
void
test(const std::string& in_fmt, const std::string& input,
const std::string& out_fmt, const std::string& output)
{
using namespace date;
std::istringstream in{input};
T t;
in >> parse(in_fmt, t);
assert(!in.fail());
auto s = format(out_fmt, t);
assert(s == output);
}
int
main()
{
using namespace date;
test<year>("%Y", "2017", "%Y", "2017");
test<month>("%m", "3", "%m", "03");
test<day>("%d", "25", "%d", "25");
test<year_month>("%Y-%m", "2017-03", "%Y-%m", "2017-03");
test<year_month>("%y%m", "1703", "%Y-%m", "2017-03");
test<month_day>("%m/%d", "3/25", "%m/%d", "03/25");
test<weekday>("%w", "3", "%w", "3");
}

View File

@ -0,0 +1,78 @@
// The MIT License (MIT)
//
// Copyright (c) 2016 Howard Hinnant
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
#include "date.h"
#include <cassert>
#include <sstream>
#include <type_traits>
using fortnights = std::chrono::duration<date::weeks::rep,
date::detail::ratio_multiply<std::ratio<2>,
date::weeks::period>>;
using microfortnights = std::chrono::duration<std::int64_t,
date::detail::ratio_multiply<fortnights::period,
std::micro>>;
int
main()
{
using namespace date;
using namespace std::chrono;
std::ostringstream os;
os << 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()});
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} +
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()});
assert(os.str() == "-32767-01-01 00:00:00");
os.str("");
os << format("%Y-%m-%d %H:%M:%S", sys_days{dec/last/year::max()});
assert(os.str() == "32767-12-31 00:00:00");
os.str("");
os << 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});
assert(os.str() == "-32767-01-01 00:00:01.2096");
os.str("");
os << format("%F %T", sys_days{dec/last/year::max()} + microfortnights{1});
assert(os.str() == "32767-12-31 00:00:01.2096");
os.str("");
os << format("%F", jan/1/year::min());
assert(os.str() == "-32767-01-01");
os.str("");
os << format("%F", dec/last/year::max());
assert(os.str() == "32767-12-31");
os.str("");
}

View File

@ -0,0 +1,121 @@
// The MIT License (MIT)
//
// Copyright (c) 2016 Howard Hinnant
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
#include "date.h"
#include <cassert>
#include <sstream>
#include <type_traits>
int
main()
{
using namespace date;
using namespace std::chrono;
std::ostringstream os;
os << format("%y", sys_days{jun/1/20001});
assert(os.str() == "01");
os.str("");
os << format("%y", sys_days{jun/1/20000});
assert(os.str() == "00");
os.str("");
os << format("%y", sys_days{jun/1/19999});
assert(os.str() == "99");
os.str("");
os << format("%y", sys_days{jun/1/2001});
assert(os.str() == "01");
os.str("");
os << format("%y", sys_days{jun/1/2000});
assert(os.str() == "00");
os.str("");
os << format("%y", sys_days{jun/1/1999});
assert(os.str() == "99");
os.str("");
os << format("%y", sys_days{jun/1/101});
assert(os.str() == "01");
os.str("");
os << format("%y", sys_days{jun/1/100});
assert(os.str() == "00");
os.str("");
os << format("%y", sys_days{jun/1/99});
assert(os.str() == "99");
os.str("");
os << format("%y", sys_days{jun/1/1});
assert(os.str() == "01");
os.str("");
os << format("%y", sys_days{jun/1/0});
assert(os.str() == "00");
os.str("");
os << format("%y", sys_days{jun/1/-1});
assert(os.str() == "01");
os.str("");
os << format("%y", sys_days{jun/1/-99});
assert(os.str() == "99");
os.str("");
os << format("%y", sys_days{jun/1/-100});
assert(os.str() == "00");
os.str("");
os << format("%y", sys_days{jun/1/-101});
assert(os.str() == "01");
os.str("");
os << format("%y", sys_days{jun/1/-1999});
assert(os.str() == "99");
os.str("");
os << format("%y", sys_days{jun/1/-2000});
assert(os.str() == "00");
os.str("");
os << format("%y", sys_days{jun/1/-2001});
assert(os.str() == "01");
os.str("");
os << format("%y", sys_days{jun/1/-19999});
assert(os.str() == "99");
os.str("");
os << format("%y", sys_days{jun/1/-20000});
assert(os.str() == "00");
os.str("");
os << format("%y", sys_days{jun/1/-20001});
assert(os.str() == "01");
os.str("");
os << format("%y", sys_days{jun/1/year::min()});
assert(os.str() == "67");
}

View File

@ -27,27 +27,6 @@
// time_of_day<std::chrono::duration<Rep, Period>>
// make_time(std::chrono::duration<Rep, Period> d) noexcept;
// constexpr
// time_of_day<std::chrono::hours>
// make_time(std::chrono::hours h, unsigned md) noexcept;
// constexpr
// time_of_day<std::chrono::minutes>
// make_time(std::chrono::hours h, std::chrono::minutes m, unsigned md) noexcept;
// constexpr
// time_of_day<std::chrono::seconds>
// make_time(std::chrono::hours h, std::chrono::minutes m, std::chrono::seconds s,
// unsigned md) noexcept;
// template <class Rep, class Period,
// class = typename std::enable_if<std::ratio_less<Period,
// std::ratio<1>>::value>::type>
// constexpr
// time_of_day<std::chrono::duration<Rep, Period>>
// make_time(std::chrono::hours h, std::chrono::minutes m, std::chrono::seconds s,
// std::chrono::duration<Rep, Period> sub_s, unsigned md) noexcept;
#include "date.h"
#include <cassert>
@ -68,7 +47,6 @@ main()
assert(tod.minutes() == minutes{7});
assert(tod.seconds() == seconds{9});
assert(tod.subseconds() == nanoseconds{22});
assert(tod.mode() == 0);
}
{
static_assert(is_same<decltype(make_time(microseconds{18429000022})),
@ -78,7 +56,6 @@ main()
assert(tod.minutes() == minutes{7});
assert(tod.seconds() == seconds{9});
assert(tod.subseconds() == microseconds{22});
assert(tod.mode() == 0);
}
{
static_assert(is_same<decltype(make_time(seconds{18429})),
@ -87,7 +64,6 @@ main()
assert(tod.hours() == hours{5});
assert(tod.minutes() == minutes{7});
assert(tod.seconds() == seconds{9});
assert(tod.mode() == 0);
}
{
static_assert(is_same<decltype(make_time(minutes{307})),
@ -95,70 +71,11 @@ main()
auto tod = make_time(minutes{307});
assert(tod.hours() == hours{5});
assert(tod.minutes() == minutes{7});
assert(tod.mode() == 0);
}
{
static_assert(is_same<decltype(make_time(hours{5})),
time_of_day<hours>>{}, "");
auto tod = make_time(hours{5});
assert(tod.hours() == hours{5});
assert(tod.mode() == 0);
}
{
static_assert(is_same<decltype(make_time(hours{5}, minutes{7}, seconds{9},
nanoseconds{22}, pm)),
time_of_day<nanoseconds>>{}, "");
auto tod = make_time(hours{5}, minutes{7}, seconds{9}, nanoseconds{22}, pm);
assert(tod.hours() == hours{5});
assert(tod.minutes() == minutes{7});
assert(tod.seconds() == seconds{9});
assert(tod.subseconds() == nanoseconds{22});
assert(tod.mode() == pm);
}
{
static_assert(is_same<decltype(make_time(hours{5}, minutes{7}, seconds{9},
microseconds{22}, 0)),
time_of_day<microseconds>>{}, "");
auto tod = make_time(hours{5}, minutes{7}, seconds{9}, microseconds{22}, 0);
assert(tod.hours() == hours{5});
assert(tod.minutes() == minutes{7});
assert(tod.seconds() == seconds{9});
assert(tod.subseconds() == microseconds{22});
assert(tod.mode() == 0);
}
{
static_assert(is_same<decltype(make_time(hours{5}, minutes{7}, seconds{9},
milliseconds{22}, am)),
time_of_day<milliseconds>>{}, "");
auto tod = make_time(hours{5}, minutes{7}, seconds{9}, milliseconds{22}, am);
assert(tod.hours() == hours{5});
assert(tod.minutes() == minutes{7});
assert(tod.seconds() == seconds{9});
assert(tod.subseconds() == milliseconds{22});
assert(tod.mode() == am);
}
{
static_assert(is_same<decltype(make_time(hours{5}, minutes{7}, seconds{9}, am)),
time_of_day<seconds>>{}, "");
auto tod = make_time(hours{5}, minutes{7}, seconds{9}, am);
assert(tod.hours() == hours{5});
assert(tod.minutes() == minutes{7});
assert(tod.seconds() == seconds{9});
assert(tod.mode() == am);
}
{
static_assert(is_same<decltype(make_time(hours{5}, minutes{7}, pm)),
time_of_day<minutes>>{}, "");
auto tod = make_time(hours{5}, minutes{7}, pm);
assert(tod.hours() == hours{5});
assert(tod.minutes() == minutes{7});
assert(tod.mode() == pm);
}
{
static_assert(is_same<decltype(make_time(hours{5}, 0)),
time_of_day<hours>>{}, "");
auto tod = make_time(hours{5}, 0);
assert(tod.hours() == hours{5});
assert(tod.mode() == 0);
}
}

View File

@ -72,7 +72,7 @@
#include <type_traits>
static_assert( std::is_trivially_destructible<date::month>{}, "");
static_assert(!std::is_default_constructible<date::month>{}, "");
static_assert( std::is_default_constructible<date::month>{}, "");
static_assert( std::is_trivially_copy_constructible<date::month>{}, "");
static_assert( std::is_trivially_copy_assignable<date::month>{}, "");
static_assert( std::is_trivially_move_constructible<date::month>{}, "");

View File

@ -47,7 +47,7 @@
#include <type_traits>
static_assert( std::is_trivially_destructible<date::month_day>{}, "");
static_assert(!std::is_default_constructible<date::month_day>{}, "");
static_assert( std::is_default_constructible<date::month_day>{}, "");
static_assert( std::is_trivially_copy_constructible<date::month_day>{}, "");
static_assert( std::is_trivially_copy_assignable<date::month_day>{}, "");
static_assert( std::is_trivially_move_constructible<date::month_day>{}, "");

View File

@ -0,0 +1,487 @@
// The MIT License (MIT)
//
// Copyright (c) 2018 Tomasz Kamiński
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
#include "date.h"
#include <chrono>
#include <cassert>
#include <type_traits>
#define CPP11_ASSERT(...) static_assert(__VA_ARGS__, "")
#if __cplusplus >= 201402
// C++14
# define CPP14_ASSERT(...) static_assert(__VA_ARGS__, "")
#else
// C++11
# define CPP14_ASSERT(...) assert(__VA_ARGS__)
#endif
#define NOEXCEPT_ASSERT(...) static_assert(noexcept(__VA_ARGS__), "")
//Invocation involves a conversion between duration that is currently
//not marked as noexcept.
#define NOEXCEPT_CONVERSION(...)
template<typename T>
constexpr T copy(T const& t) noexcept { return t; }
struct ConvertibleToYears
{
CONSTCD11 operator date::years() const NOEXCEPT
{ return date::years{1}; };
};
struct ConvertibleToMonths
{
CONSTCD11 operator date::months() const NOEXCEPT
{ return date::months{1}; };
};
struct ConvertibleToYearsAndMonths
{
CONSTCD11 operator date::years() const NOEXCEPT
{ return date::years{1}; };
CONSTCD11 operator date::months() const NOEXCEPT
{ return date::months{1}; };
};
int
main()
{
using namespace date;
using namespace std::chrono;
using decades = duration<int, date::detail::ratio_multiply<std::ratio<10>, years::period>>;
using decamonths = duration<int, date::detail::ratio_multiply<std::ratio<10>, months::period>>;
constexpr months one_month{1};
constexpr years one_year{1};
constexpr decades one_decade{1};
constexpr decamonths one_decamonth{1};
constexpr ConvertibleToMonths custom_month;
constexpr ConvertibleToYears custom_year;
constexpr ConvertibleToYearsAndMonths prefer_year;
{
constexpr year_month ym = 2001_y/feb;
CPP14_ASSERT(ym + one_month == 2001_y/mar);
NOEXCEPT_ASSERT(ym + one_month);
CPP14_ASSERT(one_month + ym == 2001_y/mar);
NOEXCEPT_ASSERT(one_month + ym);
CPP14_ASSERT(ym - one_month == 2001_y/jan);
NOEXCEPT_ASSERT(ym - one_month);
CPP14_ASSERT((copy(ym) += one_month) == 2001_y/mar);
NOEXCEPT_ASSERT(copy(ym) += one_month);
CPP14_ASSERT((copy(ym) -= one_month) == 2001_y/jan);
NOEXCEPT_ASSERT(copy(ym) -= one_month);
CPP11_ASSERT(ym + one_year == 2002_y/feb);
NOEXCEPT_ASSERT(ym + one_year);
CPP11_ASSERT(one_year + ym == 2002_y/feb);
NOEXCEPT_ASSERT(one_year + ym);
CPP11_ASSERT(ym - one_year == 2000_y/feb);
NOEXCEPT_ASSERT(ym - one_year);
CPP14_ASSERT((copy(ym) += one_year) == 2002_y/feb);
NOEXCEPT_ASSERT(copy(ym) += one_year);
CPP14_ASSERT((copy(ym) -= one_year) == 2000_y/feb);
NOEXCEPT_ASSERT(copy(ym) -= one_year);
CPP11_ASSERT(ym + one_decade == 2011_y/feb);
NOEXCEPT_CONVERSION(ym + one_decade);
CPP11_ASSERT(one_decade + ym == 2011_y/feb);
NOEXCEPT_CONVERSION(one_decade + ym);
CPP11_ASSERT(ym - one_decade == 1991_y/feb);
NOEXCEPT_CONVERSION(ym - one_decade);
CPP14_ASSERT((copy(ym) += one_decade) == 2011_y/feb);
NOEXCEPT_CONVERSION(copy(ym) += one_decade);
CPP14_ASSERT((copy(ym) -= one_decade) == 1991_y/feb);
NOEXCEPT_CONVERSION(copy(ym) -= one_decade);
CPP14_ASSERT(ym + one_decamonth == 2001_y/dec);
NOEXCEPT_CONVERSION(ym + one_decamonth);
CPP14_ASSERT(one_decamonth + ym == 2001_y/dec);
NOEXCEPT_CONVERSION(one_decamonth + ym);
CPP14_ASSERT(ym - one_decamonth == 2000_y/apr);
NOEXCEPT_CONVERSION(ym - one_decamonth);
CPP14_ASSERT((copy(ym) += one_decamonth) == 2001_y/dec);
NOEXCEPT_CONVERSION(copy(ym) += one_decamonth);
CPP14_ASSERT((copy(ym) -= one_decamonth) == 2000_y/apr);
NOEXCEPT_CONVERSION(copy(ym) -= one_decamonth);
CPP14_ASSERT(ym + custom_month == 2001_y/mar);
NOEXCEPT_ASSERT(ym + custom_month);
CPP14_ASSERT(custom_month + ym == 2001_y/mar);
NOEXCEPT_ASSERT(custom_month + ym);
CPP14_ASSERT(ym - custom_month == 2001_y/jan);
NOEXCEPT_ASSERT(ym - custom_month);
CPP14_ASSERT((copy(ym) += custom_month) == 2001_y/mar);
NOEXCEPT_ASSERT(copy(ym) += custom_month);
CPP14_ASSERT((copy(ym) -= custom_month) == 2001_y/jan);
NOEXCEPT_ASSERT(copy(ym) -= custom_month);
CPP11_ASSERT(ym + custom_year == 2002_y/feb);
NOEXCEPT_ASSERT(ym + custom_year);
CPP11_ASSERT(custom_year + ym == 2002_y/feb);
NOEXCEPT_ASSERT(custom_year + ym);
CPP11_ASSERT(ym - custom_year == 2000_y/feb);
NOEXCEPT_ASSERT(ym - custom_year);
CPP14_ASSERT((copy(ym) += custom_year) == 2002_y/feb);
NOEXCEPT_ASSERT(copy(ym) += custom_year);
CPP14_ASSERT((copy(ym) -= custom_year) == 2000_y/feb);
NOEXCEPT_ASSERT(copy(ym) -= custom_year);
CPP11_ASSERT(ym + prefer_year == 2002_y/feb);
NOEXCEPT_ASSERT(ym + prefer_year);
CPP11_ASSERT(prefer_year + ym == 2002_y/feb);
NOEXCEPT_ASSERT(prefer_year + ym);
CPP11_ASSERT(ym - prefer_year == 2000_y/feb);
NOEXCEPT_ASSERT(ym - prefer_year);
CPP14_ASSERT((copy(ym) += prefer_year) == 2002_y/feb);
NOEXCEPT_ASSERT(copy(ym) += prefer_year);
CPP14_ASSERT((copy(ym) -= prefer_year) == 2000_y/feb);
NOEXCEPT_ASSERT(copy(ym) -= prefer_year);
}
{
constexpr year_month_day ym = 2001_y/feb/10;
CPP14_ASSERT(ym + one_month == 2001_y/mar/10);
NOEXCEPT_ASSERT(ym + one_month);
CPP14_ASSERT(one_month + ym == 2001_y/mar/10);
NOEXCEPT_ASSERT(one_month + ym);
CPP14_ASSERT(ym - one_month == 2001_y/jan/10);
NOEXCEPT_ASSERT(ym - one_month);
CPP14_ASSERT((copy(ym) += one_month) == 2001_y/mar/10);
NOEXCEPT_ASSERT(copy(ym) += one_month);
CPP14_ASSERT((copy(ym) -= one_month) == 2001_y/jan/10);
NOEXCEPT_ASSERT(copy(ym) -= one_month);
CPP11_ASSERT(ym + one_year == 2002_y/feb/10);
NOEXCEPT_ASSERT(ym + one_year);
CPP11_ASSERT(one_year + ym == 2002_y/feb/10);
NOEXCEPT_ASSERT(one_year + ym);
CPP11_ASSERT(ym - one_year == 2000_y/feb/10);
NOEXCEPT_ASSERT(ym - one_year);
CPP14_ASSERT((copy(ym) += one_year) == 2002_y/feb/10);
NOEXCEPT_ASSERT(copy(ym) += one_year);
CPP14_ASSERT((copy(ym) -= one_year) == 2000_y/feb/10);
NOEXCEPT_ASSERT(copy(ym) -= one_year);
CPP11_ASSERT(ym + one_decade == 2011_y/feb/10);
NOEXCEPT_CONVERSION(ym + one_decade);
CPP11_ASSERT(one_decade + ym == 2011_y/feb/10);
NOEXCEPT_CONVERSION(one_decade + ym);
CPP11_ASSERT(ym - one_decade == 1991_y/feb/10);
NOEXCEPT_CONVERSION(ym - one_decade);
CPP14_ASSERT((copy(ym) += one_decade) == 2011_y/feb/10);
NOEXCEPT_CONVERSION(copy(ym) += one_decade);
CPP14_ASSERT((copy(ym) -= one_decade) == 1991_y/feb/10);
NOEXCEPT_CONVERSION(copy(ym) -= one_decade);
CPP14_ASSERT(ym + one_decamonth == 2001_y/dec/10);
NOEXCEPT_CONVERSION(ym + one_decamonth);
CPP14_ASSERT(one_decamonth + ym == 2001_y/dec/10);
NOEXCEPT_CONVERSION(one_decamonth + ym);
CPP14_ASSERT(ym - one_decamonth == 2000_y/apr/10);
NOEXCEPT_CONVERSION(ym - one_decamonth);
CPP14_ASSERT((copy(ym) += one_decamonth) == 2001_y/dec/10);
NOEXCEPT_CONVERSION(copy(ym) += one_decamonth);
CPP14_ASSERT((copy(ym) -= one_decamonth) == 2000_y/apr/10);
NOEXCEPT_CONVERSION(copy(ym) -= one_decamonth);
CPP14_ASSERT(ym + custom_month == 2001_y/mar/10);
NOEXCEPT_ASSERT(ym + custom_month);
CPP14_ASSERT(custom_month + ym == 2001_y/mar/10);
NOEXCEPT_ASSERT(custom_month + ym);
CPP14_ASSERT(ym - custom_month == 2001_y/jan/10);
NOEXCEPT_ASSERT(ym - custom_month);
CPP14_ASSERT((copy(ym) += custom_month) == 2001_y/mar/10);
NOEXCEPT_ASSERT(copy(ym) += custom_month);
CPP14_ASSERT((copy(ym) -= custom_month) == 2001_y/jan/10);
NOEXCEPT_ASSERT(copy(ym) -= custom_month);
CPP11_ASSERT(ym + custom_year == 2002_y/feb/10);
NOEXCEPT_ASSERT(ym + custom_year);
CPP11_ASSERT(custom_year + ym == 2002_y/feb/10);
NOEXCEPT_ASSERT(custom_year + ym);
CPP11_ASSERT(ym - custom_year == 2000_y/feb/10);
NOEXCEPT_ASSERT(ym - custom_year);
CPP14_ASSERT((copy(ym) += custom_year) == 2002_y/feb/10);
NOEXCEPT_ASSERT(copy(ym) += custom_year);
CPP14_ASSERT((copy(ym) -= custom_year) == 2000_y/feb/10);
NOEXCEPT_ASSERT(copy(ym) -= custom_year);
CPP11_ASSERT(ym + prefer_year == 2002_y/feb/10);
NOEXCEPT_ASSERT(ym + prefer_year);
CPP11_ASSERT(prefer_year + ym == 2002_y/feb/10);
NOEXCEPT_ASSERT(prefer_year + ym);
CPP11_ASSERT(ym - prefer_year == 2000_y/feb/10);
NOEXCEPT_ASSERT(ym - prefer_year);
CPP14_ASSERT((copy(ym) += prefer_year) == 2002_y/feb/10);
NOEXCEPT_ASSERT(copy(ym) += prefer_year);
CPP14_ASSERT((copy(ym) -= prefer_year) == 2000_y/feb/10);
NOEXCEPT_ASSERT(copy(ym) -= prefer_year);
}
{
constexpr year_month_day_last ym = 2001_y/feb/last;
CPP14_ASSERT(ym + one_month == 2001_y/mar/last);
NOEXCEPT_ASSERT(ym + one_month);
CPP14_ASSERT(one_month + ym == 2001_y/mar/last);
NOEXCEPT_ASSERT(one_month + ym);
CPP14_ASSERT(ym - one_month == 2001_y/jan/last);
NOEXCEPT_ASSERT(ym - one_month);
CPP14_ASSERT((copy(ym) += one_month) == 2001_y/mar/last);
NOEXCEPT_ASSERT(copy(ym) += one_month);
CPP14_ASSERT((copy(ym) -= one_month) == 2001_y/jan/last);
NOEXCEPT_ASSERT(copy(ym) -= one_month);
CPP11_ASSERT(ym + one_year == 2002_y/feb/last);
NOEXCEPT_ASSERT(ym + one_year);
CPP11_ASSERT(one_year + ym == 2002_y/feb/last);
NOEXCEPT_ASSERT(one_year + ym);
CPP11_ASSERT(ym - one_year == 2000_y/feb/last);
NOEXCEPT_ASSERT(ym - one_year);
CPP14_ASSERT((copy(ym) += one_year) == 2002_y/feb/last);
NOEXCEPT_ASSERT(copy(ym) += one_year);
CPP14_ASSERT((copy(ym) -= one_year) == 2000_y/feb/last);
NOEXCEPT_ASSERT(copy(ym) -= one_year);
CPP11_ASSERT(ym + one_decade == 2011_y/feb/last);
NOEXCEPT_CONVERSION(ym + one_decade);
CPP11_ASSERT(one_decade + ym == 2011_y/feb/last);
NOEXCEPT_CONVERSION(one_decade + ym);
CPP11_ASSERT(ym - one_decade == 1991_y/feb/last);
NOEXCEPT_CONVERSION(ym - one_decade);
CPP14_ASSERT((copy(ym) += one_decade) == 2011_y/feb/last);
NOEXCEPT_CONVERSION(copy(ym) += one_decade);
CPP14_ASSERT((copy(ym) -= one_decade) == 1991_y/feb/last);
NOEXCEPT_CONVERSION(copy(ym) -= one_decade);
CPP14_ASSERT(ym + one_decamonth == 2001_y/dec/last);
NOEXCEPT_CONVERSION(ym + one_decamonth);
CPP14_ASSERT(one_decamonth + ym == 2001_y/dec/last);
NOEXCEPT_CONVERSION(one_decamonth + ym);
CPP14_ASSERT(ym - one_decamonth == 2000_y/apr/last);
NOEXCEPT_CONVERSION(ym - one_decamonth);
CPP14_ASSERT((copy(ym) += one_decamonth) == 2001_y/dec/last);
NOEXCEPT_CONVERSION(copy(ym) += one_decamonth);
CPP14_ASSERT((copy(ym) -= one_decamonth) == 2000_y/apr/last);
NOEXCEPT_CONVERSION(copy(ym) -= one_decamonth);
CPP14_ASSERT(ym + custom_month == 2001_y/mar/last);
NOEXCEPT_ASSERT(ym + custom_month);
CPP14_ASSERT(custom_month + ym == 2001_y/mar/last);
NOEXCEPT_ASSERT(custom_month + ym);
CPP14_ASSERT(ym - custom_month == 2001_y/jan/last);
NOEXCEPT_ASSERT(ym - custom_month);
CPP14_ASSERT((copy(ym) += custom_month) == 2001_y/mar/last);
NOEXCEPT_ASSERT(copy(ym) += custom_month);
CPP14_ASSERT((copy(ym) -= custom_month) == 2001_y/jan/last);
NOEXCEPT_ASSERT(copy(ym) -= custom_month);
CPP11_ASSERT(ym + custom_year == 2002_y/feb/last);
NOEXCEPT_ASSERT(ym + custom_year);
CPP11_ASSERT(custom_year + ym == 2002_y/feb/last);
NOEXCEPT_ASSERT(custom_year + ym);
CPP11_ASSERT(ym - custom_year == 2000_y/feb/last);
NOEXCEPT_ASSERT(ym - custom_year);
CPP14_ASSERT((copy(ym) += custom_year) == 2002_y/feb/last);
NOEXCEPT_ASSERT(copy(ym) += custom_year);
CPP14_ASSERT((copy(ym) -= custom_year) == 2000_y/feb/last);
NOEXCEPT_ASSERT(copy(ym) -= custom_year);
CPP11_ASSERT(ym + prefer_year == 2002_y/feb/last);
NOEXCEPT_ASSERT(ym + prefer_year);
CPP11_ASSERT(prefer_year + ym == 2002_y/feb/last);
NOEXCEPT_ASSERT(prefer_year + ym);
CPP11_ASSERT(ym - prefer_year == 2000_y/feb/last);
NOEXCEPT_ASSERT(ym - prefer_year);
CPP14_ASSERT((copy(ym) += prefer_year) == 2002_y/feb/last);
NOEXCEPT_ASSERT(copy(ym) += prefer_year);
CPP14_ASSERT((copy(ym) -= prefer_year) == 2000_y/feb/last);
NOEXCEPT_ASSERT(copy(ym) -= prefer_year);
}
{
constexpr year_month_weekday ym = 2001_y/feb/fri[4];
CPP14_ASSERT(ym + one_month == 2001_y/mar/fri[4]);
NOEXCEPT_ASSERT(ym + one_month);
CPP14_ASSERT(one_month + ym == 2001_y/mar/fri[4]);
NOEXCEPT_ASSERT(one_month + ym);
CPP14_ASSERT(ym - one_month == 2001_y/jan/fri[4]);
NOEXCEPT_ASSERT(ym - one_month);
CPP14_ASSERT((copy(ym) += one_month) == 2001_y/mar/fri[4]);
NOEXCEPT_ASSERT(copy(ym) += one_month);
CPP14_ASSERT((copy(ym) -= one_month) == 2001_y/jan/fri[4]);
NOEXCEPT_ASSERT(copy(ym) -= one_month);
CPP11_ASSERT(ym + one_year == 2002_y/feb/fri[4]);
NOEXCEPT_ASSERT(ym + one_year);
CPP11_ASSERT(one_year + ym == 2002_y/feb/fri[4]);
NOEXCEPT_ASSERT(one_year + ym);
CPP11_ASSERT(ym - one_year == 2000_y/feb/fri[4]);
NOEXCEPT_ASSERT(ym - one_year);
CPP14_ASSERT((copy(ym) += one_year) == 2002_y/feb/fri[4]);
NOEXCEPT_ASSERT(copy(ym) += one_year);
CPP14_ASSERT((copy(ym) -= one_year) == 2000_y/feb/fri[4]);
NOEXCEPT_ASSERT(copy(ym) -= one_year);
CPP11_ASSERT(ym + one_decade == 2011_y/feb/fri[4]);
NOEXCEPT_CONVERSION(ym + one_decade);
CPP11_ASSERT(one_decade + ym == 2011_y/feb/fri[4]);
NOEXCEPT_CONVERSION(one_decade + ym);
CPP11_ASSERT(ym - one_decade == 1991_y/feb/fri[4]);
NOEXCEPT_CONVERSION(ym - one_decade);
CPP14_ASSERT((copy(ym) += one_decade) == 2011_y/feb/fri[4]);
NOEXCEPT_CONVERSION(copy(ym) += one_decade);
CPP14_ASSERT((copy(ym) -= one_decade) == 1991_y/feb/fri[4]);
NOEXCEPT_CONVERSION(copy(ym) -= one_decade);
CPP14_ASSERT(ym + one_decamonth == 2001_y/dec/fri[4]);
NOEXCEPT_CONVERSION(ym + one_decamonth);
CPP14_ASSERT(one_decamonth + ym == 2001_y/dec/fri[4]);
NOEXCEPT_CONVERSION(one_decamonth + ym);
CPP14_ASSERT(ym - one_decamonth == 2000_y/apr/fri[4]);
NOEXCEPT_CONVERSION(ym - one_decamonth);
CPP14_ASSERT((copy(ym) += one_decamonth) == 2001_y/dec/fri[4]);
NOEXCEPT_CONVERSION(copy(ym) += one_decamonth);
CPP14_ASSERT((copy(ym) -= one_decamonth) == 2000_y/apr/fri[4]);
NOEXCEPT_CONVERSION(copy(ym) -= one_decamonth);
CPP14_ASSERT(ym + custom_month == 2001_y/mar/fri[4]);
NOEXCEPT_ASSERT(ym + custom_month);
CPP14_ASSERT(custom_month + ym == 2001_y/mar/fri[4]);
NOEXCEPT_ASSERT(custom_month + ym);
CPP14_ASSERT(ym - custom_month == 2001_y/jan/fri[4]);
NOEXCEPT_ASSERT(ym - custom_month);
CPP14_ASSERT((copy(ym) += custom_month) == 2001_y/mar/fri[4]);
NOEXCEPT_ASSERT(copy(ym) += custom_month);
CPP14_ASSERT((copy(ym) -= custom_month) == 2001_y/jan/fri[4]);
NOEXCEPT_ASSERT(copy(ym) -= custom_month);
CPP11_ASSERT(ym + custom_year == 2002_y/feb/fri[4]);
NOEXCEPT_ASSERT(ym + custom_year);
CPP11_ASSERT(custom_year + ym == 2002_y/feb/fri[4]);
NOEXCEPT_ASSERT(custom_year + ym);
CPP11_ASSERT(ym - custom_year == 2000_y/feb/fri[4]);
NOEXCEPT_ASSERT(ym - custom_year);
CPP14_ASSERT((copy(ym) += custom_year) == 2002_y/feb/fri[4]);
NOEXCEPT_ASSERT(copy(ym) += custom_year);
CPP14_ASSERT((copy(ym) -= custom_year) == 2000_y/feb/fri[4]);
NOEXCEPT_ASSERT(copy(ym) -= custom_year);
CPP11_ASSERT(ym + prefer_year == 2002_y/feb/fri[4]);
NOEXCEPT_ASSERT(ym + prefer_year);
CPP11_ASSERT(prefer_year + ym == 2002_y/feb/fri[4]);
NOEXCEPT_ASSERT(prefer_year + ym);
CPP11_ASSERT(ym - prefer_year == 2000_y/feb/fri[4]);
NOEXCEPT_ASSERT(ym - prefer_year);
CPP14_ASSERT((copy(ym) += prefer_year) == 2002_y/feb/fri[4]);
NOEXCEPT_ASSERT(copy(ym) += prefer_year);
CPP14_ASSERT((copy(ym) -= prefer_year) == 2000_y/feb/fri[4]);
NOEXCEPT_ASSERT(copy(ym) -= prefer_year);
}
{
constexpr year_month_weekday_last ym = 2001_y/feb/fri[last];
CPP14_ASSERT(ym + one_month == 2001_y/mar/fri[last]);
NOEXCEPT_ASSERT(ym + one_month);
CPP14_ASSERT(one_month + ym == 2001_y/mar/fri[last]);
NOEXCEPT_ASSERT(one_month + ym);
CPP14_ASSERT(ym - one_month == 2001_y/jan/fri[last]);
NOEXCEPT_ASSERT(ym - one_month);
CPP14_ASSERT((copy(ym) += one_month) == 2001_y/mar/fri[last]);
NOEXCEPT_ASSERT(copy(ym) += one_month);
CPP14_ASSERT((copy(ym) -= one_month) == 2001_y/jan/fri[last]);
NOEXCEPT_ASSERT(copy(ym) -= one_month);
CPP11_ASSERT(ym + one_year == 2002_y/feb/fri[last]);
NOEXCEPT_ASSERT(ym + one_year);
CPP11_ASSERT(one_year + ym == 2002_y/feb/fri[last]);
NOEXCEPT_ASSERT(one_year + ym);
CPP11_ASSERT(ym - one_year == 2000_y/feb/fri[last]);
NOEXCEPT_ASSERT(ym - one_year);
CPP14_ASSERT((copy(ym) += one_year) == 2002_y/feb/fri[last]);
NOEXCEPT_ASSERT(copy(ym) += one_year);
CPP14_ASSERT((copy(ym) -= one_year) == 2000_y/feb/fri[last]);
NOEXCEPT_ASSERT(copy(ym) -= one_year);
CPP11_ASSERT(ym + one_decade == 2011_y/feb/fri[last]);
NOEXCEPT_CONVERSION(ym + one_decade);
CPP11_ASSERT(one_decade + ym == 2011_y/feb/fri[last]);
NOEXCEPT_CONVERSION(one_decade + ym);
CPP11_ASSERT(ym - one_decade == 1991_y/feb/fri[last]);
NOEXCEPT_CONVERSION(ym - one_decade);
CPP14_ASSERT((copy(ym) += one_decade) == 2011_y/feb/fri[last]);
NOEXCEPT_CONVERSION(copy(ym) += one_decade);
CPP14_ASSERT((copy(ym) -= one_decade) == 1991_y/feb/fri[last]);
NOEXCEPT_CONVERSION(copy(ym) -= one_decade);
CPP14_ASSERT(ym + one_decamonth == 2001_y/dec/fri[last]);
NOEXCEPT_CONVERSION(ym + one_decamonth);
CPP14_ASSERT(one_decamonth + ym == 2001_y/dec/fri[last]);
NOEXCEPT_CONVERSION(one_decamonth + ym);
CPP14_ASSERT(ym - one_decamonth == 2000_y/apr/fri[last]);
NOEXCEPT_CONVERSION(ym - one_decamonth);
CPP14_ASSERT((copy(ym) += one_decamonth) == 2001_y/dec/fri[last]);
NOEXCEPT_CONVERSION(copy(ym) += one_decamonth);
CPP14_ASSERT((copy(ym) -= one_decamonth) == 2000_y/apr/fri[last]);
NOEXCEPT_CONVERSION(copy(ym) -= one_decamonth);
CPP14_ASSERT(ym + custom_month == 2001_y/mar/fri[last]);
NOEXCEPT_ASSERT(ym + custom_month);
CPP14_ASSERT(custom_month + ym == 2001_y/mar/fri[last]);
NOEXCEPT_ASSERT(custom_month + ym);
CPP14_ASSERT(ym - custom_month == 2001_y/jan/fri[last]);
NOEXCEPT_ASSERT(ym - custom_month);
CPP14_ASSERT((copy(ym) += custom_month) == 2001_y/mar/fri[last]);
NOEXCEPT_ASSERT(copy(ym) += custom_month);
CPP14_ASSERT((copy(ym) -= custom_month) == 2001_y/jan/fri[last]);
NOEXCEPT_ASSERT(copy(ym) -= custom_month);
CPP11_ASSERT(ym + custom_year == 2002_y/feb/fri[last]);
NOEXCEPT_ASSERT(ym + custom_year);
CPP11_ASSERT(custom_year + ym == 2002_y/feb/fri[last]);
NOEXCEPT_ASSERT(custom_year + ym);
CPP11_ASSERT(ym - custom_year == 2000_y/feb/fri[last]);
NOEXCEPT_ASSERT(ym - custom_year);
CPP14_ASSERT((copy(ym) += custom_year) == 2002_y/feb/fri[last]);
NOEXCEPT_ASSERT(copy(ym) += custom_year);
CPP14_ASSERT((copy(ym) -= custom_year) == 2000_y/feb/fri[last]);
NOEXCEPT_ASSERT(copy(ym) -= custom_year);
CPP11_ASSERT(ym + prefer_year == 2002_y/feb/fri[last]);
NOEXCEPT_ASSERT(ym + prefer_year);
CPP11_ASSERT(prefer_year + ym == 2002_y/feb/fri[last]);
NOEXCEPT_ASSERT(prefer_year + ym);
CPP11_ASSERT(ym - prefer_year == 2000_y/feb/fri[last]);
NOEXCEPT_ASSERT(ym - prefer_year);
CPP14_ASSERT((copy(ym) += prefer_year) == 2002_y/feb/fri[last]);
NOEXCEPT_ASSERT(copy(ym) += prefer_year);
CPP14_ASSERT((copy(ym) -= prefer_year) == 2000_y/feb/fri[last]);
NOEXCEPT_ASSERT(copy(ym) -= prefer_year);
}
}

View File

@ -0,0 +1,906 @@
// The MIT License (MIT)
//
// Copyright (c) 2016 Howard Hinnant
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
// This test is meant to maintain a record of the sizeof each type.
#include "date.h"
#include <cassert>
#include <sstream>
void
test_a()
{
using namespace date;
{
// correct abbreviation
std::istringstream in{"Sun 2016-12-11"};
sys_days tp;
in >> parse("%a %F", tp);
assert(!in.fail());
assert(!in.bad());
assert(!in.eof());
assert(tp == 2016_y/12/11);
}
{
// correct abbreviation
std::istringstream in{"Sun 2016-12-11"};
sys_days tp;
in >> parse("%A %F", tp);
// this may fail with libstdc++, see https://github.com/HowardHinnant/date/issues/388
// possible workaround: compile date.h with -DONLY_C_LOCALE=1
assert(!in.fail());
assert(!in.bad());
assert(!in.eof());
assert(tp == 2016_y/12/11);
}
{
// correct full name
std::istringstream in{"Sunday 2016-12-11"};
sys_days tp;
in >> parse("%a %F", tp);
assert(!in.fail());
assert(!in.bad());
assert(!in.eof());
assert(tp == 2016_y/12/11);
}
{
// correct full name
std::istringstream in{"Sunday 2016-12-11"};
sys_days tp;
in >> parse("%A %F", tp);
assert(!in.fail());
assert(!in.bad());
assert(!in.eof());
assert(tp == 2016_y/12/11);
}
{
// not a valid name
std::istringstream in{"Dec 2016-12-11"};
sys_days tp;
in >> parse("%a %F", tp);
assert( in.fail());
assert(!in.bad());
assert(!in.eof());
assert(tp == 1970_y/1/1);
}
{
// wrong name
std::istringstream in{"Sat 2016-12-11"};
sys_days tp;
in >> parse("%a %F", tp);
assert( in.fail());
assert(!in.bad());
assert(!in.eof());
assert(tp == 1970_y/1/1);
}
{
// extra ws in input
std::istringstream in{"Sun 2016-12-11"};
sys_days tp;
in >> parse("%a %F", tp);
assert(!in.fail());
assert(!in.bad());
assert(!in.eof());
assert(tp == 2016_y/12/11);
}
{
// extra ws in format
std::istringstream in{"Sun 2016-12-11"};
sys_days tp;
in >> parse("%a %F", tp);
assert(!in.fail());
assert(!in.bad());
assert(!in.eof());
assert(tp == 2016_y/12/11);
}
}
void
test_b()
{
using namespace date;
{
// correct abbreviation
std::istringstream in{"Dec 11 2016"};
sys_days tp;
in >> parse("%b %d %Y", tp);
assert(!in.fail());
assert(!in.bad());
assert(!in.eof());
assert(tp == 2016_y/12/11);
}
{
// correct abbreviation
std::istringstream in{"Dec 11 2016"};
sys_days tp;
in >> parse("%B %d %Y", tp);
assert(!in.fail());
assert(!in.bad());
assert(!in.eof());
assert(tp == 2016_y/12/11);
}
{
// correct abbreviation
std::istringstream in{"Dec 11 2016"};
sys_days tp;
in >> parse("%h %d %Y", tp);
assert(!in.fail());
assert(!in.bad());
assert(!in.eof());
assert(tp == 2016_y/12/11);
}
{
// correct full name
std::istringstream in{"December 11 2016"};
sys_days tp;
in >> parse("%b %d %Y", tp);
assert(!in.fail());
assert(!in.bad());
assert(!in.eof());
assert(tp == 2016_y/12/11);
}
{
// correct full name
std::istringstream in{"December 11 2016"};
sys_days tp;
in >> parse("%B %d %Y", tp);
assert(!in.fail());
assert(!in.bad());
assert(!in.eof());
assert(tp == 2016_y/12/11);
}
{
// correct full name
std::istringstream in{"December 11 2016"};
sys_days tp;
in >> parse("%h %d %Y", tp);
assert(!in.fail());
assert(!in.bad());
assert(!in.eof());
assert(tp == 2016_y/12/11);
}
{
// incorrect abbreviation
std::istringstream in{"Dece 11 2016"};
sys_days tp;
in >> parse("%b %d %Y", tp);
assert( in.fail());
assert(!in.bad());
assert(!in.eof());
assert(tp == 1970_y/1/1);
}
}
void
test_c()
{
using namespace date;
using namespace std::chrono;
{
// correct abbreviation
std::istringstream in{"Sun Dec 11 14:02:43 2016"};
sys_seconds tp;
in >> parse("%c", tp);
assert(!in.fail());
assert(!in.bad());
assert(tp == sys_days{2016_y/12/11} + hours{14} + minutes{2} + seconds{43});
}
}
void
test_x()
{
using namespace date;
using namespace std::chrono;
{
// correct abbreviation
std::istringstream in{"12/11/16"};
sys_seconds tp;
in >> parse("%x", tp);
assert(!in.fail());
assert(!in.bad());
assert(tp == sys_days{2016_y/12/11});
}
}
void
test_X()
{
using namespace date;
using namespace std::chrono;
{
// correct abbreviation
std::istringstream in{"2016-12-11 14:02:43"};
sys_seconds tp;
in >> parse("%F %X", tp);
assert(!in.fail());
assert(!in.bad());
assert(tp == sys_days{2016_y/12/11} + hours{14} + minutes{2} + seconds{43});
}
}
void
test_C()
{
using namespace date;
using namespace std::chrono;
{
std::istringstream in{"20 16 12 11"};
sys_days tp;
in >> parse("%C %y %m %d", tp);
assert(!in.fail());
assert(!in.bad());
assert(tp == 2016_y/12/11);
}
{
std::istringstream in{"-2 1 12 11"};
sys_days tp;
in >> parse("%C %y %m %d", tp);
assert(!in.fail());
assert(!in.bad());
assert(tp == -101_y/12/11);
}
{
std::istringstream in{"-1 0 12 11"};
sys_days tp;
in >> parse("%C %y %m %d", tp);
assert(!in.fail());
assert(!in.bad());
assert(tp == -100_y/12/11);
}
{
std::istringstream in{"-1 99 12 11"};
sys_days tp;
in >> parse("%C %y %m %d", tp);
assert(!in.fail());
assert(!in.bad());
assert(tp == -99_y/12/11);
}
{
std::istringstream in{"-1 1 12 11"};
sys_days tp;
in >> parse("%C %y %m %d", tp);
assert(!in.fail());
assert(!in.bad());
assert(tp == -1_y/12/11);
}
{
std::istringstream in{"0 0 12 11"};
sys_days tp;
in >> parse("%C %y %m %d", tp);
assert(!in.fail());
assert(!in.bad());
assert(tp == 0_y/12/11);
}
{
std::istringstream in{"0 1 12 11"};
sys_days tp;
in >> parse("%C %y %m %d", tp);
assert(!in.fail());
assert(!in.bad());
assert(tp == 1_y/12/11);
}
{
std::istringstream in{"0 99 12 11"};
sys_days tp;
in >> parse("%C %y %m %d", tp);
assert(!in.fail());
assert(!in.bad());
assert(tp == 99_y/12/11);
}
{
std::istringstream in{"1 0 12 11"};
sys_days tp;
in >> parse("%C %y %m %d", tp);
assert(!in.fail());
assert(!in.bad());
assert(tp == 100_y/12/11);
}
{
std::istringstream in{"1 1 12 11"};
sys_days tp;
in >> parse("%C %y %m %d", tp);
assert(!in.fail());
assert(!in.bad());
assert(tp == 101_y/12/11);
}
}
void
test_d()
{
using namespace date;
using namespace std::chrono;
{
std::istringstream in{"2016 09 12"};
sys_days tp;
in >> parse("%Y %d %m", tp);
assert(!in.fail());
assert(!in.bad());
assert(tp == 2016_y/12/9);
}
{
std::istringstream in{"2016 09 12"};
sys_days tp;
in >> parse("%Y %e %m", tp);
assert(!in.fail());
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());
assert(!in.bad());
assert(tp == 2016_y/12/9);
}
{
std::istringstream in{"2016 9 12"};
sys_days tp;
in >> parse("%Y %e %m", tp);
assert(!in.fail());
assert(!in.bad());
assert(tp == 2016_y/12/9);
}
{
std::istringstream in{"2016 31 11"};
sys_days tp;
in >> parse("%Y %e %m", tp);
assert(in.fail());
}
}
void
test_D()
{
using namespace date;
using namespace std::chrono;
{
std::istringstream in{"12/11/16"};
sys_days tp;
in >> parse("%D", tp);
assert(!in.fail());
assert(!in.bad());
assert(tp == 2016_y/12/11);
}
}
void
test_F()
{
using namespace date;
using namespace std::chrono;
{
std::istringstream in{"2016-12-13"};
sys_days tp;
in >> parse("%F", tp);
assert(!in.fail());
assert(!in.bad());
assert(tp == 2016_y/12/13);
}
{
std::istringstream in{"2016-12-13"};
year_month_day tp;
in >> parse("%F", tp);
assert(!in.fail());
assert(!in.bad());
assert(tp == 2016_y/12/13);
}
}
void
test_H()
{
using namespace date;
using namespace std::chrono;
{
std::istringstream in{"2016-12-11 15"};
sys_time<hours> tp;
in >> parse("%F %H", tp);
assert(!in.fail());
assert(!in.bad());
assert(tp == sys_days{2016_y/12/11} + hours{15});
}
{
std::istringstream in{"2016-12-11 24"};
sys_time<hours> tp;
in >> parse("%F %H", tp);
assert(in.fail());
}
}
void
test_Ip()
{
using namespace date;
using namespace std::chrono;
{
std::istringstream in{"2016-12-11 1 pm"};
sys_time<hours> tp;
in >> parse("%F %I %p", tp);
assert(!in.fail());
assert(!in.bad());
assert(tp == sys_days{2016_y/12/11} + hours{13});
}
{
std::istringstream in{"2016-12-11 1 am"};
sys_time<hours> tp;
in >> parse("%F %I %p", tp);
assert(!in.fail());
assert(!in.bad());
assert(tp == sys_days{2016_y/12/11} + hours{1});
}
{
std::istringstream in{"2016-12-11 13 am"};
sys_time<hours> tp;
in >> parse("%F %I %p", tp);
assert(in.fail());
}
}
void
test_j()
{
using namespace date;
using namespace std::chrono;
{
std::istringstream in{"2016 361"};
sys_days tp;
in >> parse("%Y %j", tp);
assert(!in.fail());
assert(!in.bad());
assert(tp == sys_days{2016_y/12/26});
}
}
void
test_m()
{
using namespace date;
using namespace std::chrono;
{
std::istringstream in{"2016 12 09"};
sys_days tp;
in >> parse("%Y %d %m", tp);
assert(!in.fail());
assert(!in.bad());
assert(tp == 2016_y/9/12);
}
{
std::istringstream in{"2016 12 9"};
sys_days tp;
in >> parse("%Y %d %m", tp);
assert(!in.fail());
assert(!in.bad());
assert(tp == 2016_y/9/12);
}
{
std::istringstream in{"2016 12 13"};
sys_days tp;
in >> parse("%Y %d %m", tp);
assert(in.fail());
}
}
void
test_M()
{
using namespace date;
using namespace std::chrono;
{
std::istringstream in{"2016-12-11 15"};
sys_time<minutes> tp;
in >> parse("%F %M", tp);
assert(!in.fail());
assert(!in.bad());
assert(tp == sys_days{2016_y/12/11} + minutes{15});
}
{
std::istringstream in{"2016-12-11 65"};
sys_time<minutes> tp;
in >> parse("%F %M", tp);
assert(in.fail());
}
}
void
test_S()
{
using namespace date;
using namespace std::chrono;
{
std::istringstream in{"2016-12-11 15"};
sys_seconds tp;
in >> parse("%F %S", tp);
assert(!in.fail());
assert(!in.bad());
assert(tp == sys_days{2016_y/12/11} + seconds{15});
}
{
std::istringstream in{"2016-12-11 15.001"};
sys_time<milliseconds> tp;
in >> parse("%F %S", tp);
assert(!in.fail());
assert(!in.bad());
assert(tp == sys_days{2016_y/12/11} + seconds{15} + milliseconds{1});
}
{
std::istringstream in{"2016-12-11 60"};
sys_seconds tp;
in >> parse("%F %S", tp);
assert(in.fail());
}
}
void
test_T()
{
using namespace date;
using namespace std::chrono;
{
std::istringstream in{"2016-12-11 15:43:22"};
sys_seconds tp;
in >> parse("%F %T", tp);
assert(!in.fail());
assert(!in.bad());
assert(tp == sys_days{2016_y/12/11} + hours{15} + minutes{43} + seconds{22});
}
{
std::istringstream in{"2016-12-11 15:43:22.001"};
sys_time<milliseconds> tp;
in >> parse("%F %T", tp);
assert(!in.fail());
assert(!in.bad());
assert(tp == sys_days{2016_y/12/11} + hours{15} + minutes{43} + seconds{22} +
milliseconds{1});
}
{
std::istringstream in{"2016-12-11 15:43:22"};
sys_time<milliseconds> tp;
in >> parse("%F %T", tp);
assert(!in.fail());
assert(!in.bad());
assert(tp == sys_days{2016_y/12/11} + hours{15} + minutes{43} + seconds{22});
}
{
std::istringstream in{"15:43:22.001"};
milliseconds d;
in >> parse("%T", d);
assert(!in.fail());
assert(!in.bad());
assert(d == hours{15} + minutes{43} + seconds{22} + milliseconds{1});
}
{
std::istringstream in{"2016-12-11 24:43:22"};
sys_seconds tp;
in >> parse("%F %T", tp);
assert(in.fail());
}
{
std::istringstream in{"2016-12-11 15:60:22"};
sys_seconds tp;
in >> parse("%F %T", tp);
assert(in.fail());
}
{
std::istringstream in{"2016-12-11 15:43:60"};
sys_seconds tp;
in >> parse("%F %T", tp);
assert(in.fail());
}
}
void
test_p()
{
using namespace date;
using namespace std::chrono;
{
std::istringstream in{"2016-12-11 11pm"};
sys_time<hours> tp;
in >> parse("%F %I%p", tp);
assert(!in.fail());
assert(!in.bad());
assert(tp == sys_days{2016_y/12/11} + hours{23});
}
}
void
test_r()
{
using namespace date;
using namespace std::chrono;
{
std::istringstream in{"2016-12-26 1:36:57 pm"};
sys_seconds tp;
in >> parse("%F %r", tp);
assert(!in.fail());
assert(!in.bad());
assert(tp == sys_days{2016_y/12/26} + hours{13} + minutes{36} + seconds{57});
}
}
void
test_R()
{
using namespace date;
using namespace std::chrono;
{
std::istringstream in{"2016-12-26 13:36"};
sys_seconds tp;
in >> parse("%F %R", tp);
assert(!in.fail());
assert(!in.bad());
assert(tp == sys_days{2016_y/12/26} + hours{13} + minutes{36});
}
}
void
test_U()
{
using namespace date;
using namespace std::chrono;
{
std::istringstream in{"2016-52-1"};
sys_days tp;
in >> parse("%Y-%U-%w", tp);
assert(!in.fail());
assert(!in.bad());
assert(tp == sys_days{2016_y/12/26});
}
}
void
test_W()
{
using namespace date;
using namespace std::chrono;
{
std::istringstream in{"2016-52-1"};
sys_days tp;
in >> parse("%Y-%W-%w", tp);
assert(!in.fail());
assert(!in.bad());
assert(tp == sys_days{2016_y/12/26});
}
}
void
test_GV()
{
using namespace date;
using namespace std::chrono;
{
std::istringstream in{"2016-52-1"};
sys_days tp;
in >> parse("%G-%V-%w", tp);
assert(!in.fail());
assert(!in.bad());
assert(tp == sys_days{2016_y/12/26});
}
{
std::istringstream in{"2016-52-1"};
sys_days tp;
in >> parse("%G-%V-%w", tp);
assert(!in.fail());
assert(!in.bad());
assert(tp == sys_days{2016_y/12/26});
}
{
std::istringstream in{"20 16-52-1"};
sys_days tp;
in >> parse("%C %g-%V-%w", tp);
assert(!in.fail());
assert(!in.bad());
assert(tp == sys_days{2016_y/12/26});
}
{
std::istringstream in{"20 16-52-1"};
sys_days tp;
in >> parse("%C %g-%V-%u", tp);
assert(!in.fail());
assert(!in.bad());
assert(tp == sys_days{2016_y/12/26});
}
}
void
test_z()
{
using namespace date;
using namespace std::chrono;
{
std::istringstream in{"2016-12-26 15:53:22 -0500"};
sys_seconds tp;
in >> parse("%F %T %z", tp);
assert(!in.fail());
assert(!in.bad());
assert(tp == sys_days{2016_y/12/26} + hours{20} + minutes{53} + seconds{22});
}
{
std::istringstream in{"2016-12-26 15:53:22 -0500"};
local_seconds tp;
in >> parse("%F %T %z", tp);
assert(!in.fail());
assert(!in.bad());
assert(tp == local_days{2016_y/12/26} + hours{15} + minutes{53} + seconds{22});
}
{
std::istringstream in{"2016-12-26 15:53:22 -05:00"};
sys_seconds tp;
in >> parse("%F %T %Ez", tp);
assert(!in.fail());
assert(!in.bad());
assert(tp == sys_days{2016_y/12/26} + hours{20} + minutes{53} + seconds{22});
}
}
void
test_Z()
{
using namespace date;
using namespace std::chrono;
{
std::string a;
std::istringstream in{"2016-12-26 15:53:22 word"};
local_seconds tp;
in >> parse("%F %T %Z", tp, a);
assert(!in.fail());
assert(!in.bad());
assert(tp == local_days{2016_y/12/26} + hours{15} + minutes{53} + seconds{22});
assert(a == "word");
}
}
void
test_trailing_Z()
{
std::string format = "%FT%TZ";
std::string datetime = "2017-2-15T13:13:13";
std::istringstream input(datetime);
date::sys_seconds tp;
input >> date::parse(format, tp);
assert(input.fail());
assert(input.eof());
}
void
test_leading_ws()
{
using namespace std;
using namespace date;
istringstream in{"05/04/17 5/4/17"};
year_month_day d1, d2;
in >> parse("%D", d1) >> parse("%n%D", d2);
assert(d1 == may/4/2017);
assert(d2 == may/4/2017);
}
void
test_space()
{
using namespace std;
using namespace date;
{
istringstream in{"05/04/17"};
year_month_day d1;
in >> parse(" %D", d1);
assert(d1 == may/4/2017);
}
{
istringstream in{" 05/04/17"};
year_month_day d1;
in >> parse(" %D", d1);
assert(d1 == may/4/2017);
}
{
istringstream in{" 05/04/17"};
year_month_day d1;
in >> parse(" %D", d1);
assert(d1 == may/4/2017);
}
}
void
test_n()
{
using namespace std;
using namespace date;
{
istringstream in{"05/04/17"};
year_month_day d1;
in >> parse("%n%D", d1);
assert(in.fail());
}
{
istringstream in{" 05/04/17"};
year_month_day d1;
in >> parse("%n%D", d1);
assert(d1 == may/4/2017);
}
{
istringstream in{" 05/04/17"};
year_month_day d1;
in >> parse("%n%D", d1);
assert(in.fail());
}
}
void
test_t()
{
using namespace std;
using namespace date;
{
istringstream in{"05/04/17"};
year_month_day d1;
in >> parse("%t%D", d1);
assert(d1 == may/4/2017);
}
{
istringstream in{" 05/04/17"};
year_month_day d1;
in >> parse("%t%D", d1);
assert(d1 == may/4/2017);
}
{
istringstream in{" 05/04/17"};
year_month_day d1;
in >> parse("%t%D", d1);
assert(in.fail());
}
}
int
main()
{
test_a();
test_b();
test_c();
test_C();
test_d();
test_D();
test_F();
test_H();
test_Ip();
test_j();
test_m();
test_M();
test_p();
test_r();
test_R();
test_S();
test_T();
test_U();
test_W();
test_GV();
test_x();
test_X();
test_z();
test_Z();
test_trailing_Z();
test_leading_ws();
test_space();
test_n();
test_t();
}

View File

@ -57,10 +57,10 @@ main()
using tod = time_of_day<hours>;
static_assert(is_same<tod::precision, hours>{}, "");
static_assert(is_same<tod::precision::period, seconds::period>{}, "");
static_assert( is_trivially_destructible<tod>{}, "");
static_assert(!is_default_constructible<tod>{}, "");
static_assert( is_default_constructible<tod>{}, "");
static_assert( is_trivially_copy_constructible<tod>{}, "");
static_assert( is_trivially_copy_assignable<tod>{}, "");
static_assert( is_trivially_move_constructible<tod>{}, "");
@ -68,14 +68,12 @@ main()
static_assert(is_nothrow_constructible<tod, hours>{}, "");
static_assert(!is_convertible<hours, tod>{}, "");
static_assert(is_nothrow_constructible<tod, hours, unsigned>{}, "");
static_assert(is_nothrow_constructible<tod::precision, tod>{}, "");
static_assert(!is_convertible<tod, tod::precision>{}, "");
constexpr tod t1 = tod{hours{13}};
static_assert(t1.hours() == hours{13}, "");
static_assert(t1.mode() == 0, "");
#if __cplusplus >= 201402
static_assert(static_cast<tod::precision>(t1) == hours{13}, "");
static_assert(t1.to_duration() == hours{13}, "");
@ -83,23 +81,14 @@ main()
auto t2 = t1;
assert(t2.hours() == t1.hours());
assert(t2.mode() == t1.mode());
assert(t2.to_duration() == t1.to_duration());
ostringstream os;
os << t2;
assert(os.str() == "1300");
t2.make12();
assert(os.str() == "13:00:00");
auto h = make12(t2.hours());
os.str("");
assert(t2.hours() == hours{1});
assert(t2.mode() == pm);
assert(h == hours{1});
assert(t2.to_duration() == t1.to_duration());
os << t2;
assert(os.str() == "1pm");
t2.make24();
os.str("");
assert(t2.hours() == hours{13});
assert(t2.mode() == 0);
assert(t2.to_duration() == t1.to_duration());
os << t2;
assert(os.str() == "1300");
assert(!is_am(t2.hours()));
assert(is_pm(t2.hours()));
}

View File

@ -0,0 +1,111 @@
// The MIT License (MIT)
//
// Copyright (c) 2015, 2016 Howard Hinnant
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
// enum {am = 1, pm};
// template <class Rep, class Period>
// class time_of_day<std::chrono::duration<Rep, Period>>
// {
// public:
// using precision = std::chrono::std::chrono::duration<Rep, Period>;
//
// constexpr explicit time_of_day(precision since_midnight) noexcept;
// constexpr time_of_day(std::chrono::hours h, std::chrono::minutes m,
// std::chrono::seconds s, precision sub_s,
// unsigned md) noexcept;
//
// constexpr std::chrono::hours hours() const noexcept;
// constexpr std::chrono::minutes minutes() const noexcept;
// constexpr std::chrono::seconds seconds() const noexcept;
// constexpr precision subseconds() const noexcept;
// constexpr unsigned mode() const noexcept;
//
// constexpr explicit operator precision() const noexcept;
// constexpr precision to_duration() const noexcept;
//
// void make24() noexcept;
// void make12() noexcept;
// };
// template <class Rep, class Period>
// std::ostream&
// operator<<(std::ostream& os, const time_of_day<std::chrono::duration<Rep, Period>>& t);
#include "date.h"
#include <cassert>
#include <sstream>
#include <type_traits>
using fortnights = std::chrono::duration<date::weeks::rep,
date::detail::ratio_multiply<std::ratio<2>,
date::weeks::period>>;
using microfortnights = std::chrono::duration<std::int64_t,
date::detail::ratio_multiply<fortnights::period,
std::micro>>;
int
main()
{
using namespace date;
using namespace std;
using namespace std::chrono;
using tod = time_of_day<typename common_type<hours, minutes, microfortnights>::type>;
static_assert(is_same<tod::precision::period, ratio<1, 10000>>{}, "");
static_assert( is_trivially_destructible<tod>{}, "");
static_assert( is_default_constructible<tod>{}, "");
static_assert( is_trivially_copy_constructible<tod>{}, "");
static_assert( is_trivially_copy_assignable<tod>{}, "");
static_assert( is_trivially_move_constructible<tod>{}, "");
static_assert( is_trivially_move_assignable<tod>{}, "");
static_assert(is_constructible<tod, microfortnights>{}, "");
static_assert(!is_convertible<microfortnights, tod>{}, "");
static_assert(is_nothrow_constructible<tod::precision, tod>{}, "");
static_assert(!is_convertible<tod, tod::precision>{}, "");
constexpr tod t1 = tod{hours{13} + minutes{7} + microfortnights{5}};
static_assert(t1.hours() == hours{13}, "");
static_assert(t1.minutes() == minutes{7}, "");
static_assert(t1.seconds() == seconds{6}, "");
static_assert(t1.subseconds() == tod::precision{480}, "");
#if __cplusplus >= 201402
static_assert(static_cast<tod::precision>(t1) == hours{13} + minutes{7}
+ microfortnights{5}, "");
static_assert(t1.to_duration() == hours{13} + minutes{7} + microfortnights{5}, "");
#endif
auto t2 = t1;
assert(t2.hours() == t1.hours());
assert(t2.minutes() == t1.minutes());
assert(t2.seconds() == t1.seconds());
assert(t2.subseconds() == t1.subseconds());
assert(t2.to_duration() == t1.to_duration());
ostringstream os;
os << t2;
assert(os.str() == "13:07:06.0480");
}

View File

@ -65,10 +65,10 @@ main()
using tod = time_of_day<milliseconds>;
static_assert(is_same<tod::precision, milliseconds>{}, "");
static_assert(is_same<tod::precision::period, milliseconds::period>{}, "");
static_assert( is_trivially_destructible<tod>{}, "");
static_assert(!is_default_constructible<tod>{}, "");
static_assert( is_default_constructible<tod>{}, "");
static_assert( is_trivially_copy_constructible<tod>{}, "");
static_assert( is_trivially_copy_assignable<tod>{}, "");
static_assert( is_trivially_move_constructible<tod>{}, "");
@ -76,8 +76,6 @@ main()
static_assert(is_nothrow_constructible<tod, milliseconds>{}, "");
static_assert(!is_convertible<milliseconds, tod>{}, "");
static_assert(is_nothrow_constructible<tod, hours, minutes, seconds, milliseconds,
unsigned>{}, "");
static_assert(is_nothrow_constructible<tod::precision, tod>{}, "");
static_assert(!is_convertible<tod, tod::precision>{}, "");
@ -87,7 +85,6 @@ main()
static_assert(t1.minutes() == minutes{7}, "");
static_assert(t1.seconds() == seconds{5}, "");
static_assert(t1.subseconds() == milliseconds{22}, "");
static_assert(t1.mode() == 0, "");
#if __cplusplus >= 201402
static_assert(static_cast<tod::precision>(t1) == hours{13} + minutes{7}
+ seconds{5} + milliseconds{22}, "");
@ -100,29 +97,8 @@ main()
assert(t2.minutes() == t1.minutes());
assert(t2.seconds() == t1.seconds());
assert(t2.subseconds() == t1.subseconds());
assert(t2.mode() == t1.mode());
assert(t2.to_duration() == t1.to_duration());
ostringstream os;
os << t2;
assert(os.str() == "13:07:05.022");
t2.make12();
os.str("");
assert(t2.hours() == hours{1});
assert(t2.minutes() == minutes{7});
assert(t2.seconds() == seconds{5});
assert(t2.subseconds() == milliseconds{22});
assert(t2.mode() == pm);
assert(t2.to_duration() == t1.to_duration());
os << t2;
assert(os.str() == "1:07:05.022pm");
t2.make24();
os.str("");
assert(t2.hours() == hours{13});
assert(t2.minutes() == minutes{7});
assert(t2.seconds() == seconds{5});
assert(t2.subseconds() == milliseconds{22});
assert(t2.mode() == 0);
assert(t2.to_duration() == t1.to_duration());
os << t2;
assert(os.str() == "13:07:05.022");
}

View File

@ -59,10 +59,10 @@ main()
using tod = time_of_day<minutes>;
static_assert(is_same<tod::precision, minutes>{}, "");
static_assert(is_same<tod::precision::period, seconds::period>{}, "");
static_assert( is_trivially_destructible<tod>{}, "");
static_assert(!is_default_constructible<tod>{}, "");
static_assert( is_default_constructible<tod>{}, "");
static_assert( is_trivially_copy_constructible<tod>{}, "");
static_assert( is_trivially_copy_assignable<tod>{}, "");
static_assert( is_trivially_move_constructible<tod>{}, "");
@ -70,7 +70,6 @@ main()
static_assert(is_nothrow_constructible<tod, minutes>{}, "");
static_assert(!is_convertible<minutes, tod>{}, "");
static_assert(is_nothrow_constructible<tod, hours, minutes, unsigned>{}, "");
static_assert(is_nothrow_constructible<tod::precision, tod>{}, "");
static_assert(!is_convertible<tod, tod::precision>{}, "");
@ -78,7 +77,6 @@ main()
constexpr tod t1 = tod{hours{13} + minutes{7}};
static_assert(t1.hours() == hours{13}, "");
static_assert(t1.minutes() == minutes{7}, "");
static_assert(t1.mode() == 0, "");
#if __cplusplus >= 201402
static_assert(static_cast<tod::precision>(t1) == hours{13} + minutes{7}, "");
static_assert(t1.to_duration() == hours{13} + minutes{7}, "");
@ -87,25 +85,8 @@ main()
auto t2 = t1;
assert(t2.hours() == t1.hours());
assert(t2.minutes() == t1.minutes());
assert(t2.mode() == t1.mode());
assert(t2.to_duration() == t1.to_duration());
ostringstream os;
os << t2;
assert(os.str() == "13:07");
t2.make12();
os.str("");
assert(t2.hours() == hours{1});
assert(t2.minutes() == minutes{7});
assert(t2.mode() == pm);
assert(t2.to_duration() == t1.to_duration());
os << t2;
assert(os.str() == "1:07pm");
t2.make24();
os.str("");
assert(t2.hours() == hours{13});
assert(t2.minutes() == minutes{7});
assert(t2.mode() == 0);
assert(t2.to_duration() == t1.to_duration());
os << t2;
assert(os.str() == "13:07");
assert(os.str() == "13:07:00");
}

View File

@ -65,10 +65,10 @@ main()
using tod = time_of_day<nanoseconds>;
static_assert(is_same<tod::precision, nanoseconds>{}, "");
static_assert(is_same<tod::precision::period, nanoseconds::period>{}, "");
static_assert( is_trivially_destructible<tod>{}, "");
static_assert(!is_default_constructible<tod>{}, "");
static_assert( is_default_constructible<tod>{}, "");
static_assert( is_trivially_copy_constructible<tod>{}, "");
static_assert( is_trivially_copy_assignable<tod>{}, "");
static_assert( is_trivially_move_constructible<tod>{}, "");
@ -76,8 +76,6 @@ main()
static_assert(is_nothrow_constructible<tod, nanoseconds>{}, "");
static_assert(!is_convertible<nanoseconds, tod>{}, "");
static_assert(is_nothrow_constructible<tod, hours, minutes, seconds, nanoseconds,
unsigned>{}, "");
static_assert(is_nothrow_constructible<tod::precision, tod>{}, "");
static_assert(!is_convertible<tod, tod::precision>{}, "");
@ -87,7 +85,6 @@ main()
static_assert(t1.minutes() == minutes{7}, "");
static_assert(t1.seconds() == seconds{5}, "");
static_assert(t1.subseconds() == nanoseconds{22}, "");
static_assert(t1.mode() == 0, "");
#if __cplusplus >= 201402
static_assert(static_cast<tod::precision>(t1) == hours{13} + minutes{7}
+ seconds{5} + nanoseconds{22}, "");
@ -100,29 +97,8 @@ main()
assert(t2.minutes() == t1.minutes());
assert(t2.seconds() == t1.seconds());
assert(t2.subseconds() == t1.subseconds());
assert(t2.mode() == t1.mode());
assert(t2.to_duration() == t1.to_duration());
ostringstream os;
os << t2;
assert(os.str() == "13:07:05.000000022");
t2.make12();
os.str("");
assert(t2.hours() == hours{1});
assert(t2.minutes() == minutes{7});
assert(t2.seconds() == seconds{5});
assert(t2.subseconds() == nanoseconds{22});
assert(t2.mode() == pm);
assert(t2.to_duration() == t1.to_duration());
os << t2;
assert(os.str() == "1:07:05.000000022pm");
t2.make24();
os.str("");
assert(t2.hours() == hours{13});
assert(t2.minutes() == minutes{7});
assert(t2.seconds() == seconds{5});
assert(t2.subseconds() == nanoseconds{22});
assert(t2.mode() == 0);
assert(t2.to_duration() == t1.to_duration());
os << t2;
assert(os.str() == "13:07:05.000000022");
}

View File

@ -60,10 +60,10 @@ main()
using tod = time_of_day<seconds>;
static_assert(is_same<tod::precision, seconds>{}, "");
static_assert(is_same<tod::precision::period, seconds::period>{}, "");
static_assert( is_trivially_destructible<tod>{}, "");
static_assert(!is_default_constructible<tod>{}, "");
static_assert( is_default_constructible<tod>{}, "");
static_assert( is_trivially_copy_constructible<tod>{}, "");
static_assert( is_trivially_copy_assignable<tod>{}, "");
static_assert( is_trivially_move_constructible<tod>{}, "");
@ -71,7 +71,6 @@ main()
static_assert(is_nothrow_constructible<tod, seconds>{}, "");
static_assert(!is_convertible<seconds, tod>{}, "");
static_assert(is_nothrow_constructible<tod, hours, minutes, seconds, unsigned>{}, "");
static_assert(is_nothrow_constructible<tod::precision, tod>{}, "");
static_assert(!is_convertible<tod, tod::precision>{}, "");
@ -80,7 +79,6 @@ main()
static_assert(t1.hours() == hours{13}, "");
static_assert(t1.minutes() == minutes{7}, "");
static_assert(t1.seconds() == seconds{5}, "");
static_assert(t1.mode() == 0, "");
#if __cplusplus >= 201402
static_assert(static_cast<tod::precision>(t1) == hours{13} + minutes{7}
+ seconds{5}, "");
@ -91,27 +89,8 @@ main()
assert(t2.hours() == t1.hours());
assert(t2.minutes() == t1.minutes());
assert(t2.seconds() == t1.seconds());
assert(t2.mode() == t1.mode());
assert(t2.to_duration() == t1.to_duration());
ostringstream os;
os << t2;
assert(os.str() == "13:07:05");
t2.make12();
os.str("");
assert(t2.hours() == hours{1});
assert(t2.minutes() == minutes{7});
assert(t2.seconds() == seconds{5});
assert(t2.mode() == pm);
assert(t2.to_duration() == t1.to_duration());
os << t2;
assert(os.str() == "1:07:05pm");
t2.make24();
os.str("");
assert(t2.hours() == hours{13});
assert(t2.minutes() == minutes{7});
assert(t2.seconds() == seconds{5});
assert(t2.mode() == 0);
assert(t2.to_duration() == t1.to_duration());
os << t2;
assert(os.str() == "13:07:05");
}

View File

@ -69,7 +69,7 @@
#include <type_traits>
static_assert( std::is_trivially_destructible<date::weekday>{}, "");
static_assert(!std::is_default_constructible<date::weekday>{}, "");
static_assert( std::is_default_constructible<date::weekday>{}, "");
static_assert( std::is_trivially_copy_constructible<date::weekday>{}, "");
static_assert( std::is_trivially_copy_assignable<date::weekday>{}, "");
static_assert( std::is_trivially_move_constructible<date::weekday>{}, "");
@ -77,11 +77,9 @@ static_assert( std::is_trivially_move_assignable<date::weekday>{}, "");
static_assert( std::is_nothrow_constructible<date::weekday, unsigned>{}, "");
static_assert( std::is_nothrow_constructible<date::weekday, date::sys_days>{}, "");
static_assert( std::is_nothrow_constructible<unsigned, date::weekday>{}, "");
static_assert(!std::is_convertible<unsigned, date::weekday>{}, "");
static_assert( std::is_convertible<date::sys_days, date::weekday>{}, "");
static_assert(!std::is_convertible<date::weekday, unsigned>{}, "");
static_assert(static_cast<unsigned>(date::weekday{1u}) == 1, "");
static_assert( date::weekday{0u}.ok(), "");
static_assert( date::weekday{1u}.ok(), "");
@ -90,7 +88,8 @@ static_assert( date::weekday{3u}.ok(), "");
static_assert( date::weekday{4u}.ok(), "");
static_assert( date::weekday{5u}.ok(), "");
static_assert( date::weekday{6u}.ok(), "");
static_assert(!date::weekday{7u}.ok(), "");
static_assert( date::weekday{7u}.ok(), "");
static_assert(!date::weekday{8u}.ok(), "");
void
test_weekday_arithmetic()

View File

@ -23,6 +23,7 @@
// class weekday_indexed
// {
// public:
// weekday_indexed() = default;
// constexpr weekday_indexed(const date::weekday& wd, unsigned index) noexcept;
//
// constexpr date::weekday weekday() const noexcept;
@ -42,7 +43,7 @@
#include <type_traits>
static_assert( std::is_trivially_destructible<date::weekday_indexed>{}, "");
static_assert(!std::is_default_constructible<date::weekday_indexed>{}, "");
static_assert( std::is_default_constructible<date::weekday_indexed>{}, "");
static_assert( std::is_trivially_copy_constructible<date::weekday_indexed>{}, "");
static_assert( std::is_trivially_copy_assignable<date::weekday_indexed>{}, "");
static_assert( std::is_trivially_move_constructible<date::weekday_indexed>{}, "");

View File

@ -64,7 +64,7 @@
#include <type_traits>
static_assert( std::is_trivially_destructible<date::year>{}, "");
static_assert(!std::is_default_constructible<date::year>{}, "");
static_assert( std::is_default_constructible<date::year>{}, "");
static_assert( std::is_trivially_copy_constructible<date::year>{}, "");
static_assert( std::is_trivially_copy_assignable<date::year>{}, "");
static_assert( std::is_trivially_move_constructible<date::year>{}, "");
@ -107,7 +107,7 @@ main()
static_assert(year::max().ok(), "");
#if __cplusplus >= 201402
using int64_t = std::int64_t;
using std::int64_t;
static_assert(sys_days(year::min()/jan/1) - sys_days(1970_y/jan/1)
>= as<int64_t>(days::min()), "");
static_assert(sys_days(year::min()/jan/1) - sys_days(1970_y/jan/1)

View File

@ -61,7 +61,7 @@
#include <type_traits>
static_assert( std::is_trivially_destructible<date::year_month>{}, "");
static_assert(!std::is_default_constructible<date::year_month>{}, "");
static_assert( std::is_default_constructible<date::year_month>{}, "");
static_assert( std::is_trivially_copy_constructible<date::year_month>{}, "");
static_assert( std::is_trivially_copy_assignable<date::year_month>{}, "");
static_assert( std::is_trivially_move_constructible<date::year_month>{}, "");
@ -109,6 +109,90 @@ test_arithmetic()
}
}
void test_arithemtic_not_ok()
{
using namespace date;
using namespace std::chrono;
year_month ym{2018_y, month{14}};
{
year_month ym2{2019_y, month{2}};
assert(ym + months{0} == ym2);
assert(ym - months{0} == ym2);
assert(ym - ym2 == months{0});
assert(ym2 - ym == months{0});
auto ymc = ym;
ymc += months{0};
assert(ymc.ok());
assert(ymc == ym2);
}
{
year_month ym2{2019_y, month{6}};
assert(ym + months{4} == ym2);
assert(ym2 - ym == months{4});
assert(ym - ym2 == -months{4});
auto ymc = ym;
ymc += months{4};
assert(ymc.ok());
assert(ymc == ym2);
}
{
year_month ym2{2018_y, month{10}};
assert(ym - months{4} == ym2);
assert(ym2 - ym == -months{4});
assert(ym - ym2 == months{4});
auto ymc = ym;
ymc -= months{4};
assert(ymc.ok());
assert(ymc == ym2);
}
{
year_month ym2{2020_y, month{6}};
assert(ym + months{16} == ym2);
assert(ym2 - ym == months{16});
assert(ym - ym2 == -months{16});
auto ymc = ym;
ymc += months{16};
assert(ymc.ok());
assert(ymc == ym2);
}
{
year_month ym2{2017_y, month{10}};
assert(ym - months{16} == ym2);
assert(ym2 - ym == -months{16});
assert(ym - ym2 == months(16));
auto ymc = ym;
ymc -= months{16};
assert(ymc.ok());
assert(ymc == ym2);
}
{
year_month ym2{2018_y, month{25}};
assert(ym2 - ym == months{11});
assert(ym - ym2 == -months{11});
}
{
year_month ym2{2019_y, month{25}};
assert(ym2 - ym == months{23});
assert(ym - ym2 == -months{23});
}
}
int
main()
{
@ -135,6 +219,7 @@ main()
static_assert(ym1 - ym2 == -months{11}, "");
test_arithmetic();
test_arithemtic_not_ok();
std::ostringstream os;
os << ym1;

View File

@ -64,7 +64,7 @@
#include <type_traits>
static_assert( std::is_trivially_destructible<date::year_month_day>{}, "");
static_assert(!std::is_default_constructible<date::year_month_day>{}, "");
static_assert( std::is_default_constructible<date::year_month_day>{}, "");
static_assert( std::is_trivially_copy_constructible<date::year_month_day>{}, "");
static_assert( std::is_trivially_copy_assignable<date::year_month_day>{}, "");
static_assert( std::is_trivially_move_constructible<date::year_month_day>{}, "");

View File

@ -105,7 +105,7 @@ test_arithmetic()
for (int y1 = 2010; y1 <= 2015; ++y1)
{
for (unsigned m1 = 1; m1 <= 12; ++m1)
for (int m1 = 1; m1 <= 12; ++m1)
{
auto ymd1 = last/m1/y1;;
auto ymd2 = ymd1 + months(24);

View File

@ -23,6 +23,7 @@
// class year_month_weekday
// {
// public:
// year_month_weekday() = default;
// constexpr year_month_weekday(const date::year& y, const date::month& m,
// const date::weekday_indexed& wdi) noexcept;
// constexpr year_month_weekday(const sys_days& dp) noexcept;
@ -83,7 +84,7 @@
#include <type_traits>
static_assert( std::is_trivially_destructible<date::year_month_weekday>{}, "");
static_assert(!std::is_default_constructible<date::year_month_weekday>{}, "");
static_assert( std::is_default_constructible<date::year_month_weekday>{}, "");
static_assert( std::is_trivially_copy_constructible<date::year_month_weekday>{}, "");
static_assert( std::is_trivially_copy_assignable<date::year_month_weekday>{}, "");
static_assert( std::is_trivially_move_constructible<date::year_month_weekday>{}, "");
@ -106,7 +107,7 @@ test_arithmetic()
for (int y1 = 2010; y1 <= 2015; ++y1)
{
for (unsigned m1 = 1; m1 <= 12; ++m1)
for (int m1 = 1; m1 <= 12; ++m1)
{
auto ymd1 = mon[2]/m1/y1;;
auto ymd2 = ymd1 + months(24);

View File

@ -101,7 +101,7 @@ test_arithmetic()
for (int y1 = 2010; y1 <= 2015; ++y1)
{
for (unsigned m1 = 1; m1 <= 12; ++m1)
for (int m1 = 1; m1 <= 12; ++m1)
{
auto ymd1 = mon[last]/m1/y1;;
auto ymd2 = ymd1 + months(24);

View File

@ -171,7 +171,7 @@ test_with_date_weekday()
auto constexpr d1 = iso_week::sun;
static_assert(unsigned{d1} == 7, "");
auto constexpr d2 = date::weekday{d1};
static_assert(unsigned{d2} == 0, "");
static_assert(d2 == date::Sunday, "");
auto constexpr d3 = iso_week::weekday{d2};
static_assert(unsigned{d3} == 7, "");
}

View File

@ -115,4 +115,15 @@ main()
std::ostringstream os;
os << x0;
assert(os.str() == "2015-W last-Tue");
for (auto y = 1950_y; y <= 2050_y; ++y)
{
auto wd = mon;
do
{
auto x = y/last/wd;
assert(date::year_month_day{x} == date::year_month_day{year_weeknum_weekday{x}});
++wd;
} while (wd != mon);
}
}

View File

@ -0,0 +1,237 @@
// The MIT License (MIT)
//
// Copyright (c) 2020 Asad. Gharighi
// Copyright (c) 2020 Howard Hinnant
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
#include "date.h"
#include "solar_hijri.h"
#include "islamic.h"
#include "tz.h"
#include <cassert>
#include <iostream>
#include <chrono>
#include <math.h>
void
test_a() {
constexpr auto civil = date::year{2020}/date::January/27;
using namespace solar_hijri;
static_assert(year_month_day{civil} == 1398_y/11/07, "");
}
void
test_b() {
using namespace solar_hijri::literals;
static_assert(date::year_month_day{475_y/far/1} == date::year{1096}/03/21, "");
static_assert(date::year_month_weekday{475_y/far/1} ==
date::year{1096}/03/date::Saturday[3], "");
}
void
test_c() {
using namespace solar_hijri;
auto date = solar_hijri::year_month_day{1398_y/bah/6};
for (auto i = 0; i < 24; i++) {
auto weekday = solar_hijri::weekday{date};
assert(date == 1398_y/11/06 + months{i});
assert(date.month() == month{(i+10u)%12 + 1});
assert(weekday == (weekday[1]/date.month()/date.year()).weekday());
auto k = weekday;
for (auto j = 0; j < 14; j++, k++) {
assert(weekday + days{j} == k);
}
date+=solar_hijri::months(1);
}
}
void
test_d() {
auto zt = date::make_zoned(date::current_zone(), std::chrono::system_clock::now());
auto ld = date::floor<date::days>(zt.get_local_time());
solar_hijri::year_month_day ymd{ld};
auto time = date::make_time(zt.get_local_time() - ld);
(void)time;
}
void
test_e() {
auto sd = date::floor<solar_hijri::days>(std::chrono::system_clock::now());
auto today = solar_hijri::year_month_day{sd};
assert(solar_hijri::year_month_weekday{today}.weekday() == solar_hijri::weekday{sd});
}
void
test_f() {
constexpr auto isl = islamic::year{1441}/6/1;
using namespace solar_hijri;
static_assert(year_month_day{isl} == 1398_y/11/07, "");
}
void
test_g() {
date::year_month_day ymdd[] = {
date::year{1583}/date::November/21,
date::year{1583}/date::November/22,
date::year{1583}/date::December/6,
date::year{1591}/date::December/26,
date::year{1616}/date::October/20,
date::year{1619}/date::October/13,
date::year{1627}/date::August/9,
date::year{1649}/date::October/15,
date::year{1657}/date::August/9,
date::year{1682}/date::June/23,
date::year{1691}/date::October/12,
date::year{1712}/date::September/13,
date::year{1718}/date::July/17,
date::year{1747}/date::January/4,
date::year{1756}/date::January/1,
date::year{1770}/date::January/15,
date::year{1798}/date::October/24,
date::year{1809}/date::July/11,
date::year{1834}/date::July/17,
date::year{1850}/date::September/9,
date::year{1865}/date::November/4,
date::year{1902}/date::December/21,
date::year{1926}/date::March/21,
date::year{1926}/date::March/22,
date::year{1957}/date::June/1,
date::year{1977}/date::March/7,
date::year{1982}/date::May/30,
date::year{1992}/date::December/8
};
solar_hijri::year_month_day ymdh[] = {
solar_hijri::year{962}/solar_hijri::Aban/30,
solar_hijri::year{962}/solar_hijri::Azar/1,
solar_hijri::year{962}/solar_hijri::Azar/15,
solar_hijri::year{970}/solar_hijri::Dey/5,
solar_hijri::year{995}/solar_hijri::Mehr/29,
solar_hijri::year{998}/solar_hijri::Mehr/21,
solar_hijri::year{1006}/solar_hijri::Mordad/18,
solar_hijri::year{1028}/solar_hijri::Mehr/24,
solar_hijri::year{1036}/solar_hijri::Mordad/19,
solar_hijri::year{1061}/solar_hijri::Tir/3,
solar_hijri::year{1070}/solar_hijri::Mehr/20,
solar_hijri::year{1091}/solar_hijri::Shahrivar/22,
solar_hijri::year{1097}/solar_hijri::Tir/26,
solar_hijri::year{1125}/solar_hijri::Dey/14,
solar_hijri::year{1134}/solar_hijri::Dey/11,
solar_hijri::year{1148}/solar_hijri::Dey/26,
solar_hijri::year{1177}/solar_hijri::Aban/2,
solar_hijri::year{1188}/solar_hijri::Tir/20,
solar_hijri::year{1213}/solar_hijri::Tir/26,
solar_hijri::year{1229}/solar_hijri::Shahrivar/18,
solar_hijri::year{1244}/solar_hijri::Aban/13,
solar_hijri::year{1281}/solar_hijri::Azar/29,
solar_hijri::year{1304}/solar_hijri::Esfand/30,
solar_hijri::year{1305}/solar_hijri::Farvardin/1,
solar_hijri::year{1336}/solar_hijri::Khordad/11,
solar_hijri::year{1355}/solar_hijri::Esfand/16,
solar_hijri::year{1361}/solar_hijri::Khordad/9,
solar_hijri::year{1371}/solar_hijri::Azar/17
};
solar_hijri::year_month_weekday ymdwd[] = {
solar_hijri::year{962}/solar_hijri::Aban/solar_hijri::Doshanbe[5],
solar_hijri::year{962}/solar_hijri::Azar/solar_hijri::Seshanbe[1],
solar_hijri::year{962}/solar_hijri::Azar/solar_hijri::Seshanbe[3],
solar_hijri::year{970}/solar_hijri::Dey/solar_hijri::Panjshanbe[1],
solar_hijri::year{995}/solar_hijri::Mehr/solar_hijri::Panjshanbe[5],
solar_hijri::year{998}/solar_hijri::Mehr/solar_hijri::Yekshanbe[3],
solar_hijri::year{1006}/solar_hijri::Mordad/solar_hijri::Doshanbe[3],
solar_hijri::year{1028}/solar_hijri::Mehr/solar_hijri::Adine[4],
solar_hijri::year{1036}/solar_hijri::Mordad/solar_hijri::Panjshanbe[3],
solar_hijri::year{1061}/solar_hijri::Tir/solar_hijri::Seshanbe[1],
solar_hijri::year{1070}/solar_hijri::Mehr/solar_hijri::Adine[3],
solar_hijri::year{1091}/solar_hijri::Shahrivar/solar_hijri::Seshanbe[4],
solar_hijri::year{1097}/solar_hijri::Tir/solar_hijri::Yekshanbe[4],
solar_hijri::year{1125}/solar_hijri::Dey/solar_hijri::Chaharshanbe[2],
solar_hijri::year{1134}/solar_hijri::Dey/solar_hijri::Panjshanbe[2],
solar_hijri::year{1148}/solar_hijri::Dey/solar_hijri::Doshanbe[4],
solar_hijri::year{1177}/solar_hijri::Aban/solar_hijri::Chaharshanbe[1],
solar_hijri::year{1188}/solar_hijri::Tir/solar_hijri::Seshanbe[3],
solar_hijri::year{1213}/solar_hijri::Tir/solar_hijri::Panjshanbe[4],
solar_hijri::year{1229}/solar_hijri::Shahrivar/solar_hijri::Doshanbe[3],
solar_hijri::year{1244}/solar_hijri::Aban/solar_hijri::Shanbe[2],
solar_hijri::year{1281}/solar_hijri::Azar/solar_hijri::Yekshanbe[5],
solar_hijri::year{1304}/solar_hijri::Esfand/solar_hijri::Yekshanbe[5],
solar_hijri::year{1305}/solar_hijri::Farvardin/solar_hijri::Doshanbe[1],
solar_hijri::year{1336}/solar_hijri::Khordad/solar_hijri::Shanbe[2],
solar_hijri::year{1355}/solar_hijri::Esfand/solar_hijri::Doshanbe[3],
solar_hijri::year{1361}/solar_hijri::Khordad/solar_hijri::Yekshanbe[2],
solar_hijri::year{1371}/solar_hijri::Azar/solar_hijri::Seshanbe[3]
};
bool leaps[] = {
true,
true,
true,
true,
true,
false,
false,
true,
true,
true,
false,
false,
false,
false,
false,
true,
false,
false,
false,
false,
false,
false,
true,
false,
false,
false,
false,
false
};
static_assert(sizeof(ymdd)/sizeof(ymdd[0]) == sizeof(ymdwd)/sizeof(ymdwd[0]), "");
static_assert(sizeof(ymdd)/sizeof(ymdd[0]) == sizeof(ymdh)/sizeof(ymdh[0]), "");
static_assert(sizeof(ymdd)/sizeof(ymdd[0]) == sizeof(leaps)/sizeof(leaps[0]), "");
for (auto i = 0; i < sizeof(ymdd)/sizeof(ymdd[0]); ++i)
{
assert(solar_hijri::year_month_day{ymdd[i]} == ymdh[i]);
assert(ymdd[i] == date::year_month_day{ymdh[i]});
assert(ymdh[i].year().is_leap() == leaps[i]);
assert(solar_hijri::year_month_weekday{ymdd[i]} == ymdwd[i]);
}
}
int
main()
{
test_a();
test_b();
test_c();
test_d();
test_e();
test_f();
test_g();
}

View File

@ -0,0 +1,168 @@
// The MIT License (MIT)
//
// Copyright (c) 2020 Asad. Gharighi
// Copyright (c) 2015, 2016 Howard Hinnant
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
// class year_month_day
// {
// public:
// constexpr year_month_day(const date::year& y, const date::month& m,
// const date::day& d) noexcept;
// constexpr year_month_day(const year_month_day_last& ymdl) noexcept;
// constexpr year_month_day(const sys_days& dp) noexcept;
//
// year_month_day& operator+=(const months& m) noexcept;
// year_month_day& operator-=(const months& m) noexcept;
// year_month_day& operator+=(const years& y) noexcept;
// year_month_day& operator-=(const years& y) noexcept;
//
// constexpr date::year year() const noexcept;
// constexpr date::month month() const noexcept;
// constexpr date::day day() const noexcept;
//
// constexpr operator sys_days() const noexcept;
// constexpr bool ok() const noexcept;
// };
// constexpr bool operator==(const year_month_day& x, const year_month_day& y) noexcept;
// constexpr bool operator!=(const year_month_day& x, const year_month_day& y) noexcept;
// constexpr bool operator< (const year_month_day& x, const year_month_day& y) noexcept;
// constexpr bool operator> (const year_month_day& x, const year_month_day& y) noexcept;
// constexpr bool operator<=(const year_month_day& x, const year_month_day& y) noexcept;
// constexpr bool operator>=(const year_month_day& x, const year_month_day& y) noexcept;
// constexpr year_month_day operator+(const year_month_day& ymd, const months& dm) noexcept;
// constexpr year_month_day operator+(const months& dm, const year_month_day& ymd) noexcept;
// constexpr year_month_day operator-(const year_month_day& ymd, const months& dm) noexcept;
// constexpr year_month_day operator+(const year_month_day& ymd, const years& dy) noexcept;
// constexpr year_month_day operator+(const years& dy, const year_month_day& ymd) noexcept;
// constexpr year_month_day operator-(const year_month_day& ymd, const years& dy) noexcept;
// std::ostream& operator<<(std::ostream& os, const year_month_day& ymd);
#include "date.h"
#include "solar_hijri.h"
#include <iostream>
#include <cassert>
#include <sstream>
#include <type_traits>
static_assert( std::is_trivially_destructible<solar_hijri::year_month_day>{}, "");
static_assert( std::is_default_constructible<solar_hijri::year_month_day>{}, "");
static_assert( std::is_trivially_copy_constructible<solar_hijri::year_month_day>{}, "");
static_assert( std::is_trivially_copy_assignable<solar_hijri::year_month_day>{}, "");
static_assert( std::is_trivially_move_constructible<solar_hijri::year_month_day>{}, "");
static_assert( std::is_trivially_move_assignable<solar_hijri::year_month_day>{}, "");
static_assert(std::is_nothrow_constructible<solar_hijri::year_month_day, solar_hijri::year,
solar_hijri::month,
solar_hijri::day>{}, "");
static_assert(std::is_nothrow_constructible<solar_hijri::year_month_day,
solar_hijri::year_month_day_last>{}, "");
static_assert(std::is_convertible<solar_hijri::year_month_day_last, solar_hijri::year_month_day>{}, "");
static_assert(std::is_nothrow_constructible<solar_hijri::year_month_day, solar_hijri::sys_days>{}, "");
static_assert(std::is_convertible<solar_hijri::sys_days, solar_hijri::year_month_day>{}, "");
static_assert(std::is_nothrow_constructible<solar_hijri::sys_days, solar_hijri::year_month_day>{}, "");
static_assert(std::is_convertible<solar_hijri::year_month_day, solar_hijri::sys_days>{}, "");
void
test_arithmetic()
{
using namespace solar_hijri;
for (int y1 = 1380; y1 <= 1400; ++y1)
{
for (unsigned m1 = 1; m1 <= 12; ++m1)
{
year_month_day ymd1{year{y1}, month{m1}, 9_d};
year_month_day ymd2 = ymd1 + months(24);
assert((ymd2 == year_month_day{year{y1+2}, ymd1.month(), ymd1.day()}));
ymd2 = ymd1 - months(24);
assert((ymd2 == year_month_day{year{y1-2}, ymd1.month(), ymd1.day()}));
for (int m2 = -24; m2 <= 24; ++m2)
{
months m{m2};
year_month_day ymd3 = ymd1 + m;
months dm = year_month{ymd3.year(), ymd3.month()} -
year_month{ymd2.year(), ymd2.month()};
assert(dm == m + years{2});
assert(ymd3 - m == ymd1);
assert(ymd3 + -m == ymd1);
assert(-m + ymd3 == ymd1);
assert((year_month_day{ymd1} += m) == ymd3);
assert((year_month_day{ymd3} -= m) == ymd1);
}
for (int y2 = -2; y2 <= 5; ++y2)
{
years y{y2};
year_month_day ymd3 = ymd1 + y;
years dy = date::floor<years>(year_month{ymd3.year(), ymd3.month()} -
year_month{ymd2.year(), ymd2.month()});
assert(dy == y + years{2});
assert(ymd3 - y == ymd1);
assert(ymd3 + -y == ymd1);
assert(-y + ymd3 == ymd1);
assert((year_month_day{ymd1} += y) == ymd3);
assert((year_month_day{ymd3} -= y) == ymd1);
}
}
}
}
void
test_day_point_conversion()
{
using namespace solar_hijri;
year y = year{-30000};
year end = 30000_y;
sys_days prev_dp = sys_days(year_month_day{y, far, 1_d}) - days{1};
weekday prev_wd = weekday{prev_dp};
for (; y <= end; ++y)
{
month m = far;
do
{
day last_day = year_month_day_last{y, month_day_last{m}}.day();
for (day d = 1_d; d <= last_day; ++d)
{
year_month_day ymd = {y, m, d};
assert(ymd.ok());
sys_days dp = sys_days(ymd);
assert(dp == prev_dp + days{1});
year_month_day ymd2 = dp;
assert(ymd2 == ymd);
weekday wd = dp;
assert(wd.ok());
assert(wd == prev_wd + days{1});
prev_wd = wd;
prev_dp = dp;
}
} while (++m != far);
}
}
int
main()
{
test_arithmetic();
test_day_point_conversion();
}

View File

@ -48,7 +48,10 @@ if [ -z "$CXX_LANG" ]
then
CXX_LANG=c++14
fi
OPTIONS="-std=${CXX_LANG} $OPTIONS -I$ROOT -Wall"
OPTIONS="-std=${CXX_LANG} $OPTIONS -I$ROOT -Wall $ROOT/src/tz.cpp -lcurl"
echo $ROOT
HEADER_INCLUDE="-I$ROOT/include -I$ROOT/include/date"
case $TRIPLE in
*-*-mingw* | *-*-cygwin* | *-*-win*)

73
test/tz_test/OffsetZone.h Normal file
View File

@ -0,0 +1,73 @@
#ifndef OFFSET_ZONE_H
#define OFFSET_ZONE_H
// The MIT License (MIT)
//
// Copyright (c) 2017 Howard Hinnant
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
// Test custom time zone support
#include "tz.h"
class OffsetZone
{
std::chrono::minutes offset_;
public:
explicit OffsetZone(std::chrono::minutes offset)
: offset_{offset}
{}
template <class Duration>
auto
to_local(date::sys_time<Duration> tp) const
{
using namespace date;
using namespace std::chrono;
using LT = local_time<std::common_type_t<Duration, minutes>>;
return LT{(tp + offset_).time_since_epoch()};
}
template <class Duration>
auto
to_sys(date::local_time<Duration> tp, date::choose = date::choose::earliest) const
{
using namespace date;
using namespace std::chrono;
using ST = sys_time<std::common_type_t<Duration, minutes>>;
return ST{(tp - offset_).time_since_epoch()};
}
template <class Duration>
date::sys_info
get_info(date::sys_time<Duration> st) const
{
using namespace date;
using namespace std::chrono;
return {sys_seconds::min(), sys_seconds::max(), offset_,
minutes{0}, offset_ >= minutes{0} ? "+" + date::format("%H%M", offset_)
: "-" + date::format("%H%M", -offset_)};
}
const OffsetZone* operator->() const {return this;}
};
#endif // OFFSET_ZONE_H

View File

@ -0,0 +1,38 @@
// The MIT License (MIT)
//
// Copyright (c) 2017 Howard Hinnant
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
// Test custom time zone support
#include "tz.h"
#include "OffsetZone.h"
#include <cassert>
int
main()
{
using namespace date;
using namespace std::chrono;
auto now = system_clock::now();
auto offset = hours{-4};
zoned_time<system_clock::duration, OffsetZone> zt{OffsetZone{offset}, now};
assert(zt.get_local_time().time_since_epoch() == now.time_since_epoch() + offset);
}

View File

@ -1,21 +1,15 @@
To test: * Install tz.cpp by downloading the IANA timezone database
at: http://www.iana.org/time-zones You only need the data, not the
code.
# TZ Test
* Change the string `install` in tz.cpp to point to your downloaded
IANA database.
## How to Test
* Install tz.cpp by downloading the IANA timezone database at: http://www.iana.org/time-zones You only need the data, not the code.
* Change the string `install` in tz.cpp to point to your downloaded IANA database.
* Compile validate.cpp along with tz.cpp.
* Run the binary and direct the terminal output to a temporary file.
* Unzip the tzdata file that has the version corresponding to the IANA database you downloaded (e.g. tzdata2015f.txt.zip).
* Compare the unzipped txt file with the output of your validate test program. If they are identical, the test passes, else it fails.
* Unzip the tzdata file that has the version corresponding to the IANA
database you downloaded (e.g. tzdata2015f.txt.zip).
* Compare the unzipped txt file with the output of your validate test
program. If they are identical, the test passes, else it fails.
Miscellaneous:
## Miscellaneous
You can also compare one version of the tzdatabase with another using
these uncompressed text files. The text files contain for each
@ -25,4 +19,4 @@ versions change, minor updates to the set of these transitions are
typically made, typically due to changes in government policies.
The tests in this section will run much faster with optimizations
cranked up.
cranked up.

View 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>{}, "");
}

View File

@ -1,4 +1,4 @@
#include "tz.h"
#include "date/tz.h"
#include <iostream>
void
@ -89,12 +89,18 @@ tzmain()
using namespace std::chrono;
auto& db = get_tzdb();
std::vector<std::string> names;
names.reserve(db.zones.size() + db.links.size());
for (const auto& zone : db.zones)
#if USE_OS_TZDB
names.reserve(db.zones.size());
for (auto& zone : db.zones)
names.push_back(zone.name());
for (const auto& link : db.links)
#else // !USE_OS_TZDB
names.reserve(db.zones.size() + db.links.size());
for (auto& zone : db.zones)
names.push_back(zone.name());
for (auto& link : db.links)
names.push_back(link.name());
std::sort(names.begin(), names.end());
#endif // !USE_OS_TZDB
std::cout << db.version << "\n\n";
for (auto const& name : names)
{

View File

@ -1,3 +1,25 @@
// The MIT License (MIT)
//
// Copyright (c) 2015, 2016 Howard Hinnant
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
#include "tz.h"
#include <type_traits>

View File

@ -0,0 +1,464 @@
// The MIT License (MIT)
//
// Copyright (c) 2017 Howard Hinnant
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
// template <class Duration>
// class zoned_time
// {
// public:
// using duration = typename std::common_type<Duration, std::chrono::seconds>::type;
//
// zoned_time();
// zoned_time(const sys_time<Duration>& st);
// explicit zoned_time(const time_zone* z);
// explicit zoned_time(std::string_view name);
//
// template <class Duration2,
// class = typename std::enable_if
// <
// std::is_convertible<sys_time<Duration2>,
// sys_time<Duration>>::value
// >::type>
// zoned_time(const zoned_time<Duration2>& zt) NOEXCEPT;
//
// zoned_time(const time_zone* z, const local_time<Duration>& tp);
// zoned_time(std::string_view name, const local_time<Duration>& tp);
// zoned_time(const time_zone* z, const local_time<Duration>& tp, choose c);
// zoned_time(std::string_view name, const local_time<Duration>& tp, choose c);
//
// zoned_time(const time_zone* z, const zoned_time<Duration>& zt);
// zoned_time(std::string_view name, const zoned_time<Duration>& zt);
// zoned_time(const time_zone* z, const zoned_time<Duration>& zt, choose);
// zoned_time(std::string_view name, const zoned_time<Duration>& zt, choose);
//
// zoned_time(const time_zone* z, const sys_time<Duration>& st);
// zoned_time(std::string_view name, const sys_time<Duration>& st);
//
// zoned_time& operator=(const sys_time<Duration>& st);
// zoned_time& operator=(const local_time<Duration>& ut);
//
// explicit operator sys_time<duration>() const;
// explicit operator local_time<duration>() const;
//
// const time_zone* get_time_zone() const;
// local_time<duration> get_local_time() const;
// sys_time<duration> get_sys_time() const;
// sys_info get_info() const;
//
// template <class Duration1, class Duration2>
// friend
// bool
// operator==(const zoned_time<Duration1>& x, const zoned_time<Duration2>& y);
//
// template <class CharT, class Traits, class Duration1>
// friend
// std::basic_ostream<CharT, Traits>&
// operator<<(std::basic_ostream<CharT, Traits>& os, const zoned_time<Duration1>& t);
// };
//
// using zoned_seconds = zoned_time<std::chrono::seconds>;
//
// template <class Duration1, class Duration2>
// inline
// bool
// operator!=(const zoned_time<Duration1>& x, const zoned_time<Duration2>& y);
//
// template <class Duration>
// zoned_time(sys_time<Duration>)
// -> zoned_time<std::common_type_t<Duration, std::chrono::seconds>>;
//
// template <class Zone, class Duration>
// zoned_time(Zone, sys_time<Duration>)
// -> zoned_time<std::common_type_t<Duration, std::chrono::seconds>>;
//
// template <class Zone, class Duration>
// zoned_time(Zone, local_time<Duration>, choose = choose::earliest)
// -> zoned_time<std::common_type_t<Duration, std::chrono::seconds>>;
//
// template <class Zone, class Duration>
// zoned_time(Zone, zoned_time<Duration>, choose = choose::earliest)
// -> zoned_time<std::common_type_t<Duration, std::chrono::seconds>>;
#include "tz.h"
#include <cassert>
#include <sstream>
#include <type_traits>
int
main()
{
using namespace std;
using namespace std::chrono;
using namespace date;
static_assert( is_nothrow_destructible<zoned_seconds>{}, "");
static_assert( is_default_constructible<zoned_seconds>{}, "");
static_assert( is_nothrow_copy_constructible<zoned_seconds>{}, "");
static_assert( is_nothrow_copy_assignable<zoned_seconds>{}, "");
static_assert( is_nothrow_move_constructible<zoned_seconds>{}, "");
static_assert( is_nothrow_move_assignable<zoned_seconds>{}, "");
static_assert(is_same<zoned_time<minutes>::duration, seconds>{}, "");
static_assert(is_same<zoned_seconds::duration, seconds>{}, "");
static_assert(is_same<zoned_time<milliseconds>::duration, milliseconds>{}, "");
// zoned_time();
{
zoned_seconds zt;
assert(zt.get_sys_time() == sys_seconds{});
assert(zt.get_time_zone()->name() == "Etc/UTC");
}
// zoned_time(const sys_time<Duration>& st);
{
static_assert(!is_convertible<sys_days, zoned_seconds>{}, "");
static_assert( is_constructible<zoned_seconds, sys_days>{}, "");
static_assert( is_convertible<sys_seconds, zoned_seconds>{}, "");
static_assert(!is_convertible<sys_time<milliseconds>, zoned_seconds>{}, "");
static_assert(!is_constructible<zoned_seconds, sys_time<milliseconds>>{}, "");
auto now = floor<seconds>(system_clock::now());
zoned_seconds zt = now;
assert(zt.get_sys_time() == now);
assert(zt.get_time_zone()->name() == "Etc/UTC");
}
// explicit zoned_time(const time_zone* z);
{
static_assert(!is_convertible<const time_zone*, zoned_seconds>{}, "");
static_assert( is_constructible<zoned_seconds, const time_zone*>{}, "");
zoned_seconds zt{locate_zone("America/New_York")};
assert(zt.get_sys_time() == sys_seconds{});
assert(zt.get_time_zone()->name() == "America/New_York");
}
// explicit zoned_time(std::string_view name);
{
static_assert(!is_convertible<std::string, zoned_seconds>{}, "");
static_assert( is_constructible<zoned_seconds, std::string>{}, "");
static_assert( is_constructible<zoned_seconds, const char*>{}, "");
static_assert( is_constructible<zoned_seconds, const char[3]>{}, "");
zoned_seconds zt{"America/New_York"};
assert(zt.get_sys_time() == sys_seconds{});
assert(zt.get_time_zone()->name() == "America/New_York");
}
// template <class Duration2,
// class = typename std::enable_if
// <
// std::is_convertible<sys_time<Duration2>,
// sys_time<Duration>>::value
// >::type>
// zoned_time(const zoned_time<Duration2>& zt) NOEXCEPT;
{
static_assert( is_convertible<zoned_time<days>, zoned_seconds>{}, "");
static_assert(!is_constructible<zoned_time<days>, zoned_seconds>{}, "");
zoned_time<days> zt1{"America/New_York", sys_days{2017_y/jul/5}};
zoned_seconds zt2 = zt1;
assert(zt2.get_sys_time() == sys_days{2017_y/jul/5});
assert(zt2.get_time_zone()->name() == "America/New_York");
}
// zoned_time(const time_zone* z, const local_time<Duration>& tp);
{
static_assert( is_constructible<zoned_seconds, const time_zone*, local_days>{}, "");
zoned_seconds zt = {locate_zone("America/New_York"), local_days{2017_y/jul/5}};
assert(zt.get_local_time() == local_days{2017_y/jul/5});
assert(zt.get_time_zone()->name() == "America/New_York");
try
{
zoned_seconds zt1 = {locate_zone("America/New_York"),
local_days{2017_y/mar/sun[2]} + hours{2} + minutes{15}};
assert(false);
}
catch(const nonexistent_local_time&)
{
}
try
{
zoned_seconds zt1 = {locate_zone("America/New_York"),
local_days{2017_y/nov/sun[1]} + hours{1} + minutes{15}};
assert(false);
}
catch(const ambiguous_local_time&)
{
}
}
// zoned_time(std::string_view name, const local_time<Duration>& tp);
{
static_assert( is_constructible<zoned_seconds, std::string, local_days>{}, "");
static_assert( is_constructible<zoned_seconds, const char*, local_days>{}, "");
zoned_seconds zt = {"America/New_York", local_days{2017_y/jul/5}};
assert(zt.get_local_time() == local_days{2017_y/jul/5});
assert(zt.get_time_zone()->name() == "America/New_York");
try
{
zoned_seconds zt1 = {"America/New_York",
local_days{2017_y/mar/sun[2]} + hours{2} + minutes{15}};
assert(false);
}
catch(const nonexistent_local_time&)
{
}
try
{
zoned_seconds zt1 = {"America/New_York",
local_days{2017_y/nov/sun[1]} + hours{1} + minutes{15}};
assert(false);
}
catch(const ambiguous_local_time&)
{
}
}
// zoned_time(const time_zone* z, const local_time<Duration>& tp, choose c);
{
static_assert( is_constructible<zoned_seconds, const time_zone*, local_days, choose>{}, "");
zoned_seconds zt = {locate_zone("America/New_York"),
local_days{2017_y/jul/5} + hours{2} + minutes{15},
choose::earliest};
assert(zt.get_sys_time() == sys_days{2017_y/jul/5} + hours{6} + minutes{15});
assert(zt.get_time_zone()->name() == "America/New_York");
zt = {locate_zone("America/New_York"),
local_days{2017_y/jul/5} + hours{2} + minutes{15},
choose::latest};
assert(zt.get_sys_time() == sys_days{2017_y/jul/5} + hours{6} + minutes{15});
assert(zt.get_time_zone()->name() == "America/New_York");
static_assert( is_constructible<zoned_seconds, const time_zone*, local_days, choose>{}, "");
zoned_seconds zt1 = {locate_zone("America/New_York"),
local_days{2017_y/mar/sun[2]} + hours{2} + minutes{15},
choose::earliest};
assert(zt1.get_sys_time() == sys_days{2017_y/mar/12} + hours{7});
assert(zt1.get_time_zone()->name() == "America/New_York");
zoned_seconds zt2 = {locate_zone("America/New_York"),
local_days{2017_y/mar/sun[2]} + hours{2} + minutes{15},
choose::latest};
assert(zt2.get_sys_time() == sys_days{2017_y/mar/12} + hours{7});
assert(zt2.get_time_zone()->name() == "America/New_York");
zoned_seconds zt3 = {locate_zone("America/New_York"),
local_days{2017_y/nov/sun[1]} + hours{1} + minutes{15},
choose::earliest};
assert(zt3.get_sys_time() == sys_days{2017_y/nov/5} + hours{5} + minutes{15});
assert(zt3.get_time_zone()->name() == "America/New_York");
zoned_seconds zt4 = {locate_zone("America/New_York"),
local_days{2017_y/nov/sun[1]} + hours{1} + minutes{15},
choose::latest};
assert(zt4.get_sys_time() == sys_days{2017_y/nov/5} + hours{6} + minutes{15});
assert(zt4.get_time_zone()->name() == "America/New_York");
}
// zoned_time(std::string_view name, const local_time<Duration>& tp, choose c);
{
static_assert( is_constructible<zoned_seconds, std::string, local_days, choose>{}, "");
static_assert( is_constructible<zoned_seconds, const char*, local_days, choose>{}, "");
zoned_seconds zt = {"America/New_York",
local_days{2017_y/jul/5} + hours{2} + minutes{15},
choose::earliest};
assert(zt.get_sys_time() == sys_days{2017_y/jul/5} + hours{6} + minutes{15});
assert(zt.get_time_zone()->name() == "America/New_York");
zt = {"America/New_York",
local_days{2017_y/jul/5} + hours{2} + minutes{15},
choose::latest};
assert(zt.get_sys_time() == sys_days{2017_y/jul/5} + hours{6} + minutes{15});
assert(zt.get_time_zone()->name() == "America/New_York");
static_assert( is_constructible<zoned_seconds, const time_zone*, local_days, choose>{}, "");
zoned_seconds zt1 = {"America/New_York",
local_days{2017_y/mar/sun[2]} + hours{2} + minutes{15},
choose::earliest};
assert(zt1.get_sys_time() == sys_days{2017_y/mar/12} + hours{7});
assert(zt1.get_time_zone()->name() == "America/New_York");
zoned_seconds zt2 = {"America/New_York",
local_days{2017_y/mar/sun[2]} + hours{2} + minutes{15},
choose::latest};
assert(zt2.get_sys_time() == sys_days{2017_y/mar/12} + hours{7});
assert(zt2.get_time_zone()->name() == "America/New_York");
zoned_seconds zt3 = {"America/New_York",
local_days{2017_y/nov/sun[1]} + hours{1} + minutes{15},
choose::earliest};
assert(zt3.get_sys_time() == sys_days{2017_y/nov/5} + hours{5} + minutes{15});
assert(zt3.get_time_zone()->name() == "America/New_York");
zoned_seconds zt4 = {"America/New_York",
local_days{2017_y/nov/sun[1]} + hours{1} + minutes{15},
choose::latest};
assert(zt4.get_sys_time() == sys_days{2017_y/nov/5} + hours{6} + minutes{15});
assert(zt4.get_time_zone()->name() == "America/New_York");
}
// zoned_time(const time_zone* z, const sys_time<Duration>& st);
{
static_assert( is_constructible<zoned_seconds, const time_zone*, sys_days>{}, "");
zoned_seconds zt = {locate_zone("America/New_York"),
sys_days{2017_y/jul/5} + hours{2} + minutes{15}};
assert(zt.get_sys_time() == sys_days{2017_y/jul/5} + hours{2} + minutes{15});
assert(zt.get_time_zone()->name() == "America/New_York");
}
// zoned_time(std::string_view name, const sys_time<Duration>& st);
{
static_assert( is_constructible<zoned_seconds, std::string, sys_days>{}, "");
static_assert( is_constructible<zoned_seconds, const char*, sys_days>{}, "");
zoned_seconds zt = {"America/New_York",
sys_days{2017_y/jul/5} + hours{2} + minutes{15}};
assert(zt.get_sys_time() == sys_days{2017_y/jul/5} + hours{2} + minutes{15});
assert(zt.get_time_zone()->name() == "America/New_York");
}
// zoned_time& operator=(const sys_time<Duration>& st);
{
static_assert( is_assignable<zoned_seconds, const sys_days&>{}, "");
zoned_seconds zt{"America/New_York"};
zt = sys_days{2017_y/jul/5};
assert(zt.get_sys_time() == sys_days{2017_y/jul/5});
assert(zt.get_time_zone()->name() == "America/New_York");
}
// zoned_time& operator=(const local_time<Duration>& st);
{
static_assert( is_assignable<zoned_seconds, const local_days&>{}, "");
zoned_seconds zt{"America/New_York"};
zt = local_days{2017_y/jul/5};
assert(zt.get_local_time() == local_days{2017_y/jul/5});
assert(zt.get_time_zone()->name() == "America/New_York");
try
{
zt = {"America/New_York",
local_days{2017_y/mar/sun[2]} + hours{2} + minutes{15}};
assert(false);
}
catch(const nonexistent_local_time&)
{
assert(zt.get_local_time() == local_days{2017_y/jul/5});
assert(zt.get_time_zone()->name() == "America/New_York");
}
try
{
zt = {"America/New_York",
local_days{2017_y/nov/sun[1]} + hours{1} + minutes{15}};
assert(false);
}
catch(const ambiguous_local_time&)
{
assert(zt.get_local_time() == local_days{2017_y/jul/5});
assert(zt.get_time_zone()->name() == "America/New_York");
}
}
// explicit operator sys_time<duration>() const;
{
static_assert(!is_convertible<zoned_seconds, sys_seconds>{}, "");
static_assert( is_constructible<sys_seconds, zoned_seconds>{}, "");
auto now = floor<seconds>(system_clock::now());
const zoned_seconds zt = {"America/New_York", now};
assert(sys_seconds{zt} == now);
}
// explicit operator local_time<duration>() const;
{
static_assert(!is_convertible<zoned_seconds, local_seconds>{}, "");
static_assert( is_constructible<local_seconds, zoned_seconds>{}, "");
auto now = local_days{2017_y/jul/5} + hours{23} + minutes{1} + seconds{48};
const zoned_seconds zt = {"America/New_York", now};
assert(local_seconds{zt} == now);
}
// const time_zone* get_time_zone() const;
{
const zoned_seconds zt{"America/New_York"};
assert(zt.get_time_zone() == locate_zone("America/New_York"));
}
// local_time<duration> get_local_time() const;
{
const zoned_seconds zt{"America/New_York", sys_days{2017_y/jul/6} +
hours{3} + minutes{7} + seconds{9}};
assert(zt.get_local_time() == local_days{2017_y/jul/5} +
hours{23} + minutes{7} + seconds{9});
}
// sys_time<duration> get_sys_time() const;
{
const zoned_seconds zt{"America/New_York", sys_days{2017_y/jul/6} +
hours{3} + minutes{7} + seconds{9}};
assert(zt.get_sys_time() == sys_days{2017_y/jul/6} +
hours{3} + minutes{7} + seconds{9});
}
// sys_info get_info() const;
{
const zoned_seconds zt{"America/New_York", sys_days{2017_y/jul/6} +
hours{3} + minutes{7} + seconds{9}};
auto info = zt.get_info();
assert(info.begin == sys_days{2017_y/mar/12} + hours{7});
assert(info.end == sys_days{2017_y/nov/5} + hours{6});
assert(info.offset == hours{-4});
assert(info.save != minutes{0});
assert(info.abbrev == "EDT");
}
// template <class Duration1, class Duration2>
// bool
// operator==(const zoned_time<Duration1>& x, const zoned_time<Duration2>& y);
{
const zoned_seconds zt{"America/New_York", sys_days{2017_y/jul/6} +
hours{3} + minutes{7} + seconds{9}};
const zoned_seconds zt1{"America/New_York", sys_days{2017_y/jul/6} +
hours{3} + minutes{7} + seconds{10}};
assert(zt == zt);
assert(!(zt == zt1));
}
// template <class Duration1, class Duration2>
// bool
// operator!=(const zoned_time<Duration1>& x, const zoned_time<Duration2>& y);
{
const zoned_seconds zt{"America/New_York", sys_days{2017_y/jul/6} +
hours{3} + minutes{7} + seconds{9}};
const zoned_seconds zt1{"America/New_York", sys_days{2017_y/jul/6} +
hours{3} + minutes{7} + seconds{10}};
assert(!(zt != zt));
assert(zt != zt1);
}
// template <class CharT, class Traits, class Duration1>
// std::basic_ostream<CharT, Traits>&
// operator<<(std::basic_ostream<CharT, Traits>& os, const zoned_time<Duration1>& t);
{
const zoned_seconds zt{"America/New_York", sys_days{2017_y/jul/6} +
hours{3} + minutes{7} + seconds{9}};
std::ostringstream test;
test << zt;
assert(test.str() == "2017-07-05 23:07:09 EDT");
}
}

View File

@ -0,0 +1,246 @@
// The MIT License (MIT)
//
// Copyright (c) 2019 Tomasz Kamiński
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
#include "tz.h"
#include "OffsetZone.h"
#include <cassert>
#include <type_traits>
#include <string>
#if HAS_DEDUCTION_GUIDES
#include <string_view>
template<typename TimeZonePtr, typename Source>
void testDeductionFrom(Source&& s)
{
using namespace date;
using namespace std::chrono;
// No time point
{
zoned_time zt(std::forward<Source>(s));
static_assert(std::is_same<decltype(zt), zoned_time<seconds, TimeZonePtr>>::value, "");
}
// sys_time
{
sys_days sd(2017_y/feb/20);
zoned_time ztd(std::forward<Source>(s), sd);
static_assert(std::is_same<decltype(ztd), zoned_time<seconds, TimeZonePtr>>::value, "");
sys_time<seconds> ss(sd);
zoned_time zts(std::forward<Source>(s), ss);
static_assert(std::is_same<decltype(zts), zoned_time<seconds, TimeZonePtr>>::value, "");
sys_time<milliseconds> sms(ss);
zoned_time ztms(std::forward<Source>(s), sms);
static_assert(std::is_same<decltype(ztms), zoned_time<milliseconds, TimeZonePtr>>::value, "");
}
// local_time
{
local_days ld(2017_y/feb/20);
zoned_time ztd(std::forward<Source>(s), ld);
static_assert(std::is_same<decltype(ztd), zoned_time<seconds, TimeZonePtr>>::value, "");
local_time<seconds> ls(ld);
zoned_time zts(std::forward<Source>(s), ls);
static_assert(std::is_same<decltype(zts), zoned_time<seconds, TimeZonePtr>>::value, "");
local_time<milliseconds> lms(ls);
zoned_time ztms(std::forward<Source>(s), lms);
static_assert(std::is_same<decltype(ztms), zoned_time<milliseconds, TimeZonePtr>>::value, "");
}
// local_time, choose
{
local_days ld(2017_y/feb/20);
zoned_time ztd(std::forward<Source>(s), ld, choose::earliest);
static_assert(std::is_same<decltype(ztd), zoned_time<seconds, TimeZonePtr>>::value, "");
local_time<seconds> ls(ld);
zoned_time zts(std::forward<Source>(s), ls, choose::earliest);
static_assert(std::is_same<decltype(zts), zoned_time<seconds, TimeZonePtr>>::value, "");
local_time<milliseconds> lms(ls);
zoned_time ztms(std::forward<Source>(s), lms, choose::earliest);
static_assert(std::is_same<decltype(ztms), zoned_time<milliseconds, TimeZonePtr>>::value, "");
}
// zoned_time
{
zoned_time<days> zd(sys_days(2017_y/feb/20));
zoned_time ztd(std::forward<Source>(s), zd);
static_assert(std::is_same<decltype(ztd), zoned_time<seconds, TimeZonePtr>>::value, "");
zoned_time<seconds> zs(zd);
zoned_time zts(std::forward<Source>(s), zs);
static_assert(std::is_same<decltype(zts), zoned_time<seconds, TimeZonePtr>>::value, "");
zoned_time<milliseconds> zms(zs);
zoned_time ztms(std::forward<Source>(s), zms);
static_assert(std::is_same<decltype(ztms), zoned_time<milliseconds, TimeZonePtr>>::value, "");
}
// zoned_time, choose
{
zoned_time<days> zd(sys_days(2017_y/feb/20));
zoned_time ztd(std::forward<Source>(s), zd, choose::earliest);
static_assert(std::is_same<decltype(ztd), zoned_time<seconds, TimeZonePtr>>::value, "");
zoned_time<seconds> zs(zd);
zoned_time zts(std::forward<Source>(s), zs, choose::earliest);
static_assert(std::is_same<decltype(zts), zoned_time<seconds, TimeZonePtr>>::value, "");
zoned_time<milliseconds> zms(zs);
zoned_time ztms(std::forward<Source>(s), zms, choose::earliest);
static_assert(std::is_same<decltype(ztms), zoned_time<milliseconds, TimeZonePtr>>::value, "");
}
}
struct MyString
{
MyString(std::string s) : ms(std::move(s)) {}
operator std::string_view() const { return ms; }
private:
std::string ms;
};
struct OnlyLValueString
{
OnlyLValueString(std::string s) : ms(std::move(s)) {}
operator std::string_view() & { return ms; }
private:
std::string ms;
};
#endif // HAS_DEDUCTION_GUIDES
template<typename T>
T const& to_const(T& t) { return t; }
int
main()
{
using namespace date;
using namespace std::chrono;
#if HAS_DEDUCTION_GUIDES
// no arguments
{
zoned_time zt{};
static_assert(std::is_same<decltype(zt), zoned_time<seconds>>::value, "");
}
// zoned_time
{
zoned_time<days> zd(sys_days(2017_y/feb/20));
zoned_time ztd(zd);
static_assert(std::is_same<decltype(ztd), zoned_time<days>>::value, "");
zoned_time<seconds> zs(zd);
zoned_time zts(zs);
static_assert(std::is_same<decltype(zts), zoned_time<seconds>>::value, "");
zoned_time<milliseconds> zms(zs);
zoned_time ztms(zms);
static_assert(std::is_same<decltype(ztms), zoned_time<milliseconds>>::value, "");
}
// sys_time
{
sys_days sd(2017_y/feb/20);
zoned_time ztd(sd);
static_assert(std::is_same<decltype(ztd), zoned_time<seconds>>::value, "");
sys_time<seconds> ss(sd);
zoned_time zts(ss);
static_assert(std::is_same<decltype(zts), zoned_time<seconds>>::value, "");
sys_time<milliseconds> sms(ss);
zoned_time ztms(sms);
static_assert(std::is_same<decltype(ztms), zoned_time<milliseconds>>::value, "");
}
// time_zone const*
{
time_zone const* tz = current_zone();
testDeductionFrom<time_zone const*>(tz);
testDeductionFrom<time_zone const*>(to_const(tz));
testDeductionFrom<time_zone const*>(std::move(tz));
}
// char const*
{
char const* tz = "Europe/Warsaw";
testDeductionFrom<time_zone const*>(tz);
testDeductionFrom<time_zone const*>(to_const(tz));
testDeductionFrom<time_zone const*>(std::move(tz));
}
// std::string
{
std::string tz = "Europe/Warsaw";
testDeductionFrom<time_zone const*>(tz);
testDeductionFrom<time_zone const*>(to_const(tz));
testDeductionFrom<time_zone const*>(std::move(tz));
}
// std::string_view
{
std::string_view tz = "Europe/Warsaw";
testDeductionFrom<time_zone const*>(tz);
testDeductionFrom<time_zone const*>(to_const(tz));
testDeductionFrom<time_zone const*>(std::move(tz));
}
// MyString
{
MyString tz("Europe/Warsaw");
testDeductionFrom<time_zone const*>(tz);
testDeductionFrom<time_zone const*>(to_const(tz));
testDeductionFrom<time_zone const*>(std::move(tz));
}
// custom time zone
{
OffsetZone tz(minutes(45));
testDeductionFrom<OffsetZone>(tz);
testDeductionFrom<OffsetZone>(to_const(tz));
testDeductionFrom<OffsetZone>(std::move(tz));
}
// OnlyLValue
{
OnlyLValueString tz("Europe/Warsaw");
testDeductionFrom<time_zone const*>(tz);
//testDeductionFrom<time_zone const*>(to_const(tz));
//testDeductionFrom<time_zone const*>(std::move(tz));
}
#endif // HAS_DEDUCTION_GUIDES
}

10
test_fail.sh Executable file
View File

@ -0,0 +1,10 @@
#!/bin/bash
echo $1
eval $1
if [ $? -eq 0 ]; then
exit 0;
fi
exit 1;

1926
tz.h

File diff suppressed because it is too large Load Diff