├── .gitignore ├── .Rbuildignore ├── tests └── simpleTests.R ├── inst ├── examples │ ├── iso_week.cpp │ └── year_month_day.cpp ├── NEWS.Rd └── include │ ├── chrono_io.h │ ├── ios.h │ ├── tz_private.h │ ├── ptz.h │ ├── iso_week.h │ └── islamic.h ├── man └── RcppDate-package.Rd ├── .github └── workflows │ └── ci.yaml ├── local └── tz.cpp ├── DESCRIPTION ├── README.md └── ChangeLog /.gitignore: -------------------------------------------------------------------------------- 1 | .Rproj.user 2 | .Rhistory 3 | .RData 4 | .Ruserdata 5 | -------------------------------------------------------------------------------- /.Rbuildignore: -------------------------------------------------------------------------------- 1 | .*\.tar\.gz 2 | ^.*\.Rproj$ 3 | ^\.Rproj\.user$ 4 | ^local 5 | ^\.travis\.yml$ 6 | ^\.github 7 | -------------------------------------------------------------------------------- /tests/simpleTests.R: -------------------------------------------------------------------------------- 1 | 2 | ## super-simple 3 | ## TODO: proper tinytest tests of a compilation or two 4 | 5 | stopifnot(system.file("include", "date.h", package="RcppDate") != "") 6 | -------------------------------------------------------------------------------- /inst/examples/iso_week.cpp: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | #include 4 | 5 | // Examples for the 'date' header library -- 'iso_week' component 6 | // cf https://howardhinnant.github.io/date/iso_week.html 7 | 8 | // The next line is needed with Rcpp::cppFunction(). 9 | // For a package use LinkingTo: instead. 10 | // 11 | // [[Rcpp::depends(RcppDate)]] 12 | 13 | // [[Rcpp::export]] 14 | void isoWeekExample() { 15 | using namespace iso_week::literals; 16 | 17 | auto iso_date = sat/51/2015; 18 | Rcpp::Rcout << iso_date << '\n'; 19 | } 20 | 21 | /*** R 22 | isoWeekExample() 23 | */ -------------------------------------------------------------------------------- /man/RcppDate-package.Rd: -------------------------------------------------------------------------------- 1 | \name{RcppDate-package} 2 | \alias{RcppDate-package} 3 | \alias{RcppDate} 4 | \docType{package} 5 | \title{\packageTitle{RcppDate}} 6 | \description{\packageDescription{RcppDate}} 7 | \section{Package Content}{\packageIndices{RcppDate}} 8 | \author{\packageAuthor{RcppDate}} 9 | \section{Maintainer}{\packageMaintainer{RcppDate}} 10 | \keyword{package} 11 | \examples{ 12 | ## see the source files in the examples/ directory of the package 13 | ## check for (optional, only in Suggests:) Rcpp, and ensure we are 14 | ## not on Windows as this runs up to the ten second time limit 15 | if (requireNamespace("Rcpp", quietly=TRUE) && (.Platform$OS.type != "windows")) { 16 | Rcpp::sourceCpp(system.file("examples", "year_month_day.cpp", package="RcppDate")) 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /.github/workflows/ci.yaml: -------------------------------------------------------------------------------- 1 | # Run CI for R using https://eddelbuettel.github.io/r-ci/ 2 | 3 | name: ci 4 | 5 | on: 6 | push: 7 | pull_request: 8 | 9 | env: 10 | _R_CHECK_FORCE_SUGGESTS_: "false" 11 | 12 | jobs: 13 | ci: 14 | strategy: 15 | matrix: 16 | include: 17 | #- {os: macOS-latest} 18 | - {os: ubuntu-latest} 19 | 20 | runs-on: ${{ matrix.os }} 21 | 22 | steps: 23 | - name: Checkout 24 | uses: actions/checkout@v4 25 | 26 | - name: Setup 27 | uses: eddelbuettel/github-actions/r-ci@master 28 | 29 | - name: Dependencies 30 | run: ./run.sh install_deps 31 | 32 | - name: Test 33 | run: ./run.sh run_tests 34 | 35 | #- name: Coverage 36 | # if: ${{ matrix.os == 'ubuntu-latest' }} 37 | # run: ./run.sh coverage 38 | -------------------------------------------------------------------------------- /local/tz.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | // Examples for the 'date' header library -- 'tz' component 6 | // cf https://howardhinnant.github.io/date/tz.html 7 | 8 | // The next line is needed with Rcpp::cppFunction(). 9 | // For a package use LinkingTo: instead. 10 | // 11 | // [[Rcpp::depends(RcppDate)]] 12 | 13 | using namespace date; 14 | 15 | // [[Rcpp::export]] 16 | void tzExample() { 17 | using namespace date::literals; 18 | using namespace std::chrono_literals; 19 | auto meet_nyc = make_zoned("America/New_York", date::local_days{Monday[1]/May/2016} + 9h); 20 | auto meet_lon = make_zoned("Europe/London", meet_nyc); 21 | auto meet_syd = make_zoned("Australia/Sydney", meet_nyc); 22 | Rcpp::Rcout << "The New York meeting is " << meet_nyc << '\n'; 23 | Rcpp::Rcout << "The London meeting is " << meet_lon << '\n'; 24 | Rcpp::Rcout << "The Sydney meeting is " << meet_syd << '\n'; 25 | } 26 | -------------------------------------------------------------------------------- /DESCRIPTION: -------------------------------------------------------------------------------- 1 | Package: RcppDate 2 | Type: Package 3 | Title: 'date' C++ Header Library for Date and Time Functionality 4 | Version: 0.0.6 5 | Date: 2025-05-29 6 | Authors@R: c(person("Dirk", "Eddelbuettel", role = c("aut", "cre"), email = "edd@debian.org", 7 | comment = c(ORCID = "0000-0001-6419-907X")), 8 | person("Howard", "Hinnant", role = "aut", comment = "author of 'date' library")) 9 | Description: A header-only C++ library is provided with support 10 | for dates, time zones, ISO weeks, Julian dates, and Islamic dates. 11 | 'date' offers extensive date and time functionality for the C++11, 12 | C++14 and C++17 standards and was written by Howard Hinnant and released 13 | under the MIT license. A slightly modified version has been accepted 14 | (along with 'tz.h') as part of C++20. This package regroups all 15 | header files from the upstream repository by Howard Hinnant so that 16 | other R packages can use them in their C++ code. At present, few of 17 | the types have explicit 'Rcpp' wrappers though these may be added as 18 | needed. 19 | License: GPL (>= 2) 20 | Suggests: Rcpp 21 | URL: https://github.com/eddelbuettel/rcppdate, https://dirk.eddelbuettel.com/code/rcpp.date.html 22 | BugReports: https://github.com/eddelbuettel/rcppdate/issues 23 | -------------------------------------------------------------------------------- /inst/NEWS.Rd: -------------------------------------------------------------------------------- 1 | \name{NEWS} 2 | \title{News for Package \pkg{RcppDate}} 3 | \newcommand{\ghpr}{\href{https://github.com/eddelbuettel/rcppdate/pull/#1}{##1}} 4 | \newcommand{\ghit}{\href{https://github.com/eddelbuettel/rcppdate/issues/#1}{##1}} 5 | 6 | \section{Changes in version 0.0.6 (2025-05-29)}{ 7 | \itemize{ 8 | \item Updated to upstream version 3.0.4 9 | } 10 | } 11 | 12 | \section{Changes in version 0.0.5 (2025-03-06)}{ 13 | \itemize{ 14 | \item Updated to upstream version 3.0.3 15 | \item Updated 'whitespace in literal' issue upsetting clang++-20; this is 16 | also fixed upstream via two PRs 17 | } 18 | } 19 | 20 | \section{Changes in version 0.0.4 (2024-10-14)}{ 21 | \itemize{ 22 | \item Updated to upstream version 3.0.2 (and adjusting one pragma) 23 | \item Several small updates to overall packaging and testing 24 | } 25 | } 26 | 27 | \section{Changes in version 0.0.3 (2021-05-19)}{ 28 | \itemize{ 29 | \item Updated to upstream version 3.0.1 30 | } 31 | } 32 | 33 | \section{Changes in version 0.0.2 (2021-01-29)}{ 34 | \itemize{ 35 | \item Added GitHub Actions CI via \code{run.sh} from \pkg{r-ci} 36 | \item Updated to upstream version 3.0.0 (plus newer commits) 37 | } 38 | } 39 | 40 | \section{Changes in version 0.0.1 (2020-03-17)}{ 41 | \itemize{ 42 | \item Initial CRAN upload of first version 43 | } 44 | } 45 | 46 | -------------------------------------------------------------------------------- /inst/include/chrono_io.h: -------------------------------------------------------------------------------- 1 | #ifndef CHRONO_IO_H 2 | #define CHRONO_IO_H 3 | 4 | // The MIT License (MIT) 5 | // 6 | // Copyright (c) 2016, 2017 Howard Hinnant 7 | // 8 | // Permission is hereby granted, free of charge, to any person obtaining a copy 9 | // of this software and associated documentation files (the "Software"), to deal 10 | // in the Software without restriction, including without limitation the rights 11 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 12 | // copies of the Software, and to permit persons to whom the Software is 13 | // furnished to do so, subject to the following conditions: 14 | // 15 | // The above copyright notice and this permission notice shall be included in all 16 | // copies or substantial portions of the Software. 17 | // 18 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 24 | // SOFTWARE. 25 | // 26 | // Our apologies. When the previous paragraph was written, lowercase had not yet 27 | // been invented (that would involve another several millennia of evolution). 28 | // We did not mean to shout. 29 | 30 | // This functionality has moved to "date.h" 31 | 32 | #include "date.h" 33 | 34 | #endif // CHRONO_IO_H 35 | -------------------------------------------------------------------------------- /inst/include/ios.h: -------------------------------------------------------------------------------- 1 | // 2 | // ios.h 3 | // DateTimeLib 4 | // 5 | // The MIT License (MIT) 6 | // 7 | // Copyright (c) 2016 Alexander Kormanovsky 8 | // 9 | // Permission is hereby granted, free of charge, to any person obtaining a copy 10 | // of this software and associated documentation files (the "Software"), to deal 11 | // in the Software without restriction, including without limitation the rights 12 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 13 | // copies of the Software, and to permit persons to whom the Software is 14 | // furnished to do so, subject to the following conditions: 15 | // 16 | // The above copyright notice and this permission notice shall be included in all 17 | // copies or substantial portions of the Software. 18 | // 19 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 20 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 21 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 22 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 23 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 24 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 25 | // SOFTWARE. 26 | 27 | #ifndef ios_hpp 28 | #define ios_hpp 29 | 30 | #if __APPLE__ 31 | # include 32 | # if TARGET_OS_IPHONE 33 | # include 34 | 35 | namespace date 36 | { 37 | namespace iOSUtils 38 | { 39 | 40 | std::string get_tzdata_path(); 41 | std::string get_current_timezone(); 42 | 43 | } // namespace iOSUtils 44 | } // namespace date 45 | 46 | # endif // TARGET_OS_IPHONE 47 | #else // !__APPLE__ 48 | # define TARGET_OS_IPHONE 0 49 | #endif // !__APPLE__ 50 | #endif // ios_hpp 51 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | 2 | ## RcppDate: date C++ header library for R 3 | 4 | [![CI](https://github.com/eddelbuettel/rcppdate/workflows/ci/badge.svg)](https://github.com/eddelbuettel/rcppdate/actions?query=workflow%3Aci) 5 | [![License](https://eddelbuettel.github.io/badges/GPL2+.svg)](https://www.gnu.org/licenses/old-licenses/gpl-2.0.html) 6 | [![CRAN](https://www.r-pkg.org/badges/version/RcppDate)](https://cran.r-project.org/package=RcppDate) 7 | [![Dependencies](https://tinyverse.netlify.app/badge/RcppDate)](https://cran.r-project.org/package=RcppDate) 8 | [![Downloads](https://cranlogs.r-pkg.org/badges/RcppDate?color=brightgreen)](https://www.r-pkg.org/pkg/RcppDate) 9 | [![Last Commit](https://img.shields.io/github/last-commit/eddelbuettel/rcppdate)](https://github.com/eddelbuettel/rcppdate) 10 | 11 | ### About 12 | 13 | The [date](https://github.com/HowardHinnant/date) library by Howard Hinnant 14 | offers extensive date and time functionality for the C++11, C++14 and C++17 15 | standards. A slighly modified version of `date.h` has been accepted (along 16 | with `tz.h`) as part of C++20. 17 | 18 | This package regroups all header files from the upstream repository by Howard 19 | Hinnant so that other R packages can use them in their C++ code. 20 | 21 | ### Example 22 | 23 | There is _a lot_ of functionality in this library. As a teaser, consider these three 24 | compile-time instantiations of `year_month_day` types: 25 | 26 | ```c++ 27 | constexpr auto x1 = 2015_y/March/22; 28 | constexpr auto x2 = March/22/2015; 29 | constexpr auto x3 = 22_d/March/2015; 30 | ``` 31 | 32 | See the file [inst/examples/year_month_day.cpp](inst/examples/year_month_day.cpp) for 33 | the complete example, and the upstream documentation for full details. 34 | 35 | ### Limitations 36 | 37 | The `tz.h` header requires compiled support from 38 | [`tz.cpp`](https://github.com/HowardHinnant/date/blob/master/src/tz.cpp) 39 | which is not currently included so that this remains a header-only library. 40 | 41 | ### See Also 42 | 43 | The [date](https://github.com/HowardHinnant/date) repository and its links to 44 | documentation. 45 | 46 | ### Author 47 | 48 | [date](https://github.com/HowardHinnant/date) was written by Howard Hinnant. 49 | 50 | This package was put together by Dirk Eddelbuettel 51 | 52 | ### License 53 | 54 | The underlying library is MIT licensed. 55 | 56 | The packaging and integrations is licensed under GPL (>= 2). 57 | -------------------------------------------------------------------------------- /inst/examples/year_month_day.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | // Examples for the 'date' header library 5 | // cf https://howardhinnant.github.io/date/date.html 6 | 7 | // The next line is needed with Rcpp::cppFunction(). 8 | // For a package use LinkingTo: instead. 9 | // 10 | // [[Rcpp::depends(RcppDate)]] 11 | 12 | using namespace date; 13 | 14 | Rcpp::Date makeDate(const year_month_day & ymd) { 15 | return Rcpp::Date(static_cast(ymd.year()), 16 | static_cast(ymd.month()), 17 | static_cast(ymd.day())); 18 | } 19 | 20 | // [[Rcpp::export]] 21 | Rcpp::DateVector ymdExample(bool verbose=false) { 22 | 23 | constexpr auto x1 = 2015_y/March/22; 24 | constexpr auto x2 = March/22/2015; 25 | constexpr auto x3 = 22_d/March/2015; 26 | 27 | if (verbose) { 28 | Rcpp::Rcout << x1 << " " << x2 << " " << x3 << std::endl; 29 | Rcpp::Rcout << x1.year() << " " << x1.month() << " " << x1.day() << std::endl; 30 | } 31 | 32 | return Rcpp::DateVector::create(makeDate(x1), makeDate(x2), makeDate(x3)); 33 | } 34 | 35 | 36 | // [[Rcpp::export]] 37 | Rcpp::DateVector ymdlExample(bool verbose=false) { 38 | 39 | constexpr auto x1 = 2015_y/February/last; 40 | constexpr auto x2 = February/last/2015; 41 | constexpr auto x3 = last/February/2015; 42 | 43 | return Rcpp::DateVector::create(makeDate(x1), makeDate(x2), makeDate(x3)); 44 | } 45 | 46 | // [[Rcpp::export]] 47 | Rcpp::DateVector ymwdExample(bool verbose=false) { 48 | 49 | constexpr auto x1 = 2015_y/March/Sunday[4]; 50 | constexpr auto x2 = March/Sunday[4]/2015; 51 | constexpr auto x3 = Sunday[4]/March/2015; 52 | 53 | return Rcpp::DateVector::create(makeDate(year_month_day{x1}), 54 | makeDate(year_month_day{x2}), 55 | makeDate(year_month_day{x3})); 56 | } 57 | 58 | // [[Rcpp::export]] 59 | Rcpp::DateVector ymwdlExample(bool verbose=false) { 60 | 61 | constexpr auto x1 = 2015_y/March/Sunday[last]; 62 | constexpr auto x2 = March/Sunday[last]/2015; 63 | constexpr auto x3 = Sunday[last]/March/2015; 64 | 65 | return Rcpp::DateVector::create(makeDate(year_month_day{x1}), 66 | makeDate(year_month_day{x2}), 67 | makeDate(year_month_day{x3})); 68 | } 69 | 70 | /*** R 71 | ymdExample() 72 | ymdlExample() 73 | ymwdExample() 74 | ymwdlExample() 75 | */ 76 | -------------------------------------------------------------------------------- /ChangeLog: -------------------------------------------------------------------------------- 1 | 2025-05-29 Dirk Eddelbuettel 2 | 3 | * DESCRIPTION (Date, Version): Release 0.0.6 4 | 5 | 2025-05-28 Dirk Eddelbuettel 6 | 7 | * inst/include/date.h: Sync with upstream release 3.0.4 8 | * inst/include/ptx.h: Idem 9 | 10 | * inst/include/date.h: As before, comment-out one 'stringop-overflow' 11 | pragma r-devel complains about 12 | 13 | 2025-03-17 Dirk Eddelbuettel 14 | 15 | * .github/workflows/ci.yaml: Switch to r-ci with implicit bootstrap 16 | 17 | 2025-03-06 Dirk Eddelbuettel 18 | 19 | * DESCRIPTION (Date, Version): Release 0.0.5 20 | 21 | 2025-03-05 Dirk Eddelbuettel 22 | 23 | * inst/include/date.h: Deal with 'whitespace in literal' that upsets 24 | newest clang; changes are upstream too in PRs #869 and #870 25 | * inst/include/islamic.h: Idem 26 | * inst/include/iso_week.h: Idem 27 | * inst/include/julian.h: Idem 28 | * inst/include/solar_hijiri.h: Idem 29 | 30 | 2024-10-21 Dirk Eddelbuettel 31 | 32 | * DESCRIPTION (Version, Date): Roll micro version and date 33 | 34 | 2024-10-20 Dirk Eddelbuettel 35 | 36 | * inst/include/tz.h: Sync with upstream release 3.0.3 37 | 38 | 2024-10-14 Dirk Eddelbuettel 39 | 40 | * DESCRIPTION (Date, Version): Release 0.0.4 41 | 42 | * inst/include/date.h (read): Comment-out one 'stringop-overflow' 43 | pragma r-devel complains about 44 | 45 | * README.md: Switch http to https for gnu.org link 46 | 47 | 2024-10-12 Dirk Eddelbuettel 48 | 49 | * DESCRIPTION (Version, Date): Roll micro version and date 50 | 51 | * inst/include/tz.h: Sync with upstream release 3.0.2 52 | 53 | 2024-09-25 Dirk Eddelbuettel 54 | 55 | * README.md: Switch http to https for r-pkg.org badge 56 | 57 | 2024-09-12 Dirk Eddelbuettel 58 | 59 | * DESCRIPTION (Authors@R): Added 60 | 61 | 2024-05-24 Dirk Eddelbuettel 62 | 63 | * inst/include/date.h: Sync with upstream 64 | * inst/include/ptz.h: Idem 65 | * inst/include/tz.h: Idem 66 | * inst/include/tz_private.h: Idem 67 | 68 | 2024-05-21 Dirk Eddelbuettel 69 | 70 | * README.md: Use tinyverse.netlify.app for dependency badge 71 | 72 | 2024-03-01 Dirk Eddelbuettel 73 | 74 | * .github/workflows/ci.yaml (jobs): Update to actions/checkout@v4, 75 | add r-ci-setup actions 76 | 77 | 2023-05-20 Dirk Eddelbuettel 78 | 79 | * DESCRIPTION (Version, Date): Roll micro version and date 80 | 81 | * inst/include/date.h: Sync with upstream 82 | * inst/include/ios.h: Idem 83 | * inst/include/iso_week.h: Idem 84 | * inst/include/julian.h: Idem 85 | * inst/include/ptz.h: Idem 86 | * inst/include/solar_hijri.h: Idem 87 | * inst/include/tz.h: Idem 88 | 89 | 2022-11-10 Dirk Eddelbuettel 90 | 91 | * .github/workflows/ci.yaml (jobs): Update to actions/checkout@v3 92 | 93 | 2021-12-08 Dirk Eddelbuettel 94 | 95 | * README.md: Remove unused continuous integration artifact and badge 96 | 97 | 2021-05-19 Dirk Eddelbuettel 98 | 99 | * DESCRIPTION (Date, Version): Release 0.0.3 100 | 101 | 2021-05-18 Dirk Eddelbuettel 102 | 103 | * inst/include/date.h: Upstream 3.0.1 104 | * inst/include/ptz.h: Ditto 105 | 106 | 2021-04-25 Dirk Eddelbuettel 107 | 108 | * DESCRIPTION (URL): Add repo 109 | 110 | 2021-01-29 Dirk Eddelbuettel 111 | 112 | * DESCRIPTION (Date, Version): Release 0.0.2 113 | (Description): Slightly reworded 114 | 115 | * inst/include/date.h: Another upstream commit since 3.0.0 116 | 117 | * README.md: Added badge for downloads 118 | 119 | 2021-01-03 Dirk Eddelbuettel 120 | 121 | * inst/include/date.h: Upstream 3.0.0 plus more recent commits 122 | * inst/include/julian.h: Ditto 123 | * inst/include/ptz.h: Ditto 124 | * inst/include/solar_hijri.h: Ditto 125 | * inst/include/tz_private.h: Ditto 126 | * inst/include/tz.h: Ditto 127 | 128 | * .github/workflows/ci.yaml: Add CI runner using r-ci 129 | * README.md: Add new badge 130 | 131 | 2020-06-19 Dirk Eddelbuettel 132 | 133 | * .travis.yml: Determine package name and version from DESCRIPTION, 134 | switch to bionic 135 | 136 | 2020-03-24 Dirk Eddelbuettel 137 | 138 | * README.md: Badges for CRAN version, dependencies and last commit 139 | 140 | * inst/NEWS.Rd: Added 141 | 142 | 2020-03-17 Dirk Eddelbuettel 143 | 144 | * DESCRIPTION (Date, Version): Initial CRAN release 0.0.1 145 | 146 | 2020-03-16 Dirk Eddelbuettel 147 | 148 | * README.md: Added two badges, added short example 149 | 150 | * inst/examples/iso_week.cpp: Simple example for ISO week support 151 | 152 | * .travis.yml: Added to support continuous integration 153 | 154 | 2020-03-15 Dirk Eddelbuettel 155 | 156 | * DESCRIPTION (Version, Date): Initial version 157 | 158 | * inst/include/*: 'date' C++ header library by Howard Hinnant 159 | 160 | * inst/examples/year_month_date.cpp: Simple example for the 161 | year_month_day type 162 | -------------------------------------------------------------------------------- /inst/include/tz_private.h: -------------------------------------------------------------------------------- 1 | #ifndef TZ_PRIVATE_H 2 | #define TZ_PRIVATE_H 3 | 4 | // The MIT License (MIT) 5 | // 6 | // Copyright (c) 2015, 2016 Howard Hinnant 7 | // 8 | // Permission is hereby granted, free of charge, to any person obtaining a copy 9 | // of this software and associated documentation files (the "Software"), to deal 10 | // in the Software without restriction, including without limitation the rights 11 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 12 | // copies of the Software, and to permit persons to whom the Software is 13 | // furnished to do so, subject to the following conditions: 14 | // 15 | // The above copyright notice and this permission notice shall be included in all 16 | // copies or substantial portions of the Software. 17 | // 18 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 24 | // SOFTWARE. 25 | // 26 | // Our apologies. When the previous paragraph was written, lowercase had not yet 27 | // been invented (that would involve another several millennia of evolution). 28 | // We did not mean to shout. 29 | 30 | #if !defined(_MSC_VER) || (_MSC_VER >= 1900) 31 | #include "tz.h" 32 | #else 33 | #include "date.h" 34 | #include 35 | #endif 36 | 37 | namespace date 38 | { 39 | 40 | namespace detail 41 | { 42 | 43 | #if !USE_OS_TZDB 44 | 45 | enum class tz {utc, local, standard}; 46 | 47 | //forward declare to avoid warnings in gcc 6.2 48 | class MonthDayTime; 49 | std::istream& operator>>(std::istream& is, MonthDayTime& x); 50 | std::ostream& operator<<(std::ostream& os, const MonthDayTime& x); 51 | 52 | 53 | class MonthDayTime 54 | { 55 | private: 56 | struct pair 57 | { 58 | #if defined(_MSC_VER) && (_MSC_VER < 1900) 59 | pair() : month_day_(date::jan / 1), weekday_(0U) {} 60 | 61 | pair(const date::month_day& month_day, const date::weekday& weekday) 62 | : month_day_(month_day), weekday_(weekday) {} 63 | #endif 64 | 65 | date::month_day month_day_; 66 | date::weekday weekday_; 67 | }; 68 | 69 | enum Type {month_day, month_last_dow, lteq, gteq}; 70 | 71 | Type type_{month_day}; 72 | 73 | #if !defined(_MSC_VER) || (_MSC_VER >= 1900) 74 | union U 75 | #else 76 | struct U 77 | #endif 78 | { 79 | date::month_day month_day_; 80 | date::month_weekday_last month_weekday_last_; 81 | pair month_day_weekday_; 82 | 83 | #if !defined(_MSC_VER) || (_MSC_VER >= 1900) 84 | U() : month_day_{date::jan/1} {} 85 | #else 86 | U() : 87 | month_day_(date::jan/1), 88 | month_weekday_last_(date::month(0U), date::weekday_last(date::weekday(0U))) 89 | {} 90 | 91 | #endif // !defined(_MSC_VER) || (_MSC_VER >= 1900) 92 | 93 | U& operator=(const date::month_day& x); 94 | U& operator=(const date::month_weekday_last& x); 95 | U& operator=(const pair& x); 96 | } u; 97 | 98 | std::chrono::hours h_{0}; 99 | std::chrono::minutes m_{0}; 100 | std::chrono::seconds s_{0}; 101 | tz zone_{tz::local}; 102 | 103 | public: 104 | MonthDayTime() = default; 105 | MonthDayTime(local_seconds tp, tz timezone); 106 | MonthDayTime(const date::month_day& md, tz timezone); 107 | 108 | date::day day() const; 109 | date::month month() const; 110 | tz zone() const {return zone_;} 111 | 112 | void canonicalize(date::year y); 113 | 114 | sys_seconds 115 | to_sys(date::year y, std::chrono::seconds offset, std::chrono::seconds save) const; 116 | sys_days to_sys_days(date::year y) const; 117 | 118 | sys_seconds to_time_point(date::year y) const; 119 | int compare(date::year y, const MonthDayTime& x, date::year yx, 120 | std::chrono::seconds offset, std::chrono::minutes prev_save) const; 121 | 122 | friend std::istream& operator>>(std::istream& is, MonthDayTime& x); 123 | friend std::ostream& operator<<(std::ostream& os, const MonthDayTime& x); 124 | }; 125 | 126 | // A Rule specifies one or more set of datetimes without using an offset. 127 | // Multiple dates are specified with multiple years. The years in effect 128 | // go from starting_year_ to ending_year_, inclusive. starting_year_ <= 129 | // ending_year_. save_ is in effect for times from the specified time 130 | // onward, including the specified time. When the specified time is 131 | // local, it uses the save_ from the chronologically previous Rule, or if 132 | // there is none, 0. 133 | 134 | //forward declare to avoid warnings in gcc 6.2 135 | class Rule; 136 | bool operator==(const Rule& x, const Rule& y); 137 | bool operator<(const Rule& x, const Rule& y); 138 | bool operator==(const Rule& x, const date::year& y); 139 | bool operator<(const Rule& x, const date::year& y); 140 | bool operator==(const date::year& x, const Rule& y); 141 | bool operator<(const date::year& x, const Rule& y); 142 | bool operator==(const Rule& x, const std::string& y); 143 | bool operator<(const Rule& x, const std::string& y); 144 | bool operator==(const std::string& x, const Rule& y); 145 | bool operator<(const std::string& x, const Rule& y); 146 | std::ostream& operator<<(std::ostream& os, const Rule& r); 147 | 148 | class Rule 149 | { 150 | private: 151 | std::string name_; 152 | date::year starting_year_{0}; 153 | date::year ending_year_{0}; 154 | MonthDayTime starting_at_; 155 | std::chrono::minutes save_{0}; 156 | std::string abbrev_; 157 | 158 | public: 159 | Rule() = default; 160 | explicit Rule(const std::string& s); 161 | Rule(const Rule& r, date::year starting_year, date::year ending_year); 162 | 163 | const std::string& name() const {return name_;} 164 | const std::string& abbrev() const {return abbrev_;} 165 | 166 | const MonthDayTime& mdt() const {return starting_at_;} 167 | const date::year& starting_year() const {return starting_year_;} 168 | const date::year& ending_year() const {return ending_year_;} 169 | const std::chrono::minutes& save() const {return save_;} 170 | 171 | static void split_overlaps(std::vector& rules); 172 | 173 | friend bool operator==(const Rule& x, const Rule& y); 174 | friend bool operator<(const Rule& x, const Rule& y); 175 | friend bool operator==(const Rule& x, const date::year& y); 176 | friend bool operator<(const Rule& x, const date::year& y); 177 | friend bool operator==(const date::year& x, const Rule& y); 178 | friend bool operator<(const date::year& x, const Rule& y); 179 | friend bool operator==(const Rule& x, const std::string& y); 180 | friend bool operator<(const Rule& x, const std::string& y); 181 | friend bool operator==(const std::string& x, const Rule& y); 182 | friend bool operator<(const std::string& x, const Rule& y); 183 | 184 | friend std::ostream& operator<<(std::ostream& os, const Rule& r); 185 | 186 | private: 187 | date::day day() const; 188 | date::month month() const; 189 | static void split_overlaps(std::vector& rules, std::size_t i, std::size_t& e); 190 | static bool overlaps(const Rule& x, const Rule& y); 191 | static void split(std::vector& rules, std::size_t i, std::size_t k, 192 | std::size_t& e); 193 | }; 194 | 195 | inline bool operator!=(const Rule& x, const Rule& y) {return !(x == y);} 196 | inline bool operator> (const Rule& x, const Rule& y) {return y < x;} 197 | inline bool operator<=(const Rule& x, const Rule& y) {return !(y < x);} 198 | inline bool operator>=(const Rule& x, const Rule& y) {return !(x < y);} 199 | 200 | inline bool operator!=(const Rule& x, const date::year& y) {return !(x == y);} 201 | inline bool operator> (const Rule& x, const date::year& y) {return y < x;} 202 | inline bool operator<=(const Rule& x, const date::year& y) {return !(y < x);} 203 | inline bool operator>=(const Rule& x, const date::year& y) {return !(x < y);} 204 | 205 | inline bool operator!=(const date::year& x, const Rule& y) {return !(x == y);} 206 | inline bool operator> (const date::year& x, const Rule& y) {return y < x;} 207 | inline bool operator<=(const date::year& x, const Rule& y) {return !(y < x);} 208 | inline bool operator>=(const date::year& x, const Rule& y) {return !(x < y);} 209 | 210 | inline bool operator!=(const Rule& x, const std::string& y) {return !(x == y);} 211 | inline bool operator> (const Rule& x, const std::string& y) {return y < x;} 212 | inline bool operator<=(const Rule& x, const std::string& y) {return !(y < x);} 213 | inline bool operator>=(const Rule& x, const std::string& y) {return !(x < y);} 214 | 215 | inline bool operator!=(const std::string& x, const Rule& y) {return !(x == y);} 216 | inline bool operator> (const std::string& x, const Rule& y) {return y < x;} 217 | inline bool operator<=(const std::string& x, const Rule& y) {return !(y < x);} 218 | inline bool operator>=(const std::string& x, const Rule& y) {return !(x < y);} 219 | 220 | struct zonelet 221 | { 222 | enum tag {has_rule, has_save, is_empty}; 223 | 224 | std::chrono::seconds gmtoff_; 225 | tag tag_ = has_rule; 226 | 227 | #if !defined(_MSC_VER) || (_MSC_VER >= 1900) 228 | union U 229 | #else 230 | struct U 231 | #endif 232 | { 233 | std::string rule_; 234 | std::chrono::minutes save_; 235 | 236 | ~U() {} 237 | U() {} 238 | U(const U&) {} 239 | U& operator=(const U&) = delete; 240 | } u; 241 | 242 | std::string format_; 243 | date::year until_year_{0}; 244 | MonthDayTime until_date_; 245 | sys_seconds until_utc_; 246 | local_seconds until_std_; 247 | local_seconds until_loc_; 248 | std::chrono::minutes initial_save_{0}; 249 | std::string initial_abbrev_; 250 | std::pair first_rule_{nullptr, date::year::min()}; 251 | std::pair last_rule_{nullptr, date::year::max()}; 252 | 253 | ~zonelet(); 254 | zonelet(); 255 | zonelet(const zonelet& i); 256 | zonelet& operator=(const zonelet&) = delete; 257 | }; 258 | 259 | #else // USE_OS_TZDB 260 | 261 | struct ttinfo 262 | { 263 | std::int32_t tt_gmtoff; 264 | unsigned char tt_isdst; 265 | unsigned char tt_abbrind; 266 | unsigned char pad[2]; 267 | }; 268 | 269 | static_assert(sizeof(ttinfo) == 8, ""); 270 | 271 | struct expanded_ttinfo 272 | { 273 | std::chrono::seconds offset; 274 | std::string abbrev; 275 | bool is_dst; 276 | }; 277 | 278 | struct transition 279 | { 280 | sys_seconds timepoint; 281 | const expanded_ttinfo* info; 282 | 283 | transition(sys_seconds tp, const expanded_ttinfo* i = nullptr) 284 | : timepoint(tp) 285 | , info(i) 286 | {} 287 | 288 | friend 289 | std::ostream& 290 | operator<<(std::ostream& os, const transition& t) 291 | { 292 | date::operator<<(os, t.timepoint) << "Z "; 293 | if (t.info->offset >= std::chrono::seconds{0}) 294 | os << '+'; 295 | os << make_time(t.info->offset); 296 | if (t.info->is_dst > 0) 297 | os << " daylight "; 298 | else 299 | os << " standard "; 300 | os << t.info->abbrev; 301 | return os; 302 | } 303 | }; 304 | 305 | #endif // USE_OS_TZDB 306 | 307 | } // namespace detail 308 | 309 | } // namespace date 310 | 311 | #if defined(_MSC_VER) && (_MSC_VER < 1900) 312 | #include "tz.h" 313 | #endif 314 | 315 | #endif // TZ_PRIVATE_H 316 | -------------------------------------------------------------------------------- /inst/include/ptz.h: -------------------------------------------------------------------------------- 1 | #ifndef PTZ_H 2 | #define PTZ_H 3 | 4 | // The MIT License (MIT) 5 | // 6 | // Copyright (c) 2017 Howard Hinnant 7 | // 8 | // Permission is hereby granted, free of charge, to any person obtaining a copy 9 | // of this software and associated documentation files (the "Software"), to deal 10 | // in the Software without restriction, including without limitation the rights 11 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 12 | // copies of the Software, and to permit persons to whom the Software is 13 | // furnished to do so, subject to the following conditions: 14 | // 15 | // The above copyright notice and this permission notice shall be included in all 16 | // copies or substantial portions of the Software. 17 | // 18 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 24 | // SOFTWARE. 25 | 26 | // This header allows Posix-style time zones as specified for TZ here: 27 | // http://pubs.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap08.html#tag_08_03 28 | // 29 | // Posix::time_zone can be constructed with a posix-style string and then used in 30 | // a zoned_time like so: 31 | // 32 | // zoned_time zt{"EST5EDT,M3.2.0,M11.1.0", 33 | // system_clock::now()}; 34 | // or: 35 | // 36 | // Posix::time_zone tz{"EST5EDT,M3.2.0,M11.1.0"}; 37 | // zoned_time zt{tz, system_clock::now()}; 38 | // 39 | // In C++17 CTAD simplifies this to: 40 | // 41 | // Posix::time_zone tz{"EST5EDT,M3.2.0,M11.1.0"}; 42 | // zoned_time zt{tz, system_clock::now()}; 43 | // 44 | // Extension to the Posix rules to allow a constant daylight saving offset: 45 | // 46 | // If the rule set is missing (everything starting with ','), then 47 | // there must be exactly one abbreviation (std or daylight) with 48 | // length 3 or greater, and that will be used as the constant offset. If 49 | // there are two, the std abbreviation is silently set to "", and the 50 | // result is constant daylight saving. If there are zero abbreviations 51 | // with no rule set, an exception is thrown. 52 | // 53 | // Example: 54 | // "EST5" yields a constant offset of -5h with 0h save and "EST abbreviation. 55 | // "5EDT" yields a constant offset of -4h with 1h save and "EDT" abbreviation. 56 | // "EST5EDT" and "5EDT4" are both equal to "5EDT". 57 | // 58 | // Note, Posix-style time zones are not recommended for all of the reasons described here: 59 | // https://stackoverflow.com/tags/timezone/info 60 | // 61 | // They are provided here as a non-trivial custom time zone example, and if you really 62 | // have to have Posix time zones, you're welcome to use this one. 63 | 64 | #include "date/tz.h" 65 | #include 66 | #include 67 | #include 68 | #include 69 | 70 | namespace Posix 71 | { 72 | 73 | namespace detail 74 | { 75 | 76 | #if HAS_STRING_VIEW 77 | 78 | using string_t = std::string_view; 79 | 80 | #else // !HAS_STRING_VIEW 81 | 82 | using string_t = std::string; 83 | 84 | #endif // !HAS_STRING_VIEW 85 | 86 | class rule; 87 | 88 | void throw_invalid(const string_t& s, unsigned i, const string_t& message); 89 | unsigned read_date(const string_t& s, unsigned i, rule& r); 90 | unsigned read_name(const string_t& s, unsigned i, std::string& name); 91 | unsigned read_signed_time(const string_t& s, unsigned i, std::chrono::seconds& t); 92 | unsigned read_unsigned_time(const string_t& s, unsigned i, std::chrono::seconds& t); 93 | unsigned read_unsigned(const string_t& s, unsigned i, unsigned limit, unsigned& u, 94 | const string_t& message = string_t{}); 95 | 96 | class rule 97 | { 98 | enum {off, J, M, N}; 99 | 100 | date::month m_; 101 | date::weekday wd_; 102 | unsigned short n_ : 14; 103 | unsigned short mode_ : 2; 104 | std::chrono::duration time_ = std::chrono::hours{2}; 105 | 106 | public: 107 | rule() : mode_(off) {} 108 | 109 | bool ok() const {return mode_ != off;} 110 | date::local_seconds operator()(date::year y) const; 111 | std::string to_string() const; 112 | 113 | friend std::ostream& operator<<(std::ostream& os, const rule& r); 114 | friend unsigned read_date(const string_t& s, unsigned i, rule& r); 115 | friend bool operator==(const rule& x, const rule& y); 116 | }; 117 | 118 | inline 119 | bool 120 | operator==(const rule& x, const rule& y) 121 | { 122 | if (x.mode_ != y.mode_) 123 | return false; 124 | switch (x.mode_) 125 | { 126 | case rule::J: 127 | case rule::N: 128 | return x.n_ == y.n_; 129 | case rule::M: 130 | return x.m_ == y.m_ && x.n_ == y.n_ && x.wd_ == y.wd_; 131 | default: 132 | return true; 133 | } 134 | } 135 | 136 | inline 137 | bool 138 | operator!=(const rule& x, const rule& y) 139 | { 140 | return !(x == y); 141 | } 142 | 143 | inline 144 | date::local_seconds 145 | rule::operator()(date::year y) const 146 | { 147 | using date::local_days; 148 | using date::January; 149 | using date::days; 150 | using date::last; 151 | using sec = std::chrono::seconds; 152 | date::local_seconds t; 153 | switch (mode_) 154 | { 155 | case J: 156 | t = local_days{y/January/0} + days{n_ + (y.is_leap() && n_ > 59)} + sec{time_}; 157 | break; 158 | case M: 159 | t = (n_ == 5 ? local_days{y/m_/wd_[last]} : local_days{y/m_/wd_[n_]}) + sec{time_}; 160 | break; 161 | case N: 162 | t = local_days{y/January/1} + days{n_} + sec{time_}; 163 | break; 164 | default: 165 | assert(!"rule called with bad mode"); 166 | } 167 | return t; 168 | } 169 | 170 | inline 171 | std::string 172 | rule::to_string() const 173 | { 174 | using namespace std::chrono; 175 | auto print_offset = [](seconds off) 176 | { 177 | std::string nm; 178 | if (off != hours{2}) 179 | { 180 | date::hh_mm_ss offset{off}; 181 | nm = '/'; 182 | nm += std::to_string(offset.hours().count()); 183 | if (offset.minutes() != minutes{0} || offset.seconds() != seconds{0}) 184 | { 185 | nm += ':'; 186 | if (offset.minutes() < minutes{10}) 187 | nm += '0'; 188 | nm += std::to_string(offset.minutes().count()); 189 | if (offset.seconds() != seconds{0}) 190 | { 191 | nm += ':'; 192 | if (offset.seconds() < seconds{10}) 193 | nm += '0'; 194 | nm += std::to_string(offset.seconds().count()); 195 | } 196 | } 197 | } 198 | return nm; 199 | }; 200 | 201 | std::string nm; 202 | switch (mode_) 203 | { 204 | case rule::J: 205 | nm = 'J'; 206 | nm += std::to_string(n_); 207 | break; 208 | case rule::M: 209 | nm = 'M'; 210 | nm += std::to_string(static_cast(m_)); 211 | nm += '.'; 212 | nm += std::to_string(n_); 213 | nm += '.'; 214 | nm += std::to_string(wd_.c_encoding()); 215 | break; 216 | case rule::N: 217 | nm = std::to_string(n_); 218 | break; 219 | default: 220 | break; 221 | } 222 | nm += print_offset(time_); 223 | return nm; 224 | } 225 | 226 | inline 227 | std::ostream& 228 | operator<<(std::ostream& os, const rule& r) 229 | { 230 | switch (r.mode_) 231 | { 232 | case rule::J: 233 | os << 'J' << r.n_ << date::format(" %T", r.time_); 234 | break; 235 | case rule::M: 236 | if (r.n_ == 5) 237 | os << r.m_/r.wd_[date::last]; 238 | else 239 | os << r.m_/r.wd_[r.n_]; 240 | os << date::format(" %T", r.time_); 241 | break; 242 | case rule::N: 243 | os << r.n_ << date::format(" %T", r.time_); 244 | break; 245 | default: 246 | break; 247 | } 248 | return os; 249 | } 250 | 251 | } // namespace detail 252 | 253 | class time_zone 254 | { 255 | std::string std_abbrev_; 256 | std::string dst_abbrev_ = {}; 257 | std::chrono::seconds offset_; 258 | std::chrono::seconds save_ = std::chrono::hours{1}; 259 | detail::rule start_rule_; 260 | detail::rule end_rule_; 261 | 262 | public: 263 | explicit time_zone(const detail::string_t& name); 264 | 265 | template 266 | date::sys_info get_info(date::sys_time st) const; 267 | template 268 | date::local_info get_info(date::local_time tp) const; 269 | 270 | template 271 | date::sys_time::type> 272 | to_sys(date::local_time tp) const; 273 | 274 | template 275 | date::sys_time::type> 276 | to_sys(date::local_time tp, date::choose z) const; 277 | 278 | template 279 | date::local_time::type> 280 | to_local(date::sys_time tp) const; 281 | 282 | friend std::ostream& operator<<(std::ostream& os, const time_zone& z); 283 | 284 | const time_zone* operator->() const {return this;} 285 | 286 | std::string name() const; 287 | 288 | friend bool operator==(const time_zone& x, const time_zone& y); 289 | 290 | private: 291 | date::sys_seconds get_start(date::year y) const; 292 | date::sys_seconds get_prev_start(date::year y) const; 293 | date::sys_seconds get_next_start(date::year y) const; 294 | date::sys_seconds get_end(date::year y) const; 295 | date::sys_seconds get_prev_end(date::year y) const; 296 | date::sys_seconds get_next_end(date::year y) const; 297 | date::sys_info contant_offset() const; 298 | }; 299 | 300 | inline 301 | date::sys_seconds 302 | time_zone::get_start(date::year y) const 303 | { 304 | return date::sys_seconds{(start_rule_(y) - offset_).time_since_epoch()}; 305 | } 306 | 307 | inline 308 | date::sys_seconds 309 | time_zone::get_prev_start(date::year y) const 310 | { 311 | return date::sys_seconds{(start_rule_(--y) - offset_).time_since_epoch()}; 312 | } 313 | 314 | inline 315 | date::sys_seconds 316 | time_zone::get_next_start(date::year y) const 317 | { 318 | return date::sys_seconds{(start_rule_(++y) - offset_).time_since_epoch()}; 319 | } 320 | 321 | inline 322 | date::sys_seconds 323 | time_zone::get_end(date::year y) const 324 | { 325 | return date::sys_seconds{(end_rule_(y) - (offset_ + save_)).time_since_epoch()}; 326 | } 327 | 328 | inline 329 | date::sys_seconds 330 | time_zone::get_prev_end(date::year y) const 331 | { 332 | return date::sys_seconds{(end_rule_(--y) - (offset_ + save_)).time_since_epoch()}; 333 | } 334 | 335 | inline 336 | date::sys_seconds 337 | time_zone::get_next_end(date::year y) const 338 | { 339 | return date::sys_seconds{(end_rule_(++y) - (offset_ + save_)).time_since_epoch()}; 340 | } 341 | 342 | inline 343 | date::sys_info 344 | time_zone::contant_offset() const 345 | { 346 | using date::year; 347 | using date::sys_info; 348 | using date::sys_days; 349 | using date::January; 350 | using date::December; 351 | using date::last; 352 | using date::days; 353 | using std::chrono::minutes; 354 | sys_info r; 355 | r.begin = sys_days{year::min()/January/1}; 356 | r.end = sys_days{year::max()/December/last} + days{1} - std::chrono::seconds{1}; 357 | if (std_abbrev_.size() > 0) 358 | { 359 | r.abbrev = std_abbrev_; 360 | r.offset = offset_; 361 | r.save = {}; 362 | } 363 | else 364 | { 365 | r.abbrev = dst_abbrev_; 366 | r.offset = offset_ + save_; 367 | r.save = date::ceil(save_); 368 | } 369 | return r; 370 | } 371 | 372 | inline 373 | time_zone::time_zone(const detail::string_t& s) 374 | { 375 | using detail::read_name; 376 | using detail::read_signed_time; 377 | using detail::throw_invalid; 378 | auto i = read_name(s, 0, std_abbrev_); 379 | auto std_name_i = i; 380 | auto abbrev_name_i = i; 381 | i = read_signed_time(s, i, offset_); 382 | offset_ = -offset_; 383 | if (i != s.size()) 384 | { 385 | i = read_name(s, i, dst_abbrev_); 386 | abbrev_name_i = i; 387 | if (i != s.size()) 388 | { 389 | if (s[i] != ',') 390 | { 391 | i = read_signed_time(s, i, save_); 392 | save_ = -save_ - offset_; 393 | } 394 | if (i != s.size()) 395 | { 396 | if (s[i] != ',') 397 | throw_invalid(s, i, "Expecting end of string or ',' to start rule"); 398 | ++i; 399 | i = read_date(s, i, start_rule_); 400 | if (i == s.size() || s[i] != ',') 401 | throw_invalid(s, i, "Expecting ',' and then the ending rule"); 402 | ++i; 403 | i = read_date(s, i, end_rule_); 404 | if (i != s.size()) 405 | throw_invalid(s, i, "Found unexpected trailing characters"); 406 | } 407 | } 408 | } 409 | if (start_rule_.ok()) 410 | { 411 | if (std_abbrev_.size() < 3) 412 | throw_invalid(s, std_name_i, "Zone with rules must have a std" 413 | " abbreviation of length 3 or greater"); 414 | if (dst_abbrev_.size() < 3) 415 | throw_invalid(s, abbrev_name_i, "Zone with rules must have a daylight" 416 | " abbreviation of length 3 or greater"); 417 | } 418 | else 419 | { 420 | if (dst_abbrev_.size() >= 3) 421 | { 422 | std_abbrev_.clear(); 423 | } 424 | else if (std_abbrev_.size() < 3) 425 | { 426 | throw_invalid(s, std_name_i, "Zone must have at least one abbreviation" 427 | " of length 3 or greater"); 428 | } 429 | else 430 | { 431 | dst_abbrev_.clear(); 432 | save_ = {}; 433 | } 434 | } 435 | } 436 | 437 | template 438 | date::sys_info 439 | time_zone::get_info(date::sys_time st) const 440 | { 441 | using date::sys_info; 442 | using date::year_month_day; 443 | using date::sys_days; 444 | using date::floor; 445 | using date::ceil; 446 | using date::days; 447 | using date::year; 448 | using date::January; 449 | using date::December; 450 | using date::last; 451 | using std::chrono::minutes; 452 | sys_info r{}; 453 | r.offset = offset_; 454 | if (start_rule_.ok()) 455 | { 456 | auto y = year_month_day{floor(st)}.year(); 457 | if (st >= get_next_start(y)) 458 | ++y; 459 | else if (st < get_prev_end(y)) 460 | --y; 461 | auto start = get_start(y); 462 | auto end = get_end(y); 463 | if (start <= end) // (northern hemisphere) 464 | { 465 | if (start <= st && st < end) 466 | { 467 | r.begin = start; 468 | r.end = end; 469 | r.offset += save_; 470 | r.save = ceil(save_); 471 | r.abbrev = dst_abbrev_; 472 | } 473 | else if (st < start) 474 | { 475 | r.begin = get_prev_end(y); 476 | r.end = start; 477 | r.abbrev = std_abbrev_; 478 | } 479 | else // st >= end 480 | { 481 | r.begin = end; 482 | r.end = get_next_start(y); 483 | r.abbrev = std_abbrev_; 484 | } 485 | } 486 | else // end < start (southern hemisphere) 487 | { 488 | if (end <= st && st < start) 489 | { 490 | r.begin = end; 491 | r.end = start; 492 | r.abbrev = std_abbrev_; 493 | } 494 | else if (st < end) 495 | { 496 | r.begin = get_prev_start(y); 497 | r.end = end; 498 | r.offset += save_; 499 | r.save = ceil(save_); 500 | r.abbrev = dst_abbrev_; 501 | } 502 | else // st >= start 503 | { 504 | r.begin = start; 505 | r.end = get_next_end(y); 506 | r.offset += save_; 507 | r.save = ceil(save_); 508 | r.abbrev = dst_abbrev_; 509 | } 510 | } 511 | } 512 | else 513 | r = contant_offset(); 514 | using seconds = std::chrono::seconds; 515 | assert(r.begin <= floor(st) && floor(st) <= r.end); 516 | return r; 517 | } 518 | 519 | template 520 | date::local_info 521 | time_zone::get_info(date::local_time tp) const 522 | { 523 | using date::local_info; 524 | using date::year_month_day; 525 | using date::days; 526 | using date::sys_days; 527 | using date::sys_seconds; 528 | using date::year; 529 | using date::ceil; 530 | using date::January; 531 | using date::December; 532 | using date::last; 533 | using std::chrono::seconds; 534 | using std::chrono::minutes; 535 | local_info r{}; 536 | using date::floor; 537 | if (start_rule_.ok()) 538 | { 539 | auto y = year_month_day{floor(tp)}.year(); 540 | auto start = get_start(y); 541 | auto end = get_end(y); 542 | auto utcs = sys_seconds{floor(tp - offset_).time_since_epoch()}; 543 | auto utcd = sys_seconds{floor(tp - (offset_ + save_)).time_since_epoch()}; 544 | auto northern = start <= end; 545 | if ((utcs < start) != (utcd < start)) 546 | { 547 | if (northern) 548 | r.first.begin = get_prev_end(y); 549 | else 550 | r.first.begin = end; 551 | r.first.end = start; 552 | r.first.offset = offset_; 553 | r.first.abbrev = std_abbrev_; 554 | r.second.begin = start; 555 | if (northern) 556 | r.second.end = end; 557 | else 558 | r.second.end = get_next_end(y); 559 | r.second.abbrev = dst_abbrev_; 560 | r.second.offset = offset_ + save_; 561 | r.second.save = ceil(save_); 562 | r.result = save_ > seconds{0} ? local_info::nonexistent 563 | : local_info::ambiguous; 564 | } 565 | else if ((utcs < end) != (utcd < end)) 566 | { 567 | if (northern) 568 | r.first.begin = start; 569 | else 570 | r.first.begin = get_prev_start(y); 571 | r.first.end = end; 572 | r.first.offset = offset_ + save_; 573 | r.first.save = ceil(save_); 574 | r.first.abbrev = dst_abbrev_; 575 | r.second.begin = end; 576 | if (northern) 577 | r.second.end = get_next_start(y); 578 | else 579 | r.second.end = start; 580 | r.second.abbrev = std_abbrev_; 581 | r.second.offset = offset_; 582 | r.result = save_ > seconds{0} ? local_info::ambiguous 583 | : local_info::nonexistent; 584 | } 585 | else 586 | r.first = get_info(utcs); 587 | } 588 | else 589 | r.first = contant_offset(); 590 | return r; 591 | } 592 | 593 | template 594 | date::sys_time::type> 595 | time_zone::to_sys(date::local_time tp) const 596 | { 597 | using date::local_info; 598 | using date::sys_time; 599 | using date::ambiguous_local_time; 600 | using date::nonexistent_local_time; 601 | auto i = get_info(tp); 602 | if (i.result == local_info::nonexistent) 603 | throw nonexistent_local_time(tp, i); 604 | else if (i.result == local_info::ambiguous) 605 | throw ambiguous_local_time(tp, i); 606 | return sys_time{tp.time_since_epoch()} - i.first.offset; 607 | } 608 | 609 | template 610 | date::sys_time::type> 611 | time_zone::to_sys(date::local_time tp, date::choose z) const 612 | { 613 | using date::local_info; 614 | using date::sys_time; 615 | using date::choose; 616 | auto i = get_info(tp); 617 | if (i.result == local_info::nonexistent) 618 | { 619 | return i.first.end; 620 | } 621 | else if (i.result == local_info::ambiguous) 622 | { 623 | if (z == choose::latest) 624 | return sys_time{tp.time_since_epoch()} - i.second.offset; 625 | } 626 | return sys_time{tp.time_since_epoch()} - i.first.offset; 627 | } 628 | 629 | template 630 | date::local_time::type> 631 | time_zone::to_local(date::sys_time tp) const 632 | { 633 | using date::local_time; 634 | using std::chrono::seconds; 635 | using LT = local_time::type>; 636 | auto i = get_info(tp); 637 | return LT{(tp + i.offset).time_since_epoch()}; 638 | } 639 | 640 | inline 641 | std::ostream& 642 | operator<<(std::ostream& os, const time_zone& z) 643 | { 644 | using date::operator<<; 645 | os << '{'; 646 | os << z.std_abbrev_ << ", " << z.dst_abbrev_ << date::format(", %T, ", z.offset_) 647 | << date::format("%T, [", z.save_) << z.start_rule_ << ", " << z.end_rule_ << ")}"; 648 | return os; 649 | } 650 | 651 | inline 652 | std::string 653 | time_zone::name() const 654 | { 655 | using namespace date; 656 | using namespace std::chrono; 657 | auto print_abbrev = [](std::string const& nm) 658 | { 659 | if (std::any_of(nm.begin(), nm.end(), 660 | [](char c) 661 | { 662 | return !std::isalpha(c); 663 | })) 664 | { 665 | return '<' + nm + '>'; 666 | } 667 | return nm; 668 | }; 669 | auto print_offset = [](seconds off) 670 | { 671 | std::string nm; 672 | date::hh_mm_ss offset{-off}; 673 | if (offset.is_negative()) 674 | nm += '-'; 675 | nm += std::to_string(offset.hours().count()); 676 | if (offset.minutes() != minutes{0} || offset.seconds() != seconds{0}) 677 | { 678 | nm += ':'; 679 | if (offset.minutes() < minutes{10}) 680 | nm += '0'; 681 | nm += std::to_string(offset.minutes().count()); 682 | if (offset.seconds() != seconds{0}) 683 | { 684 | nm += ':'; 685 | if (offset.seconds() < seconds{10}) 686 | nm += '0'; 687 | nm += std::to_string(offset.seconds().count()); 688 | } 689 | } 690 | return nm; 691 | }; 692 | auto nm = print_abbrev(std_abbrev_); 693 | nm += print_offset(offset_); 694 | if (!dst_abbrev_.empty()) 695 | { 696 | nm += print_abbrev(dst_abbrev_); 697 | if (save_ != hours{1}) 698 | nm += print_offset(offset_+save_); 699 | if (start_rule_.ok()) 700 | { 701 | nm += ','; 702 | nm += start_rule_.to_string(); 703 | nm += ','; 704 | nm += end_rule_.to_string(); 705 | } 706 | } 707 | return nm; 708 | } 709 | 710 | inline 711 | bool 712 | operator==(const time_zone& x, const time_zone& y) 713 | { 714 | return x.std_abbrev_ == y.std_abbrev_ && 715 | x.dst_abbrev_ == y. dst_abbrev_ && 716 | x.offset_ == y.offset_ && 717 | x.save_ == y.save_ && 718 | x.start_rule_ == y.start_rule_ && 719 | x.end_rule_ == y.end_rule_; 720 | } 721 | 722 | inline 723 | bool 724 | operator!=(const time_zone& x, const time_zone& y) 725 | { 726 | return !(x == y); 727 | } 728 | 729 | namespace detail 730 | { 731 | 732 | inline 733 | void 734 | throw_invalid(const string_t& s, unsigned i, const string_t& message) 735 | { 736 | throw std::runtime_error(std::string("Invalid time_zone initializer.\n") + 737 | std::string(message) + ":\n" + 738 | std::string(s) + '\n' + 739 | "\x1b[1;32m" + 740 | std::string(i, '~') + '^' + 741 | std::string(i < s.size() ? s.size()-i-1 : 0, '~') + 742 | "\x1b[0m"); 743 | } 744 | 745 | inline 746 | unsigned 747 | read_date(const string_t& s, unsigned i, rule& r) 748 | { 749 | using date::month; 750 | using date::weekday; 751 | if (i == s.size()) 752 | throw_invalid(s, i, "Expected rule but found end of string"); 753 | if (s[i] == 'J') 754 | { 755 | ++i; 756 | unsigned n; 757 | i = read_unsigned(s, i, 3, n, "Expected to find the Julian day [1, 365]"); 758 | if (!(1 <= n && n <= 365)) 759 | throw_invalid(s, i-1, "Expected Julian day to be in the range [1, 365]"); 760 | r.mode_ = rule::J; 761 | r.n_ = n; 762 | } 763 | else if (s[i] == 'M') 764 | { 765 | ++i; 766 | unsigned m; 767 | i = read_unsigned(s, i, 2, m, "Expected to find month [1, 12]"); 768 | if (!(1 <= m && m <= 12)) 769 | throw_invalid(s, i-1, "Expected month to be in the range [1, 12]"); 770 | if (i == s.size() || s[i] != '.') 771 | throw_invalid(s, i, "Expected '.' after month"); 772 | ++i; 773 | unsigned n; 774 | i = read_unsigned(s, i, 1, n, "Expected to find week number [1, 5]"); 775 | if (!(1 <= n && n <= 5)) 776 | throw_invalid(s, i-1, "Expected week number to be in the range [1, 5]"); 777 | if (i == s.size() || s[i] != '.') 778 | throw_invalid(s, i, "Expected '.' after weekday index"); 779 | ++i; 780 | unsigned wd; 781 | i = read_unsigned(s, i, 1, wd, "Expected to find day of week [0, 6]"); 782 | if (wd > 6) 783 | throw_invalid(s, i-1, "Expected day of week to be in the range [0, 6]"); 784 | r.mode_ = rule::M; 785 | r.m_ = month{m}; 786 | r.wd_ = weekday{wd}; 787 | r.n_ = n; 788 | } 789 | else if (std::isdigit(s[i])) 790 | { 791 | unsigned n; 792 | i = read_unsigned(s, i, 3, n); 793 | if (n > 365) 794 | throw_invalid(s, i-1, "Expected Julian day to be in the range [0, 365]"); 795 | r.mode_ = rule::N; 796 | r.n_ = n; 797 | } 798 | else 799 | throw_invalid(s, i, "Expected 'J', 'M', or a digit to start rule"); 800 | if (i != s.size() && s[i] == '/') 801 | { 802 | ++i; 803 | std::chrono::seconds t; 804 | i = read_unsigned_time(s, i, t); 805 | r.time_ = t; 806 | } 807 | return i; 808 | } 809 | 810 | inline 811 | unsigned 812 | read_name(const string_t& s, unsigned i, std::string& name) 813 | { 814 | if (i == s.size()) 815 | throw_invalid(s, i, "Expected a name but found end of string"); 816 | if (s[i] == '<') 817 | { 818 | ++i; 819 | while (true) 820 | { 821 | if (i == s.size()) 822 | throw_invalid(s, i, 823 | "Expected to find closing '>', but found end of string"); 824 | if (s[i] == '>') 825 | break; 826 | name.push_back(s[i]); 827 | ++i; 828 | } 829 | ++i; 830 | } 831 | else 832 | { 833 | while (i != s.size() && std::isalpha(s[i])) 834 | { 835 | name.push_back(s[i]); 836 | ++i; 837 | } 838 | } 839 | return i; 840 | } 841 | 842 | inline 843 | unsigned 844 | read_signed_time(const string_t& s, unsigned i, 845 | std::chrono::seconds& t) 846 | { 847 | if (i == s.size()) 848 | throw_invalid(s, i, "Expected to read signed time, but found end of string"); 849 | bool negative = false; 850 | if (s[i] == '-') 851 | { 852 | negative = true; 853 | ++i; 854 | } 855 | else if (s[i] == '+') 856 | ++i; 857 | i = read_unsigned_time(s, i, t); 858 | if (negative) 859 | t = -t; 860 | return i; 861 | } 862 | 863 | inline 864 | unsigned 865 | read_unsigned_time(const string_t& s, unsigned i, std::chrono::seconds& t) 866 | { 867 | using std::chrono::seconds; 868 | using std::chrono::minutes; 869 | using std::chrono::hours; 870 | if (i == s.size()) 871 | throw_invalid(s, i, "Expected to read unsigned time, but found end of string"); 872 | unsigned x; 873 | i = read_unsigned(s, i, 2, x, "Expected to find hours [0, 24]"); 874 | if (x > 24) 875 | throw_invalid(s, i-1, "Expected hours to be in the range [0, 24]"); 876 | t = hours{x}; 877 | if (i != s.size() && s[i] == ':') 878 | { 879 | ++i; 880 | i = read_unsigned(s, i, 2, x, "Expected to find minutes [0, 59]"); 881 | if (x > 59) 882 | throw_invalid(s, i-1, "Expected minutes to be in the range [0, 59]"); 883 | t += minutes{x}; 884 | if (i != s.size() && s[i] == ':') 885 | { 886 | ++i; 887 | i = read_unsigned(s, i, 2, x, "Expected to find seconds [0, 59]"); 888 | if (x > 59) 889 | throw_invalid(s, i-1, "Expected seconds to be in the range [0, 59]"); 890 | t += seconds{x}; 891 | } 892 | } 893 | return i; 894 | } 895 | 896 | inline 897 | unsigned 898 | read_unsigned(const string_t& s, unsigned i, unsigned limit, unsigned& u, 899 | const string_t& message) 900 | { 901 | if (i == s.size() || !std::isdigit(s[i])) 902 | throw_invalid(s, i, message); 903 | u = static_cast(s[i] - '0'); 904 | unsigned count = 1; 905 | for (++i; count < limit && i != s.size() && std::isdigit(s[i]); ++i, ++count) 906 | u = u * 10 + static_cast(s[i] - '0'); 907 | return i; 908 | } 909 | 910 | } // namespace detail 911 | 912 | } // namespace Posix 913 | 914 | namespace date 915 | { 916 | 917 | template <> 918 | struct zoned_traits 919 | { 920 | 921 | #if HAS_STRING_VIEW 922 | 923 | static 924 | Posix::time_zone 925 | locate_zone(std::string_view name) 926 | { 927 | return Posix::time_zone{name}; 928 | } 929 | 930 | #else // !HAS_STRING_VIEW 931 | 932 | static 933 | Posix::time_zone 934 | locate_zone(const std::string& name) 935 | { 936 | return Posix::time_zone{name}; 937 | } 938 | 939 | static 940 | Posix::time_zone 941 | locate_zone(const char* name) 942 | { 943 | return Posix::time_zone{name}; 944 | } 945 | 946 | #endif // !HAS_STRING_VIEW 947 | 948 | }; 949 | 950 | } // namespace date 951 | 952 | #endif // PTZ_H 953 | -------------------------------------------------------------------------------- /inst/include/iso_week.h: -------------------------------------------------------------------------------- 1 | #ifndef ISO_WEEK_H 2 | #define ISO_WEEK_H 3 | 4 | // The MIT License (MIT) 5 | // 6 | // Copyright (c) 2015, 2016, 2017 Howard Hinnant 7 | // 8 | // Permission is hereby granted, free of charge, to any person obtaining a copy 9 | // of this software and associated documentation files (the "Software"), to deal 10 | // in the Software without restriction, including without limitation the rights 11 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 12 | // copies of the Software, and to permit persons to whom the Software is 13 | // furnished to do so, subject to the following conditions: 14 | // 15 | // The above copyright notice and this permission notice shall be included in all 16 | // copies or substantial portions of the Software. 17 | // 18 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 24 | // SOFTWARE. 25 | 26 | #include "date.h" 27 | 28 | #include 29 | 30 | namespace iso_week 31 | { 32 | 33 | // y/wn/wd 34 | // wn/wd/y 35 | // wd/wn/y 36 | 37 | using days = date::days; 38 | using weeks = date::weeks; 39 | using years = date::years; 40 | 41 | // time_point 42 | 43 | using sys_days = date::sys_days; 44 | using local_days = date::local_days; 45 | 46 | // types 47 | 48 | struct last_week 49 | { 50 | explicit last_week() = default; 51 | }; 52 | 53 | class weekday; 54 | class weeknum; 55 | class year; 56 | 57 | class year_weeknum; 58 | class year_lastweek; 59 | class weeknum_weekday; 60 | class lastweek_weekday; 61 | 62 | class year_weeknum_weekday; 63 | class year_lastweek_weekday; 64 | 65 | // date composition operators 66 | 67 | CONSTCD11 year_weeknum operator/(const year& y, const weeknum& wn) NOEXCEPT; 68 | CONSTCD11 year_weeknum operator/(const year& y, int wn) NOEXCEPT; 69 | 70 | CONSTCD11 year_lastweek operator/(const year& y, last_week wn) NOEXCEPT; 71 | 72 | CONSTCD11 weeknum_weekday operator/(const weeknum& wn, const weekday& wd) NOEXCEPT; 73 | CONSTCD11 weeknum_weekday operator/(const weeknum& wn, int wd) NOEXCEPT; 74 | CONSTCD11 weeknum_weekday operator/(const weekday& wd, const weeknum& wn) NOEXCEPT; 75 | CONSTCD11 weeknum_weekday operator/(const weekday& wd, int wn) NOEXCEPT; 76 | 77 | CONSTCD11 lastweek_weekday operator/(const last_week& wn, const weekday& wd) NOEXCEPT; 78 | CONSTCD11 lastweek_weekday operator/(const last_week& wn, int wd) NOEXCEPT; 79 | CONSTCD11 lastweek_weekday operator/(const weekday& wd, const last_week& wn) NOEXCEPT; 80 | 81 | CONSTCD11 year_weeknum_weekday operator/(const year_weeknum& ywn, const weekday& wd) NOEXCEPT; 82 | CONSTCD11 year_weeknum_weekday operator/(const year_weeknum& ywn, int wd) NOEXCEPT; 83 | CONSTCD11 year_weeknum_weekday operator/(const weeknum_weekday& wnwd, const year& y) NOEXCEPT; 84 | CONSTCD11 year_weeknum_weekday operator/(const weeknum_weekday& wnwd, int y) NOEXCEPT; 85 | 86 | CONSTCD11 year_lastweek_weekday operator/(const year_lastweek& ylw, const weekday& wd) NOEXCEPT; 87 | CONSTCD11 year_lastweek_weekday operator/(const year_lastweek& ylw, int wd) NOEXCEPT; 88 | 89 | CONSTCD11 year_lastweek_weekday operator/(const lastweek_weekday& lwwd, const year& y) NOEXCEPT; 90 | CONSTCD11 year_lastweek_weekday operator/(const lastweek_weekday& lwwd, int y) NOEXCEPT; 91 | 92 | // weekday 93 | 94 | class weekday 95 | { 96 | unsigned char wd_; 97 | public: 98 | explicit CONSTCD11 weekday(unsigned wd) NOEXCEPT; 99 | CONSTCD11 weekday(date::weekday wd) NOEXCEPT; 100 | explicit weekday(int) = delete; 101 | CONSTCD11 weekday(const sys_days& dp) NOEXCEPT; 102 | CONSTCD11 explicit weekday(const local_days& dp) NOEXCEPT; 103 | 104 | weekday& operator++() NOEXCEPT; 105 | weekday operator++(int) NOEXCEPT; 106 | weekday& operator--() NOEXCEPT; 107 | weekday operator--(int) NOEXCEPT; 108 | 109 | weekday& operator+=(const days& d) NOEXCEPT; 110 | weekday& operator-=(const days& d) NOEXCEPT; 111 | 112 | CONSTCD11 explicit operator unsigned() const NOEXCEPT; 113 | CONSTCD11 operator date::weekday() const NOEXCEPT; 114 | CONSTCD11 bool ok() const NOEXCEPT; 115 | 116 | private: 117 | static CONSTCD11 unsigned char weekday_from_days(int z) NOEXCEPT; 118 | static CONSTCD11 unsigned char to_iso_encoding(unsigned char) NOEXCEPT; 119 | static CONSTCD11 unsigned from_iso_encoding(unsigned) NOEXCEPT; 120 | }; 121 | 122 | CONSTCD11 bool operator==(const weekday& x, const weekday& y) NOEXCEPT; 123 | CONSTCD11 bool operator!=(const weekday& x, const weekday& y) NOEXCEPT; 124 | 125 | CONSTCD14 weekday operator+(const weekday& x, const days& y) NOEXCEPT; 126 | CONSTCD14 weekday operator+(const days& x, const weekday& y) NOEXCEPT; 127 | CONSTCD14 weekday operator-(const weekday& x, const days& y) NOEXCEPT; 128 | CONSTCD14 days operator-(const weekday& x, const weekday& y) NOEXCEPT; 129 | 130 | template 131 | std::basic_ostream& 132 | operator<<(std::basic_ostream& os, const weekday& wd); 133 | 134 | // year 135 | 136 | class year 137 | { 138 | short y_; 139 | 140 | public: 141 | explicit CONSTCD11 year(int y) NOEXCEPT; 142 | 143 | year& operator++() NOEXCEPT; 144 | year operator++(int) NOEXCEPT; 145 | year& operator--() NOEXCEPT; 146 | year operator--(int) NOEXCEPT; 147 | 148 | year& operator+=(const years& y) NOEXCEPT; 149 | year& operator-=(const years& y) NOEXCEPT; 150 | 151 | CONSTCD14 bool is_leap() const NOEXCEPT; 152 | 153 | CONSTCD11 explicit operator int() const NOEXCEPT; 154 | CONSTCD11 bool ok() const NOEXCEPT; 155 | 156 | static CONSTCD11 year min() NOEXCEPT; 157 | static CONSTCD11 year max() NOEXCEPT; 158 | }; 159 | 160 | CONSTCD11 bool operator==(const year& x, const year& y) NOEXCEPT; 161 | CONSTCD11 bool operator!=(const year& x, const year& y) NOEXCEPT; 162 | CONSTCD11 bool operator< (const year& x, const year& y) NOEXCEPT; 163 | CONSTCD11 bool operator> (const year& x, const year& y) NOEXCEPT; 164 | CONSTCD11 bool operator<=(const year& x, const year& y) NOEXCEPT; 165 | CONSTCD11 bool operator>=(const year& x, const year& y) NOEXCEPT; 166 | 167 | CONSTCD11 year operator+(const year& x, const years& y) NOEXCEPT; 168 | CONSTCD11 year operator+(const years& x, const year& y) NOEXCEPT; 169 | CONSTCD11 year operator-(const year& x, const years& y) NOEXCEPT; 170 | CONSTCD11 years operator-(const year& x, const year& y) NOEXCEPT; 171 | 172 | template 173 | std::basic_ostream& 174 | operator<<(std::basic_ostream& os, const year& y); 175 | 176 | // weeknum 177 | 178 | class weeknum 179 | { 180 | unsigned char wn_; 181 | 182 | public: 183 | explicit CONSTCD11 weeknum(unsigned wn) NOEXCEPT; 184 | 185 | weeknum& operator++() NOEXCEPT; 186 | weeknum operator++(int) NOEXCEPT; 187 | weeknum& operator--() NOEXCEPT; 188 | weeknum operator--(int) NOEXCEPT; 189 | 190 | weeknum& operator+=(const weeks& y) NOEXCEPT; 191 | weeknum& operator-=(const weeks& y) NOEXCEPT; 192 | 193 | CONSTCD11 explicit operator unsigned() const NOEXCEPT; 194 | CONSTCD11 bool ok() const NOEXCEPT; 195 | }; 196 | 197 | CONSTCD11 bool operator==(const weeknum& x, const weeknum& y) NOEXCEPT; 198 | CONSTCD11 bool operator!=(const weeknum& x, const weeknum& y) NOEXCEPT; 199 | CONSTCD11 bool operator< (const weeknum& x, const weeknum& y) NOEXCEPT; 200 | CONSTCD11 bool operator> (const weeknum& x, const weeknum& y) NOEXCEPT; 201 | CONSTCD11 bool operator<=(const weeknum& x, const weeknum& y) NOEXCEPT; 202 | CONSTCD11 bool operator>=(const weeknum& x, const weeknum& y) NOEXCEPT; 203 | 204 | CONSTCD11 weeknum operator+(const weeknum& x, const weeks& y) NOEXCEPT; 205 | CONSTCD11 weeknum operator+(const weeks& x, const weeknum& y) NOEXCEPT; 206 | CONSTCD11 weeknum operator-(const weeknum& x, const weeks& y) NOEXCEPT; 207 | CONSTCD11 weeks operator-(const weeknum& x, const weeknum& y) NOEXCEPT; 208 | 209 | template 210 | std::basic_ostream& 211 | operator<<(std::basic_ostream& os, const weeknum& wn); 212 | 213 | // year_weeknum 214 | 215 | class year_weeknum 216 | { 217 | iso_week::year y_; 218 | iso_week::weeknum wn_; 219 | 220 | public: 221 | CONSTCD11 year_weeknum(const iso_week::year& y, const iso_week::weeknum& wn) NOEXCEPT; 222 | 223 | CONSTCD11 iso_week::year year() const NOEXCEPT; 224 | CONSTCD11 iso_week::weeknum weeknum() const NOEXCEPT; 225 | 226 | year_weeknum& operator+=(const years& dy) NOEXCEPT; 227 | year_weeknum& operator-=(const years& dy) NOEXCEPT; 228 | 229 | CONSTCD11 bool ok() const NOEXCEPT; 230 | }; 231 | 232 | CONSTCD11 bool operator==(const year_weeknum& x, const year_weeknum& y) NOEXCEPT; 233 | CONSTCD11 bool operator!=(const year_weeknum& x, const year_weeknum& y) NOEXCEPT; 234 | CONSTCD11 bool operator< (const year_weeknum& x, const year_weeknum& y) NOEXCEPT; 235 | CONSTCD11 bool operator> (const year_weeknum& x, const year_weeknum& y) NOEXCEPT; 236 | CONSTCD11 bool operator<=(const year_weeknum& x, const year_weeknum& y) NOEXCEPT; 237 | CONSTCD11 bool operator>=(const year_weeknum& x, const year_weeknum& y) NOEXCEPT; 238 | 239 | CONSTCD11 year_weeknum operator+(const year_weeknum& ym, const years& dy) NOEXCEPT; 240 | CONSTCD11 year_weeknum operator+(const years& dy, const year_weeknum& ym) NOEXCEPT; 241 | CONSTCD11 year_weeknum operator-(const year_weeknum& ym, const years& dy) NOEXCEPT; 242 | 243 | template 244 | std::basic_ostream& 245 | operator<<(std::basic_ostream& os, const year_weeknum& ym); 246 | 247 | // year_lastweek 248 | 249 | class year_lastweek 250 | { 251 | iso_week::year y_; 252 | 253 | public: 254 | CONSTCD11 explicit year_lastweek(const iso_week::year& y) NOEXCEPT; 255 | 256 | CONSTCD11 iso_week::year year() const NOEXCEPT; 257 | CONSTCD14 iso_week::weeknum weeknum() const NOEXCEPT; 258 | 259 | year_lastweek& operator+=(const years& dy) NOEXCEPT; 260 | year_lastweek& operator-=(const years& dy) NOEXCEPT; 261 | 262 | CONSTCD11 bool ok() const NOEXCEPT; 263 | }; 264 | 265 | CONSTCD11 bool operator==(const year_lastweek& x, const year_lastweek& y) NOEXCEPT; 266 | CONSTCD11 bool operator!=(const year_lastweek& x, const year_lastweek& y) NOEXCEPT; 267 | CONSTCD11 bool operator< (const year_lastweek& x, const year_lastweek& y) NOEXCEPT; 268 | CONSTCD11 bool operator> (const year_lastweek& x, const year_lastweek& y) NOEXCEPT; 269 | CONSTCD11 bool operator<=(const year_lastweek& x, const year_lastweek& y) NOEXCEPT; 270 | CONSTCD11 bool operator>=(const year_lastweek& x, const year_lastweek& y) NOEXCEPT; 271 | 272 | CONSTCD11 year_lastweek operator+(const year_lastweek& ym, const years& dy) NOEXCEPT; 273 | CONSTCD11 year_lastweek operator+(const years& dy, const year_lastweek& ym) NOEXCEPT; 274 | CONSTCD11 year_lastweek operator-(const year_lastweek& ym, const years& dy) NOEXCEPT; 275 | 276 | template 277 | std::basic_ostream& 278 | operator<<(std::basic_ostream& os, const year_lastweek& ym); 279 | 280 | // weeknum_weekday 281 | 282 | class weeknum_weekday 283 | { 284 | iso_week::weeknum wn_; 285 | iso_week::weekday wd_; 286 | 287 | public: 288 | CONSTCD11 weeknum_weekday(const iso_week::weeknum& wn, 289 | const iso_week::weekday& wd) NOEXCEPT; 290 | 291 | CONSTCD11 iso_week::weeknum weeknum() const NOEXCEPT; 292 | CONSTCD11 iso_week::weekday weekday() const NOEXCEPT; 293 | 294 | CONSTCD14 bool ok() const NOEXCEPT; 295 | }; 296 | 297 | CONSTCD11 bool operator==(const weeknum_weekday& x, const weeknum_weekday& y) NOEXCEPT; 298 | CONSTCD11 bool operator!=(const weeknum_weekday& x, const weeknum_weekday& y) NOEXCEPT; 299 | CONSTCD11 bool operator< (const weeknum_weekday& x, const weeknum_weekday& y) NOEXCEPT; 300 | CONSTCD11 bool operator> (const weeknum_weekday& x, const weeknum_weekday& y) NOEXCEPT; 301 | CONSTCD11 bool operator<=(const weeknum_weekday& x, const weeknum_weekday& y) NOEXCEPT; 302 | CONSTCD11 bool operator>=(const weeknum_weekday& x, const weeknum_weekday& y) NOEXCEPT; 303 | 304 | template 305 | std::basic_ostream& 306 | operator<<(std::basic_ostream& os, const weeknum_weekday& md); 307 | 308 | // lastweek_weekday 309 | 310 | class lastweek_weekday 311 | { 312 | iso_week::weekday wd_; 313 | 314 | public: 315 | CONSTCD11 explicit lastweek_weekday(const iso_week::weekday& wd) NOEXCEPT; 316 | 317 | CONSTCD11 iso_week::weekday weekday() const NOEXCEPT; 318 | 319 | CONSTCD14 bool ok() const NOEXCEPT; 320 | }; 321 | 322 | CONSTCD11 bool operator==(const lastweek_weekday& x, const lastweek_weekday& y) NOEXCEPT; 323 | CONSTCD11 bool operator!=(const lastweek_weekday& x, const lastweek_weekday& y) NOEXCEPT; 324 | CONSTCD11 bool operator< (const lastweek_weekday& x, const lastweek_weekday& y) NOEXCEPT; 325 | CONSTCD11 bool operator> (const lastweek_weekday& x, const lastweek_weekday& y) NOEXCEPT; 326 | CONSTCD11 bool operator<=(const lastweek_weekday& x, const lastweek_weekday& y) NOEXCEPT; 327 | CONSTCD11 bool operator>=(const lastweek_weekday& x, const lastweek_weekday& y) NOEXCEPT; 328 | 329 | template 330 | std::basic_ostream& 331 | operator<<(std::basic_ostream& os, const lastweek_weekday& md); 332 | 333 | // year_lastweek_weekday 334 | 335 | class year_lastweek_weekday 336 | { 337 | iso_week::year y_; 338 | iso_week::weekday wd_; 339 | 340 | public: 341 | CONSTCD11 year_lastweek_weekday(const iso_week::year& y, 342 | const iso_week::weekday& wd) NOEXCEPT; 343 | 344 | year_lastweek_weekday& operator+=(const years& y) NOEXCEPT; 345 | year_lastweek_weekday& operator-=(const years& y) NOEXCEPT; 346 | 347 | CONSTCD11 iso_week::year year() const NOEXCEPT; 348 | CONSTCD14 iso_week::weeknum weeknum() const NOEXCEPT; 349 | CONSTCD11 iso_week::weekday weekday() const NOEXCEPT; 350 | 351 | CONSTCD14 operator sys_days() const NOEXCEPT; 352 | CONSTCD14 explicit operator local_days() const NOEXCEPT; 353 | CONSTCD11 bool ok() const NOEXCEPT; 354 | }; 355 | 356 | CONSTCD11 bool operator==(const year_lastweek_weekday& x, const year_lastweek_weekday& y) NOEXCEPT; 357 | CONSTCD11 bool operator!=(const year_lastweek_weekday& x, const year_lastweek_weekday& y) NOEXCEPT; 358 | CONSTCD11 bool operator< (const year_lastweek_weekday& x, const year_lastweek_weekday& y) NOEXCEPT; 359 | CONSTCD11 bool operator> (const year_lastweek_weekday& x, const year_lastweek_weekday& y) NOEXCEPT; 360 | CONSTCD11 bool operator<=(const year_lastweek_weekday& x, const year_lastweek_weekday& y) NOEXCEPT; 361 | CONSTCD11 bool operator>=(const year_lastweek_weekday& x, const year_lastweek_weekday& y) NOEXCEPT; 362 | 363 | CONSTCD11 year_lastweek_weekday operator+(const year_lastweek_weekday& ywnwd, const years& y) NOEXCEPT; 364 | CONSTCD11 year_lastweek_weekday operator+(const years& y, const year_lastweek_weekday& ywnwd) NOEXCEPT; 365 | CONSTCD11 year_lastweek_weekday operator-(const year_lastweek_weekday& ywnwd, const years& y) NOEXCEPT; 366 | 367 | template 368 | std::basic_ostream& 369 | operator<<(std::basic_ostream& os, const year_lastweek_weekday& ywnwd); 370 | 371 | // class year_weeknum_weekday 372 | 373 | class year_weeknum_weekday 374 | { 375 | iso_week::year y_; 376 | iso_week::weeknum wn_; 377 | iso_week::weekday wd_; 378 | 379 | public: 380 | CONSTCD11 year_weeknum_weekday(const iso_week::year& y, const iso_week::weeknum& wn, 381 | const iso_week::weekday& wd) NOEXCEPT; 382 | CONSTCD14 year_weeknum_weekday(const year_lastweek_weekday& ylwwd) NOEXCEPT; 383 | CONSTCD14 year_weeknum_weekday(const sys_days& dp) NOEXCEPT; 384 | CONSTCD14 explicit year_weeknum_weekday(const local_days& dp) NOEXCEPT; 385 | 386 | year_weeknum_weekday& operator+=(const years& y) NOEXCEPT; 387 | year_weeknum_weekday& operator-=(const years& y) NOEXCEPT; 388 | 389 | CONSTCD11 iso_week::year year() const NOEXCEPT; 390 | CONSTCD11 iso_week::weeknum weeknum() const NOEXCEPT; 391 | CONSTCD11 iso_week::weekday weekday() const NOEXCEPT; 392 | 393 | CONSTCD14 operator sys_days() const NOEXCEPT; 394 | CONSTCD14 explicit operator local_days() const NOEXCEPT; 395 | CONSTCD14 bool ok() const NOEXCEPT; 396 | 397 | private: 398 | static CONSTCD14 year_weeknum_weekday from_days(days dp) NOEXCEPT; 399 | }; 400 | 401 | CONSTCD11 bool operator==(const year_weeknum_weekday& x, const year_weeknum_weekday& y) NOEXCEPT; 402 | CONSTCD11 bool operator!=(const year_weeknum_weekday& x, const year_weeknum_weekday& y) NOEXCEPT; 403 | CONSTCD11 bool operator< (const year_weeknum_weekday& x, const year_weeknum_weekday& y) NOEXCEPT; 404 | CONSTCD11 bool operator> (const year_weeknum_weekday& x, const year_weeknum_weekday& y) NOEXCEPT; 405 | CONSTCD11 bool operator<=(const year_weeknum_weekday& x, const year_weeknum_weekday& y) NOEXCEPT; 406 | CONSTCD11 bool operator>=(const year_weeknum_weekday& x, const year_weeknum_weekday& y) NOEXCEPT; 407 | 408 | CONSTCD11 year_weeknum_weekday operator+(const year_weeknum_weekday& ywnwd, const years& y) NOEXCEPT; 409 | CONSTCD11 year_weeknum_weekday operator+(const years& y, const year_weeknum_weekday& ywnwd) NOEXCEPT; 410 | CONSTCD11 year_weeknum_weekday operator-(const year_weeknum_weekday& ywnwd, const years& y) NOEXCEPT; 411 | 412 | template 413 | std::basic_ostream& 414 | operator<<(std::basic_ostream& os, const year_weeknum_weekday& ywnwd); 415 | 416 | //----------------+ 417 | // Implementation | 418 | //----------------+ 419 | 420 | // weekday 421 | 422 | CONSTCD11 423 | inline 424 | unsigned char 425 | weekday::to_iso_encoding(unsigned char z) NOEXCEPT 426 | { 427 | return z != 0 ? z : (unsigned char)7; 428 | } 429 | 430 | CONSTCD11 431 | inline 432 | unsigned 433 | weekday::from_iso_encoding(unsigned z) NOEXCEPT 434 | { 435 | return z != 7 ? z : 0u; 436 | } 437 | 438 | CONSTCD11 439 | inline 440 | unsigned char 441 | weekday::weekday_from_days(int z) NOEXCEPT 442 | { 443 | return to_iso_encoding(static_cast(static_cast( 444 | z >= -4 ? (z+4) % 7 : (z+5) % 7 + 6))); 445 | } 446 | 447 | CONSTCD11 448 | inline 449 | weekday::weekday(unsigned wd) NOEXCEPT 450 | : wd_(static_cast(wd)) 451 | {} 452 | 453 | CONSTCD11 454 | inline 455 | weekday::weekday(date::weekday wd) NOEXCEPT 456 | : wd_(wd.iso_encoding()) 457 | {} 458 | 459 | CONSTCD11 460 | inline 461 | weekday::weekday(const sys_days& dp) NOEXCEPT 462 | : wd_(weekday_from_days(dp.time_since_epoch().count())) 463 | {} 464 | 465 | CONSTCD11 466 | inline 467 | weekday::weekday(const local_days& dp) NOEXCEPT 468 | : wd_(weekday_from_days(dp.time_since_epoch().count())) 469 | {} 470 | 471 | inline weekday& weekday::operator++() NOEXCEPT {if (++wd_ == 8) wd_ = 1; return *this;} 472 | inline weekday weekday::operator++(int) NOEXCEPT {auto tmp(*this); ++(*this); return tmp;} 473 | inline weekday& weekday::operator--() NOEXCEPT {if (wd_-- == 1) wd_ = 7; return *this;} 474 | inline weekday weekday::operator--(int) NOEXCEPT {auto tmp(*this); --(*this); return tmp;} 475 | 476 | inline 477 | weekday& 478 | weekday::operator+=(const days& d) NOEXCEPT 479 | { 480 | *this = *this + d; 481 | return *this; 482 | } 483 | 484 | inline 485 | weekday& 486 | weekday::operator-=(const days& d) NOEXCEPT 487 | { 488 | *this = *this - d; 489 | return *this; 490 | } 491 | 492 | CONSTCD11 493 | inline 494 | weekday::operator unsigned() const NOEXCEPT 495 | { 496 | return wd_; 497 | } 498 | 499 | CONSTCD11 500 | inline 501 | weekday::operator date::weekday() const NOEXCEPT 502 | { 503 | return date::weekday{from_iso_encoding(unsigned{wd_})}; 504 | } 505 | 506 | CONSTCD11 inline bool weekday::ok() const NOEXCEPT {return 1 <= wd_ && wd_ <= 7;} 507 | 508 | CONSTCD11 509 | inline 510 | bool 511 | operator==(const weekday& x, const weekday& y) NOEXCEPT 512 | { 513 | return static_cast(x) == static_cast(y); 514 | } 515 | 516 | CONSTCD11 517 | inline 518 | bool 519 | operator!=(const weekday& x, const weekday& y) NOEXCEPT 520 | { 521 | return !(x == y); 522 | } 523 | 524 | CONSTCD14 525 | inline 526 | days 527 | operator-(const weekday& x, const weekday& y) NOEXCEPT 528 | { 529 | auto const diff = static_cast(x) - static_cast(y); 530 | return days{diff <= 6 ? diff : diff + 7}; 531 | } 532 | 533 | CONSTCD14 534 | inline 535 | weekday 536 | operator+(const weekday& x, const days& y) NOEXCEPT 537 | { 538 | auto const wdu = static_cast(static_cast(x) - 1u) + y.count(); 539 | auto const wk = (wdu >= 0 ? wdu : wdu-6) / 7; 540 | return weekday{static_cast(wdu - wk * 7) + 1u}; 541 | } 542 | 543 | CONSTCD14 544 | inline 545 | weekday 546 | operator+(const days& x, const weekday& y) NOEXCEPT 547 | { 548 | return y + x; 549 | } 550 | 551 | CONSTCD14 552 | inline 553 | weekday 554 | operator-(const weekday& x, const days& y) NOEXCEPT 555 | { 556 | return x + -y; 557 | } 558 | 559 | template 560 | inline 561 | std::basic_ostream& 562 | operator<<(std::basic_ostream& os, const weekday& wd) 563 | { 564 | switch (static_cast(wd)) 565 | { 566 | case 7: 567 | os << "Sun"; 568 | break; 569 | case 1: 570 | os << "Mon"; 571 | break; 572 | case 2: 573 | os << "Tue"; 574 | break; 575 | case 3: 576 | os << "Wed"; 577 | break; 578 | case 4: 579 | os << "Thu"; 580 | break; 581 | case 5: 582 | os << "Fri"; 583 | break; 584 | case 6: 585 | os << "Sat"; 586 | break; 587 | default: 588 | os << static_cast(wd) << " is not a valid weekday"; 589 | break; 590 | } 591 | return os; 592 | } 593 | 594 | // year 595 | 596 | CONSTCD11 inline year::year(int y) NOEXCEPT : y_(static_cast(y)) {} 597 | inline year& year::operator++() NOEXCEPT {++y_; return *this;} 598 | inline year year::operator++(int) NOEXCEPT {auto tmp(*this); ++(*this); return tmp;} 599 | inline year& year::operator--() NOEXCEPT {--y_; return *this;} 600 | inline year year::operator--(int) NOEXCEPT {auto tmp(*this); --(*this); return tmp;} 601 | inline year& year::operator+=(const years& y) NOEXCEPT {*this = *this + y; return *this;} 602 | inline year& year::operator-=(const years& y) NOEXCEPT {*this = *this - y; return *this;} 603 | 604 | CONSTCD14 605 | inline 606 | bool 607 | year::is_leap() const NOEXCEPT 608 | { 609 | const auto y = date::year{static_cast(y_)}; 610 | const auto s0 = sys_days((y-years{1})/12/date::thu[date::last]); 611 | const auto s1 = sys_days(y/12/date::thu[date::last]); 612 | return s1-s0 != days{7*52}; 613 | } 614 | 615 | CONSTCD11 inline year::operator int() const NOEXCEPT {return y_;} 616 | CONSTCD11 inline bool year::ok() const NOEXCEPT {return min() <= *this && *this <= max();} 617 | 618 | CONSTCD11 619 | inline 620 | year 621 | year::min() NOEXCEPT 622 | { 623 | using std::chrono::seconds; 624 | using std::chrono::minutes; 625 | using std::chrono::hours; 626 | using std::chrono::duration_cast; 627 | static_assert(sizeof(seconds)*CHAR_BIT >= 41, "seconds may overflow"); 628 | static_assert(sizeof(hours)*CHAR_BIT >= 30, "hours may overflow"); 629 | return sizeof(minutes)*CHAR_BIT < 34 ? 630 | year{1970} + duration_cast(minutes::min()) : 631 | year{std::numeric_limits::min()}; 632 | } 633 | 634 | CONSTCD11 635 | inline 636 | year 637 | year::max() NOEXCEPT 638 | { 639 | using std::chrono::seconds; 640 | using std::chrono::minutes; 641 | using std::chrono::hours; 642 | using std::chrono::duration_cast; 643 | static_assert(sizeof(seconds)*CHAR_BIT >= 41, "seconds may overflow"); 644 | static_assert(sizeof(hours)*CHAR_BIT >= 30, "hours may overflow"); 645 | return sizeof(minutes)*CHAR_BIT < 34 ? 646 | year{1969} + duration_cast(minutes::max()) : 647 | year{std::numeric_limits::max()}; 648 | } 649 | 650 | CONSTCD11 651 | inline 652 | bool 653 | operator==(const year& x, const year& y) NOEXCEPT 654 | { 655 | return static_cast(x) == static_cast(y); 656 | } 657 | 658 | CONSTCD11 659 | inline 660 | bool 661 | operator!=(const year& x, const year& y) NOEXCEPT 662 | { 663 | return !(x == y); 664 | } 665 | 666 | CONSTCD11 667 | inline 668 | bool 669 | operator<(const year& x, const year& y) NOEXCEPT 670 | { 671 | return static_cast(x) < static_cast(y); 672 | } 673 | 674 | CONSTCD11 675 | inline 676 | bool 677 | operator>(const year& x, const year& y) NOEXCEPT 678 | { 679 | return y < x; 680 | } 681 | 682 | CONSTCD11 683 | inline 684 | bool 685 | operator<=(const year& x, const year& y) NOEXCEPT 686 | { 687 | return !(y < x); 688 | } 689 | 690 | CONSTCD11 691 | inline 692 | bool 693 | operator>=(const year& x, const year& y) NOEXCEPT 694 | { 695 | return !(x < y); 696 | } 697 | 698 | CONSTCD11 699 | inline 700 | years 701 | operator-(const year& x, const year& y) NOEXCEPT 702 | { 703 | return years{static_cast(x) - static_cast(y)}; 704 | } 705 | 706 | CONSTCD11 707 | inline 708 | year 709 | operator+(const year& x, const years& y) NOEXCEPT 710 | { 711 | return year{static_cast(x) + y.count()}; 712 | } 713 | 714 | CONSTCD11 715 | inline 716 | year 717 | operator+(const years& x, const year& y) NOEXCEPT 718 | { 719 | return y + x; 720 | } 721 | 722 | CONSTCD11 723 | inline 724 | year 725 | operator-(const year& x, const years& y) NOEXCEPT 726 | { 727 | return year{static_cast(x) - y.count()}; 728 | } 729 | 730 | template 731 | inline 732 | std::basic_ostream& 733 | operator<<(std::basic_ostream& os, const year& y) 734 | { 735 | date::detail::save_ostream _(os); 736 | os.fill('0'); 737 | os.flags(std::ios::dec | std::ios::internal); 738 | os.width(4 + (y < year{0})); 739 | os << static_cast(y); 740 | return os; 741 | } 742 | 743 | #if !defined(_MSC_VER) || (_MSC_VER >= 1900) 744 | inline namespace literals 745 | { 746 | 747 | CONSTCD11 748 | inline 749 | iso_week::year 750 | operator ""_y(unsigned long long y) NOEXCEPT 751 | { 752 | return iso_week::year(static_cast(y)); 753 | } 754 | 755 | CONSTCD11 756 | inline 757 | iso_week::weeknum 758 | operator ""_w(unsigned long long wn) NOEXCEPT 759 | { 760 | return iso_week::weeknum(static_cast(wn)); 761 | } 762 | 763 | #endif // !defined(_MSC_VER) || (_MSC_VER >= 1900) 764 | 765 | CONSTDATA iso_week::last_week last{}; 766 | 767 | CONSTDATA iso_week::weekday sun{7u}; 768 | CONSTDATA iso_week::weekday mon{1u}; 769 | CONSTDATA iso_week::weekday tue{2u}; 770 | CONSTDATA iso_week::weekday wed{3u}; 771 | CONSTDATA iso_week::weekday thu{4u}; 772 | CONSTDATA iso_week::weekday fri{5u}; 773 | CONSTDATA iso_week::weekday sat{6u}; 774 | 775 | #if !defined(_MSC_VER) || (_MSC_VER >= 1900) 776 | } // inline namespace literals 777 | #endif 778 | 779 | // weeknum 780 | 781 | CONSTCD11 782 | inline 783 | weeknum::weeknum(unsigned wn) NOEXCEPT 784 | : wn_(static_cast(wn)) 785 | {} 786 | 787 | inline weeknum& weeknum::operator++() NOEXCEPT {++wn_; return *this;} 788 | inline weeknum weeknum::operator++(int) NOEXCEPT {auto tmp(*this); ++(*this); return tmp;} 789 | inline weeknum& weeknum::operator--() NOEXCEPT {--wn_; return *this;} 790 | inline weeknum weeknum::operator--(int) NOEXCEPT {auto tmp(*this); --(*this); return tmp;} 791 | 792 | inline 793 | weeknum& 794 | weeknum::operator+=(const weeks& y) NOEXCEPT 795 | { 796 | *this = *this + y; 797 | return *this; 798 | } 799 | 800 | inline 801 | weeknum& 802 | weeknum::operator-=(const weeks& y) NOEXCEPT 803 | { 804 | *this = *this - y; 805 | return *this; 806 | } 807 | 808 | CONSTCD11 inline weeknum::operator unsigned() const NOEXCEPT {return wn_;} 809 | CONSTCD11 inline bool weeknum::ok() const NOEXCEPT {return 1 <= wn_ && wn_ <= 53;} 810 | 811 | CONSTCD11 812 | inline 813 | bool 814 | operator==(const weeknum& x, const weeknum& y) NOEXCEPT 815 | { 816 | return static_cast(x) == static_cast(y); 817 | } 818 | 819 | CONSTCD11 820 | inline 821 | bool 822 | operator!=(const weeknum& x, const weeknum& y) NOEXCEPT 823 | { 824 | return !(x == y); 825 | } 826 | 827 | CONSTCD11 828 | inline 829 | bool 830 | operator<(const weeknum& x, const weeknum& y) NOEXCEPT 831 | { 832 | return static_cast(x) < static_cast(y); 833 | } 834 | 835 | CONSTCD11 836 | inline 837 | bool 838 | operator>(const weeknum& x, const weeknum& y) NOEXCEPT 839 | { 840 | return y < x; 841 | } 842 | 843 | CONSTCD11 844 | inline 845 | bool 846 | operator<=(const weeknum& x, const weeknum& y) NOEXCEPT 847 | { 848 | return !(y < x); 849 | } 850 | 851 | CONSTCD11 852 | inline 853 | bool 854 | operator>=(const weeknum& x, const weeknum& y) NOEXCEPT 855 | { 856 | return !(x < y); 857 | } 858 | 859 | CONSTCD11 860 | inline 861 | weeks 862 | operator-(const weeknum& x, const weeknum& y) NOEXCEPT 863 | { 864 | return weeks{static_cast(static_cast(x)) - 865 | static_cast(static_cast(y))}; 866 | } 867 | 868 | CONSTCD11 869 | inline 870 | weeknum 871 | operator+(const weeknum& x, const weeks& y) NOEXCEPT 872 | { 873 | return weeknum{static_cast(x) + static_cast(y.count())}; 874 | } 875 | 876 | CONSTCD11 877 | inline 878 | weeknum 879 | operator+(const weeks& x, const weeknum& y) NOEXCEPT 880 | { 881 | return y + x; 882 | } 883 | 884 | CONSTCD11 885 | inline 886 | weeknum 887 | operator-(const weeknum& x, const weeks& y) NOEXCEPT 888 | { 889 | return x + -y; 890 | } 891 | 892 | template 893 | inline 894 | std::basic_ostream& 895 | operator<<(std::basic_ostream& os, const weeknum& wn) 896 | { 897 | date::detail::save_ostream _(os); 898 | os << 'W'; 899 | os.fill('0'); 900 | os.flags(std::ios::dec | std::ios::right); 901 | os.width(2); 902 | os << static_cast(wn); 903 | return os; 904 | } 905 | 906 | // year_weeknum 907 | 908 | CONSTCD11 909 | inline 910 | year_weeknum::year_weeknum(const iso_week::year& y, const iso_week::weeknum& wn) NOEXCEPT 911 | : y_(y) 912 | , wn_(wn) 913 | {} 914 | 915 | CONSTCD11 inline year year_weeknum::year() const NOEXCEPT {return y_;} 916 | CONSTCD11 inline weeknum year_weeknum::weeknum() const NOEXCEPT {return wn_;} 917 | CONSTCD11 inline bool year_weeknum::ok() const NOEXCEPT 918 | { 919 | return y_.ok() && 1u <= static_cast(wn_) && wn_ <= (y_/last).weeknum(); 920 | } 921 | 922 | inline 923 | year_weeknum& 924 | year_weeknum::operator+=(const years& dy) NOEXCEPT 925 | { 926 | *this = *this + dy; 927 | return *this; 928 | } 929 | 930 | inline 931 | year_weeknum& 932 | year_weeknum::operator-=(const years& dy) NOEXCEPT 933 | { 934 | *this = *this - dy; 935 | return *this; 936 | } 937 | 938 | CONSTCD11 939 | inline 940 | bool 941 | operator==(const year_weeknum& x, const year_weeknum& y) NOEXCEPT 942 | { 943 | return x.year() == y.year() && x.weeknum() == y.weeknum(); 944 | } 945 | 946 | CONSTCD11 947 | inline 948 | bool 949 | operator!=(const year_weeknum& x, const year_weeknum& y) NOEXCEPT 950 | { 951 | return !(x == y); 952 | } 953 | 954 | CONSTCD11 955 | inline 956 | bool 957 | operator<(const year_weeknum& x, const year_weeknum& y) NOEXCEPT 958 | { 959 | return x.year() < y.year() ? true 960 | : (x.year() > y.year() ? false 961 | : (x.weeknum() < y.weeknum())); 962 | } 963 | 964 | CONSTCD11 965 | inline 966 | bool 967 | operator>(const year_weeknum& x, const year_weeknum& y) NOEXCEPT 968 | { 969 | return y < x; 970 | } 971 | 972 | CONSTCD11 973 | inline 974 | bool 975 | operator<=(const year_weeknum& x, const year_weeknum& y) NOEXCEPT 976 | { 977 | return !(y < x); 978 | } 979 | 980 | CONSTCD11 981 | inline 982 | bool 983 | operator>=(const year_weeknum& x, const year_weeknum& y) NOEXCEPT 984 | { 985 | return !(x < y); 986 | } 987 | 988 | CONSTCD11 989 | inline 990 | year_weeknum 991 | operator+(const year_weeknum& ym, const years& dy) NOEXCEPT 992 | { 993 | return (ym.year() + dy) / ym.weeknum(); 994 | } 995 | 996 | CONSTCD11 997 | inline 998 | year_weeknum 999 | operator+(const years& dy, const year_weeknum& ym) NOEXCEPT 1000 | { 1001 | return ym + dy; 1002 | } 1003 | 1004 | CONSTCD11 1005 | inline 1006 | year_weeknum 1007 | operator-(const year_weeknum& ym, const years& dy) NOEXCEPT 1008 | { 1009 | return ym + -dy; 1010 | } 1011 | 1012 | template 1013 | inline 1014 | std::basic_ostream& 1015 | operator<<(std::basic_ostream& os, const year_weeknum& ywn) 1016 | { 1017 | return os << ywn.year() << '-' << ywn.weeknum(); 1018 | } 1019 | 1020 | 1021 | // year_lastweek 1022 | 1023 | CONSTCD11 1024 | inline 1025 | year_lastweek::year_lastweek(const iso_week::year& y) NOEXCEPT 1026 | : y_(y) 1027 | {} 1028 | 1029 | CONSTCD11 inline year year_lastweek::year() const NOEXCEPT {return y_;} 1030 | 1031 | CONSTCD14 1032 | inline 1033 | weeknum 1034 | year_lastweek::weeknum() const NOEXCEPT 1035 | { 1036 | return iso_week::weeknum(y_.is_leap() ? 53u : 52u); 1037 | } 1038 | 1039 | CONSTCD11 inline bool year_lastweek::ok() const NOEXCEPT {return y_.ok();} 1040 | 1041 | inline 1042 | year_lastweek& 1043 | year_lastweek::operator+=(const years& dy) NOEXCEPT 1044 | { 1045 | *this = *this + dy; 1046 | return *this; 1047 | } 1048 | 1049 | inline 1050 | year_lastweek& 1051 | year_lastweek::operator-=(const years& dy) NOEXCEPT 1052 | { 1053 | *this = *this - dy; 1054 | return *this; 1055 | } 1056 | 1057 | CONSTCD11 1058 | inline 1059 | bool 1060 | operator==(const year_lastweek& x, const year_lastweek& y) NOEXCEPT 1061 | { 1062 | return x.year() == y.year(); 1063 | } 1064 | 1065 | CONSTCD11 1066 | inline 1067 | bool 1068 | operator!=(const year_lastweek& x, const year_lastweek& y) NOEXCEPT 1069 | { 1070 | return !(x == y); 1071 | } 1072 | 1073 | CONSTCD11 1074 | inline 1075 | bool 1076 | operator<(const year_lastweek& x, const year_lastweek& y) NOEXCEPT 1077 | { 1078 | return x.year() < y.year(); 1079 | } 1080 | 1081 | CONSTCD11 1082 | inline 1083 | bool 1084 | operator>(const year_lastweek& x, const year_lastweek& y) NOEXCEPT 1085 | { 1086 | return y < x; 1087 | } 1088 | 1089 | CONSTCD11 1090 | inline 1091 | bool 1092 | operator<=(const year_lastweek& x, const year_lastweek& y) NOEXCEPT 1093 | { 1094 | return !(y < x); 1095 | } 1096 | 1097 | CONSTCD11 1098 | inline 1099 | bool 1100 | operator>=(const year_lastweek& x, const year_lastweek& y) NOEXCEPT 1101 | { 1102 | return !(x < y); 1103 | } 1104 | 1105 | CONSTCD11 1106 | inline 1107 | year_lastweek 1108 | operator+(const year_lastweek& ym, const years& dy) NOEXCEPT 1109 | { 1110 | return year_lastweek{ym.year() + dy}; 1111 | } 1112 | 1113 | CONSTCD11 1114 | inline 1115 | year_lastweek 1116 | operator+(const years& dy, const year_lastweek& ym) NOEXCEPT 1117 | { 1118 | return ym + dy; 1119 | } 1120 | 1121 | CONSTCD11 1122 | inline 1123 | year_lastweek 1124 | operator-(const year_lastweek& ym, const years& dy) NOEXCEPT 1125 | { 1126 | return ym + -dy; 1127 | } 1128 | 1129 | template 1130 | inline 1131 | std::basic_ostream& 1132 | operator<<(std::basic_ostream& os, const year_lastweek& ywn) 1133 | { 1134 | return os << ywn.year() << "-W last"; 1135 | } 1136 | 1137 | // weeknum_weekday 1138 | 1139 | CONSTCD11 1140 | inline 1141 | weeknum_weekday::weeknum_weekday(const iso_week::weeknum& wn, 1142 | const iso_week::weekday& wd) NOEXCEPT 1143 | : wn_(wn) 1144 | , wd_(wd) 1145 | {} 1146 | 1147 | CONSTCD11 inline weeknum weeknum_weekday::weeknum() const NOEXCEPT {return wn_;} 1148 | CONSTCD11 inline weekday weeknum_weekday::weekday() const NOEXCEPT {return wd_;} 1149 | 1150 | CONSTCD14 1151 | inline 1152 | bool 1153 | weeknum_weekday::ok() const NOEXCEPT 1154 | { 1155 | return wn_.ok() && wd_.ok(); 1156 | } 1157 | 1158 | CONSTCD11 1159 | inline 1160 | bool 1161 | operator==(const weeknum_weekday& x, const weeknum_weekday& y) NOEXCEPT 1162 | { 1163 | return x.weeknum() == y.weeknum() && x.weekday() == y.weekday(); 1164 | } 1165 | 1166 | CONSTCD11 1167 | inline 1168 | bool 1169 | operator!=(const weeknum_weekday& x, const weeknum_weekday& y) NOEXCEPT 1170 | { 1171 | return !(x == y); 1172 | } 1173 | 1174 | CONSTCD11 1175 | inline 1176 | bool 1177 | operator<(const weeknum_weekday& x, const weeknum_weekday& y) NOEXCEPT 1178 | { 1179 | return x.weeknum() < y.weeknum() ? true 1180 | : (x.weeknum() > y.weeknum() ? false 1181 | : (static_cast(x.weekday()) < static_cast(y.weekday()))); 1182 | } 1183 | 1184 | CONSTCD11 1185 | inline 1186 | bool 1187 | operator>(const weeknum_weekday& x, const weeknum_weekday& y) NOEXCEPT 1188 | { 1189 | return y < x; 1190 | } 1191 | 1192 | CONSTCD11 1193 | inline 1194 | bool 1195 | operator<=(const weeknum_weekday& x, const weeknum_weekday& y) NOEXCEPT 1196 | { 1197 | return !(y < x); 1198 | } 1199 | 1200 | CONSTCD11 1201 | inline 1202 | bool 1203 | operator>=(const weeknum_weekday& x, const weeknum_weekday& y) NOEXCEPT 1204 | { 1205 | return !(x < y); 1206 | } 1207 | 1208 | template 1209 | inline 1210 | std::basic_ostream& 1211 | operator<<(std::basic_ostream& os, const weeknum_weekday& md) 1212 | { 1213 | return os << md.weeknum() << '-' << md.weekday(); 1214 | } 1215 | 1216 | // lastweek_weekday 1217 | 1218 | CONSTCD11 1219 | inline 1220 | lastweek_weekday::lastweek_weekday(const iso_week::weekday& wd) NOEXCEPT 1221 | : wd_(wd) 1222 | {} 1223 | 1224 | CONSTCD11 inline weekday lastweek_weekday::weekday() const NOEXCEPT {return wd_;} 1225 | 1226 | CONSTCD14 1227 | inline 1228 | bool 1229 | lastweek_weekday::ok() const NOEXCEPT 1230 | { 1231 | return wd_.ok(); 1232 | } 1233 | 1234 | CONSTCD11 1235 | inline 1236 | bool 1237 | operator==(const lastweek_weekday& x, const lastweek_weekday& y) NOEXCEPT 1238 | { 1239 | return x.weekday() == y.weekday(); 1240 | } 1241 | 1242 | CONSTCD11 1243 | inline 1244 | bool 1245 | operator!=(const lastweek_weekday& x, const lastweek_weekday& y) NOEXCEPT 1246 | { 1247 | return !(x == y); 1248 | } 1249 | 1250 | CONSTCD11 1251 | inline 1252 | bool 1253 | operator<(const lastweek_weekday& x, const lastweek_weekday& y) NOEXCEPT 1254 | { 1255 | return static_cast(x.weekday()) < static_cast(y.weekday()); 1256 | } 1257 | 1258 | CONSTCD11 1259 | inline 1260 | bool 1261 | operator>(const lastweek_weekday& x, const lastweek_weekday& y) NOEXCEPT 1262 | { 1263 | return y < x; 1264 | } 1265 | 1266 | CONSTCD11 1267 | inline 1268 | bool 1269 | operator<=(const lastweek_weekday& x, const lastweek_weekday& y) NOEXCEPT 1270 | { 1271 | return !(y < x); 1272 | } 1273 | 1274 | CONSTCD11 1275 | inline 1276 | bool 1277 | operator>=(const lastweek_weekday& x, const lastweek_weekday& y) NOEXCEPT 1278 | { 1279 | return !(x < y); 1280 | } 1281 | 1282 | template 1283 | inline 1284 | std::basic_ostream& 1285 | operator<<(std::basic_ostream& os, const lastweek_weekday& md) 1286 | { 1287 | return os << "W last-" << md.weekday(); 1288 | } 1289 | 1290 | // year_lastweek_weekday 1291 | 1292 | CONSTCD11 1293 | inline 1294 | year_lastweek_weekday::year_lastweek_weekday(const iso_week::year& y, 1295 | const iso_week::weekday& wd) NOEXCEPT 1296 | : y_(y) 1297 | , wd_(wd) 1298 | {} 1299 | 1300 | inline 1301 | year_lastweek_weekday& 1302 | year_lastweek_weekday::operator+=(const years& y) NOEXCEPT 1303 | { 1304 | *this = *this + y; 1305 | return *this; 1306 | } 1307 | 1308 | inline 1309 | year_lastweek_weekday& 1310 | year_lastweek_weekday::operator-=(const years& y) NOEXCEPT 1311 | { 1312 | *this = *this - y; 1313 | return *this; 1314 | } 1315 | 1316 | CONSTCD11 inline year year_lastweek_weekday::year() const NOEXCEPT {return y_;} 1317 | 1318 | CONSTCD14 1319 | inline 1320 | weeknum 1321 | year_lastweek_weekday::weeknum() const NOEXCEPT 1322 | { 1323 | return (y_ / last).weeknum(); 1324 | } 1325 | 1326 | CONSTCD11 inline weekday year_lastweek_weekday::weekday() const NOEXCEPT {return wd_;} 1327 | 1328 | CONSTCD14 1329 | inline 1330 | year_lastweek_weekday::operator sys_days() const NOEXCEPT 1331 | { 1332 | return sys_days(date::year{static_cast(y_)}/date::dec/date::thu[date::last]) 1333 | + (sun - thu) - (sun - wd_); 1334 | } 1335 | 1336 | CONSTCD14 1337 | inline 1338 | year_lastweek_weekday::operator local_days() const NOEXCEPT 1339 | { 1340 | return local_days(date::year{static_cast(y_)}/date::dec/date::thu[date::last]) 1341 | + (sun - thu) - (sun - wd_); 1342 | } 1343 | 1344 | CONSTCD11 1345 | inline 1346 | bool 1347 | year_lastweek_weekday::ok() const NOEXCEPT 1348 | { 1349 | return y_.ok() && wd_.ok(); 1350 | } 1351 | 1352 | CONSTCD11 1353 | inline 1354 | bool 1355 | operator==(const year_lastweek_weekday& x, const year_lastweek_weekday& y) NOEXCEPT 1356 | { 1357 | return x.year() == y.year() && x.weekday() == y.weekday(); 1358 | } 1359 | 1360 | CONSTCD11 1361 | inline 1362 | bool 1363 | operator!=(const year_lastweek_weekday& x, const year_lastweek_weekday& y) NOEXCEPT 1364 | { 1365 | return !(x == y); 1366 | } 1367 | 1368 | CONSTCD11 1369 | inline 1370 | bool 1371 | operator<(const year_lastweek_weekday& x, const year_lastweek_weekday& y) NOEXCEPT 1372 | { 1373 | return x.year() < y.year() ? true 1374 | : (x.year() > y.year() ? false 1375 | : (static_cast(x.weekday()) < static_cast(y.weekday()))); 1376 | } 1377 | 1378 | CONSTCD11 1379 | inline 1380 | bool 1381 | operator>(const year_lastweek_weekday& x, const year_lastweek_weekday& y) NOEXCEPT 1382 | { 1383 | return y < x; 1384 | } 1385 | 1386 | CONSTCD11 1387 | inline 1388 | bool 1389 | operator<=(const year_lastweek_weekday& x, const year_lastweek_weekday& y) NOEXCEPT 1390 | { 1391 | return !(y < x); 1392 | } 1393 | 1394 | CONSTCD11 1395 | inline 1396 | bool 1397 | operator>=(const year_lastweek_weekday& x, const year_lastweek_weekday& y) NOEXCEPT 1398 | { 1399 | return !(x < y); 1400 | } 1401 | 1402 | CONSTCD11 1403 | inline 1404 | year_lastweek_weekday 1405 | operator+(const year_lastweek_weekday& ywnwd, const years& y) NOEXCEPT 1406 | { 1407 | return (ywnwd.year() + y) / last / ywnwd.weekday(); 1408 | } 1409 | 1410 | CONSTCD11 1411 | inline 1412 | year_lastweek_weekday 1413 | operator+(const years& y, const year_lastweek_weekday& ywnwd) NOEXCEPT 1414 | { 1415 | return ywnwd + y; 1416 | } 1417 | 1418 | CONSTCD11 1419 | inline 1420 | year_lastweek_weekday 1421 | operator-(const year_lastweek_weekday& ywnwd, const years& y) NOEXCEPT 1422 | { 1423 | return ywnwd + -y; 1424 | } 1425 | 1426 | template 1427 | inline 1428 | std::basic_ostream& 1429 | operator<<(std::basic_ostream& os, const year_lastweek_weekday& ywnwd) 1430 | { 1431 | return os << ywnwd.year() << "-W last-" << ywnwd.weekday(); 1432 | } 1433 | 1434 | // year_weeknum_weekday 1435 | 1436 | CONSTCD11 1437 | inline 1438 | year_weeknum_weekday::year_weeknum_weekday(const iso_week::year& y, 1439 | const iso_week::weeknum& wn, 1440 | const iso_week::weekday& wd) NOEXCEPT 1441 | : y_(y) 1442 | , wn_(wn) 1443 | , wd_(wd) 1444 | {} 1445 | 1446 | CONSTCD14 1447 | inline 1448 | year_weeknum_weekday::year_weeknum_weekday(const year_lastweek_weekday& ylwwd) NOEXCEPT 1449 | : y_(ylwwd.year()) 1450 | , wn_(ylwwd.weeknum()) 1451 | , wd_(ylwwd.weekday()) 1452 | {} 1453 | 1454 | CONSTCD14 1455 | inline 1456 | year_weeknum_weekday::year_weeknum_weekday(const sys_days& dp) NOEXCEPT 1457 | : year_weeknum_weekday(from_days(dp.time_since_epoch())) 1458 | {} 1459 | 1460 | CONSTCD14 1461 | inline 1462 | year_weeknum_weekday::year_weeknum_weekday(const local_days& dp) NOEXCEPT 1463 | : year_weeknum_weekday(from_days(dp.time_since_epoch())) 1464 | {} 1465 | 1466 | inline 1467 | year_weeknum_weekday& 1468 | year_weeknum_weekday::operator+=(const years& y) NOEXCEPT 1469 | { 1470 | *this = *this + y; 1471 | return *this; 1472 | } 1473 | 1474 | inline 1475 | year_weeknum_weekday& 1476 | year_weeknum_weekday::operator-=(const years& y) NOEXCEPT 1477 | { 1478 | *this = *this - y; 1479 | return *this; 1480 | } 1481 | 1482 | CONSTCD11 inline year year_weeknum_weekday::year() const NOEXCEPT {return y_;} 1483 | CONSTCD11 inline weeknum year_weeknum_weekday::weeknum() const NOEXCEPT {return wn_;} 1484 | CONSTCD11 inline weekday year_weeknum_weekday::weekday() const NOEXCEPT {return wd_;} 1485 | 1486 | CONSTCD14 1487 | inline 1488 | year_weeknum_weekday::operator sys_days() const NOEXCEPT 1489 | { 1490 | return sys_days(date::year{static_cast(y_)-1}/date::dec/date::thu[date::last]) 1491 | + (date::mon - date::thu) + weeks{static_cast(wn_)-1} + (wd_ - mon); 1492 | } 1493 | 1494 | CONSTCD14 1495 | inline 1496 | year_weeknum_weekday::operator local_days() const NOEXCEPT 1497 | { 1498 | return local_days(date::year{static_cast(y_)-1}/date::dec/date::thu[date::last]) 1499 | + (date::mon - date::thu) + weeks{static_cast(wn_)-1} + (wd_ - mon); 1500 | } 1501 | 1502 | CONSTCD14 1503 | inline 1504 | bool 1505 | year_weeknum_weekday::ok() const NOEXCEPT 1506 | { 1507 | return y_.ok() && wd_.ok() && iso_week::weeknum{1u} <= wn_ && wn_ <= year_lastweek{y_}.weeknum(); 1508 | } 1509 | 1510 | CONSTCD14 1511 | inline 1512 | year_weeknum_weekday 1513 | year_weeknum_weekday::from_days(days d) NOEXCEPT 1514 | { 1515 | const auto dp = sys_days{d}; 1516 | const auto wd = iso_week::weekday{dp}; 1517 | auto y = date::year_month_day{dp + days{3}}.year(); 1518 | auto start = sys_days((y - date::years{1})/date::dec/date::thu[date::last]) + (mon-thu); 1519 | if (dp < start) 1520 | { 1521 | --y; 1522 | start = sys_days((y - date::years{1})/date::dec/date::thu[date::last]) + (mon-thu); 1523 | } 1524 | const auto wn = iso_week::weeknum( 1525 | static_cast(date::trunc(dp - start).count() + 1)); 1526 | return {iso_week::year(static_cast(y)), wn, wd}; 1527 | } 1528 | 1529 | CONSTCD11 1530 | inline 1531 | bool 1532 | operator==(const year_weeknum_weekday& x, const year_weeknum_weekday& y) NOEXCEPT 1533 | { 1534 | return x.year() == y.year() && x.weeknum() == y.weeknum() && x.weekday() == y.weekday(); 1535 | } 1536 | 1537 | CONSTCD11 1538 | inline 1539 | bool 1540 | operator!=(const year_weeknum_weekday& x, const year_weeknum_weekday& y) NOEXCEPT 1541 | { 1542 | return !(x == y); 1543 | } 1544 | 1545 | CONSTCD11 1546 | inline 1547 | bool 1548 | operator<(const year_weeknum_weekday& x, const year_weeknum_weekday& y) NOEXCEPT 1549 | { 1550 | return x.year() < y.year() ? true 1551 | : (x.year() > y.year() ? false 1552 | : (x.weeknum() < y.weeknum() ? true 1553 | : (x.weeknum() > y.weeknum() ? false 1554 | : (static_cast(x.weekday()) < static_cast(y.weekday()))))); 1555 | } 1556 | 1557 | CONSTCD11 1558 | inline 1559 | bool 1560 | operator>(const year_weeknum_weekday& x, const year_weeknum_weekday& y) NOEXCEPT 1561 | { 1562 | return y < x; 1563 | } 1564 | 1565 | CONSTCD11 1566 | inline 1567 | bool 1568 | operator<=(const year_weeknum_weekday& x, const year_weeknum_weekday& y) NOEXCEPT 1569 | { 1570 | return !(y < x); 1571 | } 1572 | 1573 | CONSTCD11 1574 | inline 1575 | bool 1576 | operator>=(const year_weeknum_weekday& x, const year_weeknum_weekday& y) NOEXCEPT 1577 | { 1578 | return !(x < y); 1579 | } 1580 | 1581 | CONSTCD11 1582 | inline 1583 | year_weeknum_weekday 1584 | operator+(const year_weeknum_weekday& ywnwd, const years& y) NOEXCEPT 1585 | { 1586 | return (ywnwd.year() + y) / ywnwd.weeknum() / ywnwd.weekday(); 1587 | } 1588 | 1589 | CONSTCD11 1590 | inline 1591 | year_weeknum_weekday 1592 | operator+(const years& y, const year_weeknum_weekday& ywnwd) NOEXCEPT 1593 | { 1594 | return ywnwd + y; 1595 | } 1596 | 1597 | CONSTCD11 1598 | inline 1599 | year_weeknum_weekday 1600 | operator-(const year_weeknum_weekday& ywnwd, const years& y) NOEXCEPT 1601 | { 1602 | return ywnwd + -y; 1603 | } 1604 | 1605 | template 1606 | inline 1607 | std::basic_ostream& 1608 | operator<<(std::basic_ostream& os, const year_weeknum_weekday& ywnwd) 1609 | { 1610 | return os << ywnwd.year() << '-' << ywnwd.weeknum() << '-' << ywnwd.weekday(); 1611 | } 1612 | 1613 | // date composition operators 1614 | 1615 | CONSTCD11 1616 | inline 1617 | year_weeknum 1618 | operator/(const year& y, const weeknum& wn) NOEXCEPT 1619 | { 1620 | return {y, wn}; 1621 | } 1622 | 1623 | CONSTCD11 1624 | inline 1625 | year_weeknum 1626 | operator/(const year& y, int wn) NOEXCEPT 1627 | { 1628 | return y/weeknum(static_cast(wn)); 1629 | } 1630 | 1631 | CONSTCD11 1632 | inline 1633 | year_lastweek 1634 | operator/(const year& y, last_week) NOEXCEPT 1635 | { 1636 | return year_lastweek{y}; 1637 | } 1638 | 1639 | CONSTCD11 1640 | inline 1641 | weeknum_weekday 1642 | operator/(const weeknum& wn, const weekday& wd) NOEXCEPT 1643 | { 1644 | return {wn, wd}; 1645 | } 1646 | 1647 | CONSTCD11 1648 | inline 1649 | weeknum_weekday 1650 | operator/(const weeknum& wn, int wd) NOEXCEPT 1651 | { 1652 | return wn/weekday{static_cast(wd)}; 1653 | } 1654 | 1655 | CONSTCD11 1656 | inline 1657 | weeknum_weekday 1658 | operator/(const weekday& wd, const weeknum& wn) NOEXCEPT 1659 | { 1660 | return wn/wd; 1661 | } 1662 | 1663 | CONSTCD11 1664 | inline 1665 | weeknum_weekday 1666 | operator/(const weekday& wd, int wn) NOEXCEPT 1667 | { 1668 | return weeknum{static_cast(wn)}/wd; 1669 | } 1670 | 1671 | CONSTCD11 1672 | inline 1673 | lastweek_weekday 1674 | operator/(const last_week&, const weekday& wd) NOEXCEPT 1675 | { 1676 | return lastweek_weekday{wd}; 1677 | } 1678 | 1679 | CONSTCD11 1680 | inline 1681 | lastweek_weekday 1682 | operator/(const last_week& wn, int wd) NOEXCEPT 1683 | { 1684 | return wn / weekday{static_cast(wd)}; 1685 | } 1686 | 1687 | CONSTCD11 1688 | inline 1689 | lastweek_weekday 1690 | operator/(const weekday& wd, const last_week& wn) NOEXCEPT 1691 | { 1692 | return wn / wd; 1693 | } 1694 | 1695 | CONSTCD11 1696 | inline 1697 | year_weeknum_weekday 1698 | operator/(const year_weeknum& ywn, const weekday& wd) NOEXCEPT 1699 | { 1700 | return {ywn.year(), ywn.weeknum(), wd}; 1701 | } 1702 | 1703 | CONSTCD11 1704 | inline 1705 | year_weeknum_weekday 1706 | operator/(const year_weeknum& ywn, int wd) NOEXCEPT 1707 | { 1708 | return ywn / weekday(static_cast(wd)); 1709 | } 1710 | 1711 | CONSTCD11 1712 | inline 1713 | year_weeknum_weekday 1714 | operator/(const weeknum_weekday& wnwd, const year& y) NOEXCEPT 1715 | { 1716 | return {y, wnwd.weeknum(), wnwd.weekday()}; 1717 | } 1718 | 1719 | CONSTCD11 1720 | inline 1721 | year_weeknum_weekday 1722 | operator/(const weeknum_weekday& wnwd, int y) NOEXCEPT 1723 | { 1724 | return wnwd / year{y}; 1725 | } 1726 | 1727 | CONSTCD11 1728 | inline 1729 | year_lastweek_weekday 1730 | operator/(const year_lastweek& ylw, const weekday& wd) NOEXCEPT 1731 | { 1732 | return {ylw.year(), wd}; 1733 | } 1734 | 1735 | CONSTCD11 1736 | inline 1737 | year_lastweek_weekday 1738 | operator/(const year_lastweek& ylw, int wd) NOEXCEPT 1739 | { 1740 | return ylw / weekday(static_cast(wd)); 1741 | } 1742 | 1743 | CONSTCD11 1744 | inline 1745 | year_lastweek_weekday 1746 | operator/(const lastweek_weekday& lwwd, const year& y) NOEXCEPT 1747 | { 1748 | return {y, lwwd.weekday()}; 1749 | } 1750 | 1751 | CONSTCD11 1752 | inline 1753 | year_lastweek_weekday 1754 | operator/(const lastweek_weekday& lwwd, int y) NOEXCEPT 1755 | { 1756 | return lwwd / year{y}; 1757 | } 1758 | 1759 | } // namespace iso_week 1760 | 1761 | #endif // ISO_WEEK_H 1762 | -------------------------------------------------------------------------------- /inst/include/islamic.h: -------------------------------------------------------------------------------- 1 | #ifndef ISLAMIC_H 2 | #define ISLAMIC_H 3 | 4 | // The MIT License (MIT) 5 | // 6 | // Copyright (c) 2016 Howard Hinnant 7 | // 8 | // Permission is hereby granted, free of charge, to any person obtaining a copy 9 | // of this software and associated documentation files (the "Software"), to deal 10 | // in the Software without restriction, including without limitation the rights 11 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 12 | // copies of the Software, and to permit persons to whom the Software is 13 | // furnished to do so, subject to the following conditions: 14 | // 15 | // The above copyright notice and this permission notice shall be included in all 16 | // copies or substantial portions of the Software. 17 | // 18 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 24 | // SOFTWARE. 25 | // 26 | // Our apologies. When the previous paragraph was written, lowercase had not yet 27 | // been invented (that would involve another several millennia of evolution). 28 | // We did not mean to shout. 29 | 30 | #include "date.h" 31 | 32 | namespace islamic 33 | { 34 | 35 | // durations 36 | 37 | using days = date::days; 38 | 39 | using weeks = date::weeks; 40 | 41 | using years = std::chrono::duration 42 | , days::period>>; 43 | 44 | using months = std::chrono::duration 45 | >>; 46 | 47 | // time_point 48 | 49 | using sys_days = date::sys_days; 50 | using local_days = date::local_days; 51 | 52 | // types 53 | 54 | struct last_spec 55 | { 56 | explicit last_spec() = default; 57 | }; 58 | 59 | class day; 60 | class month; 61 | class year; 62 | 63 | class weekday; 64 | class weekday_indexed; 65 | class weekday_last; 66 | 67 | class month_day; 68 | class month_day_last; 69 | class month_weekday; 70 | class month_weekday_last; 71 | 72 | class year_month; 73 | 74 | class year_month_day; 75 | class year_month_day_last; 76 | class year_month_weekday; 77 | class year_month_weekday_last; 78 | 79 | // date composition operators 80 | 81 | CONSTCD11 year_month operator/(const year& y, const month& m) NOEXCEPT; 82 | CONSTCD11 year_month operator/(const year& y, int m) NOEXCEPT; 83 | 84 | CONSTCD11 month_day operator/(const day& d, const month& m) NOEXCEPT; 85 | CONSTCD11 month_day operator/(const day& d, int m) NOEXCEPT; 86 | CONSTCD11 month_day operator/(const month& m, const day& d) NOEXCEPT; 87 | CONSTCD11 month_day operator/(const month& m, int d) NOEXCEPT; 88 | CONSTCD11 month_day operator/(int m, const day& d) NOEXCEPT; 89 | 90 | CONSTCD11 month_day_last operator/(const month& m, last_spec) NOEXCEPT; 91 | CONSTCD11 month_day_last operator/(int m, last_spec) NOEXCEPT; 92 | CONSTCD11 month_day_last operator/(last_spec, const month& m) NOEXCEPT; 93 | CONSTCD11 month_day_last operator/(last_spec, int m) NOEXCEPT; 94 | 95 | CONSTCD11 month_weekday operator/(const month& m, const weekday_indexed& wdi) NOEXCEPT; 96 | CONSTCD11 month_weekday operator/(int m, const weekday_indexed& wdi) NOEXCEPT; 97 | CONSTCD11 month_weekday operator/(const weekday_indexed& wdi, const month& m) NOEXCEPT; 98 | CONSTCD11 month_weekday operator/(const weekday_indexed& wdi, int m) NOEXCEPT; 99 | 100 | CONSTCD11 month_weekday_last operator/(const month& m, const weekday_last& wdl) NOEXCEPT; 101 | CONSTCD11 month_weekday_last operator/(int m, const weekday_last& wdl) NOEXCEPT; 102 | CONSTCD11 month_weekday_last operator/(const weekday_last& wdl, const month& m) NOEXCEPT; 103 | CONSTCD11 month_weekday_last operator/(const weekday_last& wdl, int m) NOEXCEPT; 104 | 105 | CONSTCD11 year_month_day operator/(const year_month& ym, const day& d) NOEXCEPT; 106 | CONSTCD11 year_month_day operator/(const year_month& ym, int d) NOEXCEPT; 107 | CONSTCD11 year_month_day operator/(const year& y, const month_day& md) NOEXCEPT; 108 | CONSTCD11 year_month_day operator/(int y, const month_day& md) NOEXCEPT; 109 | CONSTCD11 year_month_day operator/(const month_day& md, const year& y) NOEXCEPT; 110 | CONSTCD11 year_month_day operator/(const month_day& md, int y) NOEXCEPT; 111 | 112 | CONSTCD11 113 | year_month_day_last operator/(const year_month& ym, last_spec) NOEXCEPT; 114 | CONSTCD11 115 | year_month_day_last operator/(const year& y, const month_day_last& mdl) NOEXCEPT; 116 | CONSTCD11 117 | year_month_day_last operator/(int y, const month_day_last& mdl) NOEXCEPT; 118 | CONSTCD11 119 | year_month_day_last operator/(const month_day_last& mdl, const year& y) NOEXCEPT; 120 | CONSTCD11 121 | year_month_day_last operator/(const month_day_last& mdl, int y) NOEXCEPT; 122 | 123 | CONSTCD11 124 | year_month_weekday 125 | operator/(const year_month& ym, const weekday_indexed& wdi) NOEXCEPT; 126 | 127 | CONSTCD11 128 | year_month_weekday 129 | operator/(const year& y, const month_weekday& mwd) NOEXCEPT; 130 | 131 | CONSTCD11 132 | year_month_weekday 133 | operator/(int y, const month_weekday& mwd) NOEXCEPT; 134 | 135 | CONSTCD11 136 | year_month_weekday 137 | operator/(const month_weekday& mwd, const year& y) NOEXCEPT; 138 | 139 | CONSTCD11 140 | year_month_weekday 141 | operator/(const month_weekday& mwd, int y) NOEXCEPT; 142 | 143 | CONSTCD11 144 | year_month_weekday_last 145 | operator/(const year_month& ym, const weekday_last& wdl) NOEXCEPT; 146 | 147 | CONSTCD11 148 | year_month_weekday_last 149 | operator/(const year& y, const month_weekday_last& mwdl) NOEXCEPT; 150 | 151 | CONSTCD11 152 | year_month_weekday_last 153 | operator/(int y, const month_weekday_last& mwdl) NOEXCEPT; 154 | 155 | CONSTCD11 156 | year_month_weekday_last 157 | operator/(const month_weekday_last& mwdl, const year& y) NOEXCEPT; 158 | 159 | CONSTCD11 160 | year_month_weekday_last 161 | operator/(const month_weekday_last& mwdl, int y) NOEXCEPT; 162 | 163 | // Detailed interface 164 | 165 | // day 166 | 167 | class day 168 | { 169 | unsigned char d_; 170 | 171 | public: 172 | explicit CONSTCD11 day(unsigned d) NOEXCEPT; 173 | 174 | CONSTCD14 day& operator++() NOEXCEPT; 175 | CONSTCD14 day operator++(int) NOEXCEPT; 176 | CONSTCD14 day& operator--() NOEXCEPT; 177 | CONSTCD14 day operator--(int) NOEXCEPT; 178 | 179 | CONSTCD14 day& operator+=(const days& d) NOEXCEPT; 180 | CONSTCD14 day& operator-=(const days& d) NOEXCEPT; 181 | 182 | CONSTCD11 explicit operator unsigned() const NOEXCEPT; 183 | CONSTCD11 bool ok() const NOEXCEPT; 184 | }; 185 | 186 | CONSTCD11 bool operator==(const day& x, const day& y) NOEXCEPT; 187 | CONSTCD11 bool operator!=(const day& x, const day& y) NOEXCEPT; 188 | CONSTCD11 bool operator< (const day& x, const day& y) NOEXCEPT; 189 | CONSTCD11 bool operator> (const day& x, const day& y) NOEXCEPT; 190 | CONSTCD11 bool operator<=(const day& x, const day& y) NOEXCEPT; 191 | CONSTCD11 bool operator>=(const day& x, const day& y) NOEXCEPT; 192 | 193 | CONSTCD11 day operator+(const day& x, const days& y) NOEXCEPT; 194 | CONSTCD11 day operator+(const days& x, const day& y) NOEXCEPT; 195 | CONSTCD11 day operator-(const day& x, const days& y) NOEXCEPT; 196 | CONSTCD11 days operator-(const day& x, const day& y) NOEXCEPT; 197 | 198 | template 199 | std::basic_ostream& 200 | operator<<(std::basic_ostream& os, const day& d); 201 | 202 | // month 203 | 204 | class month 205 | { 206 | unsigned char m_; 207 | 208 | public: 209 | explicit CONSTCD11 month(unsigned m) NOEXCEPT; 210 | 211 | CONSTCD14 month& operator++() NOEXCEPT; 212 | CONSTCD14 month operator++(int) NOEXCEPT; 213 | CONSTCD14 month& operator--() NOEXCEPT; 214 | CONSTCD14 month operator--(int) NOEXCEPT; 215 | 216 | CONSTCD14 month& operator+=(const months& m) NOEXCEPT; 217 | CONSTCD14 month& operator-=(const months& m) NOEXCEPT; 218 | 219 | CONSTCD11 explicit operator unsigned() const NOEXCEPT; 220 | CONSTCD11 bool ok() const NOEXCEPT; 221 | }; 222 | 223 | CONSTCD11 bool operator==(const month& x, const month& y) NOEXCEPT; 224 | CONSTCD11 bool operator!=(const month& x, const month& y) NOEXCEPT; 225 | CONSTCD11 bool operator< (const month& x, const month& y) NOEXCEPT; 226 | CONSTCD11 bool operator> (const month& x, const month& y) NOEXCEPT; 227 | CONSTCD11 bool operator<=(const month& x, const month& y) NOEXCEPT; 228 | CONSTCD11 bool operator>=(const month& x, const month& y) NOEXCEPT; 229 | 230 | CONSTCD14 month operator+(const month& x, const months& y) NOEXCEPT; 231 | CONSTCD14 month operator+(const months& x, const month& y) NOEXCEPT; 232 | CONSTCD14 month operator-(const month& x, const months& y) NOEXCEPT; 233 | CONSTCD14 months operator-(const month& x, const month& y) NOEXCEPT; 234 | 235 | template 236 | std::basic_ostream& 237 | operator<<(std::basic_ostream& os, const month& m); 238 | 239 | // year 240 | 241 | class year 242 | { 243 | short y_; 244 | 245 | public: 246 | explicit CONSTCD11 year(int y) NOEXCEPT; 247 | 248 | CONSTCD14 year& operator++() NOEXCEPT; 249 | CONSTCD14 year operator++(int) NOEXCEPT; 250 | CONSTCD14 year& operator--() NOEXCEPT; 251 | CONSTCD14 year operator--(int) NOEXCEPT; 252 | 253 | CONSTCD14 year& operator+=(const years& y) NOEXCEPT; 254 | CONSTCD14 year& operator-=(const years& y) NOEXCEPT; 255 | 256 | CONSTCD14 bool is_leap() const NOEXCEPT; 257 | 258 | CONSTCD11 explicit operator int() const NOEXCEPT; 259 | CONSTCD11 bool ok() const NOEXCEPT; 260 | 261 | static CONSTCD11 year min() NOEXCEPT; 262 | static CONSTCD11 year max() NOEXCEPT; 263 | }; 264 | 265 | CONSTCD11 bool operator==(const year& x, const year& y) NOEXCEPT; 266 | CONSTCD11 bool operator!=(const year& x, const year& y) NOEXCEPT; 267 | CONSTCD11 bool operator< (const year& x, const year& y) NOEXCEPT; 268 | CONSTCD11 bool operator> (const year& x, const year& y) NOEXCEPT; 269 | CONSTCD11 bool operator<=(const year& x, const year& y) NOEXCEPT; 270 | CONSTCD11 bool operator>=(const year& x, const year& y) NOEXCEPT; 271 | 272 | CONSTCD11 year operator+(const year& x, const years& y) NOEXCEPT; 273 | CONSTCD11 year operator+(const years& x, const year& y) NOEXCEPT; 274 | CONSTCD11 year operator-(const year& x, const years& y) NOEXCEPT; 275 | CONSTCD11 years operator-(const year& x, const year& y) NOEXCEPT; 276 | 277 | template 278 | std::basic_ostream& 279 | operator<<(std::basic_ostream& os, const year& y); 280 | 281 | // weekday 282 | 283 | class weekday 284 | { 285 | unsigned char wd_; 286 | public: 287 | explicit CONSTCD11 weekday(unsigned wd) NOEXCEPT; 288 | explicit weekday(int) = delete; 289 | CONSTCD11 weekday(const sys_days& dp) NOEXCEPT; 290 | CONSTCD11 explicit weekday(const local_days& dp) NOEXCEPT; 291 | 292 | CONSTCD14 weekday& operator++() NOEXCEPT; 293 | CONSTCD14 weekday operator++(int) NOEXCEPT; 294 | CONSTCD14 weekday& operator--() NOEXCEPT; 295 | CONSTCD14 weekday operator--(int) NOEXCEPT; 296 | 297 | CONSTCD14 weekday& operator+=(const days& d) NOEXCEPT; 298 | CONSTCD14 weekday& operator-=(const days& d) NOEXCEPT; 299 | 300 | CONSTCD11 explicit operator unsigned() const NOEXCEPT; 301 | CONSTCD11 bool ok() const NOEXCEPT; 302 | 303 | CONSTCD11 weekday_indexed operator[](unsigned index) const NOEXCEPT; 304 | CONSTCD11 weekday_last operator[](last_spec) const NOEXCEPT; 305 | 306 | private: 307 | static CONSTCD11 unsigned char weekday_from_days(int z) NOEXCEPT; 308 | }; 309 | 310 | CONSTCD11 bool operator==(const weekday& x, const weekday& y) NOEXCEPT; 311 | CONSTCD11 bool operator!=(const weekday& x, const weekday& y) NOEXCEPT; 312 | 313 | CONSTCD14 weekday operator+(const weekday& x, const days& y) NOEXCEPT; 314 | CONSTCD14 weekday operator+(const days& x, const weekday& y) NOEXCEPT; 315 | CONSTCD14 weekday operator-(const weekday& x, const days& y) NOEXCEPT; 316 | CONSTCD14 days operator-(const weekday& x, const weekday& y) NOEXCEPT; 317 | 318 | template 319 | std::basic_ostream& 320 | operator<<(std::basic_ostream& os, const weekday& wd); 321 | 322 | // weekday_indexed 323 | 324 | class weekday_indexed 325 | { 326 | unsigned char wd_ : 4; 327 | unsigned char index_ : 4; 328 | 329 | public: 330 | CONSTCD11 weekday_indexed(const islamic::weekday& wd, unsigned index) NOEXCEPT; 331 | 332 | CONSTCD11 islamic::weekday weekday() const NOEXCEPT; 333 | CONSTCD11 unsigned index() const NOEXCEPT; 334 | CONSTCD11 bool ok() const NOEXCEPT; 335 | }; 336 | 337 | CONSTCD11 bool operator==(const weekday_indexed& x, const weekday_indexed& y) NOEXCEPT; 338 | CONSTCD11 bool operator!=(const weekday_indexed& x, const weekday_indexed& y) NOEXCEPT; 339 | 340 | template 341 | std::basic_ostream& 342 | operator<<(std::basic_ostream& os, const weekday_indexed& wdi); 343 | 344 | // weekday_last 345 | 346 | class weekday_last 347 | { 348 | islamic::weekday wd_; 349 | 350 | public: 351 | explicit CONSTCD11 weekday_last(const islamic::weekday& wd) NOEXCEPT; 352 | 353 | CONSTCD11 islamic::weekday weekday() const NOEXCEPT; 354 | CONSTCD11 bool ok() const NOEXCEPT; 355 | }; 356 | 357 | CONSTCD11 bool operator==(const weekday_last& x, const weekday_last& y) NOEXCEPT; 358 | CONSTCD11 bool operator!=(const weekday_last& x, const weekday_last& y) NOEXCEPT; 359 | 360 | template 361 | std::basic_ostream& 362 | operator<<(std::basic_ostream& os, const weekday_last& wdl); 363 | 364 | // year_month 365 | 366 | class year_month 367 | { 368 | islamic::year y_; 369 | islamic::month m_; 370 | 371 | public: 372 | CONSTCD11 year_month(const islamic::year& y, const islamic::month& m) NOEXCEPT; 373 | 374 | CONSTCD11 islamic::year year() const NOEXCEPT; 375 | CONSTCD11 islamic::month month() const NOEXCEPT; 376 | 377 | CONSTCD14 year_month& operator+=(const months& dm) NOEXCEPT; 378 | CONSTCD14 year_month& operator-=(const months& dm) NOEXCEPT; 379 | CONSTCD14 year_month& operator+=(const years& dy) NOEXCEPT; 380 | CONSTCD14 year_month& operator-=(const years& dy) NOEXCEPT; 381 | 382 | CONSTCD11 bool ok() const NOEXCEPT; 383 | }; 384 | 385 | CONSTCD11 bool operator==(const year_month& x, const year_month& y) NOEXCEPT; 386 | CONSTCD11 bool operator!=(const year_month& x, const year_month& y) NOEXCEPT; 387 | CONSTCD11 bool operator< (const year_month& x, const year_month& y) NOEXCEPT; 388 | CONSTCD11 bool operator> (const year_month& x, const year_month& y) NOEXCEPT; 389 | CONSTCD11 bool operator<=(const year_month& x, const year_month& y) NOEXCEPT; 390 | CONSTCD11 bool operator>=(const year_month& x, const year_month& y) NOEXCEPT; 391 | 392 | CONSTCD14 year_month operator+(const year_month& ym, const months& dm) NOEXCEPT; 393 | CONSTCD14 year_month operator+(const months& dm, const year_month& ym) NOEXCEPT; 394 | CONSTCD14 year_month operator-(const year_month& ym, const months& dm) NOEXCEPT; 395 | 396 | CONSTCD11 months operator-(const year_month& x, const year_month& y) NOEXCEPT; 397 | CONSTCD11 year_month operator+(const year_month& ym, const years& dy) NOEXCEPT; 398 | CONSTCD11 year_month operator+(const years& dy, const year_month& ym) NOEXCEPT; 399 | CONSTCD11 year_month operator-(const year_month& ym, const years& dy) NOEXCEPT; 400 | 401 | template 402 | std::basic_ostream& 403 | operator<<(std::basic_ostream& os, const year_month& ym); 404 | 405 | // month_day 406 | 407 | class month_day 408 | { 409 | islamic::month m_; 410 | islamic::day d_; 411 | 412 | public: 413 | CONSTCD11 month_day(const islamic::month& m, const islamic::day& d) NOEXCEPT; 414 | 415 | CONSTCD11 islamic::month month() const NOEXCEPT; 416 | CONSTCD11 islamic::day day() const NOEXCEPT; 417 | 418 | CONSTCD14 bool ok() const NOEXCEPT; 419 | }; 420 | 421 | CONSTCD11 bool operator==(const month_day& x, const month_day& y) NOEXCEPT; 422 | CONSTCD11 bool operator!=(const month_day& x, const month_day& y) NOEXCEPT; 423 | CONSTCD11 bool operator< (const month_day& x, const month_day& y) NOEXCEPT; 424 | CONSTCD11 bool operator> (const month_day& x, const month_day& y) NOEXCEPT; 425 | CONSTCD11 bool operator<=(const month_day& x, const month_day& y) NOEXCEPT; 426 | CONSTCD11 bool operator>=(const month_day& x, const month_day& y) NOEXCEPT; 427 | 428 | template 429 | std::basic_ostream& 430 | operator<<(std::basic_ostream& os, const month_day& md); 431 | 432 | // month_day_last 433 | 434 | class month_day_last 435 | { 436 | islamic::month m_; 437 | 438 | public: 439 | CONSTCD11 explicit month_day_last(const islamic::month& m) NOEXCEPT; 440 | 441 | CONSTCD11 islamic::month month() const NOEXCEPT; 442 | CONSTCD11 bool ok() const NOEXCEPT; 443 | }; 444 | 445 | CONSTCD11 bool operator==(const month_day_last& x, const month_day_last& y) NOEXCEPT; 446 | CONSTCD11 bool operator!=(const month_day_last& x, const month_day_last& y) NOEXCEPT; 447 | CONSTCD11 bool operator< (const month_day_last& x, const month_day_last& y) NOEXCEPT; 448 | CONSTCD11 bool operator> (const month_day_last& x, const month_day_last& y) NOEXCEPT; 449 | CONSTCD11 bool operator<=(const month_day_last& x, const month_day_last& y) NOEXCEPT; 450 | CONSTCD11 bool operator>=(const month_day_last& x, const month_day_last& y) NOEXCEPT; 451 | 452 | template 453 | std::basic_ostream& 454 | operator<<(std::basic_ostream& os, const month_day_last& mdl); 455 | 456 | // month_weekday 457 | 458 | class month_weekday 459 | { 460 | islamic::month m_; 461 | islamic::weekday_indexed wdi_; 462 | public: 463 | CONSTCD11 month_weekday(const islamic::month& m, 464 | const islamic::weekday_indexed& wdi) NOEXCEPT; 465 | 466 | CONSTCD11 islamic::month month() const NOEXCEPT; 467 | CONSTCD11 islamic::weekday_indexed weekday_indexed() const NOEXCEPT; 468 | 469 | CONSTCD11 bool ok() const NOEXCEPT; 470 | }; 471 | 472 | CONSTCD11 bool operator==(const month_weekday& x, const month_weekday& y) NOEXCEPT; 473 | CONSTCD11 bool operator!=(const month_weekday& x, const month_weekday& y) NOEXCEPT; 474 | 475 | template 476 | std::basic_ostream& 477 | operator<<(std::basic_ostream& os, const month_weekday& mwd); 478 | 479 | // month_weekday_last 480 | 481 | class month_weekday_last 482 | { 483 | islamic::month m_; 484 | islamic::weekday_last wdl_; 485 | 486 | public: 487 | CONSTCD11 month_weekday_last(const islamic::month& m, 488 | const islamic::weekday_last& wd) NOEXCEPT; 489 | 490 | CONSTCD11 islamic::month month() const NOEXCEPT; 491 | CONSTCD11 islamic::weekday_last weekday_last() const NOEXCEPT; 492 | 493 | CONSTCD11 bool ok() const NOEXCEPT; 494 | }; 495 | 496 | CONSTCD11 497 | bool operator==(const month_weekday_last& x, const month_weekday_last& y) NOEXCEPT; 498 | CONSTCD11 499 | bool operator!=(const month_weekday_last& x, const month_weekday_last& y) NOEXCEPT; 500 | 501 | template 502 | std::basic_ostream& 503 | operator<<(std::basic_ostream& os, const month_weekday_last& mwdl); 504 | 505 | // class year_month_day 506 | 507 | class year_month_day 508 | { 509 | islamic::year y_; 510 | islamic::month m_; 511 | islamic::day d_; 512 | 513 | public: 514 | CONSTCD11 year_month_day(const islamic::year& y, const islamic::month& m, 515 | const islamic::day& d) NOEXCEPT; 516 | CONSTCD14 year_month_day(const year_month_day_last& ymdl) NOEXCEPT; 517 | 518 | CONSTCD14 year_month_day(sys_days dp) NOEXCEPT; 519 | CONSTCD14 explicit year_month_day(local_days dp) NOEXCEPT; 520 | 521 | CONSTCD14 year_month_day& operator+=(const months& m) NOEXCEPT; 522 | CONSTCD14 year_month_day& operator-=(const months& m) NOEXCEPT; 523 | CONSTCD14 year_month_day& operator+=(const years& y) NOEXCEPT; 524 | CONSTCD14 year_month_day& operator-=(const years& y) NOEXCEPT; 525 | 526 | CONSTCD11 islamic::year year() const NOEXCEPT; 527 | CONSTCD11 islamic::month month() const NOEXCEPT; 528 | CONSTCD11 islamic::day day() const NOEXCEPT; 529 | 530 | CONSTCD14 operator sys_days() const NOEXCEPT; 531 | CONSTCD14 explicit operator local_days() const NOEXCEPT; 532 | CONSTCD14 bool ok() const NOEXCEPT; 533 | 534 | private: 535 | static CONSTCD14 year_month_day from_days(days dp) NOEXCEPT; 536 | CONSTCD14 days to_days() const NOEXCEPT; 537 | }; 538 | 539 | CONSTCD11 bool operator==(const year_month_day& x, const year_month_day& y) NOEXCEPT; 540 | CONSTCD11 bool operator!=(const year_month_day& x, const year_month_day& y) NOEXCEPT; 541 | CONSTCD11 bool operator< (const year_month_day& x, const year_month_day& y) NOEXCEPT; 542 | CONSTCD11 bool operator> (const year_month_day& x, const year_month_day& y) NOEXCEPT; 543 | CONSTCD11 bool operator<=(const year_month_day& x, const year_month_day& y) NOEXCEPT; 544 | CONSTCD11 bool operator>=(const year_month_day& x, const year_month_day& y) NOEXCEPT; 545 | 546 | CONSTCD14 year_month_day operator+(const year_month_day& ymd, const months& dm) NOEXCEPT; 547 | CONSTCD14 year_month_day operator+(const months& dm, const year_month_day& ymd) NOEXCEPT; 548 | CONSTCD14 year_month_day operator-(const year_month_day& ymd, const months& dm) NOEXCEPT; 549 | CONSTCD11 year_month_day operator+(const year_month_day& ymd, const years& dy) NOEXCEPT; 550 | CONSTCD11 year_month_day operator+(const years& dy, const year_month_day& ymd) NOEXCEPT; 551 | CONSTCD11 year_month_day operator-(const year_month_day& ymd, const years& dy) NOEXCEPT; 552 | 553 | template 554 | std::basic_ostream& 555 | operator<<(std::basic_ostream& os, const year_month_day& ymd); 556 | 557 | // year_month_day_last 558 | 559 | class year_month_day_last 560 | { 561 | islamic::year y_; 562 | islamic::month_day_last mdl_; 563 | 564 | public: 565 | CONSTCD11 year_month_day_last(const islamic::year& y, 566 | const islamic::month_day_last& mdl) NOEXCEPT; 567 | 568 | CONSTCD14 year_month_day_last& operator+=(const months& m) NOEXCEPT; 569 | CONSTCD14 year_month_day_last& operator-=(const months& m) NOEXCEPT; 570 | CONSTCD14 year_month_day_last& operator+=(const years& y) NOEXCEPT; 571 | CONSTCD14 year_month_day_last& operator-=(const years& y) NOEXCEPT; 572 | 573 | CONSTCD11 islamic::year year() const NOEXCEPT; 574 | CONSTCD11 islamic::month month() const NOEXCEPT; 575 | CONSTCD11 islamic::month_day_last month_day_last() const NOEXCEPT; 576 | CONSTCD14 islamic::day day() const NOEXCEPT; 577 | 578 | CONSTCD14 operator sys_days() const NOEXCEPT; 579 | CONSTCD14 explicit operator local_days() const NOEXCEPT; 580 | CONSTCD11 bool ok() const NOEXCEPT; 581 | }; 582 | 583 | CONSTCD11 584 | bool operator==(const year_month_day_last& x, const year_month_day_last& y) NOEXCEPT; 585 | CONSTCD11 586 | bool operator!=(const year_month_day_last& x, const year_month_day_last& y) NOEXCEPT; 587 | CONSTCD11 588 | bool operator< (const year_month_day_last& x, const year_month_day_last& y) NOEXCEPT; 589 | CONSTCD11 590 | bool operator> (const year_month_day_last& x, const year_month_day_last& y) NOEXCEPT; 591 | CONSTCD11 592 | bool operator<=(const year_month_day_last& x, const year_month_day_last& y) NOEXCEPT; 593 | CONSTCD11 594 | bool operator>=(const year_month_day_last& x, const year_month_day_last& y) NOEXCEPT; 595 | 596 | CONSTCD14 597 | year_month_day_last 598 | operator+(const year_month_day_last& ymdl, const months& dm) NOEXCEPT; 599 | 600 | CONSTCD14 601 | year_month_day_last 602 | operator+(const months& dm, const year_month_day_last& ymdl) NOEXCEPT; 603 | 604 | CONSTCD11 605 | year_month_day_last 606 | operator+(const year_month_day_last& ymdl, const years& dy) NOEXCEPT; 607 | 608 | CONSTCD11 609 | year_month_day_last 610 | operator+(const years& dy, const year_month_day_last& ymdl) NOEXCEPT; 611 | 612 | CONSTCD14 613 | year_month_day_last 614 | operator-(const year_month_day_last& ymdl, const months& dm) NOEXCEPT; 615 | 616 | CONSTCD11 617 | year_month_day_last 618 | operator-(const year_month_day_last& ymdl, const years& dy) NOEXCEPT; 619 | 620 | template 621 | std::basic_ostream& 622 | operator<<(std::basic_ostream& os, const year_month_day_last& ymdl); 623 | 624 | // year_month_weekday 625 | 626 | class year_month_weekday 627 | { 628 | islamic::year y_; 629 | islamic::month m_; 630 | islamic::weekday_indexed wdi_; 631 | 632 | public: 633 | CONSTCD11 year_month_weekday(const islamic::year& y, const islamic::month& m, 634 | const islamic::weekday_indexed& wdi) NOEXCEPT; 635 | CONSTCD14 year_month_weekday(const sys_days& dp) NOEXCEPT; 636 | CONSTCD14 explicit year_month_weekday(const local_days& dp) NOEXCEPT; 637 | 638 | CONSTCD14 year_month_weekday& operator+=(const months& m) NOEXCEPT; 639 | CONSTCD14 year_month_weekday& operator-=(const months& m) NOEXCEPT; 640 | CONSTCD14 year_month_weekday& operator+=(const years& y) NOEXCEPT; 641 | CONSTCD14 year_month_weekday& operator-=(const years& y) NOEXCEPT; 642 | 643 | CONSTCD11 islamic::year year() const NOEXCEPT; 644 | CONSTCD11 islamic::month month() const NOEXCEPT; 645 | CONSTCD11 islamic::weekday weekday() const NOEXCEPT; 646 | CONSTCD11 unsigned index() const NOEXCEPT; 647 | CONSTCD11 islamic::weekday_indexed weekday_indexed() const NOEXCEPT; 648 | 649 | CONSTCD14 operator sys_days() const NOEXCEPT; 650 | CONSTCD14 explicit operator local_days() const NOEXCEPT; 651 | CONSTCD14 bool ok() const NOEXCEPT; 652 | 653 | private: 654 | static CONSTCD14 year_month_weekday from_days(days dp) NOEXCEPT; 655 | CONSTCD14 days to_days() const NOEXCEPT; 656 | }; 657 | 658 | CONSTCD11 659 | bool operator==(const year_month_weekday& x, const year_month_weekday& y) NOEXCEPT; 660 | CONSTCD11 661 | bool operator!=(const year_month_weekday& x, const year_month_weekday& y) NOEXCEPT; 662 | 663 | CONSTCD14 664 | year_month_weekday 665 | operator+(const year_month_weekday& ymwd, const months& dm) NOEXCEPT; 666 | 667 | CONSTCD14 668 | year_month_weekday 669 | operator+(const months& dm, const year_month_weekday& ymwd) NOEXCEPT; 670 | 671 | CONSTCD11 672 | year_month_weekday 673 | operator+(const year_month_weekday& ymwd, const years& dy) NOEXCEPT; 674 | 675 | CONSTCD11 676 | year_month_weekday 677 | operator+(const years& dy, const year_month_weekday& ymwd) NOEXCEPT; 678 | 679 | CONSTCD14 680 | year_month_weekday 681 | operator-(const year_month_weekday& ymwd, const months& dm) NOEXCEPT; 682 | 683 | CONSTCD11 684 | year_month_weekday 685 | operator-(const year_month_weekday& ymwd, const years& dy) NOEXCEPT; 686 | 687 | template 688 | std::basic_ostream& 689 | operator<<(std::basic_ostream& os, const year_month_weekday& ymwdi); 690 | 691 | // year_month_weekday_last 692 | 693 | class year_month_weekday_last 694 | { 695 | islamic::year y_; 696 | islamic::month m_; 697 | islamic::weekday_last wdl_; 698 | 699 | public: 700 | CONSTCD11 year_month_weekday_last(const islamic::year& y, const islamic::month& m, 701 | const islamic::weekday_last& wdl) NOEXCEPT; 702 | 703 | CONSTCD14 year_month_weekday_last& operator+=(const months& m) NOEXCEPT; 704 | CONSTCD14 year_month_weekday_last& operator-=(const months& m) NOEXCEPT; 705 | CONSTCD14 year_month_weekday_last& operator+=(const years& y) NOEXCEPT; 706 | CONSTCD14 year_month_weekday_last& operator-=(const years& y) NOEXCEPT; 707 | 708 | CONSTCD11 islamic::year year() const NOEXCEPT; 709 | CONSTCD11 islamic::month month() const NOEXCEPT; 710 | CONSTCD11 islamic::weekday weekday() const NOEXCEPT; 711 | CONSTCD11 islamic::weekday_last weekday_last() const NOEXCEPT; 712 | 713 | CONSTCD14 operator sys_days() const NOEXCEPT; 714 | CONSTCD14 explicit operator local_days() const NOEXCEPT; 715 | CONSTCD11 bool ok() const NOEXCEPT; 716 | 717 | private: 718 | CONSTCD14 days to_days() const NOEXCEPT; 719 | }; 720 | 721 | CONSTCD11 722 | bool 723 | operator==(const year_month_weekday_last& x, const year_month_weekday_last& y) NOEXCEPT; 724 | 725 | CONSTCD11 726 | bool 727 | operator!=(const year_month_weekday_last& x, const year_month_weekday_last& y) NOEXCEPT; 728 | 729 | CONSTCD14 730 | year_month_weekday_last 731 | operator+(const year_month_weekday_last& ymwdl, const months& dm) NOEXCEPT; 732 | 733 | CONSTCD14 734 | year_month_weekday_last 735 | operator+(const months& dm, const year_month_weekday_last& ymwdl) NOEXCEPT; 736 | 737 | CONSTCD11 738 | year_month_weekday_last 739 | operator+(const year_month_weekday_last& ymwdl, const years& dy) NOEXCEPT; 740 | 741 | CONSTCD11 742 | year_month_weekday_last 743 | operator+(const years& dy, const year_month_weekday_last& ymwdl) NOEXCEPT; 744 | 745 | CONSTCD14 746 | year_month_weekday_last 747 | operator-(const year_month_weekday_last& ymwdl, const months& dm) NOEXCEPT; 748 | 749 | CONSTCD11 750 | year_month_weekday_last 751 | operator-(const year_month_weekday_last& ymwdl, const years& dy) NOEXCEPT; 752 | 753 | template 754 | std::basic_ostream& 755 | operator<<(std::basic_ostream& os, const year_month_weekday_last& ymwdl); 756 | 757 | #if !defined(_MSC_VER) || (_MSC_VER >= 1900) 758 | inline namespace literals 759 | { 760 | 761 | CONSTCD11 islamic::day operator ""_d(unsigned long long d) NOEXCEPT; 762 | CONSTCD11 islamic::year operator ""_y(unsigned long long y) NOEXCEPT; 763 | 764 | } // inline namespace literals 765 | #endif // !defined(_MSC_VER) || (_MSC_VER >= 1900) 766 | 767 | //----------------+ 768 | // Implementation | 769 | //----------------+ 770 | 771 | // day 772 | 773 | CONSTCD11 inline day::day(unsigned d) NOEXCEPT : d_(static_cast(d)) {} 774 | CONSTCD14 inline day& day::operator++() NOEXCEPT {++d_; return *this;} 775 | CONSTCD14 inline day day::operator++(int) NOEXCEPT {auto tmp(*this); ++(*this); return tmp;} 776 | CONSTCD14 inline day& day::operator--() NOEXCEPT {--d_; return *this;} 777 | CONSTCD14 inline day day::operator--(int) NOEXCEPT {auto tmp(*this); --(*this); return tmp;} 778 | CONSTCD14 inline day& day::operator+=(const days& d) NOEXCEPT {*this = *this + d; return *this;} 779 | CONSTCD14 inline day& day::operator-=(const days& d) NOEXCEPT {*this = *this - d; return *this;} 780 | CONSTCD11 inline day::operator unsigned() const NOEXCEPT {return d_;} 781 | CONSTCD11 inline bool day::ok() const NOEXCEPT {return 1 <= d_ && d_ <= 30;} 782 | 783 | CONSTCD11 784 | inline 785 | bool 786 | operator==(const day& x, const day& y) NOEXCEPT 787 | { 788 | return static_cast(x) == static_cast(y); 789 | } 790 | 791 | CONSTCD11 792 | inline 793 | bool 794 | operator!=(const day& x, const day& y) NOEXCEPT 795 | { 796 | return !(x == y); 797 | } 798 | 799 | CONSTCD11 800 | inline 801 | bool 802 | operator<(const day& x, const day& y) NOEXCEPT 803 | { 804 | return static_cast(x) < static_cast(y); 805 | } 806 | 807 | CONSTCD11 808 | inline 809 | bool 810 | operator>(const day& x, const day& y) NOEXCEPT 811 | { 812 | return y < x; 813 | } 814 | 815 | CONSTCD11 816 | inline 817 | bool 818 | operator<=(const day& x, const day& y) NOEXCEPT 819 | { 820 | return !(y < x); 821 | } 822 | 823 | CONSTCD11 824 | inline 825 | bool 826 | operator>=(const day& x, const day& y) NOEXCEPT 827 | { 828 | return !(x < y); 829 | } 830 | 831 | CONSTCD11 832 | inline 833 | days 834 | operator-(const day& x, const day& y) NOEXCEPT 835 | { 836 | return days{static_cast(static_cast(x) 837 | - static_cast(y))}; 838 | } 839 | 840 | CONSTCD11 841 | inline 842 | day 843 | operator+(const day& x, const days& y) NOEXCEPT 844 | { 845 | return day{static_cast(x) + static_cast(y.count())}; 846 | } 847 | 848 | CONSTCD11 849 | inline 850 | day 851 | operator+(const days& x, const day& y) NOEXCEPT 852 | { 853 | return y + x; 854 | } 855 | 856 | CONSTCD11 857 | inline 858 | day 859 | operator-(const day& x, const days& y) NOEXCEPT 860 | { 861 | return x + -y; 862 | } 863 | 864 | template 865 | inline 866 | std::basic_ostream& 867 | operator<<(std::basic_ostream& os, const day& d) 868 | { 869 | date::detail::save_ostream _(os); 870 | os.fill('0'); 871 | os.flags(std::ios::dec | std::ios::right); 872 | os.width(2); 873 | os << static_cast(d); 874 | return os; 875 | } 876 | 877 | // month 878 | 879 | CONSTCD11 inline month::month(unsigned m) NOEXCEPT : m_(static_cast(m)) {} 880 | CONSTCD14 inline month& month::operator++() NOEXCEPT {if (++m_ == 13) m_ = 1; return *this;} 881 | CONSTCD14 inline month month::operator++(int) NOEXCEPT {auto tmp(*this); ++(*this); return tmp;} 882 | CONSTCD14 inline month& month::operator--() NOEXCEPT {if (--m_ == 0) m_ = 12; return *this;} 883 | CONSTCD14 inline month month::operator--(int) NOEXCEPT {auto tmp(*this); --(*this); return tmp;} 884 | 885 | CONSTCD14 886 | inline 887 | month& 888 | month::operator+=(const months& m) NOEXCEPT 889 | { 890 | *this = *this + m; 891 | return *this; 892 | } 893 | 894 | CONSTCD14 895 | inline 896 | month& 897 | month::operator-=(const months& m) NOEXCEPT 898 | { 899 | *this = *this - m; 900 | return *this; 901 | } 902 | 903 | CONSTCD11 inline month::operator unsigned() const NOEXCEPT {return m_;} 904 | CONSTCD11 inline bool month::ok() const NOEXCEPT {return 1 <= m_ && m_ <= 12;} 905 | 906 | CONSTCD11 907 | inline 908 | bool 909 | operator==(const month& x, const month& y) NOEXCEPT 910 | { 911 | return static_cast(x) == static_cast(y); 912 | } 913 | 914 | CONSTCD11 915 | inline 916 | bool 917 | operator!=(const month& x, const month& y) NOEXCEPT 918 | { 919 | return !(x == y); 920 | } 921 | 922 | CONSTCD11 923 | inline 924 | bool 925 | operator<(const month& x, const month& y) NOEXCEPT 926 | { 927 | return static_cast(x) < static_cast(y); 928 | } 929 | 930 | CONSTCD11 931 | inline 932 | bool 933 | operator>(const month& x, const month& y) NOEXCEPT 934 | { 935 | return y < x; 936 | } 937 | 938 | CONSTCD11 939 | inline 940 | bool 941 | operator<=(const month& x, const month& y) NOEXCEPT 942 | { 943 | return !(y < x); 944 | } 945 | 946 | CONSTCD11 947 | inline 948 | bool 949 | operator>=(const month& x, const month& y) NOEXCEPT 950 | { 951 | return !(x < y); 952 | } 953 | 954 | CONSTCD14 955 | inline 956 | months 957 | operator-(const month& x, const month& y) NOEXCEPT 958 | { 959 | auto const d = static_cast(x) - static_cast(y); 960 | return months(d <= 11 ? d : d + 12); 961 | } 962 | 963 | CONSTCD14 964 | inline 965 | month 966 | operator+(const month& x, const months& y) NOEXCEPT 967 | { 968 | auto const mu = static_cast(static_cast(x)) - 1 + y.count(); 969 | auto const yr = (mu >= 0 ? mu : mu-11) / 12; 970 | return month{static_cast(mu - yr * 12 + 1)}; 971 | } 972 | 973 | CONSTCD14 974 | inline 975 | month 976 | operator+(const months& x, const month& y) NOEXCEPT 977 | { 978 | return y + x; 979 | } 980 | 981 | CONSTCD14 982 | inline 983 | month 984 | operator-(const month& x, const months& y) NOEXCEPT 985 | { 986 | return x + -y; 987 | } 988 | 989 | template 990 | inline 991 | std::basic_ostream& 992 | operator<<(std::basic_ostream& os, const month& m) 993 | { 994 | switch (static_cast(m)) 995 | { 996 | case 1: 997 | os << "Muharram"; 998 | break; 999 | case 2: 1000 | os << "Safar"; 1001 | break; 1002 | case 3: 1003 | os << "Rabi' al-awwal"; 1004 | break; 1005 | case 4: 1006 | os << "Rabi' al-thani"; 1007 | break; 1008 | case 5: 1009 | os << "Jumada al-awwal"; 1010 | break; 1011 | case 6: 1012 | os << "Jumada al-Thani"; 1013 | break; 1014 | case 7: 1015 | os << "Rajab"; 1016 | break; 1017 | case 8: 1018 | os << "Sha'ban"; 1019 | break; 1020 | case 9: 1021 | os << "Ramadan"; 1022 | break; 1023 | case 10: 1024 | os << "Shawwal"; 1025 | break; 1026 | case 11: 1027 | os << "Dhu al-Qi'dah"; 1028 | break; 1029 | case 12: 1030 | os << "Dhu al-Hijjah"; 1031 | break; 1032 | default: 1033 | os << static_cast(m) << " is not a valid month"; 1034 | break; 1035 | } 1036 | return os; 1037 | } 1038 | 1039 | // year 1040 | 1041 | CONSTCD11 inline year::year(int y) NOEXCEPT : y_(static_cast(y)) {} 1042 | CONSTCD14 inline year& year::operator++() NOEXCEPT {++y_; return *this;} 1043 | CONSTCD14 inline year year::operator++(int) NOEXCEPT {auto tmp(*this); ++(*this); return tmp;} 1044 | CONSTCD14 inline year& year::operator--() NOEXCEPT {--y_; return *this;} 1045 | CONSTCD14 inline year year::operator--(int) NOEXCEPT {auto tmp(*this); --(*this); return tmp;} 1046 | CONSTCD14 inline year& year::operator+=(const years& y) NOEXCEPT {*this = *this + y; return *this;} 1047 | CONSTCD14 inline year& year::operator-=(const years& y) NOEXCEPT {*this = *this - y; return *this;} 1048 | 1049 | CONSTCD14 1050 | inline 1051 | bool 1052 | year::is_leap() const NOEXCEPT 1053 | { 1054 | int y = y_ - 1; 1055 | const int era = (y >= 0 ? y : y-29) / 30; 1056 | const unsigned yoe = static_cast(y - era * 30); 1057 | switch (yoe) 1058 | { 1059 | case 1: 1060 | case 4: 1061 | case 6: 1062 | case 9: 1063 | case 12: 1064 | case 15: 1065 | case 17: 1066 | case 20: 1067 | case 23: 1068 | case 25: 1069 | case 28: 1070 | return true; 1071 | default: 1072 | return false; 1073 | } 1074 | } 1075 | 1076 | CONSTCD11 inline year::operator int() const NOEXCEPT {return y_;} 1077 | CONSTCD11 inline bool year::ok() const NOEXCEPT {return true;} 1078 | 1079 | CONSTCD11 1080 | inline 1081 | year 1082 | year::min() NOEXCEPT 1083 | { 1084 | return year{std::numeric_limits::min()}; 1085 | } 1086 | 1087 | CONSTCD11 1088 | inline 1089 | year 1090 | year::max() NOEXCEPT 1091 | { 1092 | return year{std::numeric_limits::max()}; 1093 | } 1094 | 1095 | CONSTCD11 1096 | inline 1097 | bool 1098 | operator==(const year& x, const year& y) NOEXCEPT 1099 | { 1100 | return static_cast(x) == static_cast(y); 1101 | } 1102 | 1103 | CONSTCD11 1104 | inline 1105 | bool 1106 | operator!=(const year& x, const year& y) NOEXCEPT 1107 | { 1108 | return !(x == y); 1109 | } 1110 | 1111 | CONSTCD11 1112 | inline 1113 | bool 1114 | operator<(const year& x, const year& y) NOEXCEPT 1115 | { 1116 | return static_cast(x) < static_cast(y); 1117 | } 1118 | 1119 | CONSTCD11 1120 | inline 1121 | bool 1122 | operator>(const year& x, const year& y) NOEXCEPT 1123 | { 1124 | return y < x; 1125 | } 1126 | 1127 | CONSTCD11 1128 | inline 1129 | bool 1130 | operator<=(const year& x, const year& y) NOEXCEPT 1131 | { 1132 | return !(y < x); 1133 | } 1134 | 1135 | CONSTCD11 1136 | inline 1137 | bool 1138 | operator>=(const year& x, const year& y) NOEXCEPT 1139 | { 1140 | return !(x < y); 1141 | } 1142 | 1143 | CONSTCD11 1144 | inline 1145 | years 1146 | operator-(const year& x, const year& y) NOEXCEPT 1147 | { 1148 | return years{static_cast(x) - static_cast(y)}; 1149 | } 1150 | 1151 | CONSTCD11 1152 | inline 1153 | year 1154 | operator+(const year& x, const years& y) NOEXCEPT 1155 | { 1156 | return year{static_cast(x) + y.count()}; 1157 | } 1158 | 1159 | CONSTCD11 1160 | inline 1161 | year 1162 | operator+(const years& x, const year& y) NOEXCEPT 1163 | { 1164 | return y + x; 1165 | } 1166 | 1167 | CONSTCD11 1168 | inline 1169 | year 1170 | operator-(const year& x, const years& y) NOEXCEPT 1171 | { 1172 | return year{static_cast(x) - y.count()}; 1173 | } 1174 | 1175 | template 1176 | inline 1177 | std::basic_ostream& 1178 | operator<<(std::basic_ostream& os, const year& y) 1179 | { 1180 | date::detail::save_ostream _(os); 1181 | os.fill('0'); 1182 | os.flags(std::ios::dec | std::ios::internal); 1183 | os.width(4 + (y < year{0})); 1184 | os << static_cast(y); 1185 | return os; 1186 | } 1187 | 1188 | // weekday 1189 | 1190 | CONSTCD11 1191 | inline 1192 | unsigned char 1193 | weekday::weekday_from_days(int z) NOEXCEPT 1194 | { 1195 | return static_cast(static_cast( 1196 | z >= -4 ? (z+4) % 7 : (z+5) % 7 + 6)); 1197 | } 1198 | 1199 | CONSTCD11 1200 | inline 1201 | weekday::weekday(unsigned wd) NOEXCEPT 1202 | : wd_(static_cast(wd)) 1203 | {} 1204 | 1205 | CONSTCD11 1206 | inline 1207 | weekday::weekday(const sys_days& dp) NOEXCEPT 1208 | : wd_(weekday_from_days(dp.time_since_epoch().count())) 1209 | {} 1210 | 1211 | CONSTCD11 1212 | inline 1213 | weekday::weekday(const local_days& dp) NOEXCEPT 1214 | : wd_(weekday_from_days(dp.time_since_epoch().count())) 1215 | {} 1216 | 1217 | CONSTCD14 inline weekday& weekday::operator++() NOEXCEPT {if (++wd_ == 7) wd_ = 0; return *this;} 1218 | CONSTCD14 inline weekday weekday::operator++(int) NOEXCEPT {auto tmp(*this); ++(*this); return tmp;} 1219 | CONSTCD14 inline weekday& weekday::operator--() NOEXCEPT {if (wd_-- == 0) wd_ = 6; return *this;} 1220 | CONSTCD14 inline weekday weekday::operator--(int) NOEXCEPT {auto tmp(*this); --(*this); return tmp;} 1221 | 1222 | CONSTCD14 1223 | inline 1224 | weekday& 1225 | weekday::operator+=(const days& d) NOEXCEPT 1226 | { 1227 | *this = *this + d; 1228 | return *this; 1229 | } 1230 | 1231 | CONSTCD14 1232 | inline 1233 | weekday& 1234 | weekday::operator-=(const days& d) NOEXCEPT 1235 | { 1236 | *this = *this - d; 1237 | return *this; 1238 | } 1239 | 1240 | CONSTCD11 1241 | inline 1242 | weekday::operator unsigned() const NOEXCEPT 1243 | { 1244 | return static_cast(wd_); 1245 | } 1246 | 1247 | CONSTCD11 inline bool weekday::ok() const NOEXCEPT {return wd_ <= 6;} 1248 | 1249 | CONSTCD11 1250 | inline 1251 | bool 1252 | operator==(const weekday& x, const weekday& y) NOEXCEPT 1253 | { 1254 | return static_cast(x) == static_cast(y); 1255 | } 1256 | 1257 | CONSTCD11 1258 | inline 1259 | bool 1260 | operator!=(const weekday& x, const weekday& y) NOEXCEPT 1261 | { 1262 | return !(x == y); 1263 | } 1264 | 1265 | CONSTCD14 1266 | inline 1267 | days 1268 | operator-(const weekday& x, const weekday& y) NOEXCEPT 1269 | { 1270 | auto const diff = static_cast(x) - static_cast(y); 1271 | return days{diff <= 6 ? diff : diff + 7}; 1272 | } 1273 | 1274 | CONSTCD14 1275 | inline 1276 | weekday 1277 | operator+(const weekday& x, const days& y) NOEXCEPT 1278 | { 1279 | auto const wdu = static_cast(static_cast(x)) + y.count(); 1280 | auto const wk = (wdu >= 0 ? wdu : wdu-6) / 7; 1281 | return weekday{static_cast(wdu - wk * 7)}; 1282 | } 1283 | 1284 | CONSTCD14 1285 | inline 1286 | weekday 1287 | operator+(const days& x, const weekday& y) NOEXCEPT 1288 | { 1289 | return y + x; 1290 | } 1291 | 1292 | CONSTCD14 1293 | inline 1294 | weekday 1295 | operator-(const weekday& x, const days& y) NOEXCEPT 1296 | { 1297 | return x + -y; 1298 | } 1299 | 1300 | template 1301 | inline 1302 | std::basic_ostream& 1303 | operator<<(std::basic_ostream& os, const weekday& wd) 1304 | { 1305 | switch (static_cast(wd)) 1306 | { 1307 | case 0: 1308 | os << "al-Aḥad"; 1309 | break; 1310 | case 1: 1311 | os << "al-Ithnayn"; 1312 | break; 1313 | case 2: 1314 | os << "ath-Thulāthā’"; 1315 | break; 1316 | case 3: 1317 | os << "al-Arba‘ā’"; 1318 | break; 1319 | case 4: 1320 | os << "al-Khamīs"; 1321 | break; 1322 | case 5: 1323 | os << "al-Jum‘ah"; 1324 | break; 1325 | case 6: 1326 | os << "as-Sabt"; 1327 | break; 1328 | default: 1329 | os << static_cast(wd) << " is not a valid weekday"; 1330 | break; 1331 | } 1332 | return os; 1333 | } 1334 | 1335 | #if !defined(_MSC_VER) || (_MSC_VER >= 1900) 1336 | inline namespace literals 1337 | { 1338 | 1339 | CONSTCD11 1340 | inline 1341 | islamic::day 1342 | operator ""_d(unsigned long long d) NOEXCEPT 1343 | { 1344 | return islamic::day{static_cast(d)}; 1345 | } 1346 | 1347 | CONSTCD11 1348 | inline 1349 | islamic::year 1350 | operator ""_y(unsigned long long y) NOEXCEPT 1351 | { 1352 | return islamic::year(static_cast(y)); 1353 | } 1354 | #endif // !defined(_MSC_VER) || (_MSC_VER >= 1900) 1355 | 1356 | CONSTDATA islamic::last_spec last{}; 1357 | 1358 | #if !defined(_MSC_VER) || (_MSC_VER >= 1900) 1359 | } // inline namespace literals 1360 | #endif 1361 | 1362 | // weekday_indexed 1363 | 1364 | CONSTCD11 1365 | inline 1366 | weekday 1367 | weekday_indexed::weekday() const NOEXCEPT 1368 | { 1369 | return islamic::weekday{static_cast(wd_)}; 1370 | } 1371 | 1372 | CONSTCD11 inline unsigned weekday_indexed::index() const NOEXCEPT {return index_;} 1373 | 1374 | CONSTCD11 1375 | inline 1376 | bool 1377 | weekday_indexed::ok() const NOEXCEPT 1378 | { 1379 | return weekday().ok() && 1 <= index_ && index_ <= 5; 1380 | } 1381 | 1382 | CONSTCD11 1383 | inline 1384 | weekday_indexed::weekday_indexed(const islamic::weekday& wd, unsigned index) NOEXCEPT 1385 | : wd_(static_cast(static_cast(wd))) 1386 | , index_(static_cast(index)) 1387 | {} 1388 | 1389 | template 1390 | inline 1391 | std::basic_ostream& 1392 | operator<<(std::basic_ostream& os, const weekday_indexed& wdi) 1393 | { 1394 | return os << wdi.weekday() << '[' << wdi.index() << ']'; 1395 | } 1396 | 1397 | CONSTCD11 1398 | inline 1399 | weekday_indexed 1400 | weekday::operator[](unsigned index) const NOEXCEPT 1401 | { 1402 | return {*this, index}; 1403 | } 1404 | 1405 | CONSTCD11 1406 | inline 1407 | bool 1408 | operator==(const weekday_indexed& x, const weekday_indexed& y) NOEXCEPT 1409 | { 1410 | return x.weekday() == y.weekday() && x.index() == y.index(); 1411 | } 1412 | 1413 | CONSTCD11 1414 | inline 1415 | bool 1416 | operator!=(const weekday_indexed& x, const weekday_indexed& y) NOEXCEPT 1417 | { 1418 | return !(x == y); 1419 | } 1420 | 1421 | // weekday_last 1422 | 1423 | CONSTCD11 inline islamic::weekday weekday_last::weekday() const NOEXCEPT {return wd_;} 1424 | CONSTCD11 inline bool weekday_last::ok() const NOEXCEPT {return wd_.ok();} 1425 | CONSTCD11 inline weekday_last::weekday_last(const islamic::weekday& wd) NOEXCEPT : wd_(wd) {} 1426 | 1427 | CONSTCD11 1428 | inline 1429 | bool 1430 | operator==(const weekday_last& x, const weekday_last& y) NOEXCEPT 1431 | { 1432 | return x.weekday() == y.weekday(); 1433 | } 1434 | 1435 | CONSTCD11 1436 | inline 1437 | bool 1438 | operator!=(const weekday_last& x, const weekday_last& y) NOEXCEPT 1439 | { 1440 | return !(x == y); 1441 | } 1442 | 1443 | template 1444 | inline 1445 | std::basic_ostream& 1446 | operator<<(std::basic_ostream& os, const weekday_last& wdl) 1447 | { 1448 | return os << wdl.weekday() << "[last]"; 1449 | } 1450 | 1451 | CONSTCD11 1452 | inline 1453 | weekday_last 1454 | weekday::operator[](last_spec) const NOEXCEPT 1455 | { 1456 | return weekday_last{*this}; 1457 | } 1458 | 1459 | // year_month 1460 | 1461 | CONSTCD11 1462 | inline 1463 | year_month::year_month(const islamic::year& y, const islamic::month& m) NOEXCEPT 1464 | : y_(y) 1465 | , m_(m) 1466 | {} 1467 | 1468 | CONSTCD11 inline year year_month::year() const NOEXCEPT {return y_;} 1469 | CONSTCD11 inline month year_month::month() const NOEXCEPT {return m_;} 1470 | CONSTCD11 inline bool year_month::ok() const NOEXCEPT {return y_.ok() && m_.ok();} 1471 | 1472 | CONSTCD14 1473 | inline 1474 | year_month& 1475 | year_month::operator+=(const months& dm) NOEXCEPT 1476 | { 1477 | *this = *this + dm; 1478 | return *this; 1479 | } 1480 | 1481 | CONSTCD14 1482 | inline 1483 | year_month& 1484 | year_month::operator-=(const months& dm) NOEXCEPT 1485 | { 1486 | *this = *this - dm; 1487 | return *this; 1488 | } 1489 | 1490 | CONSTCD14 1491 | inline 1492 | year_month& 1493 | year_month::operator+=(const years& dy) NOEXCEPT 1494 | { 1495 | *this = *this + dy; 1496 | return *this; 1497 | } 1498 | 1499 | CONSTCD14 1500 | inline 1501 | year_month& 1502 | year_month::operator-=(const years& dy) NOEXCEPT 1503 | { 1504 | *this = *this - dy; 1505 | return *this; 1506 | } 1507 | 1508 | CONSTCD11 1509 | inline 1510 | bool 1511 | operator==(const year_month& x, const year_month& y) NOEXCEPT 1512 | { 1513 | return x.year() == y.year() && x.month() == y.month(); 1514 | } 1515 | 1516 | CONSTCD11 1517 | inline 1518 | bool 1519 | operator!=(const year_month& x, const year_month& y) NOEXCEPT 1520 | { 1521 | return !(x == y); 1522 | } 1523 | 1524 | CONSTCD11 1525 | inline 1526 | bool 1527 | operator<(const year_month& x, const year_month& y) NOEXCEPT 1528 | { 1529 | return x.year() < y.year() ? true 1530 | : (x.year() > y.year() ? false 1531 | : (x.month() < y.month())); 1532 | } 1533 | 1534 | CONSTCD11 1535 | inline 1536 | bool 1537 | operator>(const year_month& x, const year_month& y) NOEXCEPT 1538 | { 1539 | return y < x; 1540 | } 1541 | 1542 | CONSTCD11 1543 | inline 1544 | bool 1545 | operator<=(const year_month& x, const year_month& y) NOEXCEPT 1546 | { 1547 | return !(y < x); 1548 | } 1549 | 1550 | CONSTCD11 1551 | inline 1552 | bool 1553 | operator>=(const year_month& x, const year_month& y) NOEXCEPT 1554 | { 1555 | return !(x < y); 1556 | } 1557 | 1558 | CONSTCD14 1559 | inline 1560 | year_month 1561 | operator+(const year_month& ym, const months& dm) NOEXCEPT 1562 | { 1563 | auto dmi = static_cast(static_cast(ym.month())) - 1 + dm.count(); 1564 | auto dy = (dmi >= 0 ? dmi : dmi-11) / 12; 1565 | dmi = dmi - dy * 12 + 1; 1566 | return (ym.year() + years(dy)) / month(static_cast(dmi)); 1567 | } 1568 | 1569 | CONSTCD14 1570 | inline 1571 | year_month 1572 | operator+(const months& dm, const year_month& ym) NOEXCEPT 1573 | { 1574 | return ym + dm; 1575 | } 1576 | 1577 | CONSTCD14 1578 | inline 1579 | year_month 1580 | operator-(const year_month& ym, const months& dm) NOEXCEPT 1581 | { 1582 | return ym + -dm; 1583 | } 1584 | 1585 | CONSTCD11 1586 | inline 1587 | months 1588 | operator-(const year_month& x, const year_month& y) NOEXCEPT 1589 | { 1590 | return (x.year() - y.year()) + 1591 | months(static_cast(x.month()) - static_cast(y.month())); 1592 | } 1593 | 1594 | CONSTCD11 1595 | inline 1596 | year_month 1597 | operator+(const year_month& ym, const years& dy) NOEXCEPT 1598 | { 1599 | return (ym.year() + dy) / ym.month(); 1600 | } 1601 | 1602 | CONSTCD11 1603 | inline 1604 | year_month 1605 | operator+(const years& dy, const year_month& ym) NOEXCEPT 1606 | { 1607 | return ym + dy; 1608 | } 1609 | 1610 | CONSTCD11 1611 | inline 1612 | year_month 1613 | operator-(const year_month& ym, const years& dy) NOEXCEPT 1614 | { 1615 | return ym + -dy; 1616 | } 1617 | 1618 | template 1619 | inline 1620 | std::basic_ostream& 1621 | operator<<(std::basic_ostream& os, const year_month& ym) 1622 | { 1623 | return os << ym.year() << '/' << ym.month(); 1624 | } 1625 | 1626 | // month_day 1627 | 1628 | CONSTCD11 1629 | inline 1630 | month_day::month_day(const islamic::month& m, const islamic::day& d) NOEXCEPT 1631 | : m_(m) 1632 | , d_(d) 1633 | {} 1634 | 1635 | CONSTCD11 inline islamic::month month_day::month() const NOEXCEPT {return m_;} 1636 | CONSTCD11 inline islamic::day month_day::day() const NOEXCEPT {return d_;} 1637 | 1638 | CONSTCD14 1639 | inline 1640 | bool 1641 | month_day::ok() const NOEXCEPT 1642 | { 1643 | CONSTDATA islamic::day d[] = 1644 | {30_d, 29_d, 30_d, 29_d, 30_d, 29_d, 30_d, 29_d, 30_d, 29_d, 30_d, 30_d}; 1645 | return m_.ok() && 1_d <= d_ && d_ <= d[static_cast(m_)-1]; 1646 | } 1647 | 1648 | CONSTCD11 1649 | inline 1650 | bool 1651 | operator==(const month_day& x, const month_day& y) NOEXCEPT 1652 | { 1653 | return x.month() == y.month() && x.day() == y.day(); 1654 | } 1655 | 1656 | CONSTCD11 1657 | inline 1658 | bool 1659 | operator!=(const month_day& x, const month_day& y) NOEXCEPT 1660 | { 1661 | return !(x == y); 1662 | } 1663 | 1664 | CONSTCD11 1665 | inline 1666 | bool 1667 | operator<(const month_day& x, const month_day& y) NOEXCEPT 1668 | { 1669 | return x.month() < y.month() ? true 1670 | : (x.month() > y.month() ? false 1671 | : (x.day() < y.day())); 1672 | } 1673 | 1674 | CONSTCD11 1675 | inline 1676 | bool 1677 | operator>(const month_day& x, const month_day& y) NOEXCEPT 1678 | { 1679 | return y < x; 1680 | } 1681 | 1682 | CONSTCD11 1683 | inline 1684 | bool 1685 | operator<=(const month_day& x, const month_day& y) NOEXCEPT 1686 | { 1687 | return !(y < x); 1688 | } 1689 | 1690 | CONSTCD11 1691 | inline 1692 | bool 1693 | operator>=(const month_day& x, const month_day& y) NOEXCEPT 1694 | { 1695 | return !(x < y); 1696 | } 1697 | 1698 | template 1699 | inline 1700 | std::basic_ostream& 1701 | operator<<(std::basic_ostream& os, const month_day& md) 1702 | { 1703 | return os << md.month() << '/' << md.day(); 1704 | } 1705 | 1706 | // month_day_last 1707 | 1708 | CONSTCD11 inline month month_day_last::month() const NOEXCEPT {return m_;} 1709 | CONSTCD11 inline bool month_day_last::ok() const NOEXCEPT {return m_.ok();} 1710 | CONSTCD11 inline month_day_last::month_day_last(const islamic::month& m) NOEXCEPT : m_(m) {} 1711 | 1712 | CONSTCD11 1713 | inline 1714 | bool 1715 | operator==(const month_day_last& x, const month_day_last& y) NOEXCEPT 1716 | { 1717 | return x.month() == y.month(); 1718 | } 1719 | 1720 | CONSTCD11 1721 | inline 1722 | bool 1723 | operator!=(const month_day_last& x, const month_day_last& y) NOEXCEPT 1724 | { 1725 | return !(x == y); 1726 | } 1727 | 1728 | CONSTCD11 1729 | inline 1730 | bool 1731 | operator<(const month_day_last& x, const month_day_last& y) NOEXCEPT 1732 | { 1733 | return x.month() < y.month(); 1734 | } 1735 | 1736 | CONSTCD11 1737 | inline 1738 | bool 1739 | operator>(const month_day_last& x, const month_day_last& y) NOEXCEPT 1740 | { 1741 | return y < x; 1742 | } 1743 | 1744 | CONSTCD11 1745 | inline 1746 | bool 1747 | operator<=(const month_day_last& x, const month_day_last& y) NOEXCEPT 1748 | { 1749 | return !(y < x); 1750 | } 1751 | 1752 | CONSTCD11 1753 | inline 1754 | bool 1755 | operator>=(const month_day_last& x, const month_day_last& y) NOEXCEPT 1756 | { 1757 | return !(x < y); 1758 | } 1759 | 1760 | template 1761 | inline 1762 | std::basic_ostream& 1763 | operator<<(std::basic_ostream& os, const month_day_last& mdl) 1764 | { 1765 | return os << mdl.month() << "/last"; 1766 | } 1767 | 1768 | // month_weekday 1769 | 1770 | CONSTCD11 1771 | inline 1772 | month_weekday::month_weekday(const islamic::month& m, 1773 | const islamic::weekday_indexed& wdi) NOEXCEPT 1774 | : m_(m) 1775 | , wdi_(wdi) 1776 | {} 1777 | 1778 | CONSTCD11 inline month month_weekday::month() const NOEXCEPT {return m_;} 1779 | 1780 | CONSTCD11 1781 | inline 1782 | weekday_indexed 1783 | month_weekday::weekday_indexed() const NOEXCEPT 1784 | { 1785 | return wdi_; 1786 | } 1787 | 1788 | CONSTCD11 1789 | inline 1790 | bool 1791 | month_weekday::ok() const NOEXCEPT 1792 | { 1793 | return m_.ok() && wdi_.ok(); 1794 | } 1795 | 1796 | CONSTCD11 1797 | inline 1798 | bool 1799 | operator==(const month_weekday& x, const month_weekday& y) NOEXCEPT 1800 | { 1801 | return x.month() == y.month() && x.weekday_indexed() == y.weekday_indexed(); 1802 | } 1803 | 1804 | CONSTCD11 1805 | inline 1806 | bool 1807 | operator!=(const month_weekday& x, const month_weekday& y) NOEXCEPT 1808 | { 1809 | return !(x == y); 1810 | } 1811 | 1812 | template 1813 | inline 1814 | std::basic_ostream& 1815 | operator<<(std::basic_ostream& os, const month_weekday& mwd) 1816 | { 1817 | return os << mwd.month() << '/' << mwd.weekday_indexed(); 1818 | } 1819 | 1820 | // month_weekday_last 1821 | 1822 | CONSTCD11 1823 | inline 1824 | month_weekday_last::month_weekday_last(const islamic::month& m, 1825 | const islamic::weekday_last& wdl) NOEXCEPT 1826 | : m_(m) 1827 | , wdl_(wdl) 1828 | {} 1829 | 1830 | CONSTCD11 inline month month_weekday_last::month() const NOEXCEPT {return m_;} 1831 | 1832 | CONSTCD11 1833 | inline 1834 | weekday_last 1835 | month_weekday_last::weekday_last() const NOEXCEPT 1836 | { 1837 | return wdl_; 1838 | } 1839 | 1840 | CONSTCD11 1841 | inline 1842 | bool 1843 | month_weekday_last::ok() const NOEXCEPT 1844 | { 1845 | return m_.ok() && wdl_.ok(); 1846 | } 1847 | 1848 | CONSTCD11 1849 | inline 1850 | bool 1851 | operator==(const month_weekday_last& x, const month_weekday_last& y) NOEXCEPT 1852 | { 1853 | return x.month() == y.month() && x.weekday_last() == y.weekday_last(); 1854 | } 1855 | 1856 | CONSTCD11 1857 | inline 1858 | bool 1859 | operator!=(const month_weekday_last& x, const month_weekday_last& y) NOEXCEPT 1860 | { 1861 | return !(x == y); 1862 | } 1863 | 1864 | template 1865 | inline 1866 | std::basic_ostream& 1867 | operator<<(std::basic_ostream& os, const month_weekday_last& mwdl) 1868 | { 1869 | return os << mwdl.month() << '/' << mwdl.weekday_last(); 1870 | } 1871 | 1872 | // year_month_day_last 1873 | 1874 | CONSTCD11 1875 | inline 1876 | year_month_day_last::year_month_day_last(const islamic::year& y, 1877 | const islamic::month_day_last& mdl) NOEXCEPT 1878 | : y_(y) 1879 | , mdl_(mdl) 1880 | {} 1881 | 1882 | CONSTCD14 1883 | inline 1884 | year_month_day_last& 1885 | year_month_day_last::operator+=(const months& m) NOEXCEPT 1886 | { 1887 | *this = *this + m; 1888 | return *this; 1889 | } 1890 | 1891 | CONSTCD14 1892 | inline 1893 | year_month_day_last& 1894 | year_month_day_last::operator-=(const months& m) NOEXCEPT 1895 | { 1896 | *this = *this - m; 1897 | return *this; 1898 | } 1899 | 1900 | CONSTCD14 1901 | inline 1902 | year_month_day_last& 1903 | year_month_day_last::operator+=(const years& y) NOEXCEPT 1904 | { 1905 | *this = *this + y; 1906 | return *this; 1907 | } 1908 | 1909 | CONSTCD14 1910 | inline 1911 | year_month_day_last& 1912 | year_month_day_last::operator-=(const years& y) NOEXCEPT 1913 | { 1914 | *this = *this - y; 1915 | return *this; 1916 | } 1917 | 1918 | CONSTCD11 inline year year_month_day_last::year() const NOEXCEPT {return y_;} 1919 | CONSTCD11 inline month year_month_day_last::month() const NOEXCEPT {return mdl_.month();} 1920 | 1921 | CONSTCD11 1922 | inline 1923 | month_day_last 1924 | year_month_day_last::month_day_last() const NOEXCEPT 1925 | { 1926 | return mdl_; 1927 | } 1928 | 1929 | CONSTCD14 1930 | inline 1931 | day 1932 | year_month_day_last::day() const NOEXCEPT 1933 | { 1934 | CONSTDATA islamic::day d[] = 1935 | {30_d, 29_d, 30_d, 29_d, 30_d, 29_d, 30_d, 29_d, 30_d, 29_d, 30_d, 29_d}; 1936 | return month() != islamic::month(12) || !y_.is_leap() ? 1937 | d[static_cast(month())-1] : 30_d; 1938 | } 1939 | 1940 | CONSTCD14 1941 | inline 1942 | year_month_day_last::operator sys_days() const NOEXCEPT 1943 | { 1944 | return sys_days(year()/month()/day()); 1945 | } 1946 | 1947 | CONSTCD14 1948 | inline 1949 | year_month_day_last::operator local_days() const NOEXCEPT 1950 | { 1951 | return local_days(year()/month()/day()); 1952 | } 1953 | 1954 | CONSTCD11 1955 | inline 1956 | bool 1957 | year_month_day_last::ok() const NOEXCEPT 1958 | { 1959 | return y_.ok() && mdl_.ok(); 1960 | } 1961 | 1962 | CONSTCD11 1963 | inline 1964 | bool 1965 | operator==(const year_month_day_last& x, const year_month_day_last& y) NOEXCEPT 1966 | { 1967 | return x.year() == y.year() && x.month_day_last() == y.month_day_last(); 1968 | } 1969 | 1970 | CONSTCD11 1971 | inline 1972 | bool 1973 | operator!=(const year_month_day_last& x, const year_month_day_last& y) NOEXCEPT 1974 | { 1975 | return !(x == y); 1976 | } 1977 | 1978 | CONSTCD11 1979 | inline 1980 | bool 1981 | operator<(const year_month_day_last& x, const year_month_day_last& y) NOEXCEPT 1982 | { 1983 | return x.year() < y.year() ? true 1984 | : (x.year() > y.year() ? false 1985 | : (x.month_day_last() < y.month_day_last())); 1986 | } 1987 | 1988 | CONSTCD11 1989 | inline 1990 | bool 1991 | operator>(const year_month_day_last& x, const year_month_day_last& y) NOEXCEPT 1992 | { 1993 | return y < x; 1994 | } 1995 | 1996 | CONSTCD11 1997 | inline 1998 | bool 1999 | operator<=(const year_month_day_last& x, const year_month_day_last& y) NOEXCEPT 2000 | { 2001 | return !(y < x); 2002 | } 2003 | 2004 | CONSTCD11 2005 | inline 2006 | bool 2007 | operator>=(const year_month_day_last& x, const year_month_day_last& y) NOEXCEPT 2008 | { 2009 | return !(x < y); 2010 | } 2011 | 2012 | template 2013 | inline 2014 | std::basic_ostream& 2015 | operator<<(std::basic_ostream& os, const year_month_day_last& ymdl) 2016 | { 2017 | return os << ymdl.year() << '/' << ymdl.month_day_last(); 2018 | } 2019 | 2020 | CONSTCD14 2021 | inline 2022 | year_month_day_last 2023 | operator+(const year_month_day_last& ymdl, const months& dm) NOEXCEPT 2024 | { 2025 | return (ymdl.year() / ymdl.month() + dm) / last; 2026 | } 2027 | 2028 | CONSTCD14 2029 | inline 2030 | year_month_day_last 2031 | operator+(const months& dm, const year_month_day_last& ymdl) NOEXCEPT 2032 | { 2033 | return ymdl + dm; 2034 | } 2035 | 2036 | CONSTCD14 2037 | inline 2038 | year_month_day_last 2039 | operator-(const year_month_day_last& ymdl, const months& dm) NOEXCEPT 2040 | { 2041 | return ymdl + (-dm); 2042 | } 2043 | 2044 | CONSTCD11 2045 | inline 2046 | year_month_day_last 2047 | operator+(const year_month_day_last& ymdl, const years& dy) NOEXCEPT 2048 | { 2049 | return {ymdl.year()+dy, ymdl.month_day_last()}; 2050 | } 2051 | 2052 | CONSTCD11 2053 | inline 2054 | year_month_day_last 2055 | operator+(const years& dy, const year_month_day_last& ymdl) NOEXCEPT 2056 | { 2057 | return ymdl + dy; 2058 | } 2059 | 2060 | CONSTCD11 2061 | inline 2062 | year_month_day_last 2063 | operator-(const year_month_day_last& ymdl, const years& dy) NOEXCEPT 2064 | { 2065 | return ymdl + (-dy); 2066 | } 2067 | 2068 | // year_month_day 2069 | 2070 | CONSTCD11 2071 | inline 2072 | year_month_day::year_month_day(const islamic::year& y, const islamic::month& m, 2073 | const islamic::day& d) NOEXCEPT 2074 | : y_(y) 2075 | , m_(m) 2076 | , d_(d) 2077 | {} 2078 | 2079 | CONSTCD14 2080 | inline 2081 | year_month_day::year_month_day(const year_month_day_last& ymdl) NOEXCEPT 2082 | : y_(ymdl.year()) 2083 | , m_(ymdl.month()) 2084 | , d_(ymdl.day()) 2085 | {} 2086 | 2087 | CONSTCD14 2088 | inline 2089 | year_month_day::year_month_day(sys_days dp) NOEXCEPT 2090 | : year_month_day(from_days(dp.time_since_epoch())) 2091 | {} 2092 | 2093 | CONSTCD14 2094 | inline 2095 | year_month_day::year_month_day(local_days dp) NOEXCEPT 2096 | : year_month_day(from_days(dp.time_since_epoch())) 2097 | {} 2098 | 2099 | CONSTCD11 inline year year_month_day::year() const NOEXCEPT {return y_;} 2100 | CONSTCD11 inline month year_month_day::month() const NOEXCEPT {return m_;} 2101 | CONSTCD11 inline day year_month_day::day() const NOEXCEPT {return d_;} 2102 | 2103 | CONSTCD14 2104 | inline 2105 | year_month_day& 2106 | year_month_day::operator+=(const months& m) NOEXCEPT 2107 | { 2108 | *this = *this + m; 2109 | return *this; 2110 | } 2111 | 2112 | CONSTCD14 2113 | inline 2114 | year_month_day& 2115 | year_month_day::operator-=(const months& m) NOEXCEPT 2116 | { 2117 | *this = *this - m; 2118 | return *this; 2119 | } 2120 | 2121 | CONSTCD14 2122 | inline 2123 | year_month_day& 2124 | year_month_day::operator+=(const years& y) NOEXCEPT 2125 | { 2126 | *this = *this + y; 2127 | return *this; 2128 | } 2129 | 2130 | CONSTCD14 2131 | inline 2132 | year_month_day& 2133 | year_month_day::operator-=(const years& y) NOEXCEPT 2134 | { 2135 | *this = *this - y; 2136 | return *this; 2137 | } 2138 | 2139 | CONSTCD14 2140 | inline 2141 | days 2142 | year_month_day::to_days() const NOEXCEPT 2143 | { 2144 | static_assert(std::numeric_limits::digits >= 18, 2145 | "This algorithm has not been ported to a 16 bit unsigned integer"); 2146 | static_assert(std::numeric_limits::digits >= 20, 2147 | "This algorithm has not been ported to a 16 bit signed integer"); 2148 | auto const y = static_cast(y_) - 1; 2149 | auto const m = static_cast(m_); 2150 | auto const d = static_cast(d_); 2151 | auto const era = (y >= 0 ? y : y-29) / 30; 2152 | auto const yoe = static_cast(y - era * 30); // [0, 29] 2153 | auto const doy = 29*(m-1) + m/2 + d-1; // [0, 354] 2154 | auto const doe = yoe * 354 + (11*(yoe+1)+3)/30 + doy; // [0, 10630] 2155 | return days{era * 10631 + static_cast(doe) - 492148}; 2156 | } 2157 | 2158 | CONSTCD14 2159 | inline 2160 | year_month_day::operator sys_days() const NOEXCEPT 2161 | { 2162 | return sys_days{to_days()}; 2163 | } 2164 | 2165 | CONSTCD14 2166 | inline 2167 | year_month_day::operator local_days() const NOEXCEPT 2168 | { 2169 | return local_days{to_days()}; 2170 | } 2171 | 2172 | CONSTCD14 2173 | inline 2174 | bool 2175 | year_month_day::ok() const NOEXCEPT 2176 | { 2177 | if (!(y_.ok() && m_.ok())) 2178 | return false; 2179 | return 1_d <= d_ && d_ <= (y_/m_/last).day(); 2180 | } 2181 | 2182 | CONSTCD11 2183 | inline 2184 | bool 2185 | operator==(const year_month_day& x, const year_month_day& y) NOEXCEPT 2186 | { 2187 | return x.year() == y.year() && x.month() == y.month() && x.day() == y.day(); 2188 | } 2189 | 2190 | CONSTCD11 2191 | inline 2192 | bool 2193 | operator!=(const year_month_day& x, const year_month_day& y) NOEXCEPT 2194 | { 2195 | return !(x == y); 2196 | } 2197 | 2198 | CONSTCD11 2199 | inline 2200 | bool 2201 | operator<(const year_month_day& x, const year_month_day& y) NOEXCEPT 2202 | { 2203 | return x.year() < y.year() ? true 2204 | : (x.year() > y.year() ? false 2205 | : (x.month() < y.month() ? true 2206 | : (x.month() > y.month() ? false 2207 | : (x.day() < y.day())))); 2208 | } 2209 | 2210 | CONSTCD11 2211 | inline 2212 | bool 2213 | operator>(const year_month_day& x, const year_month_day& y) NOEXCEPT 2214 | { 2215 | return y < x; 2216 | } 2217 | 2218 | CONSTCD11 2219 | inline 2220 | bool 2221 | operator<=(const year_month_day& x, const year_month_day& y) NOEXCEPT 2222 | { 2223 | return !(y < x); 2224 | } 2225 | 2226 | CONSTCD11 2227 | inline 2228 | bool 2229 | operator>=(const year_month_day& x, const year_month_day& y) NOEXCEPT 2230 | { 2231 | return !(x < y); 2232 | } 2233 | 2234 | template 2235 | inline 2236 | std::basic_ostream& 2237 | operator<<(std::basic_ostream& os, const year_month_day& ymd) 2238 | { 2239 | date::detail::save_ostream _(os); 2240 | os.fill('0'); 2241 | os.flags(std::ios::dec | std::ios::right); 2242 | os << ymd.year() << '-'; 2243 | os.width(2); 2244 | os << static_cast(ymd.month()) << '-'; 2245 | os << ymd.day(); 2246 | return os; 2247 | } 2248 | 2249 | CONSTCD14 2250 | inline 2251 | year_month_day 2252 | year_month_day::from_days(days dp) NOEXCEPT 2253 | { 2254 | static_assert(std::numeric_limits::digits >= 18, 2255 | "This algorithm has not been ported to a 16 bit unsigned integer"); 2256 | static_assert(std::numeric_limits::digits >= 20, 2257 | "This algorithm has not been ported to a 16 bit signed integer"); 2258 | auto const z = dp.count() + 492148; 2259 | auto const era = (z >= 0 ? z : z - 10630) / 10631; 2260 | auto const doe = static_cast(z - era * 10631); // [0, 10630] 2261 | auto const yoe = (30*doe + 10646)/10631 - 1; // [0, 29] 2262 | auto const y = static_cast(yoe) + era * 30 + 1; 2263 | auto const doy = doe - (yoe * 354 + (11*(yoe+1)+3)/30); // [0, 354] 2264 | auto const m = (11*doy + 330) / 325; // [1, 12] 2265 | auto const d = doy - (29*(m-1) + m/2) + 1; // [1, 30] 2266 | return year_month_day{islamic::year{y}, islamic::month(m), islamic::day(d)}; 2267 | } 2268 | 2269 | CONSTCD14 2270 | inline 2271 | year_month_day 2272 | operator+(const year_month_day& ymd, const months& dm) NOEXCEPT 2273 | { 2274 | return (ymd.year() / ymd.month() + dm) / ymd.day(); 2275 | } 2276 | 2277 | CONSTCD14 2278 | inline 2279 | year_month_day 2280 | operator+(const months& dm, const year_month_day& ymd) NOEXCEPT 2281 | { 2282 | return ymd + dm; 2283 | } 2284 | 2285 | CONSTCD14 2286 | inline 2287 | year_month_day 2288 | operator-(const year_month_day& ymd, const months& dm) NOEXCEPT 2289 | { 2290 | return ymd + (-dm); 2291 | } 2292 | 2293 | CONSTCD11 2294 | inline 2295 | year_month_day 2296 | operator+(const year_month_day& ymd, const years& dy) NOEXCEPT 2297 | { 2298 | return (ymd.year() + dy) / ymd.month() / ymd.day(); 2299 | } 2300 | 2301 | CONSTCD11 2302 | inline 2303 | year_month_day 2304 | operator+(const years& dy, const year_month_day& ymd) NOEXCEPT 2305 | { 2306 | return ymd + dy; 2307 | } 2308 | 2309 | CONSTCD11 2310 | inline 2311 | year_month_day 2312 | operator-(const year_month_day& ymd, const years& dy) NOEXCEPT 2313 | { 2314 | return ymd + (-dy); 2315 | } 2316 | 2317 | // year_month_weekday 2318 | 2319 | CONSTCD11 2320 | inline 2321 | year_month_weekday::year_month_weekday(const islamic::year& y, const islamic::month& m, 2322 | const islamic::weekday_indexed& wdi) 2323 | NOEXCEPT 2324 | : y_(y) 2325 | , m_(m) 2326 | , wdi_(wdi) 2327 | {} 2328 | 2329 | CONSTCD14 2330 | inline 2331 | year_month_weekday::year_month_weekday(const sys_days& dp) NOEXCEPT 2332 | : year_month_weekday(from_days(dp.time_since_epoch())) 2333 | {} 2334 | 2335 | CONSTCD14 2336 | inline 2337 | year_month_weekday::year_month_weekday(const local_days& dp) NOEXCEPT 2338 | : year_month_weekday(from_days(dp.time_since_epoch())) 2339 | {} 2340 | 2341 | CONSTCD14 2342 | inline 2343 | year_month_weekday& 2344 | year_month_weekday::operator+=(const months& m) NOEXCEPT 2345 | { 2346 | *this = *this + m; 2347 | return *this; 2348 | } 2349 | 2350 | CONSTCD14 2351 | inline 2352 | year_month_weekday& 2353 | year_month_weekday::operator-=(const months& m) NOEXCEPT 2354 | { 2355 | *this = *this - m; 2356 | return *this; 2357 | } 2358 | 2359 | CONSTCD14 2360 | inline 2361 | year_month_weekday& 2362 | year_month_weekday::operator+=(const years& y) NOEXCEPT 2363 | { 2364 | *this = *this + y; 2365 | return *this; 2366 | } 2367 | 2368 | CONSTCD14 2369 | inline 2370 | year_month_weekday& 2371 | year_month_weekday::operator-=(const years& y) NOEXCEPT 2372 | { 2373 | *this = *this - y; 2374 | return *this; 2375 | } 2376 | 2377 | CONSTCD11 inline year year_month_weekday::year() const NOEXCEPT {return y_;} 2378 | CONSTCD11 inline month year_month_weekday::month() const NOEXCEPT {return m_;} 2379 | 2380 | CONSTCD11 2381 | inline 2382 | weekday 2383 | year_month_weekday::weekday() const NOEXCEPT 2384 | { 2385 | return wdi_.weekday(); 2386 | } 2387 | 2388 | CONSTCD11 2389 | inline 2390 | unsigned 2391 | year_month_weekday::index() const NOEXCEPT 2392 | { 2393 | return wdi_.index(); 2394 | } 2395 | 2396 | CONSTCD11 2397 | inline 2398 | weekday_indexed 2399 | year_month_weekday::weekday_indexed() const NOEXCEPT 2400 | { 2401 | return wdi_; 2402 | } 2403 | 2404 | CONSTCD14 2405 | inline 2406 | year_month_weekday::operator sys_days() const NOEXCEPT 2407 | { 2408 | return sys_days{to_days()}; 2409 | } 2410 | 2411 | CONSTCD14 2412 | inline 2413 | year_month_weekday::operator local_days() const NOEXCEPT 2414 | { 2415 | return local_days{to_days()}; 2416 | } 2417 | 2418 | CONSTCD14 2419 | inline 2420 | bool 2421 | year_month_weekday::ok() const NOEXCEPT 2422 | { 2423 | if (!y_.ok() || !m_.ok() || !wdi_.weekday().ok() || wdi_.index() < 1) 2424 | return false; 2425 | if (wdi_.index() <= 4) 2426 | return true; 2427 | auto d2 = wdi_.weekday() - islamic::weekday(y_/m_/1) + days((wdi_.index()-1)*7 + 1); 2428 | return static_cast(d2.count()) <= static_cast((y_/m_/last).day()); 2429 | } 2430 | 2431 | CONSTCD14 2432 | inline 2433 | year_month_weekday 2434 | year_month_weekday::from_days(days d) NOEXCEPT 2435 | { 2436 | sys_days dp{d}; 2437 | auto const wd = islamic::weekday(dp); 2438 | auto const ymd = year_month_day(dp); 2439 | return {ymd.year(), ymd.month(), wd[(static_cast(ymd.day())-1)/7+1]}; 2440 | } 2441 | 2442 | CONSTCD14 2443 | inline 2444 | days 2445 | year_month_weekday::to_days() const NOEXCEPT 2446 | { 2447 | auto d = sys_days(y_/m_/1); 2448 | return (d + (wdi_.weekday() - islamic::weekday(d) + days{(wdi_.index()-1)*7}) 2449 | ).time_since_epoch(); 2450 | } 2451 | 2452 | CONSTCD11 2453 | inline 2454 | bool 2455 | operator==(const year_month_weekday& x, const year_month_weekday& y) NOEXCEPT 2456 | { 2457 | return x.year() == y.year() && x.month() == y.month() && 2458 | x.weekday_indexed() == y.weekday_indexed(); 2459 | } 2460 | 2461 | CONSTCD11 2462 | inline 2463 | bool 2464 | operator!=(const year_month_weekday& x, const year_month_weekday& y) NOEXCEPT 2465 | { 2466 | return !(x == y); 2467 | } 2468 | 2469 | template 2470 | inline 2471 | std::basic_ostream& 2472 | operator<<(std::basic_ostream& os, const year_month_weekday& ymwdi) 2473 | { 2474 | return os << ymwdi.year() << '/' << ymwdi.month() 2475 | << '/' << ymwdi.weekday_indexed(); 2476 | } 2477 | 2478 | CONSTCD14 2479 | inline 2480 | year_month_weekday 2481 | operator+(const year_month_weekday& ymwd, const months& dm) NOEXCEPT 2482 | { 2483 | return (ymwd.year() / ymwd.month() + dm) / ymwd.weekday_indexed(); 2484 | } 2485 | 2486 | CONSTCD14 2487 | inline 2488 | year_month_weekday 2489 | operator+(const months& dm, const year_month_weekday& ymwd) NOEXCEPT 2490 | { 2491 | return ymwd + dm; 2492 | } 2493 | 2494 | CONSTCD14 2495 | inline 2496 | year_month_weekday 2497 | operator-(const year_month_weekday& ymwd, const months& dm) NOEXCEPT 2498 | { 2499 | return ymwd + (-dm); 2500 | } 2501 | 2502 | CONSTCD11 2503 | inline 2504 | year_month_weekday 2505 | operator+(const year_month_weekday& ymwd, const years& dy) NOEXCEPT 2506 | { 2507 | return {ymwd.year()+dy, ymwd.month(), ymwd.weekday_indexed()}; 2508 | } 2509 | 2510 | CONSTCD11 2511 | inline 2512 | year_month_weekday 2513 | operator+(const years& dy, const year_month_weekday& ymwd) NOEXCEPT 2514 | { 2515 | return ymwd + dy; 2516 | } 2517 | 2518 | CONSTCD11 2519 | inline 2520 | year_month_weekday 2521 | operator-(const year_month_weekday& ymwd, const years& dy) NOEXCEPT 2522 | { 2523 | return ymwd + (-dy); 2524 | } 2525 | 2526 | // year_month_weekday_last 2527 | 2528 | CONSTCD11 2529 | inline 2530 | year_month_weekday_last::year_month_weekday_last(const islamic::year& y, 2531 | const islamic::month& m, 2532 | const islamic::weekday_last& wdl) NOEXCEPT 2533 | : y_(y) 2534 | , m_(m) 2535 | , wdl_(wdl) 2536 | {} 2537 | 2538 | CONSTCD14 2539 | inline 2540 | year_month_weekday_last& 2541 | year_month_weekday_last::operator+=(const months& m) NOEXCEPT 2542 | { 2543 | *this = *this + m; 2544 | return *this; 2545 | } 2546 | 2547 | CONSTCD14 2548 | inline 2549 | year_month_weekday_last& 2550 | year_month_weekday_last::operator-=(const months& m) NOEXCEPT 2551 | { 2552 | *this = *this - m; 2553 | return *this; 2554 | } 2555 | 2556 | CONSTCD14 2557 | inline 2558 | year_month_weekday_last& 2559 | year_month_weekday_last::operator+=(const years& y) NOEXCEPT 2560 | { 2561 | *this = *this + y; 2562 | return *this; 2563 | } 2564 | 2565 | CONSTCD14 2566 | inline 2567 | year_month_weekday_last& 2568 | year_month_weekday_last::operator-=(const years& y) NOEXCEPT 2569 | { 2570 | *this = *this - y; 2571 | return *this; 2572 | } 2573 | 2574 | CONSTCD11 inline year year_month_weekday_last::year() const NOEXCEPT {return y_;} 2575 | CONSTCD11 inline month year_month_weekday_last::month() const NOEXCEPT {return m_;} 2576 | 2577 | CONSTCD11 2578 | inline 2579 | weekday 2580 | year_month_weekday_last::weekday() const NOEXCEPT 2581 | { 2582 | return wdl_.weekday(); 2583 | } 2584 | 2585 | CONSTCD11 2586 | inline 2587 | weekday_last 2588 | year_month_weekday_last::weekday_last() const NOEXCEPT 2589 | { 2590 | return wdl_; 2591 | } 2592 | 2593 | CONSTCD14 2594 | inline 2595 | year_month_weekday_last::operator sys_days() const NOEXCEPT 2596 | { 2597 | return sys_days{to_days()}; 2598 | } 2599 | 2600 | CONSTCD14 2601 | inline 2602 | year_month_weekday_last::operator local_days() const NOEXCEPT 2603 | { 2604 | return local_days{to_days()}; 2605 | } 2606 | 2607 | CONSTCD11 2608 | inline 2609 | bool 2610 | year_month_weekday_last::ok() const NOEXCEPT 2611 | { 2612 | return y_.ok() && m_.ok() && wdl_.ok(); 2613 | } 2614 | 2615 | CONSTCD14 2616 | inline 2617 | days 2618 | year_month_weekday_last::to_days() const NOEXCEPT 2619 | { 2620 | auto const d = sys_days(y_/m_/last); 2621 | return (d - (islamic::weekday{d} - wdl_.weekday())).time_since_epoch(); 2622 | } 2623 | 2624 | CONSTCD11 2625 | inline 2626 | bool 2627 | operator==(const year_month_weekday_last& x, const year_month_weekday_last& y) NOEXCEPT 2628 | { 2629 | return x.year() == y.year() && x.month() == y.month() && 2630 | x.weekday_last() == y.weekday_last(); 2631 | } 2632 | 2633 | CONSTCD11 2634 | inline 2635 | bool 2636 | operator!=(const year_month_weekday_last& x, const year_month_weekday_last& y) NOEXCEPT 2637 | { 2638 | return !(x == y); 2639 | } 2640 | 2641 | template 2642 | inline 2643 | std::basic_ostream& 2644 | operator<<(std::basic_ostream& os, const year_month_weekday_last& ymwdl) 2645 | { 2646 | return os << ymwdl.year() << '/' << ymwdl.month() << '/' << ymwdl.weekday_last(); 2647 | } 2648 | 2649 | CONSTCD14 2650 | inline 2651 | year_month_weekday_last 2652 | operator+(const year_month_weekday_last& ymwdl, const months& dm) NOEXCEPT 2653 | { 2654 | return (ymwdl.year() / ymwdl.month() + dm) / ymwdl.weekday_last(); 2655 | } 2656 | 2657 | CONSTCD14 2658 | inline 2659 | year_month_weekday_last 2660 | operator+(const months& dm, const year_month_weekday_last& ymwdl) NOEXCEPT 2661 | { 2662 | return ymwdl + dm; 2663 | } 2664 | 2665 | CONSTCD14 2666 | inline 2667 | year_month_weekday_last 2668 | operator-(const year_month_weekday_last& ymwdl, const months& dm) NOEXCEPT 2669 | { 2670 | return ymwdl + (-dm); 2671 | } 2672 | 2673 | CONSTCD11 2674 | inline 2675 | year_month_weekday_last 2676 | operator+(const year_month_weekday_last& ymwdl, const years& dy) NOEXCEPT 2677 | { 2678 | return {ymwdl.year()+dy, ymwdl.month(), ymwdl.weekday_last()}; 2679 | } 2680 | 2681 | CONSTCD11 2682 | inline 2683 | year_month_weekday_last 2684 | operator+(const years& dy, const year_month_weekday_last& ymwdl) NOEXCEPT 2685 | { 2686 | return ymwdl + dy; 2687 | } 2688 | 2689 | CONSTCD11 2690 | inline 2691 | year_month_weekday_last 2692 | operator-(const year_month_weekday_last& ymwdl, const years& dy) NOEXCEPT 2693 | { 2694 | return ymwdl + (-dy); 2695 | } 2696 | 2697 | // year_month from operator/() 2698 | 2699 | CONSTCD11 2700 | inline 2701 | year_month 2702 | operator/(const year& y, const month& m) NOEXCEPT 2703 | { 2704 | return {y, m}; 2705 | } 2706 | 2707 | CONSTCD11 2708 | inline 2709 | year_month 2710 | operator/(const year& y, int m) NOEXCEPT 2711 | { 2712 | return y / month(static_cast(m)); 2713 | } 2714 | 2715 | // month_day from operator/() 2716 | 2717 | CONSTCD11 2718 | inline 2719 | month_day 2720 | operator/(const month& m, const day& d) NOEXCEPT 2721 | { 2722 | return {m, d}; 2723 | } 2724 | 2725 | CONSTCD11 2726 | inline 2727 | month_day 2728 | operator/(const day& d, const month& m) NOEXCEPT 2729 | { 2730 | return m / d; 2731 | } 2732 | 2733 | CONSTCD11 2734 | inline 2735 | month_day 2736 | operator/(const month& m, int d) NOEXCEPT 2737 | { 2738 | return m / day(static_cast(d)); 2739 | } 2740 | 2741 | CONSTCD11 2742 | inline 2743 | month_day 2744 | operator/(int m, const day& d) NOEXCEPT 2745 | { 2746 | return month(static_cast(m)) / d; 2747 | } 2748 | 2749 | CONSTCD11 inline month_day operator/(const day& d, int m) NOEXCEPT {return m / d;} 2750 | 2751 | // month_day_last from operator/() 2752 | 2753 | CONSTCD11 2754 | inline 2755 | month_day_last 2756 | operator/(const month& m, last_spec) NOEXCEPT 2757 | { 2758 | return month_day_last{m}; 2759 | } 2760 | 2761 | CONSTCD11 2762 | inline 2763 | month_day_last 2764 | operator/(last_spec, const month& m) NOEXCEPT 2765 | { 2766 | return m/last; 2767 | } 2768 | 2769 | CONSTCD11 2770 | inline 2771 | month_day_last 2772 | operator/(int m, last_spec) NOEXCEPT 2773 | { 2774 | return month(static_cast(m))/last; 2775 | } 2776 | 2777 | CONSTCD11 2778 | inline 2779 | month_day_last 2780 | operator/(last_spec, int m) NOEXCEPT 2781 | { 2782 | return m/last; 2783 | } 2784 | 2785 | // month_weekday from operator/() 2786 | 2787 | CONSTCD11 2788 | inline 2789 | month_weekday 2790 | operator/(const month& m, const weekday_indexed& wdi) NOEXCEPT 2791 | { 2792 | return {m, wdi}; 2793 | } 2794 | 2795 | CONSTCD11 2796 | inline 2797 | month_weekday 2798 | operator/(const weekday_indexed& wdi, const month& m) NOEXCEPT 2799 | { 2800 | return m / wdi; 2801 | } 2802 | 2803 | CONSTCD11 2804 | inline 2805 | month_weekday 2806 | operator/(int m, const weekday_indexed& wdi) NOEXCEPT 2807 | { 2808 | return month(static_cast(m)) / wdi; 2809 | } 2810 | 2811 | CONSTCD11 2812 | inline 2813 | month_weekday 2814 | operator/(const weekday_indexed& wdi, int m) NOEXCEPT 2815 | { 2816 | return m / wdi; 2817 | } 2818 | 2819 | // month_weekday_last from operator/() 2820 | 2821 | CONSTCD11 2822 | inline 2823 | month_weekday_last 2824 | operator/(const month& m, const weekday_last& wdl) NOEXCEPT 2825 | { 2826 | return {m, wdl}; 2827 | } 2828 | 2829 | CONSTCD11 2830 | inline 2831 | month_weekday_last 2832 | operator/(const weekday_last& wdl, const month& m) NOEXCEPT 2833 | { 2834 | return m / wdl; 2835 | } 2836 | 2837 | CONSTCD11 2838 | inline 2839 | month_weekday_last 2840 | operator/(int m, const weekday_last& wdl) NOEXCEPT 2841 | { 2842 | return month(static_cast(m)) / wdl; 2843 | } 2844 | 2845 | CONSTCD11 2846 | inline 2847 | month_weekday_last 2848 | operator/(const weekday_last& wdl, int m) NOEXCEPT 2849 | { 2850 | return m / wdl; 2851 | } 2852 | 2853 | // year_month_day from operator/() 2854 | 2855 | CONSTCD11 2856 | inline 2857 | year_month_day 2858 | operator/(const year_month& ym, const day& d) NOEXCEPT 2859 | { 2860 | return {ym.year(), ym.month(), d}; 2861 | } 2862 | 2863 | CONSTCD11 2864 | inline 2865 | year_month_day 2866 | operator/(const year_month& ym, int d) NOEXCEPT 2867 | { 2868 | return ym / day(static_cast(d)); 2869 | } 2870 | 2871 | CONSTCD11 2872 | inline 2873 | year_month_day 2874 | operator/(const year& y, const month_day& md) NOEXCEPT 2875 | { 2876 | return y / md.month() / md.day(); 2877 | } 2878 | 2879 | CONSTCD11 2880 | inline 2881 | year_month_day 2882 | operator/(int y, const month_day& md) NOEXCEPT 2883 | { 2884 | return year(y) / md; 2885 | } 2886 | 2887 | CONSTCD11 2888 | inline 2889 | year_month_day 2890 | operator/(const month_day& md, const year& y) NOEXCEPT 2891 | { 2892 | return y / md; 2893 | } 2894 | 2895 | CONSTCD11 2896 | inline 2897 | year_month_day 2898 | operator/(const month_day& md, int y) NOEXCEPT 2899 | { 2900 | return year(y) / md; 2901 | } 2902 | 2903 | // year_month_day_last from operator/() 2904 | 2905 | CONSTCD11 2906 | inline 2907 | year_month_day_last 2908 | operator/(const year_month& ym, last_spec) NOEXCEPT 2909 | { 2910 | return {ym.year(), month_day_last{ym.month()}}; 2911 | } 2912 | 2913 | CONSTCD11 2914 | inline 2915 | year_month_day_last 2916 | operator/(const year& y, const month_day_last& mdl) NOEXCEPT 2917 | { 2918 | return {y, mdl}; 2919 | } 2920 | 2921 | CONSTCD11 2922 | inline 2923 | year_month_day_last 2924 | operator/(int y, const month_day_last& mdl) NOEXCEPT 2925 | { 2926 | return year(y) / mdl; 2927 | } 2928 | 2929 | CONSTCD11 2930 | inline 2931 | year_month_day_last 2932 | operator/(const month_day_last& mdl, const year& y) NOEXCEPT 2933 | { 2934 | return y / mdl; 2935 | } 2936 | 2937 | CONSTCD11 2938 | inline 2939 | year_month_day_last 2940 | operator/(const month_day_last& mdl, int y) NOEXCEPT 2941 | { 2942 | return year(y) / mdl; 2943 | } 2944 | 2945 | // year_month_weekday from operator/() 2946 | 2947 | CONSTCD11 2948 | inline 2949 | year_month_weekday 2950 | operator/(const year_month& ym, const weekday_indexed& wdi) NOEXCEPT 2951 | { 2952 | return {ym.year(), ym.month(), wdi}; 2953 | } 2954 | 2955 | CONSTCD11 2956 | inline 2957 | year_month_weekday 2958 | operator/(const year& y, const month_weekday& mwd) NOEXCEPT 2959 | { 2960 | return {y, mwd.month(), mwd.weekday_indexed()}; 2961 | } 2962 | 2963 | CONSTCD11 2964 | inline 2965 | year_month_weekday 2966 | operator/(int y, const month_weekday& mwd) NOEXCEPT 2967 | { 2968 | return year(y) / mwd; 2969 | } 2970 | 2971 | CONSTCD11 2972 | inline 2973 | year_month_weekday 2974 | operator/(const month_weekday& mwd, const year& y) NOEXCEPT 2975 | { 2976 | return y / mwd; 2977 | } 2978 | 2979 | CONSTCD11 2980 | inline 2981 | year_month_weekday 2982 | operator/(const month_weekday& mwd, int y) NOEXCEPT 2983 | { 2984 | return year(y) / mwd; 2985 | } 2986 | 2987 | // year_month_weekday_last from operator/() 2988 | 2989 | CONSTCD11 2990 | inline 2991 | year_month_weekday_last 2992 | operator/(const year_month& ym, const weekday_last& wdl) NOEXCEPT 2993 | { 2994 | return {ym.year(), ym.month(), wdl}; 2995 | } 2996 | 2997 | CONSTCD11 2998 | inline 2999 | year_month_weekday_last 3000 | operator/(const year& y, const month_weekday_last& mwdl) NOEXCEPT 3001 | { 3002 | return {y, mwdl.month(), mwdl.weekday_last()}; 3003 | } 3004 | 3005 | CONSTCD11 3006 | inline 3007 | year_month_weekday_last 3008 | operator/(int y, const month_weekday_last& mwdl) NOEXCEPT 3009 | { 3010 | return year(y) / mwdl; 3011 | } 3012 | 3013 | CONSTCD11 3014 | inline 3015 | year_month_weekday_last 3016 | operator/(const month_weekday_last& mwdl, const year& y) NOEXCEPT 3017 | { 3018 | return y / mwdl; 3019 | } 3020 | 3021 | CONSTCD11 3022 | inline 3023 | year_month_weekday_last 3024 | operator/(const month_weekday_last& mwdl, int y) NOEXCEPT 3025 | { 3026 | return year(y) / mwdl; 3027 | } 3028 | 3029 | } // namespace islamic 3030 | 3031 | #endif // ISLAMIC_H 3032 | --------------------------------------------------------------------------------