You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@nifi.apache.org by al...@apache.org on 2018/05/19 00:06:45 UTC
[01/10] [nifi-minifi-cpp] Git Push Summary
Repository: nifi-minifi-cpp
Updated Branches:
refs/heads/master 02f18238e -> 8777ab5f0
[06/10] nifi-minifi-cpp git commit: MINIFICPP-472 Added date
formatting EL functions
Posted by al...@apache.org.
http://git-wip-us.apache.org/repos/asf/nifi-minifi-cpp/blob/8777ab5f/thirdparty/date/include/date/julian.h
----------------------------------------------------------------------
diff --git a/thirdparty/date/include/date/julian.h b/thirdparty/date/include/date/julian.h
new file mode 100644
index 0000000..4aac963
--- /dev/null
+++ b/thirdparty/date/include/date/julian.h
@@ -0,0 +1,3046 @@
+#ifndef JULIAN_H
+#define JULIAN_H
+
+// The MIT License (MIT)
+//
+// Copyright (c) 2016 Howard Hinnant
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in all
+// copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+// SOFTWARE.
+//
+// Our apologies. When the previous paragraph was written, lowercase had not yet
+// been invented (that would involve another several millennia of evolution).
+// We did not mean to shout.
+
+#include "date.h"
+
+namespace julian
+{
+
+// durations
+
+using days = date::days;
+
+using weeks = date::weeks;
+
+using years = std::chrono::duration
+ <int, std::ratio_multiply<std::ratio<1461, 4>, days::period>>;
+
+using months = std::chrono::duration
+ <int, std::ratio_divide<years::period, std::ratio<12>>>;
+
+// time_point
+
+using sys_days = date::sys_days;
+using local_days = date::local_days;
+
+// types
+
+struct last_spec
+{
+ explicit last_spec() = default;
+};
+
+class day;
+class month;
+class year;
+
+class weekday;
+class weekday_indexed;
+class weekday_last;
+
+class month_day;
+class month_day_last;
+class month_weekday;
+class month_weekday_last;
+
+class year_month;
+
+class year_month_day;
+class year_month_day_last;
+class year_month_weekday;
+class year_month_weekday_last;
+
+// date composition operators
+
+CONSTCD11 year_month operator/(const year& y, const month& m) NOEXCEPT;
+CONSTCD11 year_month operator/(const year& y, int m) NOEXCEPT;
+
+CONSTCD11 month_day operator/(const day& d, const month& m) NOEXCEPT;
+CONSTCD11 month_day operator/(const day& d, int m) NOEXCEPT;
+CONSTCD11 month_day operator/(const month& m, const day& d) NOEXCEPT;
+CONSTCD11 month_day operator/(const month& m, int d) NOEXCEPT;
+CONSTCD11 month_day operator/(int m, const day& d) NOEXCEPT;
+
+CONSTCD11 month_day_last operator/(const month& m, last_spec) NOEXCEPT;
+CONSTCD11 month_day_last operator/(int m, last_spec) NOEXCEPT;
+CONSTCD11 month_day_last operator/(last_spec, const month& m) NOEXCEPT;
+CONSTCD11 month_day_last operator/(last_spec, int m) NOEXCEPT;
+
+CONSTCD11 month_weekday operator/(const month& m, const weekday_indexed& wdi) NOEXCEPT;
+CONSTCD11 month_weekday operator/(int m, const weekday_indexed& wdi) NOEXCEPT;
+CONSTCD11 month_weekday operator/(const weekday_indexed& wdi, const month& m) NOEXCEPT;
+CONSTCD11 month_weekday operator/(const weekday_indexed& wdi, int m) NOEXCEPT;
+
+CONSTCD11 month_weekday_last operator/(const month& m, const weekday_last& wdl) NOEXCEPT;
+CONSTCD11 month_weekday_last operator/(int m, const weekday_last& wdl) NOEXCEPT;
+CONSTCD11 month_weekday_last operator/(const weekday_last& wdl, const month& m) NOEXCEPT;
+CONSTCD11 month_weekday_last operator/(const weekday_last& wdl, int m) NOEXCEPT;
+
+CONSTCD11 year_month_day operator/(const year_month& ym, const day& d) NOEXCEPT;
+CONSTCD11 year_month_day operator/(const year_month& ym, int d) NOEXCEPT;
+CONSTCD11 year_month_day operator/(const year& y, const month_day& md) NOEXCEPT;
+CONSTCD11 year_month_day operator/(int y, const month_day& md) NOEXCEPT;
+CONSTCD11 year_month_day operator/(const month_day& md, const year& y) NOEXCEPT;
+CONSTCD11 year_month_day operator/(const month_day& md, int y) NOEXCEPT;
+
+CONSTCD11
+ year_month_day_last operator/(const year_month& ym, last_spec) NOEXCEPT;
+CONSTCD11
+ year_month_day_last operator/(const year& y, const month_day_last& mdl) NOEXCEPT;
+CONSTCD11
+ year_month_day_last operator/(int y, const month_day_last& mdl) NOEXCEPT;
+CONSTCD11
+ year_month_day_last operator/(const month_day_last& mdl, const year& y) NOEXCEPT;
+CONSTCD11
+ year_month_day_last operator/(const month_day_last& mdl, int y) NOEXCEPT;
+
+CONSTCD11
+year_month_weekday
+operator/(const year_month& ym, const weekday_indexed& wdi) NOEXCEPT;
+
+CONSTCD11
+year_month_weekday
+operator/(const year& y, const month_weekday& mwd) NOEXCEPT;
+
+CONSTCD11
+year_month_weekday
+operator/(int y, const month_weekday& mwd) NOEXCEPT;
+
+CONSTCD11
+year_month_weekday
+operator/(const month_weekday& mwd, const year& y) NOEXCEPT;
+
+CONSTCD11
+year_month_weekday
+operator/(const month_weekday& mwd, int y) NOEXCEPT;
+
+CONSTCD11
+year_month_weekday_last
+operator/(const year_month& ym, const weekday_last& wdl) NOEXCEPT;
+
+CONSTCD11
+year_month_weekday_last
+operator/(const year& y, const month_weekday_last& mwdl) NOEXCEPT;
+
+CONSTCD11
+year_month_weekday_last
+operator/(int y, const month_weekday_last& mwdl) NOEXCEPT;
+
+CONSTCD11
+year_month_weekday_last
+operator/(const month_weekday_last& mwdl, const year& y) NOEXCEPT;
+
+CONSTCD11
+year_month_weekday_last
+operator/(const month_weekday_last& mwdl, int y) NOEXCEPT;
+
+// Detailed interface
+
+// day
+
+class day
+{
+ unsigned char d_;
+
+public:
+ explicit CONSTCD11 day(unsigned d) NOEXCEPT;
+
+ CONSTCD14 day& operator++() NOEXCEPT;
+ CONSTCD14 day operator++(int) NOEXCEPT;
+ CONSTCD14 day& operator--() NOEXCEPT;
+ CONSTCD14 day operator--(int) NOEXCEPT;
+
+ CONSTCD14 day& operator+=(const days& d) NOEXCEPT;
+ CONSTCD14 day& operator-=(const days& d) NOEXCEPT;
+
+ CONSTCD11 explicit operator unsigned() const NOEXCEPT;
+ CONSTCD11 bool ok() const NOEXCEPT;
+};
+
+CONSTCD11 bool operator==(const day& x, const day& y) NOEXCEPT;
+CONSTCD11 bool operator!=(const day& x, const day& y) NOEXCEPT;
+CONSTCD11 bool operator< (const day& x, const day& y) NOEXCEPT;
+CONSTCD11 bool operator> (const day& x, const day& y) NOEXCEPT;
+CONSTCD11 bool operator<=(const day& x, const day& y) NOEXCEPT;
+CONSTCD11 bool operator>=(const day& x, const day& y) NOEXCEPT;
+
+CONSTCD11 day operator+(const day& x, const days& y) NOEXCEPT;
+CONSTCD11 day operator+(const days& x, const day& y) NOEXCEPT;
+CONSTCD11 day operator-(const day& x, const days& y) NOEXCEPT;
+CONSTCD11 days operator-(const day& x, const day& y) NOEXCEPT;
+
+template<class CharT, class Traits>
+std::basic_ostream<CharT, Traits>&
+operator<<(std::basic_ostream<CharT, Traits>& os, const day& d);
+
+// month
+
+class month
+{
+ unsigned char m_;
+
+public:
+ explicit CONSTCD11 month(unsigned m) NOEXCEPT;
+
+ CONSTCD14 month& operator++() NOEXCEPT;
+ CONSTCD14 month operator++(int) NOEXCEPT;
+ CONSTCD14 month& operator--() NOEXCEPT;
+ CONSTCD14 month operator--(int) NOEXCEPT;
+
+ CONSTCD14 month& operator+=(const months& m) NOEXCEPT;
+ CONSTCD14 month& operator-=(const months& m) NOEXCEPT;
+
+ CONSTCD11 explicit operator unsigned() const NOEXCEPT;
+ CONSTCD11 bool ok() const NOEXCEPT;
+};
+
+CONSTCD11 bool operator==(const month& x, const month& y) NOEXCEPT;
+CONSTCD11 bool operator!=(const month& x, const month& y) NOEXCEPT;
+CONSTCD11 bool operator< (const month& x, const month& y) NOEXCEPT;
+CONSTCD11 bool operator> (const month& x, const month& y) NOEXCEPT;
+CONSTCD11 bool operator<=(const month& x, const month& y) NOEXCEPT;
+CONSTCD11 bool operator>=(const month& x, const month& y) NOEXCEPT;
+
+CONSTCD14 month operator+(const month& x, const months& y) NOEXCEPT;
+CONSTCD14 month operator+(const months& x, const month& y) NOEXCEPT;
+CONSTCD14 month operator-(const month& x, const months& y) NOEXCEPT;
+CONSTCD14 months operator-(const month& x, const month& y) NOEXCEPT;
+
+template<class CharT, class Traits>
+std::basic_ostream<CharT, Traits>&
+operator<<(std::basic_ostream<CharT, Traits>& os, const month& m);
+
+// year
+
+class year
+{
+ short y_;
+
+public:
+ explicit CONSTCD11 year(int y) NOEXCEPT;
+
+ CONSTCD14 year& operator++() NOEXCEPT;
+ CONSTCD14 year operator++(int) NOEXCEPT;
+ CONSTCD14 year& operator--() NOEXCEPT;
+ CONSTCD14 year operator--(int) NOEXCEPT;
+
+ CONSTCD14 year& operator+=(const years& y) NOEXCEPT;
+ CONSTCD14 year& operator-=(const years& y) NOEXCEPT;
+
+ CONSTCD11 bool is_leap() const NOEXCEPT;
+
+ CONSTCD11 explicit operator int() const NOEXCEPT;
+ CONSTCD11 bool ok() const NOEXCEPT;
+
+ static CONSTCD11 year min() NOEXCEPT;
+ static CONSTCD11 year max() NOEXCEPT;
+};
+
+CONSTCD11 bool operator==(const year& x, const year& y) NOEXCEPT;
+CONSTCD11 bool operator!=(const year& x, const year& y) NOEXCEPT;
+CONSTCD11 bool operator< (const year& x, const year& y) NOEXCEPT;
+CONSTCD11 bool operator> (const year& x, const year& y) NOEXCEPT;
+CONSTCD11 bool operator<=(const year& x, const year& y) NOEXCEPT;
+CONSTCD11 bool operator>=(const year& x, const year& y) NOEXCEPT;
+
+CONSTCD11 year operator+(const year& x, const years& y) NOEXCEPT;
+CONSTCD11 year operator+(const years& x, const year& y) NOEXCEPT;
+CONSTCD11 year operator-(const year& x, const years& y) NOEXCEPT;
+CONSTCD11 years operator-(const year& x, const year& y) NOEXCEPT;
+
+template<class CharT, class Traits>
+std::basic_ostream<CharT, Traits>&
+operator<<(std::basic_ostream<CharT, Traits>& os, const year& y);
+
+// weekday
+
+class weekday
+{
+ unsigned char wd_;
+public:
+ explicit CONSTCD11 weekday(unsigned wd) NOEXCEPT;
+ explicit weekday(int) = delete;
+ CONSTCD11 weekday(const sys_days& dp) NOEXCEPT;
+ CONSTCD11 explicit weekday(const local_days& dp) NOEXCEPT;
+
+ CONSTCD14 weekday& operator++() NOEXCEPT;
+ CONSTCD14 weekday operator++(int) NOEXCEPT;
+ CONSTCD14 weekday& operator--() NOEXCEPT;
+ CONSTCD14 weekday operator--(int) NOEXCEPT;
+
+ CONSTCD14 weekday& operator+=(const days& d) NOEXCEPT;
+ CONSTCD14 weekday& operator-=(const days& d) NOEXCEPT;
+
+ CONSTCD11 explicit operator unsigned() const NOEXCEPT;
+ CONSTCD11 bool ok() const NOEXCEPT;
+
+ CONSTCD11 weekday_indexed operator[](unsigned index) const NOEXCEPT;
+ CONSTCD11 weekday_last operator[](last_spec) const NOEXCEPT;
+
+private:
+ static CONSTCD11 unsigned char weekday_from_days(int z) NOEXCEPT;
+};
+
+CONSTCD11 bool operator==(const weekday& x, const weekday& y) NOEXCEPT;
+CONSTCD11 bool operator!=(const weekday& x, const weekday& y) NOEXCEPT;
+
+CONSTCD14 weekday operator+(const weekday& x, const days& y) NOEXCEPT;
+CONSTCD14 weekday operator+(const days& x, const weekday& y) NOEXCEPT;
+CONSTCD14 weekday operator-(const weekday& x, const days& y) NOEXCEPT;
+CONSTCD14 days operator-(const weekday& x, const weekday& y) NOEXCEPT;
+
+template<class CharT, class Traits>
+std::basic_ostream<CharT, Traits>&
+operator<<(std::basic_ostream<CharT, Traits>& os, const weekday& wd);
+
+// weekday_indexed
+
+class weekday_indexed
+{
+ unsigned char wd_ : 4;
+ unsigned char index_ : 4;
+
+public:
+ CONSTCD11 weekday_indexed(const julian::weekday& wd, unsigned index) NOEXCEPT;
+
+ CONSTCD11 julian::weekday weekday() const NOEXCEPT;
+ CONSTCD11 unsigned index() const NOEXCEPT;
+ CONSTCD11 bool ok() const NOEXCEPT;
+};
+
+CONSTCD11 bool operator==(const weekday_indexed& x, const weekday_indexed& y) NOEXCEPT;
+CONSTCD11 bool operator!=(const weekday_indexed& x, const weekday_indexed& y) NOEXCEPT;
+
+template<class CharT, class Traits>
+std::basic_ostream<CharT, Traits>&
+operator<<(std::basic_ostream<CharT, Traits>& os, const weekday_indexed& wdi);
+
+// weekday_last
+
+class weekday_last
+{
+ julian::weekday wd_;
+
+public:
+ explicit CONSTCD11 weekday_last(const julian::weekday& wd) NOEXCEPT;
+
+ CONSTCD11 julian::weekday weekday() const NOEXCEPT;
+ CONSTCD11 bool ok() const NOEXCEPT;
+};
+
+CONSTCD11 bool operator==(const weekday_last& x, const weekday_last& y) NOEXCEPT;
+CONSTCD11 bool operator!=(const weekday_last& x, const weekday_last& y) NOEXCEPT;
+
+template<class CharT, class Traits>
+std::basic_ostream<CharT, Traits>&
+operator<<(std::basic_ostream<CharT, Traits>& os, const weekday_last& wdl);
+
+// year_month
+
+class year_month
+{
+ julian::year y_;
+ julian::month m_;
+
+public:
+ CONSTCD11 year_month(const julian::year& y, const julian::month& m) NOEXCEPT;
+
+ CONSTCD11 julian::year year() const NOEXCEPT;
+ CONSTCD11 julian::month month() const NOEXCEPT;
+
+ CONSTCD14 year_month& operator+=(const months& dm) NOEXCEPT;
+ CONSTCD14 year_month& operator-=(const months& dm) NOEXCEPT;
+ CONSTCD14 year_month& operator+=(const years& dy) NOEXCEPT;
+ CONSTCD14 year_month& operator-=(const years& dy) NOEXCEPT;
+
+ CONSTCD11 bool ok() const NOEXCEPT;
+};
+
+CONSTCD11 bool operator==(const year_month& x, const year_month& y) NOEXCEPT;
+CONSTCD11 bool operator!=(const year_month& x, const year_month& y) NOEXCEPT;
+CONSTCD11 bool operator< (const year_month& x, const year_month& y) NOEXCEPT;
+CONSTCD11 bool operator> (const year_month& x, const year_month& y) NOEXCEPT;
+CONSTCD11 bool operator<=(const year_month& x, const year_month& y) NOEXCEPT;
+CONSTCD11 bool operator>=(const year_month& x, const year_month& y) NOEXCEPT;
+
+CONSTCD14 year_month operator+(const year_month& ym, const months& dm) NOEXCEPT;
+CONSTCD14 year_month operator+(const months& dm, const year_month& ym) NOEXCEPT;
+CONSTCD14 year_month operator-(const year_month& ym, const months& dm) NOEXCEPT;
+
+CONSTCD11 months operator-(const year_month& x, const year_month& y) NOEXCEPT;
+CONSTCD11 year_month operator+(const year_month& ym, const years& dy) NOEXCEPT;
+CONSTCD11 year_month operator+(const years& dy, const year_month& ym) NOEXCEPT;
+CONSTCD11 year_month operator-(const year_month& ym, const years& dy) NOEXCEPT;
+
+template<class CharT, class Traits>
+std::basic_ostream<CharT, Traits>&
+operator<<(std::basic_ostream<CharT, Traits>& os, const year_month& ym);
+
+// month_day
+
+class month_day
+{
+ julian::month m_;
+ julian::day d_;
+
+public:
+ CONSTCD11 month_day(const julian::month& m, const julian::day& d) NOEXCEPT;
+
+ CONSTCD11 julian::month month() const NOEXCEPT;
+ CONSTCD11 julian::day day() const NOEXCEPT;
+
+ CONSTCD14 bool ok() const NOEXCEPT;
+};
+
+CONSTCD11 bool operator==(const month_day& x, const month_day& y) NOEXCEPT;
+CONSTCD11 bool operator!=(const month_day& x, const month_day& y) NOEXCEPT;
+CONSTCD11 bool operator< (const month_day& x, const month_day& y) NOEXCEPT;
+CONSTCD11 bool operator> (const month_day& x, const month_day& y) NOEXCEPT;
+CONSTCD11 bool operator<=(const month_day& x, const month_day& y) NOEXCEPT;
+CONSTCD11 bool operator>=(const month_day& x, const month_day& y) NOEXCEPT;
+
+template<class CharT, class Traits>
+std::basic_ostream<CharT, Traits>&
+operator<<(std::basic_ostream<CharT, Traits>& os, const month_day& md);
+
+// month_day_last
+
+class month_day_last
+{
+ julian::month m_;
+
+public:
+ CONSTCD11 explicit month_day_last(const julian::month& m) NOEXCEPT;
+
+ CONSTCD11 julian::month month() const NOEXCEPT;
+ CONSTCD11 bool ok() const NOEXCEPT;
+};
+
+CONSTCD11 bool operator==(const month_day_last& x, const month_day_last& y) NOEXCEPT;
+CONSTCD11 bool operator!=(const month_day_last& x, const month_day_last& y) NOEXCEPT;
+CONSTCD11 bool operator< (const month_day_last& x, const month_day_last& y) NOEXCEPT;
+CONSTCD11 bool operator> (const month_day_last& x, const month_day_last& y) NOEXCEPT;
+CONSTCD11 bool operator<=(const month_day_last& x, const month_day_last& y) NOEXCEPT;
+CONSTCD11 bool operator>=(const month_day_last& x, const month_day_last& y) NOEXCEPT;
+
+template<class CharT, class Traits>
+std::basic_ostream<CharT, Traits>&
+operator<<(std::basic_ostream<CharT, Traits>& os, const month_day_last& mdl);
+
+// month_weekday
+
+class month_weekday
+{
+ julian::month m_;
+ julian::weekday_indexed wdi_;
+public:
+ CONSTCD11 month_weekday(const julian::month& m,
+ const julian::weekday_indexed& wdi) NOEXCEPT;
+
+ CONSTCD11 julian::month month() const NOEXCEPT;
+ CONSTCD11 julian::weekday_indexed weekday_indexed() const NOEXCEPT;
+
+ CONSTCD11 bool ok() const NOEXCEPT;
+};
+
+CONSTCD11 bool operator==(const month_weekday& x, const month_weekday& y) NOEXCEPT;
+CONSTCD11 bool operator!=(const month_weekday& x, const month_weekday& y) NOEXCEPT;
+
+template<class CharT, class Traits>
+std::basic_ostream<CharT, Traits>&
+operator<<(std::basic_ostream<CharT, Traits>& os, const month_weekday& mwd);
+
+// month_weekday_last
+
+class month_weekday_last
+{
+ julian::month m_;
+ julian::weekday_last wdl_;
+
+public:
+ CONSTCD11 month_weekday_last(const julian::month& m,
+ const julian::weekday_last& wd) NOEXCEPT;
+
+ CONSTCD11 julian::month month() const NOEXCEPT;
+ CONSTCD11 julian::weekday_last weekday_last() const NOEXCEPT;
+
+ CONSTCD11 bool ok() const NOEXCEPT;
+};
+
+CONSTCD11
+ bool operator==(const month_weekday_last& x, const month_weekday_last& y) NOEXCEPT;
+CONSTCD11
+ bool operator!=(const month_weekday_last& x, const month_weekday_last& y) NOEXCEPT;
+
+template<class CharT, class Traits>
+std::basic_ostream<CharT, Traits>&
+operator<<(std::basic_ostream<CharT, Traits>& os, const month_weekday_last& mwdl);
+
+// class year_month_day
+
+class year_month_day
+{
+ julian::year y_;
+ julian::month m_;
+ julian::day d_;
+
+public:
+ CONSTCD11 year_month_day(const julian::year& y, const julian::month& m,
+ const julian::day& d) NOEXCEPT;
+ CONSTCD14 year_month_day(const year_month_day_last& ymdl) NOEXCEPT;
+
+ CONSTCD14 year_month_day(sys_days dp) NOEXCEPT;
+ CONSTCD14 explicit year_month_day(local_days dp) NOEXCEPT;
+
+ CONSTCD14 year_month_day& operator+=(const months& m) NOEXCEPT;
+ CONSTCD14 year_month_day& operator-=(const months& m) NOEXCEPT;
+ CONSTCD14 year_month_day& operator+=(const years& y) NOEXCEPT;
+ CONSTCD14 year_month_day& operator-=(const years& y) NOEXCEPT;
+
+ CONSTCD11 julian::year year() const NOEXCEPT;
+ CONSTCD11 julian::month month() const NOEXCEPT;
+ CONSTCD11 julian::day day() const NOEXCEPT;
+
+ CONSTCD14 operator sys_days() const NOEXCEPT;
+ CONSTCD14 explicit operator local_days() const NOEXCEPT;
+ CONSTCD14 bool ok() const NOEXCEPT;
+
+private:
+ static CONSTCD14 year_month_day from_days(days dp) NOEXCEPT;
+ CONSTCD14 days to_days() const NOEXCEPT;
+};
+
+CONSTCD11 bool operator==(const year_month_day& x, const year_month_day& y) NOEXCEPT;
+CONSTCD11 bool operator!=(const year_month_day& x, const year_month_day& y) NOEXCEPT;
+CONSTCD11 bool operator< (const year_month_day& x, const year_month_day& y) NOEXCEPT;
+CONSTCD11 bool operator> (const year_month_day& x, const year_month_day& y) NOEXCEPT;
+CONSTCD11 bool operator<=(const year_month_day& x, const year_month_day& y) NOEXCEPT;
+CONSTCD11 bool operator>=(const year_month_day& x, const year_month_day& y) NOEXCEPT;
+
+CONSTCD14 year_month_day operator+(const year_month_day& ymd, const months& dm) NOEXCEPT;
+CONSTCD14 year_month_day operator+(const months& dm, const year_month_day& ymd) NOEXCEPT;
+CONSTCD14 year_month_day operator-(const year_month_day& ymd, const months& dm) NOEXCEPT;
+CONSTCD11 year_month_day operator+(const year_month_day& ymd, const years& dy) NOEXCEPT;
+CONSTCD11 year_month_day operator+(const years& dy, const year_month_day& ymd) NOEXCEPT;
+CONSTCD11 year_month_day operator-(const year_month_day& ymd, const years& dy) NOEXCEPT;
+
+template<class CharT, class Traits>
+std::basic_ostream<CharT, Traits>&
+operator<<(std::basic_ostream<CharT, Traits>& os, const year_month_day& ymd);
+
+// year_month_day_last
+
+class year_month_day_last
+{
+ julian::year y_;
+ julian::month_day_last mdl_;
+
+public:
+ CONSTCD11 year_month_day_last(const julian::year& y,
+ const julian::month_day_last& mdl) NOEXCEPT;
+
+ CONSTCD14 year_month_day_last& operator+=(const months& m) NOEXCEPT;
+ CONSTCD14 year_month_day_last& operator-=(const months& m) NOEXCEPT;
+ CONSTCD14 year_month_day_last& operator+=(const years& y) NOEXCEPT;
+ CONSTCD14 year_month_day_last& operator-=(const years& y) NOEXCEPT;
+
+ CONSTCD11 julian::year year() const NOEXCEPT;
+ CONSTCD11 julian::month month() const NOEXCEPT;
+ CONSTCD11 julian::month_day_last month_day_last() const NOEXCEPT;
+ CONSTCD14 julian::day day() const NOEXCEPT;
+
+ CONSTCD14 operator sys_days() const NOEXCEPT;
+ CONSTCD14 explicit operator local_days() const NOEXCEPT;
+ CONSTCD11 bool ok() const NOEXCEPT;
+};
+
+CONSTCD11
+ bool operator==(const year_month_day_last& x, const year_month_day_last& y) NOEXCEPT;
+CONSTCD11
+ bool operator!=(const year_month_day_last& x, const year_month_day_last& y) NOEXCEPT;
+CONSTCD11
+ bool operator< (const year_month_day_last& x, const year_month_day_last& y) NOEXCEPT;
+CONSTCD11
+ bool operator> (const year_month_day_last& x, const year_month_day_last& y) NOEXCEPT;
+CONSTCD11
+ bool operator<=(const year_month_day_last& x, const year_month_day_last& y) NOEXCEPT;
+CONSTCD11
+ bool operator>=(const year_month_day_last& x, const year_month_day_last& y) NOEXCEPT;
+
+CONSTCD14
+year_month_day_last
+operator+(const year_month_day_last& ymdl, const months& dm) NOEXCEPT;
+
+CONSTCD14
+year_month_day_last
+operator+(const months& dm, const year_month_day_last& ymdl) NOEXCEPT;
+
+CONSTCD11
+year_month_day_last
+operator+(const year_month_day_last& ymdl, const years& dy) NOEXCEPT;
+
+CONSTCD11
+year_month_day_last
+operator+(const years& dy, const year_month_day_last& ymdl) NOEXCEPT;
+
+CONSTCD14
+year_month_day_last
+operator-(const year_month_day_last& ymdl, const months& dm) NOEXCEPT;
+
+CONSTCD11
+year_month_day_last
+operator-(const year_month_day_last& ymdl, const years& dy) NOEXCEPT;
+
+template<class CharT, class Traits>
+std::basic_ostream<CharT, Traits>&
+operator<<(std::basic_ostream<CharT, Traits>& os, const year_month_day_last& ymdl);
+
+// year_month_weekday
+
+class year_month_weekday
+{
+ julian::year y_;
+ julian::month m_;
+ julian::weekday_indexed wdi_;
+
+public:
+ CONSTCD11 year_month_weekday(const julian::year& y, const julian::month& m,
+ const julian::weekday_indexed& wdi) NOEXCEPT;
+ CONSTCD14 year_month_weekday(const sys_days& dp) NOEXCEPT;
+ CONSTCD14 explicit year_month_weekday(const local_days& dp) NOEXCEPT;
+
+ CONSTCD14 year_month_weekday& operator+=(const months& m) NOEXCEPT;
+ CONSTCD14 year_month_weekday& operator-=(const months& m) NOEXCEPT;
+ CONSTCD14 year_month_weekday& operator+=(const years& y) NOEXCEPT;
+ CONSTCD14 year_month_weekday& operator-=(const years& y) NOEXCEPT;
+
+ CONSTCD11 julian::year year() const NOEXCEPT;
+ CONSTCD11 julian::month month() const NOEXCEPT;
+ CONSTCD11 julian::weekday weekday() const NOEXCEPT;
+ CONSTCD11 unsigned index() const NOEXCEPT;
+ CONSTCD11 julian::weekday_indexed weekday_indexed() const NOEXCEPT;
+
+ CONSTCD14 operator sys_days() const NOEXCEPT;
+ CONSTCD14 explicit operator local_days() const NOEXCEPT;
+ CONSTCD14 bool ok() const NOEXCEPT;
+
+private:
+ static CONSTCD14 year_month_weekday from_days(days dp) NOEXCEPT;
+ CONSTCD14 days to_days() const NOEXCEPT;
+};
+
+CONSTCD11
+ bool operator==(const year_month_weekday& x, const year_month_weekday& y) NOEXCEPT;
+CONSTCD11
+ bool operator!=(const year_month_weekday& x, const year_month_weekday& y) NOEXCEPT;
+
+CONSTCD14
+year_month_weekday
+operator+(const year_month_weekday& ymwd, const months& dm) NOEXCEPT;
+
+CONSTCD14
+year_month_weekday
+operator+(const months& dm, const year_month_weekday& ymwd) NOEXCEPT;
+
+CONSTCD11
+year_month_weekday
+operator+(const year_month_weekday& ymwd, const years& dy) NOEXCEPT;
+
+CONSTCD11
+year_month_weekday
+operator+(const years& dy, const year_month_weekday& ymwd) NOEXCEPT;
+
+CONSTCD14
+year_month_weekday
+operator-(const year_month_weekday& ymwd, const months& dm) NOEXCEPT;
+
+CONSTCD11
+year_month_weekday
+operator-(const year_month_weekday& ymwd, const years& dy) NOEXCEPT;
+
+template<class CharT, class Traits>
+std::basic_ostream<CharT, Traits>&
+operator<<(std::basic_ostream<CharT, Traits>& os, const year_month_weekday& ymwdi);
+
+// year_month_weekday_last
+
+class year_month_weekday_last
+{
+ julian::year y_;
+ julian::month m_;
+ julian::weekday_last wdl_;
+
+public:
+ CONSTCD11 year_month_weekday_last(const julian::year& y, const julian::month& m,
+ const julian::weekday_last& wdl) NOEXCEPT;
+
+ CONSTCD14 year_month_weekday_last& operator+=(const months& m) NOEXCEPT;
+ CONSTCD14 year_month_weekday_last& operator-=(const months& m) NOEXCEPT;
+ CONSTCD14 year_month_weekday_last& operator+=(const years& y) NOEXCEPT;
+ CONSTCD14 year_month_weekday_last& operator-=(const years& y) NOEXCEPT;
+
+ CONSTCD11 julian::year year() const NOEXCEPT;
+ CONSTCD11 julian::month month() const NOEXCEPT;
+ CONSTCD11 julian::weekday weekday() const NOEXCEPT;
+ CONSTCD11 julian::weekday_last weekday_last() const NOEXCEPT;
+
+ CONSTCD14 operator sys_days() const NOEXCEPT;
+ CONSTCD14 explicit operator local_days() const NOEXCEPT;
+ CONSTCD11 bool ok() const NOEXCEPT;
+
+private:
+ CONSTCD14 days to_days() const NOEXCEPT;
+};
+
+CONSTCD11
+bool
+operator==(const year_month_weekday_last& x, const year_month_weekday_last& y) NOEXCEPT;
+
+CONSTCD11
+bool
+operator!=(const year_month_weekday_last& x, const year_month_weekday_last& y) NOEXCEPT;
+
+CONSTCD14
+year_month_weekday_last
+operator+(const year_month_weekday_last& ymwdl, const months& dm) NOEXCEPT;
+
+CONSTCD14
+year_month_weekday_last
+operator+(const months& dm, const year_month_weekday_last& ymwdl) NOEXCEPT;
+
+CONSTCD11
+year_month_weekday_last
+operator+(const year_month_weekday_last& ymwdl, const years& dy) NOEXCEPT;
+
+CONSTCD11
+year_month_weekday_last
+operator+(const years& dy, const year_month_weekday_last& ymwdl) NOEXCEPT;
+
+CONSTCD14
+year_month_weekday_last
+operator-(const year_month_weekday_last& ymwdl, const months& dm) NOEXCEPT;
+
+CONSTCD11
+year_month_weekday_last
+operator-(const year_month_weekday_last& ymwdl, const years& dy) NOEXCEPT;
+
+template<class CharT, class Traits>
+std::basic_ostream<CharT, Traits>&
+operator<<(std::basic_ostream<CharT, Traits>& os, const year_month_weekday_last& ymwdl);
+
+#if !defined(_MSC_VER) || (_MSC_VER >= 1900)
+inline namespace literals
+{
+
+CONSTCD11 julian::day operator "" _d(unsigned long long d) NOEXCEPT;
+CONSTCD11 julian::year operator "" _y(unsigned long long y) NOEXCEPT;
+
+// CONSTDATA julian::month jan{1};
+// CONSTDATA julian::month feb{2};
+// CONSTDATA julian::month mar{3};
+// CONSTDATA julian::month apr{4};
+// CONSTDATA julian::month may{5};
+// CONSTDATA julian::month jun{6};
+// CONSTDATA julian::month jul{7};
+// CONSTDATA julian::month aug{8};
+// CONSTDATA julian::month sep{9};
+// CONSTDATA julian::month oct{10};
+// CONSTDATA julian::month nov{11};
+// CONSTDATA julian::month dec{12};
+
+} // inline namespace literals
+#endif // !defined(_MSC_VER) || (_MSC_VER >= 1900)
+
+//----------------+
+// Implementation |
+//----------------+
+
+// day
+
+CONSTCD11 inline day::day(unsigned d) NOEXCEPT : d_(static_cast<unsigned char>(d)) {}
+CONSTCD14 inline day& day::operator++() NOEXCEPT {++d_; return *this;}
+CONSTCD14 inline day day::operator++(int) NOEXCEPT {auto tmp(*this); ++(*this); return tmp;}
+CONSTCD14 inline day& day::operator--() NOEXCEPT {--d_; return *this;}
+CONSTCD14 inline day day::operator--(int) NOEXCEPT {auto tmp(*this); --(*this); return tmp;}
+CONSTCD14 inline day& day::operator+=(const days& d) NOEXCEPT {*this = *this + d; return *this;}
+CONSTCD14 inline day& day::operator-=(const days& d) NOEXCEPT {*this = *this - d; return *this;}
+CONSTCD11 inline day::operator unsigned() const NOEXCEPT {return d_;}
+CONSTCD11 inline bool day::ok() const NOEXCEPT {return 1 <= d_ && d_ <= 31;}
+
+CONSTCD11
+inline
+bool
+operator==(const day& x, const day& y) NOEXCEPT
+{
+ return static_cast<unsigned>(x) == static_cast<unsigned>(y);
+}
+
+CONSTCD11
+inline
+bool
+operator!=(const day& x, const day& y) NOEXCEPT
+{
+ return !(x == y);
+}
+
+CONSTCD11
+inline
+bool
+operator<(const day& x, const day& y) NOEXCEPT
+{
+ return static_cast<unsigned>(x) < static_cast<unsigned>(y);
+}
+
+CONSTCD11
+inline
+bool
+operator>(const day& x, const day& y) NOEXCEPT
+{
+ return y < x;
+}
+
+CONSTCD11
+inline
+bool
+operator<=(const day& x, const day& y) NOEXCEPT
+{
+ return !(y < x);
+}
+
+CONSTCD11
+inline
+bool
+operator>=(const day& x, const day& y) NOEXCEPT
+{
+ return !(x < y);
+}
+
+CONSTCD11
+inline
+days
+operator-(const day& x, const day& y) NOEXCEPT
+{
+ return days{static_cast<days::rep>(static_cast<unsigned>(x)
+ - static_cast<unsigned>(y))};
+}
+
+CONSTCD11
+inline
+day
+operator+(const day& x, const days& y) NOEXCEPT
+{
+ return day{static_cast<unsigned>(x) + static_cast<unsigned>(y.count())};
+}
+
+CONSTCD11
+inline
+day
+operator+(const days& x, const day& y) NOEXCEPT
+{
+ return y + x;
+}
+
+CONSTCD11
+inline
+day
+operator-(const day& x, const days& y) NOEXCEPT
+{
+ return x + -y;
+}
+
+template<class CharT, class Traits>
+inline
+std::basic_ostream<CharT, Traits>&
+operator<<(std::basic_ostream<CharT, Traits>& os, const day& d)
+{
+ date::detail::save_stream<CharT, Traits> _(os);
+ os.fill('0');
+ os.flags(std::ios::dec | std::ios::right);
+ os.width(2);
+ os << static_cast<unsigned>(d);
+ return os;
+}
+
+// month
+
+CONSTCD11 inline month::month(unsigned m) NOEXCEPT : m_(static_cast<decltype(m_)>(m)) {}
+CONSTCD14 inline month& month::operator++() NOEXCEPT {if (++m_ == 13) m_ = 1; return *this;}
+CONSTCD14 inline month month::operator++(int) NOEXCEPT {auto tmp(*this); ++(*this); return tmp;}
+CONSTCD14 inline month& month::operator--() NOEXCEPT {if (--m_ == 0) m_ = 12; return *this;}
+CONSTCD14 inline month month::operator--(int) NOEXCEPT {auto tmp(*this); --(*this); return tmp;}
+
+CONSTCD14
+inline
+month&
+month::operator+=(const months& m) NOEXCEPT
+{
+ *this = *this + m;
+ return *this;
+}
+
+CONSTCD14
+inline
+month&
+month::operator-=(const months& m) NOEXCEPT
+{
+ *this = *this - m;
+ return *this;
+}
+
+CONSTCD11 inline month::operator unsigned() const NOEXCEPT {return m_;}
+CONSTCD11 inline bool month::ok() const NOEXCEPT {return 1 <= m_ && m_ <= 12;}
+
+CONSTCD11
+inline
+bool
+operator==(const month& x, const month& y) NOEXCEPT
+{
+ return static_cast<unsigned>(x) == static_cast<unsigned>(y);
+}
+
+CONSTCD11
+inline
+bool
+operator!=(const month& x, const month& y) NOEXCEPT
+{
+ return !(x == y);
+}
+
+CONSTCD11
+inline
+bool
+operator<(const month& x, const month& y) NOEXCEPT
+{
+ return static_cast<unsigned>(x) < static_cast<unsigned>(y);
+}
+
+CONSTCD11
+inline
+bool
+operator>(const month& x, const month& y) NOEXCEPT
+{
+ return y < x;
+}
+
+CONSTCD11
+inline
+bool
+operator<=(const month& x, const month& y) NOEXCEPT
+{
+ return !(y < x);
+}
+
+CONSTCD11
+inline
+bool
+operator>=(const month& x, const month& y) NOEXCEPT
+{
+ return !(x < y);
+}
+
+CONSTCD14
+inline
+months
+operator-(const month& x, const month& y) NOEXCEPT
+{
+ auto const d = static_cast<unsigned>(x) - static_cast<unsigned>(y);
+ return months(d <= 11 ? d : d + 12);
+}
+
+CONSTCD14
+inline
+month
+operator+(const month& x, const months& y) NOEXCEPT
+{
+ auto const mu = static_cast<long long>(static_cast<unsigned>(x)) - 1 + y.count();
+ auto const yr = (mu >= 0 ? mu : mu-11) / 12;
+ return month{static_cast<unsigned>(mu - yr * 12 + 1)};
+}
+
+CONSTCD14
+inline
+month
+operator+(const months& x, const month& y) NOEXCEPT
+{
+ return y + x;
+}
+
+CONSTCD14
+inline
+month
+operator-(const month& x, const months& y) NOEXCEPT
+{
+ return x + -y;
+}
+
+template<class CharT, class Traits>
+inline
+std::basic_ostream<CharT, Traits>&
+operator<<(std::basic_ostream<CharT, Traits>& os, const month& m)
+{
+ switch (static_cast<unsigned>(m))
+ {
+ case 1:
+ os << "Jan";
+ break;
+ case 2:
+ os << "Feb";
+ break;
+ case 3:
+ os << "Mar";
+ break;
+ case 4:
+ os << "Apr";
+ break;
+ case 5:
+ os << "May";
+ break;
+ case 6:
+ os << "Jun";
+ break;
+ case 7:
+ os << "Jul";
+ break;
+ case 8:
+ os << "Aug";
+ break;
+ case 9:
+ os << "Sep";
+ break;
+ case 10:
+ os << "Oct";
+ break;
+ case 11:
+ os << "Nov";
+ break;
+ case 12:
+ os << "Dec";
+ break;
+ default:
+ os << static_cast<unsigned>(m) << " is not a valid month";
+ break;
+ }
+ return os;
+}
+
+// year
+
+CONSTCD11 inline year::year(int y) NOEXCEPT : y_(static_cast<decltype(y_)>(y)) {}
+CONSTCD14 inline year& year::operator++() NOEXCEPT {++y_; return *this;}
+CONSTCD14 inline year year::operator++(int) NOEXCEPT {auto tmp(*this); ++(*this); return tmp;}
+CONSTCD14 inline year& year::operator--() NOEXCEPT {--y_; return *this;}
+CONSTCD14 inline year year::operator--(int) NOEXCEPT {auto tmp(*this); --(*this); return tmp;}
+CONSTCD14 inline year& year::operator+=(const years& y) NOEXCEPT {*this = *this + y; return *this;}
+CONSTCD14 inline year& year::operator-=(const years& y) NOEXCEPT {*this = *this - y; return *this;}
+
+CONSTCD11
+inline
+bool
+year::is_leap() const NOEXCEPT
+{
+ return y_ % 4 == 0;
+}
+
+CONSTCD11 inline year::operator int() const NOEXCEPT {return y_;}
+CONSTCD11 inline bool year::ok() const NOEXCEPT {return true;}
+
+CONSTCD11
+inline
+year
+year::min() NOEXCEPT
+{
+ return year{std::numeric_limits<short>::min()};
+}
+
+CONSTCD11
+inline
+year
+year::max() NOEXCEPT
+{
+ return year{std::numeric_limits<short>::max()};
+}
+
+CONSTCD11
+inline
+bool
+operator==(const year& x, const year& y) NOEXCEPT
+{
+ return static_cast<int>(x) == static_cast<int>(y);
+}
+
+CONSTCD11
+inline
+bool
+operator!=(const year& x, const year& y) NOEXCEPT
+{
+ return !(x == y);
+}
+
+CONSTCD11
+inline
+bool
+operator<(const year& x, const year& y) NOEXCEPT
+{
+ return static_cast<int>(x) < static_cast<int>(y);
+}
+
+CONSTCD11
+inline
+bool
+operator>(const year& x, const year& y) NOEXCEPT
+{
+ return y < x;
+}
+
+CONSTCD11
+inline
+bool
+operator<=(const year& x, const year& y) NOEXCEPT
+{
+ return !(y < x);
+}
+
+CONSTCD11
+inline
+bool
+operator>=(const year& x, const year& y) NOEXCEPT
+{
+ return !(x < y);
+}
+
+CONSTCD11
+inline
+years
+operator-(const year& x, const year& y) NOEXCEPT
+{
+ return years{static_cast<int>(x) - static_cast<int>(y)};
+}
+
+CONSTCD11
+inline
+year
+operator+(const year& x, const years& y) NOEXCEPT
+{
+ return year{static_cast<int>(x) + y.count()};
+}
+
+CONSTCD11
+inline
+year
+operator+(const years& x, const year& y) NOEXCEPT
+{
+ return y + x;
+}
+
+CONSTCD11
+inline
+year
+operator-(const year& x, const years& y) NOEXCEPT
+{
+ return year{static_cast<int>(x) - y.count()};
+}
+
+template<class CharT, class Traits>
+inline
+std::basic_ostream<CharT, Traits>&
+operator<<(std::basic_ostream<CharT, Traits>& os, const year& y)
+{
+ date::detail::save_stream<CharT, Traits> _(os);
+ os.fill('0');
+ os.flags(std::ios::dec | std::ios::internal);
+ os.width(4 + (y < year{0}));
+ os << static_cast<int>(y);
+ return os;
+}
+
+// weekday
+
+CONSTCD11
+inline
+unsigned char
+weekday::weekday_from_days(int z) NOEXCEPT
+{
+ return static_cast<unsigned char>(static_cast<unsigned>(
+ z >= -4 ? (z+4) % 7 : (z+5) % 7 + 6));
+}
+
+CONSTCD11
+inline
+weekday::weekday(unsigned wd) NOEXCEPT
+ : wd_(static_cast<decltype(wd_)>(wd))
+ {}
+
+CONSTCD11
+inline
+weekday::weekday(const sys_days& dp) NOEXCEPT
+ : wd_(weekday_from_days(dp.time_since_epoch().count()))
+ {}
+
+CONSTCD11
+inline
+weekday::weekday(const local_days& dp) NOEXCEPT
+ : wd_(weekday_from_days(dp.time_since_epoch().count()))
+ {}
+
+CONSTCD14 inline weekday& weekday::operator++() NOEXCEPT {if (++wd_ == 7) wd_ = 0; return *this;}
+CONSTCD14 inline weekday weekday::operator++(int) NOEXCEPT {auto tmp(*this); ++(*this); return tmp;}
+CONSTCD14 inline weekday& weekday::operator--() NOEXCEPT {if (wd_-- == 0) wd_ = 6; return *this;}
+CONSTCD14 inline weekday weekday::operator--(int) NOEXCEPT {auto tmp(*this); --(*this); return tmp;}
+
+CONSTCD14
+inline
+weekday&
+weekday::operator+=(const days& d) NOEXCEPT
+{
+ *this = *this + d;
+ return *this;
+}
+
+CONSTCD14
+inline
+weekday&
+weekday::operator-=(const days& d) NOEXCEPT
+{
+ *this = *this - d;
+ return *this;
+}
+
+CONSTCD11
+inline
+weekday::operator unsigned() const NOEXCEPT
+{
+ return static_cast<unsigned>(wd_);
+}
+
+CONSTCD11 inline bool weekday::ok() const NOEXCEPT {return wd_ <= 6;}
+
+CONSTCD11
+inline
+bool
+operator==(const weekday& x, const weekday& y) NOEXCEPT
+{
+ return static_cast<unsigned>(x) == static_cast<unsigned>(y);
+}
+
+CONSTCD11
+inline
+bool
+operator!=(const weekday& x, const weekday& y) NOEXCEPT
+{
+ return !(x == y);
+}
+
+CONSTCD14
+inline
+days
+operator-(const weekday& x, const weekday& y) NOEXCEPT
+{
+ auto const diff = static_cast<unsigned>(x) - static_cast<unsigned>(y);
+ return days{diff <= 6 ? diff : diff + 7};
+}
+
+CONSTCD14
+inline
+weekday
+operator+(const weekday& x, const days& y) NOEXCEPT
+{
+ auto const wdu = static_cast<long long>(static_cast<unsigned>(x)) + y.count();
+ auto const wk = (wdu >= 0 ? wdu : wdu-6) / 7;
+ return weekday{static_cast<unsigned>(wdu - wk * 7)};
+}
+
+CONSTCD14
+inline
+weekday
+operator+(const days& x, const weekday& y) NOEXCEPT
+{
+ return y + x;
+}
+
+CONSTCD14
+inline
+weekday
+operator-(const weekday& x, const days& y) NOEXCEPT
+{
+ return x + -y;
+}
+
+template<class CharT, class Traits>
+inline
+std::basic_ostream<CharT, Traits>&
+operator<<(std::basic_ostream<CharT, Traits>& os, const weekday& wd)
+{
+ switch (static_cast<unsigned>(wd))
+ {
+ case 0:
+ os << "Sun";
+ break;
+ case 1:
+ os << "Mon";
+ break;
+ case 2:
+ os << "Tue";
+ break;
+ case 3:
+ os << "Wed";
+ break;
+ case 4:
+ os << "Thu";
+ break;
+ case 5:
+ os << "Fri";
+ break;
+ case 6:
+ os << "Sat";
+ break;
+ default:
+ os << static_cast<unsigned>(wd) << " is not a valid weekday";
+ break;
+ }
+ return os;
+}
+
+#if !defined(_MSC_VER) || (_MSC_VER >= 1900)
+inline namespace literals
+{
+
+CONSTCD11
+inline
+julian::day
+operator "" _d(unsigned long long d) NOEXCEPT
+{
+ return julian::day{static_cast<unsigned>(d)};
+}
+
+CONSTCD11
+inline
+julian::year
+operator "" _y(unsigned long long y) NOEXCEPT
+{
+ return julian::year(static_cast<int>(y));
+}
+#endif // !defined(_MSC_VER) || (_MSC_VER >= 1900)
+
+CONSTDATA julian::last_spec last{};
+
+CONSTDATA julian::month jan{1};
+CONSTDATA julian::month feb{2};
+CONSTDATA julian::month mar{3};
+CONSTDATA julian::month apr{4};
+CONSTDATA julian::month may{5};
+CONSTDATA julian::month jun{6};
+CONSTDATA julian::month jul{7};
+CONSTDATA julian::month aug{8};
+CONSTDATA julian::month sep{9};
+CONSTDATA julian::month oct{10};
+CONSTDATA julian::month nov{11};
+CONSTDATA julian::month dec{12};
+
+CONSTDATA julian::weekday sun{0u};
+CONSTDATA julian::weekday mon{1u};
+CONSTDATA julian::weekday tue{2u};
+CONSTDATA julian::weekday wed{3u};
+CONSTDATA julian::weekday thu{4u};
+CONSTDATA julian::weekday fri{5u};
+CONSTDATA julian::weekday sat{6u};
+
+#if !defined(_MSC_VER) || (_MSC_VER >= 1900)
+} // inline namespace literals
+#endif
+
+// weekday_indexed
+
+CONSTCD11
+inline
+weekday
+weekday_indexed::weekday() const NOEXCEPT
+{
+ return julian::weekday{static_cast<unsigned>(wd_)};
+}
+
+CONSTCD11 inline unsigned weekday_indexed::index() const NOEXCEPT {return index_;}
+
+CONSTCD11
+inline
+bool
+weekday_indexed::ok() const NOEXCEPT
+{
+ return weekday().ok() && 1 <= index_ && index_ <= 5;
+}
+
+CONSTCD11
+inline
+weekday_indexed::weekday_indexed(const julian::weekday& wd, unsigned index) NOEXCEPT
+ : wd_(static_cast<decltype(wd_)>(static_cast<unsigned>(wd)))
+ , index_(static_cast<decltype(index_)>(index))
+ {}
+
+template<class CharT, class Traits>
+inline
+std::basic_ostream<CharT, Traits>&
+operator<<(std::basic_ostream<CharT, Traits>& os, const weekday_indexed& wdi)
+{
+ return os << wdi.weekday() << '[' << wdi.index() << ']';
+}
+
+CONSTCD11
+inline
+weekday_indexed
+weekday::operator[](unsigned index) const NOEXCEPT
+{
+ return {*this, index};
+}
+
+CONSTCD11
+inline
+bool
+operator==(const weekday_indexed& x, const weekday_indexed& y) NOEXCEPT
+{
+ return x.weekday() == y.weekday() && x.index() == y.index();
+}
+
+CONSTCD11
+inline
+bool
+operator!=(const weekday_indexed& x, const weekday_indexed& y) NOEXCEPT
+{
+ return !(x == y);
+}
+
+// weekday_last
+
+CONSTCD11 inline julian::weekday weekday_last::weekday() const NOEXCEPT {return wd_;}
+CONSTCD11 inline bool weekday_last::ok() const NOEXCEPT {return wd_.ok();}
+CONSTCD11 inline weekday_last::weekday_last(const julian::weekday& wd) NOEXCEPT : wd_(wd) {}
+
+CONSTCD11
+inline
+bool
+operator==(const weekday_last& x, const weekday_last& y) NOEXCEPT
+{
+ return x.weekday() == y.weekday();
+}
+
+CONSTCD11
+inline
+bool
+operator!=(const weekday_last& x, const weekday_last& y) NOEXCEPT
+{
+ return !(x == y);
+}
+
+template<class CharT, class Traits>
+inline
+std::basic_ostream<CharT, Traits>&
+operator<<(std::basic_ostream<CharT, Traits>& os, const weekday_last& wdl)
+{
+ return os << wdl.weekday() << "[last]";
+}
+
+CONSTCD11
+inline
+weekday_last
+weekday::operator[](last_spec) const NOEXCEPT
+{
+ return weekday_last{*this};
+}
+
+// year_month
+
+CONSTCD11
+inline
+year_month::year_month(const julian::year& y, const julian::month& m) NOEXCEPT
+ : y_(y)
+ , m_(m)
+ {}
+
+CONSTCD11 inline year year_month::year() const NOEXCEPT {return y_;}
+CONSTCD11 inline month year_month::month() const NOEXCEPT {return m_;}
+CONSTCD11 inline bool year_month::ok() const NOEXCEPT {return y_.ok() && m_.ok();}
+
+CONSTCD14
+inline
+year_month&
+year_month::operator+=(const months& dm) NOEXCEPT
+{
+ *this = *this + dm;
+ return *this;
+}
+
+CONSTCD14
+inline
+year_month&
+year_month::operator-=(const months& dm) NOEXCEPT
+{
+ *this = *this - dm;
+ return *this;
+}
+
+CONSTCD14
+inline
+year_month&
+year_month::operator+=(const years& dy) NOEXCEPT
+{
+ *this = *this + dy;
+ return *this;
+}
+
+CONSTCD14
+inline
+year_month&
+year_month::operator-=(const years& dy) NOEXCEPT
+{
+ *this = *this - dy;
+ return *this;
+}
+
+CONSTCD11
+inline
+bool
+operator==(const year_month& x, const year_month& y) NOEXCEPT
+{
+ return x.year() == y.year() && x.month() == y.month();
+}
+
+CONSTCD11
+inline
+bool
+operator!=(const year_month& x, const year_month& y) NOEXCEPT
+{
+ return !(x == y);
+}
+
+CONSTCD11
+inline
+bool
+operator<(const year_month& x, const year_month& y) NOEXCEPT
+{
+ return x.year() < y.year() ? true
+ : (x.year() > y.year() ? false
+ : (x.month() < y.month()));
+}
+
+CONSTCD11
+inline
+bool
+operator>(const year_month& x, const year_month& y) NOEXCEPT
+{
+ return y < x;
+}
+
+CONSTCD11
+inline
+bool
+operator<=(const year_month& x, const year_month& y) NOEXCEPT
+{
+ return !(y < x);
+}
+
+CONSTCD11
+inline
+bool
+operator>=(const year_month& x, const year_month& y) NOEXCEPT
+{
+ return !(x < y);
+}
+
+CONSTCD14
+inline
+year_month
+operator+(const year_month& ym, const months& dm) NOEXCEPT
+{
+ auto dmi = static_cast<int>(static_cast<unsigned>(ym.month())) - 1 + dm.count();
+ auto dy = (dmi >= 0 ? dmi : dmi-11) / 12;
+ dmi = dmi - dy * 12 + 1;
+ return (ym.year() + years(dy)) / month(static_cast<unsigned>(dmi));
+}
+
+CONSTCD14
+inline
+year_month
+operator+(const months& dm, const year_month& ym) NOEXCEPT
+{
+ return ym + dm;
+}
+
+CONSTCD14
+inline
+year_month
+operator-(const year_month& ym, const months& dm) NOEXCEPT
+{
+ return ym + -dm;
+}
+
+CONSTCD11
+inline
+months
+operator-(const year_month& x, const year_month& y) NOEXCEPT
+{
+ return (x.year() - y.year()) +
+ months(static_cast<unsigned>(x.month()) - static_cast<unsigned>(y.month()));
+}
+
+CONSTCD11
+inline
+year_month
+operator+(const year_month& ym, const years& dy) NOEXCEPT
+{
+ return (ym.year() + dy) / ym.month();
+}
+
+CONSTCD11
+inline
+year_month
+operator+(const years& dy, const year_month& ym) NOEXCEPT
+{
+ return ym + dy;
+}
+
+CONSTCD11
+inline
+year_month
+operator-(const year_month& ym, const years& dy) NOEXCEPT
+{
+ return ym + -dy;
+}
+
+template<class CharT, class Traits>
+inline
+std::basic_ostream<CharT, Traits>&
+operator<<(std::basic_ostream<CharT, Traits>& os, const year_month& ym)
+{
+ return os << ym.year() << '/' << ym.month();
+}
+
+// month_day
+
+CONSTCD11
+inline
+month_day::month_day(const julian::month& m, const julian::day& d) NOEXCEPT
+ : m_(m)
+ , d_(d)
+ {}
+
+CONSTCD11 inline julian::month month_day::month() const NOEXCEPT {return m_;}
+CONSTCD11 inline julian::day month_day::day() const NOEXCEPT {return d_;}
+
+CONSTCD14
+inline
+bool
+month_day::ok() const NOEXCEPT
+{
+ CONSTDATA julian::day d[] =
+ {31_d, 29_d, 31_d, 30_d, 31_d, 30_d, 31_d, 31_d, 30_d, 31_d, 30_d, 31_d};
+ return m_.ok() && 1_d <= d_ && d_ <= d[static_cast<unsigned>(m_)-1];
+}
+
+CONSTCD11
+inline
+bool
+operator==(const month_day& x, const month_day& y) NOEXCEPT
+{
+ return x.month() == y.month() && x.day() == y.day();
+}
+
+CONSTCD11
+inline
+bool
+operator!=(const month_day& x, const month_day& y) NOEXCEPT
+{
+ return !(x == y);
+}
+
+CONSTCD11
+inline
+bool
+operator<(const month_day& x, const month_day& y) NOEXCEPT
+{
+ return x.month() < y.month() ? true
+ : (x.month() > y.month() ? false
+ : (x.day() < y.day()));
+}
+
+CONSTCD11
+inline
+bool
+operator>(const month_day& x, const month_day& y) NOEXCEPT
+{
+ return y < x;
+}
+
+CONSTCD11
+inline
+bool
+operator<=(const month_day& x, const month_day& y) NOEXCEPT
+{
+ return !(y < x);
+}
+
+CONSTCD11
+inline
+bool
+operator>=(const month_day& x, const month_day& y) NOEXCEPT
+{
+ return !(x < y);
+}
+
+template<class CharT, class Traits>
+inline
+std::basic_ostream<CharT, Traits>&
+operator<<(std::basic_ostream<CharT, Traits>& os, const month_day& md)
+{
+ return os << md.month() << '/' << md.day();
+}
+
+// month_day_last
+
+CONSTCD11 inline month month_day_last::month() const NOEXCEPT {return m_;}
+CONSTCD11 inline bool month_day_last::ok() const NOEXCEPT {return m_.ok();}
+CONSTCD11 inline month_day_last::month_day_last(const julian::month& m) NOEXCEPT : m_(m) {}
+
+CONSTCD11
+inline
+bool
+operator==(const month_day_last& x, const month_day_last& y) NOEXCEPT
+{
+ return x.month() == y.month();
+}
+
+CONSTCD11
+inline
+bool
+operator!=(const month_day_last& x, const month_day_last& y) NOEXCEPT
+{
+ return !(x == y);
+}
+
+CONSTCD11
+inline
+bool
+operator<(const month_day_last& x, const month_day_last& y) NOEXCEPT
+{
+ return x.month() < y.month();
+}
+
+CONSTCD11
+inline
+bool
+operator>(const month_day_last& x, const month_day_last& y) NOEXCEPT
+{
+ return y < x;
+}
+
+CONSTCD11
+inline
+bool
+operator<=(const month_day_last& x, const month_day_last& y) NOEXCEPT
+{
+ return !(y < x);
+}
+
+CONSTCD11
+inline
+bool
+operator>=(const month_day_last& x, const month_day_last& y) NOEXCEPT
+{
+ return !(x < y);
+}
+
+template<class CharT, class Traits>
+inline
+std::basic_ostream<CharT, Traits>&
+operator<<(std::basic_ostream<CharT, Traits>& os, const month_day_last& mdl)
+{
+ return os << mdl.month() << "/last";
+}
+
+// month_weekday
+
+CONSTCD11
+inline
+month_weekday::month_weekday(const julian::month& m,
+ const julian::weekday_indexed& wdi) NOEXCEPT
+ : m_(m)
+ , wdi_(wdi)
+ {}
+
+CONSTCD11 inline month month_weekday::month() const NOEXCEPT {return m_;}
+
+CONSTCD11
+inline
+weekday_indexed
+month_weekday::weekday_indexed() const NOEXCEPT
+{
+ return wdi_;
+}
+
+CONSTCD11
+inline
+bool
+month_weekday::ok() const NOEXCEPT
+{
+ return m_.ok() && wdi_.ok();
+}
+
+CONSTCD11
+inline
+bool
+operator==(const month_weekday& x, const month_weekday& y) NOEXCEPT
+{
+ return x.month() == y.month() && x.weekday_indexed() == y.weekday_indexed();
+}
+
+CONSTCD11
+inline
+bool
+operator!=(const month_weekday& x, const month_weekday& y) NOEXCEPT
+{
+ return !(x == y);
+}
+
+template<class CharT, class Traits>
+inline
+std::basic_ostream<CharT, Traits>&
+operator<<(std::basic_ostream<CharT, Traits>& os, const month_weekday& mwd)
+{
+ return os << mwd.month() << '/' << mwd.weekday_indexed();
+}
+
+// month_weekday_last
+
+CONSTCD11
+inline
+month_weekday_last::month_weekday_last(const julian::month& m,
+ const julian::weekday_last& wdl) NOEXCEPT
+ : m_(m)
+ , wdl_(wdl)
+ {}
+
+CONSTCD11 inline month month_weekday_last::month() const NOEXCEPT {return m_;}
+
+CONSTCD11
+inline
+weekday_last
+month_weekday_last::weekday_last() const NOEXCEPT
+{
+ return wdl_;
+}
+
+CONSTCD11
+inline
+bool
+month_weekday_last::ok() const NOEXCEPT
+{
+ return m_.ok() && wdl_.ok();
+}
+
+CONSTCD11
+inline
+bool
+operator==(const month_weekday_last& x, const month_weekday_last& y) NOEXCEPT
+{
+ return x.month() == y.month() && x.weekday_last() == y.weekday_last();
+}
+
+CONSTCD11
+inline
+bool
+operator!=(const month_weekday_last& x, const month_weekday_last& y) NOEXCEPT
+{
+ return !(x == y);
+}
+
+template<class CharT, class Traits>
+inline
+std::basic_ostream<CharT, Traits>&
+operator<<(std::basic_ostream<CharT, Traits>& os, const month_weekday_last& mwdl)
+{
+ return os << mwdl.month() << '/' << mwdl.weekday_last();
+}
+
+// year_month_day_last
+
+CONSTCD11
+inline
+year_month_day_last::year_month_day_last(const julian::year& y,
+ const julian::month_day_last& mdl) NOEXCEPT
+ : y_(y)
+ , mdl_(mdl)
+ {}
+
+CONSTCD14
+inline
+year_month_day_last&
+year_month_day_last::operator+=(const months& m) NOEXCEPT
+{
+ *this = *this + m;
+ return *this;
+}
+
+CONSTCD14
+inline
+year_month_day_last&
+year_month_day_last::operator-=(const months& m) NOEXCEPT
+{
+ *this = *this - m;
+ return *this;
+}
+
+CONSTCD14
+inline
+year_month_day_last&
+year_month_day_last::operator+=(const years& y) NOEXCEPT
+{
+ *this = *this + y;
+ return *this;
+}
+
+CONSTCD14
+inline
+year_month_day_last&
+year_month_day_last::operator-=(const years& y) NOEXCEPT
+{
+ *this = *this - y;
+ return *this;
+}
+
+CONSTCD11 inline year year_month_day_last::year() const NOEXCEPT {return y_;}
+CONSTCD11 inline month year_month_day_last::month() const NOEXCEPT {return mdl_.month();}
+
+CONSTCD11
+inline
+month_day_last
+year_month_day_last::month_day_last() const NOEXCEPT
+{
+ return mdl_;
+}
+
+CONSTCD14
+inline
+day
+year_month_day_last::day() const NOEXCEPT
+{
+ CONSTDATA julian::day d[] =
+ {31_d, 28_d, 31_d, 30_d, 31_d, 30_d, 31_d, 31_d, 30_d, 31_d, 30_d, 31_d};
+ return month() != feb || !y_.is_leap() ? d[static_cast<unsigned>(month())-1] : 29_d;
+}
+
+CONSTCD14
+inline
+year_month_day_last::operator sys_days() const NOEXCEPT
+{
+ return sys_days(year()/month()/day());
+}
+
+CONSTCD14
+inline
+year_month_day_last::operator local_days() const NOEXCEPT
+{
+ return local_days(year()/month()/day());
+}
+
+CONSTCD11
+inline
+bool
+year_month_day_last::ok() const NOEXCEPT
+{
+ return y_.ok() && mdl_.ok();
+}
+
+CONSTCD11
+inline
+bool
+operator==(const year_month_day_last& x, const year_month_day_last& y) NOEXCEPT
+{
+ return x.year() == y.year() && x.month_day_last() == y.month_day_last();
+}
+
+CONSTCD11
+inline
+bool
+operator!=(const year_month_day_last& x, const year_month_day_last& y) NOEXCEPT
+{
+ return !(x == y);
+}
+
+CONSTCD11
+inline
+bool
+operator<(const year_month_day_last& x, const year_month_day_last& y) NOEXCEPT
+{
+ return x.year() < y.year() ? true
+ : (x.year() > y.year() ? false
+ : (x.month_day_last() < y.month_day_last()));
+}
+
+CONSTCD11
+inline
+bool
+operator>(const year_month_day_last& x, const year_month_day_last& y) NOEXCEPT
+{
+ return y < x;
+}
+
+CONSTCD11
+inline
+bool
+operator<=(const year_month_day_last& x, const year_month_day_last& y) NOEXCEPT
+{
+ return !(y < x);
+}
+
+CONSTCD11
+inline
+bool
+operator>=(const year_month_day_last& x, const year_month_day_last& y) NOEXCEPT
+{
+ return !(x < y);
+}
+
+template<class CharT, class Traits>
+inline
+std::basic_ostream<CharT, Traits>&
+operator<<(std::basic_ostream<CharT, Traits>& os, const year_month_day_last& ymdl)
+{
+ return os << ymdl.year() << '/' << ymdl.month_day_last();
+}
+
+CONSTCD14
+inline
+year_month_day_last
+operator+(const year_month_day_last& ymdl, const months& dm) NOEXCEPT
+{
+ return (ymdl.year() / ymdl.month() + dm) / last;
+}
+
+CONSTCD14
+inline
+year_month_day_last
+operator+(const months& dm, const year_month_day_last& ymdl) NOEXCEPT
+{
+ return ymdl + dm;
+}
+
+CONSTCD14
+inline
+year_month_day_last
+operator-(const year_month_day_last& ymdl, const months& dm) NOEXCEPT
+{
+ return ymdl + (-dm);
+}
+
+CONSTCD11
+inline
+year_month_day_last
+operator+(const year_month_day_last& ymdl, const years& dy) NOEXCEPT
+{
+ return {ymdl.year()+dy, ymdl.month_day_last()};
+}
+
+CONSTCD11
+inline
+year_month_day_last
+operator+(const years& dy, const year_month_day_last& ymdl) NOEXCEPT
+{
+ return ymdl + dy;
+}
+
+CONSTCD11
+inline
+year_month_day_last
+operator-(const year_month_day_last& ymdl, const years& dy) NOEXCEPT
+{
+ return ymdl + (-dy);
+}
+
+// year_month_day
+
+CONSTCD11
+inline
+year_month_day::year_month_day(const julian::year& y, const julian::month& m,
+ const julian::day& d) NOEXCEPT
+ : y_(y)
+ , m_(m)
+ , d_(d)
+ {}
+
+CONSTCD14
+inline
+year_month_day::year_month_day(const year_month_day_last& ymdl) NOEXCEPT
+ : y_(ymdl.year())
+ , m_(ymdl.month())
+ , d_(ymdl.day())
+ {}
+
+CONSTCD14
+inline
+year_month_day::year_month_day(sys_days dp) NOEXCEPT
+ : year_month_day(from_days(dp.time_since_epoch()))
+ {}
+
+CONSTCD14
+inline
+year_month_day::year_month_day(local_days dp) NOEXCEPT
+ : year_month_day(from_days(dp.time_since_epoch()))
+ {}
+
+CONSTCD11 inline year year_month_day::year() const NOEXCEPT {return y_;}
+CONSTCD11 inline month year_month_day::month() const NOEXCEPT {return m_;}
+CONSTCD11 inline day year_month_day::day() const NOEXCEPT {return d_;}
+
+CONSTCD14
+inline
+year_month_day&
+year_month_day::operator+=(const months& m) NOEXCEPT
+{
+ *this = *this + m;
+ return *this;
+}
+
+CONSTCD14
+inline
+year_month_day&
+year_month_day::operator-=(const months& m) NOEXCEPT
+{
+ *this = *this - m;
+ return *this;
+}
+
+CONSTCD14
+inline
+year_month_day&
+year_month_day::operator+=(const years& y) NOEXCEPT
+{
+ *this = *this + y;
+ return *this;
+}
+
+CONSTCD14
+inline
+year_month_day&
+year_month_day::operator-=(const years& y) NOEXCEPT
+{
+ *this = *this - y;
+ return *this;
+}
+
+CONSTCD14
+inline
+days
+year_month_day::to_days() const NOEXCEPT
+{
+ static_assert(std::numeric_limits<unsigned>::digits >= 18,
+ "This algorithm has not been ported to a 16 bit unsigned integer");
+ static_assert(std::numeric_limits<int>::digits >= 20,
+ "This algorithm has not been ported to a 16 bit signed integer");
+ auto const y = static_cast<int>(y_) - (m_ <= feb);
+ auto const m = static_cast<unsigned>(m_);
+ auto const d = static_cast<unsigned>(d_);
+ auto const era = (y >= 0 ? y : y-3) / 4;
+ auto const yoe = static_cast<unsigned>(y - era * 4); // [0, 3]
+ auto const doy = (153*(m > 2 ? m-3 : m+9) + 2)/5 + d-1; // [0, 365]
+ auto const doe = yoe * 365 + doy; // [0, 1460]
+ return days{era * 1461 + static_cast<int>(doe) - 719470};
+}
+
+CONSTCD14
+inline
+year_month_day::operator sys_days() const NOEXCEPT
+{
+ return sys_days{to_days()};
+}
+
+CONSTCD14
+inline
+year_month_day::operator local_days() const NOEXCEPT
+{
+ return local_days{to_days()};
+}
+
+CONSTCD14
+inline
+bool
+year_month_day::ok() const NOEXCEPT
+{
+ if (!(y_.ok() && m_.ok()))
+ return false;
+ return 1_d <= d_ && d_ <= (y_/m_/last).day();
+}
+
+CONSTCD11
+inline
+bool
+operator==(const year_month_day& x, const year_month_day& y) NOEXCEPT
+{
+ return x.year() == y.year() && x.month() == y.month() && x.day() == y.day();
+}
+
+CONSTCD11
+inline
+bool
+operator!=(const year_month_day& x, const year_month_day& y) NOEXCEPT
+{
+ return !(x == y);
+}
+
+CONSTCD11
+inline
+bool
+operator<(const year_month_day& x, const year_month_day& y) NOEXCEPT
+{
+ return x.year() < y.year() ? true
+ : (x.year() > y.year() ? false
+ : (x.month() < y.month() ? true
+ : (x.month() > y.month() ? false
+ : (x.day() < y.day()))));
+}
+
+CONSTCD11
+inline
+bool
+operator>(const year_month_day& x, const year_month_day& y) NOEXCEPT
+{
+ return y < x;
+}
+
+CONSTCD11
+inline
+bool
+operator<=(const year_month_day& x, const year_month_day& y) NOEXCEPT
+{
+ return !(y < x);
+}
+
+CONSTCD11
+inline
+bool
+operator>=(const year_month_day& x, const year_month_day& y) NOEXCEPT
+{
+ return !(x < y);
+}
+
+template<class CharT, class Traits>
+inline
+std::basic_ostream<CharT, Traits>&
+operator<<(std::basic_ostream<CharT, Traits>& os, const year_month_day& ymd)
+{
+ date::detail::save_stream<CharT, Traits> _(os);
+ os.fill('0');
+ os.flags(std::ios::dec | std::ios::right);
+ os << ymd.year() << '-';
+ os.width(2);
+ os << static_cast<unsigned>(ymd.month()) << '-';
+ os << ymd.day();
+ return os;
+}
+
+CONSTCD14
+inline
+year_month_day
+year_month_day::from_days(days dp) NOEXCEPT
+{
+ static_assert(std::numeric_limits<unsigned>::digits >= 18,
+ "This algorithm has not been ported to a 16 bit unsigned integer");
+ static_assert(std::numeric_limits<int>::digits >= 20,
+ "This algorithm has not been ported to a 16 bit signed integer");
+ auto const z = dp.count() + 719470;
+ auto const era = (z >= 0 ? z : z - 1460) / 1461;
+ auto const doe = static_cast<unsigned>(z - era * 1461); // [0, 1460]
+ auto const yoe = (doe - doe/1460) / 365; // [0, 3]
+ auto const y = static_cast<sys_days::rep>(yoe) + era * 4;
+ auto const doy = doe - 365*yoe; // [0, 365]
+ auto const mp = (5*doy + 2)/153; // [0, 11]
+ auto const d = doy - (153*mp+2)/5 + 1; // [1, 31]
+ auto const m = mp < 10 ? mp+3 : mp-9; // [1, 12]
+ return year_month_day{julian::year{y + (m <= 2)}, julian::month(m), julian::day(d)};
+}
+
+CONSTCD14
+inline
+year_month_day
+operator+(const year_month_day& ymd, const months& dm) NOEXCEPT
+{
+ return (ymd.year() / ymd.month() + dm) / ymd.day();
+}
+
+CONSTCD14
+inline
+year_month_day
+operator+(const months& dm, const year_month_day& ymd) NOEXCEPT
+{
+ return ymd + dm;
+}
+
+CONSTCD14
+inline
+year_month_day
+operator-(const year_month_day& ymd, const months& dm) NOEXCEPT
+{
+ return ymd + (-dm);
+}
+
+CONSTCD11
+inline
+year_month_day
+operator+(const year_month_day& ymd, const years& dy) NOEXCEPT
+{
+ return (ymd.year() + dy) / ymd.month() / ymd.day();
+}
+
+CONSTCD11
+inline
+year_month_day
+operator+(const years& dy, const year_month_day& ymd) NOEXCEPT
+{
+ return ymd + dy;
+}
+
+CONSTCD11
+inline
+year_month_day
+operator-(const year_month_day& ymd, const years& dy) NOEXCEPT
+{
+ return ymd + (-dy);
+}
+
+// year_month_weekday
+
+CONSTCD11
+inline
+year_month_weekday::year_month_weekday(const julian::year& y, const julian::month& m,
+ const julian::weekday_indexed& wdi)
+ NOEXCEPT
+ : y_(y)
+ , m_(m)
+ , wdi_(wdi)
+ {}
+
+CONSTCD14
+inline
+year_month_weekday::year_month_weekday(const sys_days& dp) NOEXCEPT
+ : year_month_weekday(from_days(dp.time_since_epoch()))
+ {}
+
+CONSTCD14
+inline
+year_month_weekday::year_month_weekday(const local_days& dp) NOEXCEPT
+ : year_month_weekday(from_days(dp.time_since_epoch()))
+ {}
+
+CONSTCD14
+inline
+year_month_weekday&
+year_month_weekday::operator+=(const months& m) NOEXCEPT
+{
+ *this = *this + m;
+ return *this;
+}
+
+CONSTCD14
+inline
+year_month_weekday&
+year_month_weekday::operator-=(const months& m) NOEXCEPT
+{
+ *this = *this - m;
+ return *this;
+}
+
+CONSTCD14
+inline
+year_month_weekday&
+year_month_weekday::operator+=(const years& y) NOEXCEPT
+{
+ *this = *this + y;
+ return *this;
+}
+
+CONSTCD14
+inline
+year_month_weekday&
+year_month_weekday::operator-=(const years& y) NOEXCEPT
+{
+ *this = *this - y;
+ return *this;
+}
+
+CONSTCD11 inline year year_month_weekday::year() const NOEXCEPT {return y_;}
+CONSTCD11 inline month year_month_weekday::month() const NOEXCEPT {return m_;}
+
+CONSTCD11
+inline
+weekday
+year_month_weekday::weekday() const NOEXCEPT
+{
+ return wdi_.weekday();
+}
+
+CONSTCD11
+inline
+unsigned
+year_month_weekday::index() const NOEXCEPT
+{
+ return wdi_.index();
+}
+
+CONSTCD11
+inline
+weekday_indexed
+year_month_weekday::weekday_indexed() const NOEXCEPT
+{
+ return wdi_;
+}
+
+CONSTCD14
+inline
+year_month_weekday::operator sys_days() const NOEXCEPT
+{
+ return sys_days{to_days()};
+}
+
+CONSTCD14
+inline
+year_month_weekday::operator local_days() const NOEXCEPT
+{
+ return local_days{to_days()};
+}
+
+CONSTCD14
+inline
+bool
+year_month_weekday::ok() const NOEXCEPT
+{
+ if (!y_.ok() || !m_.ok() || !wdi_.weekday().ok() || wdi_.index() < 1)
+ return false;
+ if (wdi_.index() <= 4)
+ return true;
+ auto d2 = wdi_.weekday() - julian::weekday(y_/m_/1) + days((wdi_.index()-1)*7 + 1);
+ return static_cast<unsigned>(d2.count()) <= static_cast<unsigned>((y_/m_/last).day());
+}
+
+CONSTCD14
+inline
+year_month_weekday
+year_month_weekday::from_days(days d) NOEXCEPT
+{
+ sys_days dp{d};
+ auto const wd = julian::weekday(dp);
+ auto const ymd = year_month_day(dp);
+ return {ymd.year(), ymd.month(), wd[(static_cast<unsigned>(ymd.day())-1)/7+1]};
+}
+
+CONSTCD14
+inline
+days
+year_month_weekday::to_days() const NOEXCEPT
+{
+ auto d = sys_days(y_/m_/1);
+ return (d + (wdi_.weekday() - julian::weekday(d) + days{(wdi_.index()-1)*7})
+ ).time_since_epoch();
+}
+
+CONSTCD11
+inline
+bool
+operator==(const year_month_weekday& x, const year_month_weekday& y) NOEXCEPT
+{
+ return x.year() == y.year() && x.month() == y.month() &&
+ x.weekday_indexed() == y.weekday_indexed();
+}
+
+CONSTCD11
+inline
+bool
+operator!=(const year_month_weekday& x, const year_month_weekday& y) NOEXCEPT
+{
+ return !(x == y);
+}
+
+template<class CharT, class Traits>
+inline
+std::basic_ostream<CharT, Traits>&
+operator<<(std::basic_ostream<CharT, Traits>& os, const year_month_weekday& ymwdi)
+{
+ return os << ymwdi.year() << '/' << ymwdi.month()
+ << '/' << ymwdi.weekday_indexed();
+}
+
+CONSTCD14
+inline
+year_month_weekday
+operator+(const year_month_weekday& ymwd, const months& dm) NOEXCEPT
+{
+ return (ymwd.year() / ymwd.month() + dm) / ymwd.weekday_indexed();
+}
+
+CONSTCD14
+inline
+year_month_weekday
+operator+(const months& dm, const year_month_weekday& ymwd) NOEXCEPT
+{
+ return ymwd + dm;
+}
+
+CONSTCD14
+inline
+year_month_weekday
+operator-(const year_month_weekday& ymwd, const months& dm) NOEXCEPT
+{
+ return ymwd + (-dm);
+}
+
+CONSTCD11
+inline
+year_month_weekday
+operator+(const year_month_weekday& ymwd, const years& dy) NOEXCEPT
+{
+ return {ymwd.year()+dy, ymwd.month(), ymwd.weekday_indexed()};
+}
+
+CONSTCD11
+inline
+year_month_weekday
+operator+(const years& dy, const year_month_weekday& ymwd) NOEXCEPT
+{
+ return ymwd + dy;
+}
+
+CONSTCD11
+inline
+year_month_weekday
+operator-(const year_month_weekday& ymwd, const years& dy) NOEXCEPT
+{
+ return ymwd + (-dy);
+}
+
+// year_month_weekday_last
+
+CONSTCD11
+inline
+year_month_weekday_last::year_month_weekday_last(const julian::year& y,
+ const julian::month& m,
+ const julian::weekday_last& wdl) NOEXCEPT
+ : y_(y)
+ , m_(m)
+ , wdl_(wdl)
+ {}
+
+CONSTCD14
+inline
+year_month_weekday_last&
+year_month_weekday_last::operator+=(const months& m) NOEXCEPT
+{
+ *this = *this + m;
+ return *this;
+}
+
+CONSTCD14
+inline
+year_month_weekday_last&
+year_month_weekday_last::operator-=(const months& m) NOEXCEPT
+{
+ *this = *this - m;
+ return *this;
+}
+
+CONSTCD14
+inline
+year_month_weekday_last&
+year_month_weekday_last::operator+=(const years& y) NOEXCEPT
+{
+ *this = *this + y;
+ return *this;
+}
+
+CONSTCD14
+inline
+year_month_weekday_last&
+year_month_weekday_last::operator-=(const years& y) NOEXCEPT
+{
+ *this = *this - y;
+ return *this;
+}
+
+CONSTCD11 inline year year_month_weekday_last::year() const NOEXCEPT {return y_;}
+CONSTCD11 inline month year_month_weekday_last::month() const NOEXCEPT {return m_;}
+
+CONSTCD11
+inline
+weekday
+year_month_weekday_last::weekday() const NOEXCEPT
+{
+ return wdl_.weekday();
+}
+
+CONSTCD11
+inline
+weekday_last
+year_month_weekday_last::weekday_last() const NOEXCEPT
+{
+ return wdl_;
+}
+
+CONSTCD14
+inline
+year_month_weekday_last::operator sys_days() const NOEXCEPT
+{
+ return sys_days{to_days()};
+}
+
+CONSTCD14
+inline
+year_month_weekday_last::operator local_days() const NOEXCEPT
+{
+ return local_days{to_days()};
+}
+
+CONSTCD11
+inline
+bool
+year_month_weekday_last::ok() const NOEXCEPT
+{
+ return y_.ok() && m_.ok() && wdl_.ok();
+}
+
+CONSTCD14
+inline
+days
+year_month_weekday_last::to_days() const NOEXCEPT
+{
+ auto const d = sys_days(y_/m_/last);
+ return (d - (julian::weekday{d} - wdl_.weekday())).time_since_epoch();
+}
+
+CONSTCD11
+inline
+bool
+operator==(const year_month_weekday_last& x, const year_month_weekday_last& y) NOEXCEPT
+{
+ return x.year() == y.year() && x.month() == y.month() &&
+ x.weekday_last() == y.weekday_last();
+}
+
+CONSTCD11
+inline
+bool
+operator!=(const year_month_weekday_last& x, const year_month_weekday_last& y) NOEXCEPT
+{
+ return !(x == y);
+}
+
+template<class CharT, class Traits>
+inline
+std::basic_ostream<CharT, Traits>&
+operator<<(std::basic_ostream<CharT, Traits>& os, const year_month_weekday_last& ymwdl)
+{
+ return os << ymwdl.year() << '/' << ymwdl.month() << '/' << ymwdl.weekday_last();
+}
+
+CONSTCD14
+inline
+year_month_weekday_last
+operator+(const year_month_weekday_last& ymwdl, const months& dm) NOEXCEPT
+{
+ return (ymwdl.year() / ymwdl.month() + dm) / ymwdl.weekday_last();
+}
+
+CONSTCD14
+inline
+year_month_weekday_last
+operator+(const months& dm, const year_month_weekday_last& ymwdl) NOEXCEPT
+{
+ return ymwdl + dm;
+}
+
+CONSTCD14
+inline
+year_month_weekday_last
+operator-(const year_month_weekday_last& ymwdl, const months& dm) NOEXCEPT
+{
+ return ymwdl + (-dm);
+}
+
+CONSTCD11
+inline
+year_month_weekday_last
+operator+(const year_month_weekday_last& ymwdl, const years& dy) NOEXCEPT
+{
+ return {ymwdl.year()+dy, ymwdl.month(), ymwdl.weekday_last()};
+}
+
+CONSTCD11
+inline
+year_month_weekday_last
+operator+(const years& dy, const year_month_weekday_last& ymwdl) NOEXCEPT
+{
+ return ymwdl + dy;
+}
+
+CONSTCD11
+inline
+year_month_weekday_last
+operator-(const year_month_weekday_last& ymwdl, const years& dy) NOEXCEPT
+{
+ return ymwdl + (-dy);
+}
+
+// year_month from operator/()
+
+CONSTCD11
+inline
+year_month
+operator/(const year& y, const month& m) NOEXCEPT
+{
+ return {y, m};
+}
+
+CONSTCD11
+inline
+year_month
+operator/(const year& y, int m) NOEXCEPT
+{
+ return y / month(static_cast<unsigned>(m));
+}
+
+// month_day from operator/()
+
+CONSTCD11
+inline
+month_day
+operator/(const month& m, const day& d) NOEXCEPT
+{
+ return {m, d};
+}
+
+CONSTCD11
+inline
+month_day
+operator/(const day& d, const month& m) NOEXCEPT
+{
+ return m / d;
+}
+
+CONSTCD11
+inline
+month_day
+operator/(const month& m, int d) NOEXCEPT
+{
+ return m / day(static_cast<unsigned>(d));
+}
+
+CONSTCD11
+inline
+month_day
+operator/(int m, const day& d) NOEXCEPT
+{
+ return month(static_cast<unsigned>(m)) / d;
+}
+
+CONSTCD11 inline month_day operator/(const day& d, int m) NOEXCEPT {return m / d;}
+
+// month_day_last from operator/()
+
+CONSTCD11
+inline
+month_day_last
+operator/(const month& m, last_spec) NOEXCEPT
+{
+ return month_day_last{m};
+}
+
+CONSTCD11
+inline
+month_day_last
+operator/(last_spec, const month& m) NOEXCEPT
+{
+ return m/last;
+}
+
+CONSTCD11
+inline
+month_day_last
+operator/(int m, last_spec) NOEXCEPT
+{
+ return month(static_cast<unsigned>(m))/last;
+}
+
+CONSTCD11
+inline
+month_day_last
+operator/(last_spec, int m) NOEXCEPT
+{
+ return m/last;
+}
+
+// month_weekday from operator/()
+
+CONSTCD11
+inline
+month_weekday
+operator/(const month& m, const weekday_indexed& wdi) NOEXCEPT
+{
+ return {m, wdi};
+}
+
+CONSTCD11
+inline
+month_weekday
+operator/(const weekday_indexed& wdi, const month& m) NOEXCEPT
+{
+ return m / wdi;
+}
+
+CONSTCD11
+inline
+month_weekday
+operator/(int m, const weekday_indexed& wdi) NOEXCEPT
+{
+ return month(static_cast<unsigned>(m)) / wdi;
+}
+
+CONSTCD11
+inline
+month_weekday
+operator/(const weekday_indexed& wdi, int m) NOEXCEPT
+{
+ return m / wdi;
+}
+
+// month_weekday_last from operator/()
+
+CONSTCD11
+inline
+month_weekday_last
+operator/(const month& m, const weekday_last& wdl) NOEXCEPT
+{
+ return {m, wdl};
+}
+
+CONSTCD11
+inline
+month_weekday_last
+operator/(const weekday_last& wdl, const month& m) NOEXCEPT
+{
+ return m / wdl;
+}
+
+CONSTCD11
+inline
+month_weekday_last
+operator/(int m, const weekday_last& wdl) NOEXCEPT
+{
+ return month(static_cast<unsigned>(m)) / wdl;
+}
+
+CONSTCD11
+inline
+month_weekday_last
+operator/(const weekday_last& wdl, int m) NOEXCEPT
+{
+ return m / wdl;
+}
+
+// year_month_day from operator/()
+
+CONSTCD11
+inline
+year_month_day
+operator/(const year_month& ym, const day& d) NOEXCEPT
+{
+ return {ym.year(), ym.month(), d};
+}
+
+CONSTCD11
+inline
+year_month_day
+operator/(const year_month& ym, int d) NOEXCEPT
+{
+ return ym / day(static_cast<unsigned>(d));
+}
+
+CONSTCD11
+inline
+year_month_day
+operator/(const year& y, const month_day& md) NOEXCEPT
+{
+ return y / md.month() / md.day();
+}
+
+CONSTCD11
+inline
+year_month_day
+operator/(int y, const month_day& md) NOEXCEPT
+{
+ return year(y) / md;
+}
+
+CONSTCD11
+inline
+year_month_day
+operator/(const month_day& md, const year& y) NOEXCEPT
+{
+ return y / md;
+}
+
+CONSTCD11
+inline
+year_month_day
+operator/(const month_day& md, int y) NOEXCEPT
+{
+ return year(y) / md;
+}
+
+// year_month_day_last from operator/()
+
+CONSTCD11
+inline
+year_month_day_last
+operator/(const year_month& ym, last_spec) NOEXCEPT
+{
+ return {ym.year(), month_day_last{ym.month()}};
+}
+
+CONSTCD11
+inline
+year_month_day_last
+operator/(const year& y, const month_day_last& mdl) NOEXCEPT
+{
+ return {y, mdl};
+}
+
+CONSTCD11
+inline
+year_month_day_last
+operator/(int y, const month_day_last& mdl) NOEXCEPT
+{
+ return year(y) / mdl;
+}
+
+CONSTCD11
+inline
+year_month_day_last
+operator/(const month_day_last& mdl, const year& y) NOEXCEPT
+{
+ return y / mdl;
+}
+
+CONSTCD11
+inline
+year_month_day_last
+operator/(const month_day_last& mdl, int y) NOEXCEPT
+{
+ return year(y) / mdl;
+}
+
+// year_month_weekday from operator/()
+
+CONSTCD11
+inline
+year_month_weekday
+operator/(const year_month& ym, const weekday_indexed& wdi) NOEXCEPT
+{
+ return {ym.year(), ym.month(), wdi};
+}
+
+CONSTCD11
+inline
+year_month_weekday
+operator/(const year& y, const month_weekday& mwd) NOEXCEPT
+{
+ return {y, mwd.month(), mwd.weekday_indexed()};
+}
+
+CONSTCD11
+inline
+year_month_weekday
+operator/(int y, const month_weekday& mwd) NOEXCEPT
+{
+ return year(y) / mwd;
+}
+
+CONSTCD11
+inline
+year_month_weekday
+operator/(const month_weekday& mwd, const year& y) NOEXCEPT
+{
+ return y / mwd;
+}
+
+CONSTCD11
+inline
+year_month_weekday
+operator/(const month_weekday& mwd, int y) NOEXCEPT
+{
+ return year(y) / mwd;
+}
+
+// year_month_weekday_last from operator/()
+
+CONSTCD11
+inline
+year_month_weekday_last
+operator/(const year_month& ym, const weekday_last& wdl) NOEXCEPT
+{
+ return {ym.year(), ym.month(), wdl};
+}
+
+CONSTCD11
+inline
+year_month_weekday_last
+operator/(const year& y, const month_weekday_last& mwdl) NOEXCEPT
+{
+ return {y, mwdl.month(), mwdl.weekday_last()};
+}
+
+CONSTCD11
+inline
+year_month_weekday_last
+operator/(int y, const month_weekday_last& mwdl) NOEXCEPT
+{
+ return year(y) / mwdl;
+}
+
+CONSTCD11
+inline
+year_month_weekday_last
+operator/(const month_weekday_last& mwdl, const year& y) NOEXCEPT
+{
+ return y / mwdl;
+}
+
+CONSTCD11
+inline
+year_month_weekday_last
+operator/(const month_weekday_last& mwdl, int y) NOEXCEPT
+{
+ return year(y) / mwdl;
+}
+
+} // namespace julian
+
+#endif // JULIAN_H
[05/10] nifi-minifi-cpp git commit: MINIFICPP-472 Added date
formatting EL functions
Posted by al...@apache.org.
http://git-wip-us.apache.org/repos/asf/nifi-minifi-cpp/blob/8777ab5f/thirdparty/date/include/date/ptz.h
----------------------------------------------------------------------
diff --git a/thirdparty/date/include/date/ptz.h b/thirdparty/date/include/date/ptz.h
new file mode 100644
index 0000000..78be1d2
--- /dev/null
+++ b/thirdparty/date/include/date/ptz.h
@@ -0,0 +1,592 @@
+#ifndef PTZ_H
+#define PTZ_H
+
+// The MIT License (MIT)
+//
+// Copyright (c) 2017 Howard Hinnant
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in all
+// copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+// SOFTWARE.
+
+// This header allows Posix-style time zones as specified for TZ here:
+// http://pubs.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap08.html#tag_08_03
+//
+// Posix::time_zone can be constructed with a posix-style string and then used in
+// a zoned_time like so:
+//
+// zoned_time<system_clock::duration, Posix::time_zone> zt{"EST5EDT,M3.2.0,M11.1.0",
+// system_clock::now()};
+// or:
+//
+// Posix::time_zone tz{"EST5EDT,M3.2.0,M11.1.0"};
+// zoned_time<system_clock::duration, Posix::time_zone> zt{tz, system_clock::now()};
+//
+// Note, Posix-style time zones are not recommended for all of the reasons described here:
+// https://stackoverflow.com/tags/timezone/info
+//
+// They are provided here as a non-trivial custom time zone example, and if you really
+// have to have Posix time zones, you're welcome to use this one.
+
+#include "date/tz.h"
+#include <cctype>
+#include <ostream>
+#include <string>
+
+namespace Posix
+{
+
+namespace detail
+{
+
+#if HAS_STRING_VIEW
+
+using string_t = std::string_view;
+
+#else // !HAS_STRING_VIEW
+
+using string_t = std::string;
+
+#endif // !HAS_STRING_VIEW
+
+class rule;
+
+void throw_invalid(const string_t& s, unsigned i, const string_t& message);
+unsigned read_date(const string_t& s, unsigned i, rule& r);
+unsigned read_name(const string_t& s, unsigned i, std::string& name);
+unsigned read_signed_time(const string_t& s, unsigned i, std::chrono::seconds& t);
+unsigned read_unsigned_time(const string_t& s, unsigned i, std::chrono::seconds& t);
+unsigned read_unsigned(const string_t& s, unsigned i, unsigned limit, unsigned& u);
+
+class rule
+{
+ enum {off, J, M, N};
+
+ date::month m_;
+ date::weekday wd_;
+ unsigned short n_ : 14;
+ unsigned short mode_ : 2;
+ std::chrono::duration<std::int32_t> time_ = std::chrono::hours{2};
+
+public:
+ rule() : mode_(off) {}
+
+ bool ok() const {return mode_ != off;}
+ date::local_seconds operator()(date::year y) const;
+
+ friend std::ostream& operator<<(std::ostream& os, const rule& r);
+ friend unsigned read_date(const string_t& s, unsigned i, rule& r);
+};
+
+inline
+date::local_seconds
+rule::operator()(date::year y) const
+{
+ using namespace date;
+ using sec = std::chrono::seconds;
+ date::local_seconds t;
+ switch (mode_)
+ {
+ case J:
+ t = local_days{y/jan/0} + days{n_ + (y.is_leap() && n_ > 59)} + sec{time_};
+ break;
+ case M:
+ t = (n_ == 5 ? local_days{y/m_/wd_[last]} : local_days{y/m_/wd_[n_]}) + sec{time_};
+ break;
+ case N:
+ t = local_days{y/jan/1} + days{n_} + sec{time_};
+ break;
+ default:
+ assert(!"rule called with bad mode");
+ }
+ return t;
+}
+
+inline
+std::ostream&
+operator<<(std::ostream& os, const rule& r)
+{
+ switch (r.mode_)
+ {
+ case rule::J:
+ os << 'J' << r.n_ << date::format(" %T", r.time_);
+ break;
+ case rule::M:
+ if (r.n_ == 5)
+ os << r.m_/r.wd_[date::last];
+ else
+ os << r.m_/r.wd_[r.n_];
+ os << date::format(" %T", r.time_);
+ break;
+ case rule::N:
+ os << r.n_ << date::format(" %T", r.time_);
+ break;
+ default:
+ break;
+ }
+ return os;
+}
+
+} // namespace detail
+
+class time_zone
+{
+ std::string std_abbrev_;
+ std::string dst_abbrev_ = {};
+ std::chrono::seconds offset_;
+ std::chrono::seconds save_ = std::chrono::hours{1};
+ detail::rule start_rule_;
+ detail::rule end_rule_;
+
+public:
+ explicit time_zone(const detail::string_t& name);
+
+ template <class Duration>
+ date::sys_info get_info(date::sys_time<Duration> st) const;
+ template <class Duration>
+ date::local_info get_info(date::local_time<Duration> tp) const;
+
+ template <class Duration>
+ date::sys_time<typename std::common_type<Duration, std::chrono::seconds>::type>
+ to_sys(date::local_time<Duration> tp) const;
+
+ template <class Duration>
+ date::sys_time<typename std::common_type<Duration, std::chrono::seconds>::type>
+ to_sys(date::local_time<Duration> tp, date::choose z) const;
+
+ template <class Duration>
+ date::local_time<typename std::common_type<Duration, std::chrono::seconds>::type>
+ to_local(date::sys_time<Duration> tp) const;
+
+ friend std::ostream& operator<<(std::ostream& os, const time_zone& z);
+
+ const time_zone* operator->() const {return this;}
+};
+
+inline
+time_zone::time_zone(const detail::string_t& s)
+{
+ using namespace detail;
+ auto i = read_name(s, 0, std_abbrev_);
+ i = read_signed_time(s, i, offset_);
+ offset_ = -offset_;
+ if (i != s.size())
+ {
+ i = read_name(s, i, dst_abbrev_);
+ if (i != s.size())
+ {
+ if (s[i] != ',')
+ i = read_signed_time(s, i, save_);
+ if (i != s.size())
+ {
+ if (s[i] != ',')
+ throw_invalid(s, i, "Expecting end of string or ',' to start rule");
+ ++i;
+ i = read_date(s, i, start_rule_);
+ if (i == s.size() || s[i] != ',')
+ throw_invalid(s, i, "Expecting ',' and then the ending rule");
+ ++i;
+ i = read_date(s, i, end_rule_);
+ if (i != s.size())
+ throw_invalid(s, i, "Found unexpected trailing characters");
+ }
+ }
+ }
+}
+
+template <class Duration>
+date::sys_info
+time_zone::get_info(date::sys_time<Duration> st) const
+{
+ using namespace date;
+ using namespace std::chrono;
+ sys_info r{};
+ r.offset = offset_;
+ if (start_rule_.ok())
+ {
+ auto y = year_month_day{floor<days>(st)}.year();
+ auto start = sys_seconds{(start_rule_(y) - offset_).time_since_epoch()};
+ auto end = sys_seconds{(end_rule_(y) - (offset_ + save_)).time_since_epoch()};
+ if (start <= st && st < end)
+ {
+ r.begin = start;
+ r.end = end;
+ r.offset += save_;
+ r.save = ceil<minutes>(save_);
+ r.abbrev = dst_abbrev_;
+ }
+ else if (st < start)
+ {
+ r.begin = sys_seconds{(end_rule_(y-years{1}) -
+ (offset_ + save_)).time_since_epoch()};
+ r.end = start;
+ r.abbrev = std_abbrev_;
+ }
+ else // st >= end
+ {
+ r.begin = end;
+ r.end = sys_seconds{(start_rule_(y+years{1}) - offset_).time_since_epoch()};
+ r.abbrev = std_abbrev_;
+ }
+ }
+ else // constant offset
+ {
+ r.begin = sys_days{year::min()/jan/1};
+ r.end = sys_days{year::max()/dec/last};
+ r.abbrev = std_abbrev_;
+ }
+ return r;
+}
+
+template <class Duration>
+date::local_info
+time_zone::get_info(date::local_time<Duration> tp) const
+{
+ using namespace date;
+ using namespace std::chrono;
+ local_info r{};
+ if (start_rule_.ok())
+ {
+ auto y = year_month_day{floor<days>(tp)}.year();
+ auto start = sys_seconds{(start_rule_(y) - offset_).time_since_epoch()};
+ auto end = sys_seconds{(end_rule_(y) - (offset_ + save_)).time_since_epoch()};
+ auto utcs = sys_seconds{floor<seconds>(tp - offset_).time_since_epoch()};
+ auto utcd = sys_seconds{floor<seconds>(tp - (offset_ + save_)).time_since_epoch()};
+ if ((utcs < start) != (utcd < start))
+ {
+ r.first.begin = sys_seconds{(end_rule_(y-years{1}) -
+ (offset_ + save_)).time_since_epoch()};
+ r.first.end = start;
+ r.first.offset = offset_;
+ r.first.abbrev = std_abbrev_;
+ r.second.begin = start;
+ r.second.end = end;
+ r.second.abbrev = dst_abbrev_;
+ r.second.offset = offset_ + save_;
+ r.second.save = ceil<minutes>(save_);
+ r.result = save_ > seconds{0} ? local_info::nonexistent
+ : local_info::ambiguous;
+ }
+ else if ((utcs < end) != (utcd < end))
+ {
+ r.first.begin = start;
+ r.first.end = end;
+ r.first.offset = offset_ + save_;
+ r.first.save = ceil<minutes>(save_);
+ r.first.abbrev = dst_abbrev_;
+ r.second.begin = end;
+ r.second.end = sys_seconds{(start_rule_(y+years{1}) -
+ offset_).time_since_epoch()};
+ r.second.abbrev = std_abbrev_;
+ r.second.offset = offset_;
+ r.result = save_ > seconds{0} ? local_info::ambiguous
+ : local_info::nonexistent;
+ }
+ else if (utcs < start)
+ {
+ r.first.begin = sys_seconds{(end_rule_(y-years{1}) -
+ (offset_ + save_)).time_since_epoch()};
+ r.first.end = start;
+ r.first.offset = offset_;
+ r.first.abbrev = std_abbrev_;
+ }
+ else if (utcs < end)
+ {
+ r.first.begin = start;
+ r.first.end = end;
+ r.first.offset = offset_ + save_;
+ r.first.save = ceil<minutes>(save_);
+ r.first.abbrev = dst_abbrev_;
+ }
+ else
+ {
+ r.first.begin = end;
+ r.first.end = sys_seconds{(start_rule_(y+years{1}) -
+ offset_).time_since_epoch()};
+ r.first.abbrev = std_abbrev_;
+ r.first.offset = offset_;
+ }
+ }
+ else // constant offset
+ {
+ r.first.begin = sys_days{year::min()/jan/1};
+ r.first.end = sys_days{year::max()/dec/last};
+ r.first.abbrev = std_abbrev_;
+ r.first.offset = offset_;
+ }
+ return r;
+}
+
+template <class Duration>
+date::sys_time<typename std::common_type<Duration, std::chrono::seconds>::type>
+time_zone::to_sys(date::local_time<Duration> tp) const
+{
+ using namespace date;
+ auto i = get_info(tp);
+ if (i.result == local_info::nonexistent)
+ throw nonexistent_local_time(tp, i);
+ else if (i.result == local_info::ambiguous)
+ throw ambiguous_local_time(tp, i);
+ return sys_time<Duration>{tp.time_since_epoch()} - i.first.offset;
+}
+
+template <class Duration>
+date::sys_time<typename std::common_type<Duration, std::chrono::seconds>::type>
+time_zone::to_sys(date::local_time<Duration> tp, date::choose z) const
+{
+ using namespace date;
+ auto i = get_info(tp);
+ if (i.result == local_info::nonexistent)
+ {
+ return i.first.end;
+ }
+ else if (i.result == local_info::ambiguous)
+ {
+ if (z == choose::latest)
+ return sys_time<Duration>{tp.time_since_epoch()} - i.second.offset;
+ }
+ return sys_time<Duration>{tp.time_since_epoch()} - i.first.offset;
+}
+
+template <class Duration>
+date::local_time<typename std::common_type<Duration, std::chrono::seconds>::type>
+time_zone::to_local(date::sys_time<Duration> tp) const
+{
+ using namespace date;
+ using namespace std::chrono;
+ using LT = local_time<typename std::common_type<Duration, seconds>::type>;
+ auto i = get_info(tp);
+ return LT{(tp + i.offset).time_since_epoch()};
+}
+
+inline
+std::ostream&
+operator<<(std::ostream& os, const time_zone& z)
+{
+ using date::operator<<;
+ os << '{';
+ os << z.std_abbrev_ << ", " << z.dst_abbrev_ << date::format(", %T, ", z.offset_)
+ << date::format("%T, [", z.save_) << z.start_rule_ << ", " << z.end_rule_ << ")}";
+ return os;
+}
+
+namespace detail
+{
+
+inline
+void
+throw_invalid(const string_t& s, unsigned i, const string_t& message)
+{
+ throw std::runtime_error(std::string("Invalid time_zone initializer.\n") +
+ std::string(message) + ":\n" +
+ s + '\n' +
+ "\x1b[1;32m" +
+ std::string(i, '~') + '^' +
+ std::string(s.size()-i-1, '~') +
+ "\x1b[0m");
+}
+
+inline
+unsigned
+read_date(const string_t& s, unsigned i, rule& r)
+{
+ using namespace date;
+ if (i == s.size())
+ throw_invalid(s, i, "Expected rule but found end of string");
+ if (s[i] == 'J')
+ {
+ ++i;
+ unsigned n;
+ i = read_unsigned(s, i, 3, n);
+ r.mode_ = rule::J;
+ r.n_ = n;
+ }
+ else if (s[i] == 'M')
+ {
+ ++i;
+ unsigned m;
+ i = read_unsigned(s, i, 2, m);
+ if (i == s.size() || s[i] != '.')
+ throw_invalid(s, i, "Expected '.' after month");
+ ++i;
+ unsigned n;
+ i = read_unsigned(s, i, 1, n);
+ if (i == s.size() || s[i] != '.')
+ throw_invalid(s, i, "Expected '.' after weekday index");
+ ++i;
+ unsigned wd;
+ i = read_unsigned(s, i, 1, wd);
+ r.mode_ = rule::M;
+ r.m_ = month{m};
+ r.wd_ = weekday{wd};
+ r.n_ = n;
+ }
+ else if (std::isdigit(s[i]))
+ {
+ unsigned n;
+ i = read_unsigned(s, i, 3, n);
+ r.mode_ = rule::N;
+ r.n_ = n;
+ }
+ else
+ throw_invalid(s, i, "Expected 'J', 'M', or a digit to start rule");
+ if (i != s.size() && s[i] == '/')
+ {
+ ++i;
+ std::chrono::seconds t;
+ i = read_unsigned_time(s, i, t);
+ r.time_ = t;
+ }
+ return i;
+}
+
+inline
+unsigned
+read_name(const string_t& s, unsigned i, std::string& name)
+{
+ if (i == s.size())
+ throw_invalid(s, i, "Expected a name but found end of string");
+ if (s[i] == '<')
+ {
+ ++i;
+ while (true)
+ {
+ if (i == s.size())
+ throw_invalid(s, i,
+ "Expected to find closing '>', but found end of string");
+ if (s[i] == '>')
+ break;
+ name.push_back(s[i]);
+ ++i;
+ }
+ ++i;
+ }
+ else
+ {
+ while (i != s.size() && std::isalpha(s[i]))
+ {
+ name.push_back(s[i]);
+ ++i;
+ }
+ }
+ if (name.size() < 3)
+ throw_invalid(s, i, "Found name to be shorter than 3 characters");
+ return i;
+}
+
+inline
+unsigned
+read_signed_time(const string_t& s, unsigned i,
+ std::chrono::seconds& t)
+{
+ if (i == s.size())
+ throw_invalid(s, i, "Expected to read signed time, but found end of string");
+ bool negative = false;
+ if (s[i] == '-')
+ {
+ negative = true;
+ ++i;
+ }
+ else if (s[i] == '+')
+ ++i;
+ i = read_unsigned_time(s, i, t);
+ if (negative)
+ t = -t;
+ return i;
+}
+
+inline
+unsigned
+read_unsigned_time(const string_t& s, unsigned i, std::chrono::seconds& t)
+{
+ using namespace std::chrono;
+ if (i == s.size())
+ throw_invalid(s, i, "Expected to read unsigned time, but found end of string");
+ unsigned x;
+ i = read_unsigned(s, i, 2, x);
+ t = hours{x};
+ if (i != s.size() && s[i] == ':')
+ {
+ ++i;
+ i = read_unsigned(s, i, 2, x);
+ t += minutes{x};
+ if (i != s.size() && s[i] == ':')
+ {
+ ++i;
+ i = read_unsigned(s, i, 2, x);
+ t += seconds{x};
+ }
+ }
+ return i;
+}
+
+inline
+unsigned
+read_unsigned(const string_t& s, unsigned i, unsigned limit, unsigned& u)
+{
+ if (i == s.size() || !std::isdigit(s[i]))
+ throw_invalid(s, i, "Expected to find a decimal digit");
+ u = static_cast<unsigned>(s[i] - '0');
+ unsigned count = 1;
+ for (++i; count < limit && i != s.size() && std::isdigit(s[i]); ++i, ++count)
+ u = u * 10 + static_cast<unsigned>(s[i] - '0');
+ return i;
+}
+
+} // namespace detail
+
+} // namespace Posix
+
+namespace date
+{
+
+template <>
+struct zoned_traits<Posix::time_zone>
+{
+
+#if HAS_STRING_VIEW
+
+ static
+ Posix::time_zone
+ locate_zone(std::string_view name)
+ {
+ return Posix::time_zone{name};
+ }
+
+#else // !HAS_STRING_VIEW
+
+ static
+ Posix::time_zone
+ locate_zone(const std::string& name)
+ {
+ return Posix::time_zone{name};
+ }
+
+ static
+ Posix::time_zone
+ locate_zone(const char* name)
+ {
+ return Posix::time_zone{name};
+ }
+
+#endif // !HAS_STRING_VIEW
+
+};
+
+} // namespace date
+
+#endif // PTZ_H
[08/10] nifi-minifi-cpp git commit: MINIFICPP-472 Added date
formatting EL functions
Posted by al...@apache.org.
http://git-wip-us.apache.org/repos/asf/nifi-minifi-cpp/blob/8777ab5f/thirdparty/date/include/date/ios.h
----------------------------------------------------------------------
diff --git a/thirdparty/date/include/date/ios.h b/thirdparty/date/include/date/ios.h
new file mode 100644
index 0000000..ee54b9d
--- /dev/null
+++ b/thirdparty/date/include/date/ios.h
@@ -0,0 +1,50 @@
+//
+// ios.h
+// DateTimeLib
+//
+// The MIT License (MIT)
+//
+// Copyright (c) 2016 Alexander Kormanovsky
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in all
+// copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+// SOFTWARE.
+
+#ifndef ios_hpp
+#define ios_hpp
+
+#if __APPLE__
+# include <TargetConditionals.h>
+# if TARGET_OS_IPHONE
+# include <string>
+
+ namespace date
+ {
+ namespace iOSUtils
+ {
+
+ std::string get_tzdata_path();
+ std::string get_current_timezone();
+
+ } // namespace iOSUtils
+ } // namespace date
+
+# endif // TARGET_OS_IPHONE
+#else // !__APPLE__
+# define TARGET_OS_IPHONE 0
+#endif // !__APPLE__
+#endif // ios_hpp
http://git-wip-us.apache.org/repos/asf/nifi-minifi-cpp/blob/8777ab5f/thirdparty/date/include/date/islamic.h
----------------------------------------------------------------------
diff --git a/thirdparty/date/include/date/islamic.h b/thirdparty/date/include/date/islamic.h
new file mode 100644
index 0000000..b18c493
--- /dev/null
+++ b/thirdparty/date/include/date/islamic.h
@@ -0,0 +1,3031 @@
+#ifndef ISLAMIC_H
+#define ISLAMIC_H
+
+// The MIT License (MIT)
+//
+// Copyright (c) 2016 Howard Hinnant
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in all
+// copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+// SOFTWARE.
+//
+// Our apologies. When the previous paragraph was written, lowercase had not yet
+// been invented (that would involve another several millennia of evolution).
+// We did not mean to shout.
+
+#include "date.h"
+
+namespace islamic
+{
+
+// durations
+
+using days = date::days;
+
+using weeks = date::weeks;
+
+using years = std::chrono::duration
+ <int, std::ratio_multiply<std::ratio<10631, 30>, days::period>>;
+
+using months = std::chrono::duration
+ <int, std::ratio_divide<years::period, std::ratio<12>>>;
+
+// time_point
+
+using sys_days = date::sys_days;
+using local_days = date::local_days;
+
+// types
+
+struct last_spec
+{
+ explicit last_spec() = default;
+};
+
+class day;
+class month;
+class year;
+
+class weekday;
+class weekday_indexed;
+class weekday_last;
+
+class month_day;
+class month_day_last;
+class month_weekday;
+class month_weekday_last;
+
+class year_month;
+
+class year_month_day;
+class year_month_day_last;
+class year_month_weekday;
+class year_month_weekday_last;
+
+// date composition operators
+
+CONSTCD11 year_month operator/(const year& y, const month& m) NOEXCEPT;
+CONSTCD11 year_month operator/(const year& y, int m) NOEXCEPT;
+
+CONSTCD11 month_day operator/(const day& d, const month& m) NOEXCEPT;
+CONSTCD11 month_day operator/(const day& d, int m) NOEXCEPT;
+CONSTCD11 month_day operator/(const month& m, const day& d) NOEXCEPT;
+CONSTCD11 month_day operator/(const month& m, int d) NOEXCEPT;
+CONSTCD11 month_day operator/(int m, const day& d) NOEXCEPT;
+
+CONSTCD11 month_day_last operator/(const month& m, last_spec) NOEXCEPT;
+CONSTCD11 month_day_last operator/(int m, last_spec) NOEXCEPT;
+CONSTCD11 month_day_last operator/(last_spec, const month& m) NOEXCEPT;
+CONSTCD11 month_day_last operator/(last_spec, int m) NOEXCEPT;
+
+CONSTCD11 month_weekday operator/(const month& m, const weekday_indexed& wdi) NOEXCEPT;
+CONSTCD11 month_weekday operator/(int m, const weekday_indexed& wdi) NOEXCEPT;
+CONSTCD11 month_weekday operator/(const weekday_indexed& wdi, const month& m) NOEXCEPT;
+CONSTCD11 month_weekday operator/(const weekday_indexed& wdi, int m) NOEXCEPT;
+
+CONSTCD11 month_weekday_last operator/(const month& m, const weekday_last& wdl) NOEXCEPT;
+CONSTCD11 month_weekday_last operator/(int m, const weekday_last& wdl) NOEXCEPT;
+CONSTCD11 month_weekday_last operator/(const weekday_last& wdl, const month& m) NOEXCEPT;
+CONSTCD11 month_weekday_last operator/(const weekday_last& wdl, int m) NOEXCEPT;
+
+CONSTCD11 year_month_day operator/(const year_month& ym, const day& d) NOEXCEPT;
+CONSTCD11 year_month_day operator/(const year_month& ym, int d) NOEXCEPT;
+CONSTCD11 year_month_day operator/(const year& y, const month_day& md) NOEXCEPT;
+CONSTCD11 year_month_day operator/(int y, const month_day& md) NOEXCEPT;
+CONSTCD11 year_month_day operator/(const month_day& md, const year& y) NOEXCEPT;
+CONSTCD11 year_month_day operator/(const month_day& md, int y) NOEXCEPT;
+
+CONSTCD11
+ year_month_day_last operator/(const year_month& ym, last_spec) NOEXCEPT;
+CONSTCD11
+ year_month_day_last operator/(const year& y, const month_day_last& mdl) NOEXCEPT;
+CONSTCD11
+ year_month_day_last operator/(int y, const month_day_last& mdl) NOEXCEPT;
+CONSTCD11
+ year_month_day_last operator/(const month_day_last& mdl, const year& y) NOEXCEPT;
+CONSTCD11
+ year_month_day_last operator/(const month_day_last& mdl, int y) NOEXCEPT;
+
+CONSTCD11
+year_month_weekday
+operator/(const year_month& ym, const weekday_indexed& wdi) NOEXCEPT;
+
+CONSTCD11
+year_month_weekday
+operator/(const year& y, const month_weekday& mwd) NOEXCEPT;
+
+CONSTCD11
+year_month_weekday
+operator/(int y, const month_weekday& mwd) NOEXCEPT;
+
+CONSTCD11
+year_month_weekday
+operator/(const month_weekday& mwd, const year& y) NOEXCEPT;
+
+CONSTCD11
+year_month_weekday
+operator/(const month_weekday& mwd, int y) NOEXCEPT;
+
+CONSTCD11
+year_month_weekday_last
+operator/(const year_month& ym, const weekday_last& wdl) NOEXCEPT;
+
+CONSTCD11
+year_month_weekday_last
+operator/(const year& y, const month_weekday_last& mwdl) NOEXCEPT;
+
+CONSTCD11
+year_month_weekday_last
+operator/(int y, const month_weekday_last& mwdl) NOEXCEPT;
+
+CONSTCD11
+year_month_weekday_last
+operator/(const month_weekday_last& mwdl, const year& y) NOEXCEPT;
+
+CONSTCD11
+year_month_weekday_last
+operator/(const month_weekday_last& mwdl, int y) NOEXCEPT;
+
+// Detailed interface
+
+// day
+
+class day
+{
+ unsigned char d_;
+
+public:
+ explicit CONSTCD11 day(unsigned d) NOEXCEPT;
+
+ CONSTCD14 day& operator++() NOEXCEPT;
+ CONSTCD14 day operator++(int) NOEXCEPT;
+ CONSTCD14 day& operator--() NOEXCEPT;
+ CONSTCD14 day operator--(int) NOEXCEPT;
+
+ CONSTCD14 day& operator+=(const days& d) NOEXCEPT;
+ CONSTCD14 day& operator-=(const days& d) NOEXCEPT;
+
+ CONSTCD11 explicit operator unsigned() const NOEXCEPT;
+ CONSTCD11 bool ok() const NOEXCEPT;
+};
+
+CONSTCD11 bool operator==(const day& x, const day& y) NOEXCEPT;
+CONSTCD11 bool operator!=(const day& x, const day& y) NOEXCEPT;
+CONSTCD11 bool operator< (const day& x, const day& y) NOEXCEPT;
+CONSTCD11 bool operator> (const day& x, const day& y) NOEXCEPT;
+CONSTCD11 bool operator<=(const day& x, const day& y) NOEXCEPT;
+CONSTCD11 bool operator>=(const day& x, const day& y) NOEXCEPT;
+
+CONSTCD11 day operator+(const day& x, const days& y) NOEXCEPT;
+CONSTCD11 day operator+(const days& x, const day& y) NOEXCEPT;
+CONSTCD11 day operator-(const day& x, const days& y) NOEXCEPT;
+CONSTCD11 days operator-(const day& x, const day& y) NOEXCEPT;
+
+template<class CharT, class Traits>
+std::basic_ostream<CharT, Traits>&
+operator<<(std::basic_ostream<CharT, Traits>& os, const day& d);
+
+// month
+
+class month
+{
+ unsigned char m_;
+
+public:
+ explicit CONSTCD11 month(unsigned m) NOEXCEPT;
+
+ CONSTCD14 month& operator++() NOEXCEPT;
+ CONSTCD14 month operator++(int) NOEXCEPT;
+ CONSTCD14 month& operator--() NOEXCEPT;
+ CONSTCD14 month operator--(int) NOEXCEPT;
+
+ CONSTCD14 month& operator+=(const months& m) NOEXCEPT;
+ CONSTCD14 month& operator-=(const months& m) NOEXCEPT;
+
+ CONSTCD11 explicit operator unsigned() const NOEXCEPT;
+ CONSTCD11 bool ok() const NOEXCEPT;
+};
+
+CONSTCD11 bool operator==(const month& x, const month& y) NOEXCEPT;
+CONSTCD11 bool operator!=(const month& x, const month& y) NOEXCEPT;
+CONSTCD11 bool operator< (const month& x, const month& y) NOEXCEPT;
+CONSTCD11 bool operator> (const month& x, const month& y) NOEXCEPT;
+CONSTCD11 bool operator<=(const month& x, const month& y) NOEXCEPT;
+CONSTCD11 bool operator>=(const month& x, const month& y) NOEXCEPT;
+
+CONSTCD14 month operator+(const month& x, const months& y) NOEXCEPT;
+CONSTCD14 month operator+(const months& x, const month& y) NOEXCEPT;
+CONSTCD14 month operator-(const month& x, const months& y) NOEXCEPT;
+CONSTCD14 months operator-(const month& x, const month& y) NOEXCEPT;
+
+template<class CharT, class Traits>
+std::basic_ostream<CharT, Traits>&
+operator<<(std::basic_ostream<CharT, Traits>& os, const month& m);
+
+// year
+
+class year
+{
+ short y_;
+
+public:
+ explicit CONSTCD11 year(int y) NOEXCEPT;
+
+ CONSTCD14 year& operator++() NOEXCEPT;
+ CONSTCD14 year operator++(int) NOEXCEPT;
+ CONSTCD14 year& operator--() NOEXCEPT;
+ CONSTCD14 year operator--(int) NOEXCEPT;
+
+ CONSTCD14 year& operator+=(const years& y) NOEXCEPT;
+ CONSTCD14 year& operator-=(const years& y) NOEXCEPT;
+
+ CONSTCD11 bool is_leap() const NOEXCEPT;
+
+ CONSTCD11 explicit operator int() const NOEXCEPT;
+ CONSTCD11 bool ok() const NOEXCEPT;
+
+ static CONSTCD11 year min() NOEXCEPT;
+ static CONSTCD11 year max() NOEXCEPT;
+};
+
+CONSTCD11 bool operator==(const year& x, const year& y) NOEXCEPT;
+CONSTCD11 bool operator!=(const year& x, const year& y) NOEXCEPT;
+CONSTCD11 bool operator< (const year& x, const year& y) NOEXCEPT;
+CONSTCD11 bool operator> (const year& x, const year& y) NOEXCEPT;
+CONSTCD11 bool operator<=(const year& x, const year& y) NOEXCEPT;
+CONSTCD11 bool operator>=(const year& x, const year& y) NOEXCEPT;
+
+CONSTCD11 year operator+(const year& x, const years& y) NOEXCEPT;
+CONSTCD11 year operator+(const years& x, const year& y) NOEXCEPT;
+CONSTCD11 year operator-(const year& x, const years& y) NOEXCEPT;
+CONSTCD11 years operator-(const year& x, const year& y) NOEXCEPT;
+
+template<class CharT, class Traits>
+std::basic_ostream<CharT, Traits>&
+operator<<(std::basic_ostream<CharT, Traits>& os, const year& y);
+
+// weekday
+
+class weekday
+{
+ unsigned char wd_;
+public:
+ explicit CONSTCD11 weekday(unsigned wd) NOEXCEPT;
+ explicit weekday(int) = delete;
+ CONSTCD11 weekday(const sys_days& dp) NOEXCEPT;
+ CONSTCD11 explicit weekday(const local_days& dp) NOEXCEPT;
+
+ CONSTCD14 weekday& operator++() NOEXCEPT;
+ CONSTCD14 weekday operator++(int) NOEXCEPT;
+ CONSTCD14 weekday& operator--() NOEXCEPT;
+ CONSTCD14 weekday operator--(int) NOEXCEPT;
+
+ CONSTCD14 weekday& operator+=(const days& d) NOEXCEPT;
+ CONSTCD14 weekday& operator-=(const days& d) NOEXCEPT;
+
+ CONSTCD11 explicit operator unsigned() const NOEXCEPT;
+ CONSTCD11 bool ok() const NOEXCEPT;
+
+ CONSTCD11 weekday_indexed operator[](unsigned index) const NOEXCEPT;
+ CONSTCD11 weekday_last operator[](last_spec) const NOEXCEPT;
+
+private:
+ static CONSTCD11 unsigned char weekday_from_days(int z) NOEXCEPT;
+};
+
+CONSTCD11 bool operator==(const weekday& x, const weekday& y) NOEXCEPT;
+CONSTCD11 bool operator!=(const weekday& x, const weekday& y) NOEXCEPT;
+
+CONSTCD14 weekday operator+(const weekday& x, const days& y) NOEXCEPT;
+CONSTCD14 weekday operator+(const days& x, const weekday& y) NOEXCEPT;
+CONSTCD14 weekday operator-(const weekday& x, const days& y) NOEXCEPT;
+CONSTCD14 days operator-(const weekday& x, const weekday& y) NOEXCEPT;
+
+template<class CharT, class Traits>
+std::basic_ostream<CharT, Traits>&
+operator<<(std::basic_ostream<CharT, Traits>& os, const weekday& wd);
+
+// weekday_indexed
+
+class weekday_indexed
+{
+ unsigned char wd_ : 4;
+ unsigned char index_ : 4;
+
+public:
+ CONSTCD11 weekday_indexed(const islamic::weekday& wd, unsigned index) NOEXCEPT;
+
+ CONSTCD11 islamic::weekday weekday() const NOEXCEPT;
+ CONSTCD11 unsigned index() const NOEXCEPT;
+ CONSTCD11 bool ok() const NOEXCEPT;
+};
+
+CONSTCD11 bool operator==(const weekday_indexed& x, const weekday_indexed& y) NOEXCEPT;
+CONSTCD11 bool operator!=(const weekday_indexed& x, const weekday_indexed& y) NOEXCEPT;
+
+template<class CharT, class Traits>
+std::basic_ostream<CharT, Traits>&
+operator<<(std::basic_ostream<CharT, Traits>& os, const weekday_indexed& wdi);
+
+// weekday_last
+
+class weekday_last
+{
+ islamic::weekday wd_;
+
+public:
+ explicit CONSTCD11 weekday_last(const islamic::weekday& wd) NOEXCEPT;
+
+ CONSTCD11 islamic::weekday weekday() const NOEXCEPT;
+ CONSTCD11 bool ok() const NOEXCEPT;
+};
+
+CONSTCD11 bool operator==(const weekday_last& x, const weekday_last& y) NOEXCEPT;
+CONSTCD11 bool operator!=(const weekday_last& x, const weekday_last& y) NOEXCEPT;
+
+template<class CharT, class Traits>
+std::basic_ostream<CharT, Traits>&
+operator<<(std::basic_ostream<CharT, Traits>& os, const weekday_last& wdl);
+
+// year_month
+
+class year_month
+{
+ islamic::year y_;
+ islamic::month m_;
+
+public:
+ CONSTCD11 year_month(const islamic::year& y, const islamic::month& m) NOEXCEPT;
+
+ CONSTCD11 islamic::year year() const NOEXCEPT;
+ CONSTCD11 islamic::month month() const NOEXCEPT;
+
+ CONSTCD14 year_month& operator+=(const months& dm) NOEXCEPT;
+ CONSTCD14 year_month& operator-=(const months& dm) NOEXCEPT;
+ CONSTCD14 year_month& operator+=(const years& dy) NOEXCEPT;
+ CONSTCD14 year_month& operator-=(const years& dy) NOEXCEPT;
+
+ CONSTCD11 bool ok() const NOEXCEPT;
+};
+
+CONSTCD11 bool operator==(const year_month& x, const year_month& y) NOEXCEPT;
+CONSTCD11 bool operator!=(const year_month& x, const year_month& y) NOEXCEPT;
+CONSTCD11 bool operator< (const year_month& x, const year_month& y) NOEXCEPT;
+CONSTCD11 bool operator> (const year_month& x, const year_month& y) NOEXCEPT;
+CONSTCD11 bool operator<=(const year_month& x, const year_month& y) NOEXCEPT;
+CONSTCD11 bool operator>=(const year_month& x, const year_month& y) NOEXCEPT;
+
+CONSTCD14 year_month operator+(const year_month& ym, const months& dm) NOEXCEPT;
+CONSTCD14 year_month operator+(const months& dm, const year_month& ym) NOEXCEPT;
+CONSTCD14 year_month operator-(const year_month& ym, const months& dm) NOEXCEPT;
+
+CONSTCD11 months operator-(const year_month& x, const year_month& y) NOEXCEPT;
+CONSTCD11 year_month operator+(const year_month& ym, const years& dy) NOEXCEPT;
+CONSTCD11 year_month operator+(const years& dy, const year_month& ym) NOEXCEPT;
+CONSTCD11 year_month operator-(const year_month& ym, const years& dy) NOEXCEPT;
+
+template<class CharT, class Traits>
+std::basic_ostream<CharT, Traits>&
+operator<<(std::basic_ostream<CharT, Traits>& os, const year_month& ym);
+
+// month_day
+
+class month_day
+{
+ islamic::month m_;
+ islamic::day d_;
+
+public:
+ CONSTCD11 month_day(const islamic::month& m, const islamic::day& d) NOEXCEPT;
+
+ CONSTCD11 islamic::month month() const NOEXCEPT;
+ CONSTCD11 islamic::day day() const NOEXCEPT;
+
+ CONSTCD14 bool ok() const NOEXCEPT;
+};
+
+CONSTCD11 bool operator==(const month_day& x, const month_day& y) NOEXCEPT;
+CONSTCD11 bool operator!=(const month_day& x, const month_day& y) NOEXCEPT;
+CONSTCD11 bool operator< (const month_day& x, const month_day& y) NOEXCEPT;
+CONSTCD11 bool operator> (const month_day& x, const month_day& y) NOEXCEPT;
+CONSTCD11 bool operator<=(const month_day& x, const month_day& y) NOEXCEPT;
+CONSTCD11 bool operator>=(const month_day& x, const month_day& y) NOEXCEPT;
+
+template<class CharT, class Traits>
+std::basic_ostream<CharT, Traits>&
+operator<<(std::basic_ostream<CharT, Traits>& os, const month_day& md);
+
+// month_day_last
+
+class month_day_last
+{
+ islamic::month m_;
+
+public:
+ CONSTCD11 explicit month_day_last(const islamic::month& m) NOEXCEPT;
+
+ CONSTCD11 islamic::month month() const NOEXCEPT;
+ CONSTCD11 bool ok() const NOEXCEPT;
+};
+
+CONSTCD11 bool operator==(const month_day_last& x, const month_day_last& y) NOEXCEPT;
+CONSTCD11 bool operator!=(const month_day_last& x, const month_day_last& y) NOEXCEPT;
+CONSTCD11 bool operator< (const month_day_last& x, const month_day_last& y) NOEXCEPT;
+CONSTCD11 bool operator> (const month_day_last& x, const month_day_last& y) NOEXCEPT;
+CONSTCD11 bool operator<=(const month_day_last& x, const month_day_last& y) NOEXCEPT;
+CONSTCD11 bool operator>=(const month_day_last& x, const month_day_last& y) NOEXCEPT;
+
+template<class CharT, class Traits>
+std::basic_ostream<CharT, Traits>&
+operator<<(std::basic_ostream<CharT, Traits>& os, const month_day_last& mdl);
+
+// month_weekday
+
+class month_weekday
+{
+ islamic::month m_;
+ islamic::weekday_indexed wdi_;
+public:
+ CONSTCD11 month_weekday(const islamic::month& m,
+ const islamic::weekday_indexed& wdi) NOEXCEPT;
+
+ CONSTCD11 islamic::month month() const NOEXCEPT;
+ CONSTCD11 islamic::weekday_indexed weekday_indexed() const NOEXCEPT;
+
+ CONSTCD11 bool ok() const NOEXCEPT;
+};
+
+CONSTCD11 bool operator==(const month_weekday& x, const month_weekday& y) NOEXCEPT;
+CONSTCD11 bool operator!=(const month_weekday& x, const month_weekday& y) NOEXCEPT;
+
+template<class CharT, class Traits>
+std::basic_ostream<CharT, Traits>&
+operator<<(std::basic_ostream<CharT, Traits>& os, const month_weekday& mwd);
+
+// month_weekday_last
+
+class month_weekday_last
+{
+ islamic::month m_;
+ islamic::weekday_last wdl_;
+
+public:
+ CONSTCD11 month_weekday_last(const islamic::month& m,
+ const islamic::weekday_last& wd) NOEXCEPT;
+
+ CONSTCD11 islamic::month month() const NOEXCEPT;
+ CONSTCD11 islamic::weekday_last weekday_last() const NOEXCEPT;
+
+ CONSTCD11 bool ok() const NOEXCEPT;
+};
+
+CONSTCD11
+ bool operator==(const month_weekday_last& x, const month_weekday_last& y) NOEXCEPT;
+CONSTCD11
+ bool operator!=(const month_weekday_last& x, const month_weekday_last& y) NOEXCEPT;
+
+template<class CharT, class Traits>
+std::basic_ostream<CharT, Traits>&
+operator<<(std::basic_ostream<CharT, Traits>& os, const month_weekday_last& mwdl);
+
+// class year_month_day
+
+class year_month_day
+{
+ islamic::year y_;
+ islamic::month m_;
+ islamic::day d_;
+
+public:
+ CONSTCD11 year_month_day(const islamic::year& y, const islamic::month& m,
+ const islamic::day& d) NOEXCEPT;
+ CONSTCD14 year_month_day(const year_month_day_last& ymdl) NOEXCEPT;
+
+ CONSTCD14 year_month_day(sys_days dp) NOEXCEPT;
+ CONSTCD14 explicit year_month_day(local_days dp) NOEXCEPT;
+
+ CONSTCD14 year_month_day& operator+=(const months& m) NOEXCEPT;
+ CONSTCD14 year_month_day& operator-=(const months& m) NOEXCEPT;
+ CONSTCD14 year_month_day& operator+=(const years& y) NOEXCEPT;
+ CONSTCD14 year_month_day& operator-=(const years& y) NOEXCEPT;
+
+ CONSTCD11 islamic::year year() const NOEXCEPT;
+ CONSTCD11 islamic::month month() const NOEXCEPT;
+ CONSTCD11 islamic::day day() const NOEXCEPT;
+
+ CONSTCD14 operator sys_days() const NOEXCEPT;
+ CONSTCD14 explicit operator local_days() const NOEXCEPT;
+ CONSTCD14 bool ok() const NOEXCEPT;
+
+private:
+ static CONSTCD14 year_month_day from_days(days dp) NOEXCEPT;
+ CONSTCD14 days to_days() const NOEXCEPT;
+};
+
+CONSTCD11 bool operator==(const year_month_day& x, const year_month_day& y) NOEXCEPT;
+CONSTCD11 bool operator!=(const year_month_day& x, const year_month_day& y) NOEXCEPT;
+CONSTCD11 bool operator< (const year_month_day& x, const year_month_day& y) NOEXCEPT;
+CONSTCD11 bool operator> (const year_month_day& x, const year_month_day& y) NOEXCEPT;
+CONSTCD11 bool operator<=(const year_month_day& x, const year_month_day& y) NOEXCEPT;
+CONSTCD11 bool operator>=(const year_month_day& x, const year_month_day& y) NOEXCEPT;
+
+CONSTCD14 year_month_day operator+(const year_month_day& ymd, const months& dm) NOEXCEPT;
+CONSTCD14 year_month_day operator+(const months& dm, const year_month_day& ymd) NOEXCEPT;
+CONSTCD14 year_month_day operator-(const year_month_day& ymd, const months& dm) NOEXCEPT;
+CONSTCD11 year_month_day operator+(const year_month_day& ymd, const years& dy) NOEXCEPT;
+CONSTCD11 year_month_day operator+(const years& dy, const year_month_day& ymd) NOEXCEPT;
+CONSTCD11 year_month_day operator-(const year_month_day& ymd, const years& dy) NOEXCEPT;
+
+template<class CharT, class Traits>
+std::basic_ostream<CharT, Traits>&
+operator<<(std::basic_ostream<CharT, Traits>& os, const year_month_day& ymd);
+
+// year_month_day_last
+
+class year_month_day_last
+{
+ islamic::year y_;
+ islamic::month_day_last mdl_;
+
+public:
+ CONSTCD11 year_month_day_last(const islamic::year& y,
+ const islamic::month_day_last& mdl) NOEXCEPT;
+
+ CONSTCD14 year_month_day_last& operator+=(const months& m) NOEXCEPT;
+ CONSTCD14 year_month_day_last& operator-=(const months& m) NOEXCEPT;
+ CONSTCD14 year_month_day_last& operator+=(const years& y) NOEXCEPT;
+ CONSTCD14 year_month_day_last& operator-=(const years& y) NOEXCEPT;
+
+ CONSTCD11 islamic::year year() const NOEXCEPT;
+ CONSTCD11 islamic::month month() const NOEXCEPT;
+ CONSTCD11 islamic::month_day_last month_day_last() const NOEXCEPT;
+ CONSTCD14 islamic::day day() const NOEXCEPT;
+
+ CONSTCD14 operator sys_days() const NOEXCEPT;
+ CONSTCD14 explicit operator local_days() const NOEXCEPT;
+ CONSTCD11 bool ok() const NOEXCEPT;
+};
+
+CONSTCD11
+ bool operator==(const year_month_day_last& x, const year_month_day_last& y) NOEXCEPT;
+CONSTCD11
+ bool operator!=(const year_month_day_last& x, const year_month_day_last& y) NOEXCEPT;
+CONSTCD11
+ bool operator< (const year_month_day_last& x, const year_month_day_last& y) NOEXCEPT;
+CONSTCD11
+ bool operator> (const year_month_day_last& x, const year_month_day_last& y) NOEXCEPT;
+CONSTCD11
+ bool operator<=(const year_month_day_last& x, const year_month_day_last& y) NOEXCEPT;
+CONSTCD11
+ bool operator>=(const year_month_day_last& x, const year_month_day_last& y) NOEXCEPT;
+
+CONSTCD14
+year_month_day_last
+operator+(const year_month_day_last& ymdl, const months& dm) NOEXCEPT;
+
+CONSTCD14
+year_month_day_last
+operator+(const months& dm, const year_month_day_last& ymdl) NOEXCEPT;
+
+CONSTCD11
+year_month_day_last
+operator+(const year_month_day_last& ymdl, const years& dy) NOEXCEPT;
+
+CONSTCD11
+year_month_day_last
+operator+(const years& dy, const year_month_day_last& ymdl) NOEXCEPT;
+
+CONSTCD14
+year_month_day_last
+operator-(const year_month_day_last& ymdl, const months& dm) NOEXCEPT;
+
+CONSTCD11
+year_month_day_last
+operator-(const year_month_day_last& ymdl, const years& dy) NOEXCEPT;
+
+template<class CharT, class Traits>
+std::basic_ostream<CharT, Traits>&
+operator<<(std::basic_ostream<CharT, Traits>& os, const year_month_day_last& ymdl);
+
+// year_month_weekday
+
+class year_month_weekday
+{
+ islamic::year y_;
+ islamic::month m_;
+ islamic::weekday_indexed wdi_;
+
+public:
+ CONSTCD11 year_month_weekday(const islamic::year& y, const islamic::month& m,
+ const islamic::weekday_indexed& wdi) NOEXCEPT;
+ CONSTCD14 year_month_weekday(const sys_days& dp) NOEXCEPT;
+ CONSTCD14 explicit year_month_weekday(const local_days& dp) NOEXCEPT;
+
+ CONSTCD14 year_month_weekday& operator+=(const months& m) NOEXCEPT;
+ CONSTCD14 year_month_weekday& operator-=(const months& m) NOEXCEPT;
+ CONSTCD14 year_month_weekday& operator+=(const years& y) NOEXCEPT;
+ CONSTCD14 year_month_weekday& operator-=(const years& y) NOEXCEPT;
+
+ CONSTCD11 islamic::year year() const NOEXCEPT;
+ CONSTCD11 islamic::month month() const NOEXCEPT;
+ CONSTCD11 islamic::weekday weekday() const NOEXCEPT;
+ CONSTCD11 unsigned index() const NOEXCEPT;
+ CONSTCD11 islamic::weekday_indexed weekday_indexed() const NOEXCEPT;
+
+ CONSTCD14 operator sys_days() const NOEXCEPT;
+ CONSTCD14 explicit operator local_days() const NOEXCEPT;
+ CONSTCD14 bool ok() const NOEXCEPT;
+
+private:
+ static CONSTCD14 year_month_weekday from_days(days dp) NOEXCEPT;
+ CONSTCD14 days to_days() const NOEXCEPT;
+};
+
+CONSTCD11
+ bool operator==(const year_month_weekday& x, const year_month_weekday& y) NOEXCEPT;
+CONSTCD11
+ bool operator!=(const year_month_weekday& x, const year_month_weekday& y) NOEXCEPT;
+
+CONSTCD14
+year_month_weekday
+operator+(const year_month_weekday& ymwd, const months& dm) NOEXCEPT;
+
+CONSTCD14
+year_month_weekday
+operator+(const months& dm, const year_month_weekday& ymwd) NOEXCEPT;
+
+CONSTCD11
+year_month_weekday
+operator+(const year_month_weekday& ymwd, const years& dy) NOEXCEPT;
+
+CONSTCD11
+year_month_weekday
+operator+(const years& dy, const year_month_weekday& ymwd) NOEXCEPT;
+
+CONSTCD14
+year_month_weekday
+operator-(const year_month_weekday& ymwd, const months& dm) NOEXCEPT;
+
+CONSTCD11
+year_month_weekday
+operator-(const year_month_weekday& ymwd, const years& dy) NOEXCEPT;
+
+template<class CharT, class Traits>
+std::basic_ostream<CharT, Traits>&
+operator<<(std::basic_ostream<CharT, Traits>& os, const year_month_weekday& ymwdi);
+
+// year_month_weekday_last
+
+class year_month_weekday_last
+{
+ islamic::year y_;
+ islamic::month m_;
+ islamic::weekday_last wdl_;
+
+public:
+ CONSTCD11 year_month_weekday_last(const islamic::year& y, const islamic::month& m,
+ const islamic::weekday_last& wdl) NOEXCEPT;
+
+ CONSTCD14 year_month_weekday_last& operator+=(const months& m) NOEXCEPT;
+ CONSTCD14 year_month_weekday_last& operator-=(const months& m) NOEXCEPT;
+ CONSTCD14 year_month_weekday_last& operator+=(const years& y) NOEXCEPT;
+ CONSTCD14 year_month_weekday_last& operator-=(const years& y) NOEXCEPT;
+
+ CONSTCD11 islamic::year year() const NOEXCEPT;
+ CONSTCD11 islamic::month month() const NOEXCEPT;
+ CONSTCD11 islamic::weekday weekday() const NOEXCEPT;
+ CONSTCD11 islamic::weekday_last weekday_last() const NOEXCEPT;
+
+ CONSTCD14 operator sys_days() const NOEXCEPT;
+ CONSTCD14 explicit operator local_days() const NOEXCEPT;
+ CONSTCD11 bool ok() const NOEXCEPT;
+
+private:
+ CONSTCD14 days to_days() const NOEXCEPT;
+};
+
+CONSTCD11
+bool
+operator==(const year_month_weekday_last& x, const year_month_weekday_last& y) NOEXCEPT;
+
+CONSTCD11
+bool
+operator!=(const year_month_weekday_last& x, const year_month_weekday_last& y) NOEXCEPT;
+
+CONSTCD14
+year_month_weekday_last
+operator+(const year_month_weekday_last& ymwdl, const months& dm) NOEXCEPT;
+
+CONSTCD14
+year_month_weekday_last
+operator+(const months& dm, const year_month_weekday_last& ymwdl) NOEXCEPT;
+
+CONSTCD11
+year_month_weekday_last
+operator+(const year_month_weekday_last& ymwdl, const years& dy) NOEXCEPT;
+
+CONSTCD11
+year_month_weekday_last
+operator+(const years& dy, const year_month_weekday_last& ymwdl) NOEXCEPT;
+
+CONSTCD14
+year_month_weekday_last
+operator-(const year_month_weekday_last& ymwdl, const months& dm) NOEXCEPT;
+
+CONSTCD11
+year_month_weekday_last
+operator-(const year_month_weekday_last& ymwdl, const years& dy) NOEXCEPT;
+
+template<class CharT, class Traits>
+std::basic_ostream<CharT, Traits>&
+operator<<(std::basic_ostream<CharT, Traits>& os, const year_month_weekday_last& ymwdl);
+
+#if !defined(_MSC_VER) || (_MSC_VER >= 1900)
+inline namespace literals
+{
+
+CONSTCD11 islamic::day operator "" _d(unsigned long long d) NOEXCEPT;
+CONSTCD11 islamic::year operator "" _y(unsigned long long y) NOEXCEPT;
+
+} // inline namespace literals
+#endif // !defined(_MSC_VER) || (_MSC_VER >= 1900)
+
+//----------------+
+// Implementation |
+//----------------+
+
+// day
+
+CONSTCD11 inline day::day(unsigned d) NOEXCEPT : d_(static_cast<unsigned char>(d)) {}
+CONSTCD14 inline day& day::operator++() NOEXCEPT {++d_; return *this;}
+CONSTCD14 inline day day::operator++(int) NOEXCEPT {auto tmp(*this); ++(*this); return tmp;}
+CONSTCD14 inline day& day::operator--() NOEXCEPT {--d_; return *this;}
+CONSTCD14 inline day day::operator--(int) NOEXCEPT {auto tmp(*this); --(*this); return tmp;}
+CONSTCD14 inline day& day::operator+=(const days& d) NOEXCEPT {*this = *this + d; return *this;}
+CONSTCD14 inline day& day::operator-=(const days& d) NOEXCEPT {*this = *this - d; return *this;}
+CONSTCD11 inline day::operator unsigned() const NOEXCEPT {return d_;}
+CONSTCD11 inline bool day::ok() const NOEXCEPT {return 1 <= d_ && d_ <= 30;}
+
+CONSTCD11
+inline
+bool
+operator==(const day& x, const day& y) NOEXCEPT
+{
+ return static_cast<unsigned>(x) == static_cast<unsigned>(y);
+}
+
+CONSTCD11
+inline
+bool
+operator!=(const day& x, const day& y) NOEXCEPT
+{
+ return !(x == y);
+}
+
+CONSTCD11
+inline
+bool
+operator<(const day& x, const day& y) NOEXCEPT
+{
+ return static_cast<unsigned>(x) < static_cast<unsigned>(y);
+}
+
+CONSTCD11
+inline
+bool
+operator>(const day& x, const day& y) NOEXCEPT
+{
+ return y < x;
+}
+
+CONSTCD11
+inline
+bool
+operator<=(const day& x, const day& y) NOEXCEPT
+{
+ return !(y < x);
+}
+
+CONSTCD11
+inline
+bool
+operator>=(const day& x, const day& y) NOEXCEPT
+{
+ return !(x < y);
+}
+
+CONSTCD11
+inline
+days
+operator-(const day& x, const day& y) NOEXCEPT
+{
+ return days{static_cast<days::rep>(static_cast<unsigned>(x)
+ - static_cast<unsigned>(y))};
+}
+
+CONSTCD11
+inline
+day
+operator+(const day& x, const days& y) NOEXCEPT
+{
+ return day{static_cast<unsigned>(x) + static_cast<unsigned>(y.count())};
+}
+
+CONSTCD11
+inline
+day
+operator+(const days& x, const day& y) NOEXCEPT
+{
+ return y + x;
+}
+
+CONSTCD11
+inline
+day
+operator-(const day& x, const days& y) NOEXCEPT
+{
+ return x + -y;
+}
+
+template<class CharT, class Traits>
+inline
+std::basic_ostream<CharT, Traits>&
+operator<<(std::basic_ostream<CharT, Traits>& os, const day& d)
+{
+ date::detail::save_stream<CharT, Traits> _(os);
+ os.fill('0');
+ os.flags(std::ios::dec | std::ios::right);
+ os.width(2);
+ os << static_cast<unsigned>(d);
+ return os;
+}
+
+// month
+
+CONSTCD11 inline month::month(unsigned m) NOEXCEPT : m_(static_cast<decltype(m_)>(m)) {}
+CONSTCD14 inline month& month::operator++() NOEXCEPT {if (++m_ == 13) m_ = 1; return *this;}
+CONSTCD14 inline month month::operator++(int) NOEXCEPT {auto tmp(*this); ++(*this); return tmp;}
+CONSTCD14 inline month& month::operator--() NOEXCEPT {if (--m_ == 0) m_ = 12; return *this;}
+CONSTCD14 inline month month::operator--(int) NOEXCEPT {auto tmp(*this); --(*this); return tmp;}
+
+CONSTCD14
+inline
+month&
+month::operator+=(const months& m) NOEXCEPT
+{
+ *this = *this + m;
+ return *this;
+}
+
+CONSTCD14
+inline
+month&
+month::operator-=(const months& m) NOEXCEPT
+{
+ *this = *this - m;
+ return *this;
+}
+
+CONSTCD11 inline month::operator unsigned() const NOEXCEPT {return m_;}
+CONSTCD11 inline bool month::ok() const NOEXCEPT {return 1 <= m_ && m_ <= 12;}
+
+CONSTCD11
+inline
+bool
+operator==(const month& x, const month& y) NOEXCEPT
+{
+ return static_cast<unsigned>(x) == static_cast<unsigned>(y);
+}
+
+CONSTCD11
+inline
+bool
+operator!=(const month& x, const month& y) NOEXCEPT
+{
+ return !(x == y);
+}
+
+CONSTCD11
+inline
+bool
+operator<(const month& x, const month& y) NOEXCEPT
+{
+ return static_cast<unsigned>(x) < static_cast<unsigned>(y);
+}
+
+CONSTCD11
+inline
+bool
+operator>(const month& x, const month& y) NOEXCEPT
+{
+ return y < x;
+}
+
+CONSTCD11
+inline
+bool
+operator<=(const month& x, const month& y) NOEXCEPT
+{
+ return !(y < x);
+}
+
+CONSTCD11
+inline
+bool
+operator>=(const month& x, const month& y) NOEXCEPT
+{
+ return !(x < y);
+}
+
+CONSTCD14
+inline
+months
+operator-(const month& x, const month& y) NOEXCEPT
+{
+ auto const d = static_cast<unsigned>(x) - static_cast<unsigned>(y);
+ return months(d <= 11 ? d : d + 12);
+}
+
+CONSTCD14
+inline
+month
+operator+(const month& x, const months& y) NOEXCEPT
+{
+ auto const mu = static_cast<long long>(static_cast<unsigned>(x)) - 1 + y.count();
+ auto const yr = (mu >= 0 ? mu : mu-11) / 12;
+ return month{static_cast<unsigned>(mu - yr * 12 + 1)};
+}
+
+CONSTCD14
+inline
+month
+operator+(const months& x, const month& y) NOEXCEPT
+{
+ return y + x;
+}
+
+CONSTCD14
+inline
+month
+operator-(const month& x, const months& y) NOEXCEPT
+{
+ return x + -y;
+}
+
+template<class CharT, class Traits>
+inline
+std::basic_ostream<CharT, Traits>&
+operator<<(std::basic_ostream<CharT, Traits>& os, const month& m)
+{
+ switch (static_cast<unsigned>(m))
+ {
+ case 1:
+ os << "Muharram";
+ break;
+ case 2:
+ os << "Safar";
+ break;
+ case 3:
+ os << "Rabi' al-awwal";
+ break;
+ case 4:
+ os << "Rabi' al-thani";
+ break;
+ case 5:
+ os << "Jumada al-awwal";
+ break;
+ case 6:
+ os << "Jumada al-Thani";
+ break;
+ case 7:
+ os << "Rajab";
+ break;
+ case 8:
+ os << "Sha'ban";
+ break;
+ case 9:
+ os << "Ramadan";
+ break;
+ case 10:
+ os << "Shawwal";
+ break;
+ case 11:
+ os << "Dhu al-Qi'dah";
+ break;
+ case 12:
+ os << "Dhu al-Hijjah";
+ break;
+ default:
+ os << static_cast<unsigned>(m) << " is not a valid month";
+ break;
+ }
+ return os;
+}
+
+// year
+
+CONSTCD11 inline year::year(int y) NOEXCEPT : y_(static_cast<decltype(y_)>(y)) {}
+CONSTCD14 inline year& year::operator++() NOEXCEPT {++y_; return *this;}
+CONSTCD14 inline year year::operator++(int) NOEXCEPT {auto tmp(*this); ++(*this); return tmp;}
+CONSTCD14 inline year& year::operator--() NOEXCEPT {--y_; return *this;}
+CONSTCD14 inline year year::operator--(int) NOEXCEPT {auto tmp(*this); --(*this); return tmp;}
+CONSTCD14 inline year& year::operator+=(const years& y) NOEXCEPT {*this = *this + y; return *this;}
+CONSTCD14 inline year& year::operator-=(const years& y) NOEXCEPT {*this = *this - y; return *this;}
+
+CONSTCD11
+inline
+bool
+year::is_leap() const NOEXCEPT
+{
+ int y = y_ - 1;
+ const int era = (y >= 0 ? y : y-29) / 30;
+ const unsigned yoe = static_cast<unsigned>(y - era * 30);
+ switch (yoe)
+ {
+ case 1:
+ case 4:
+ case 6:
+ case 9:
+ case 12:
+ case 15:
+ case 17:
+ case 20:
+ case 23:
+ case 25:
+ case 28:
+ return true;
+ default:
+ return false;
+ }
+}
+
+CONSTCD11 inline year::operator int() const NOEXCEPT {return y_;}
+CONSTCD11 inline bool year::ok() const NOEXCEPT {return true;}
+
+CONSTCD11
+inline
+year
+year::min() NOEXCEPT
+{
+ return year{std::numeric_limits<short>::min()};
+}
+
+CONSTCD11
+inline
+year
+year::max() NOEXCEPT
+{
+ return year{std::numeric_limits<short>::max()};
+}
+
+CONSTCD11
+inline
+bool
+operator==(const year& x, const year& y) NOEXCEPT
+{
+ return static_cast<int>(x) == static_cast<int>(y);
+}
+
+CONSTCD11
+inline
+bool
+operator!=(const year& x, const year& y) NOEXCEPT
+{
+ return !(x == y);
+}
+
+CONSTCD11
+inline
+bool
+operator<(const year& x, const year& y) NOEXCEPT
+{
+ return static_cast<int>(x) < static_cast<int>(y);
+}
+
+CONSTCD11
+inline
+bool
+operator>(const year& x, const year& y) NOEXCEPT
+{
+ return y < x;
+}
+
+CONSTCD11
+inline
+bool
+operator<=(const year& x, const year& y) NOEXCEPT
+{
+ return !(y < x);
+}
+
+CONSTCD11
+inline
+bool
+operator>=(const year& x, const year& y) NOEXCEPT
+{
+ return !(x < y);
+}
+
+CONSTCD11
+inline
+years
+operator-(const year& x, const year& y) NOEXCEPT
+{
+ return years{static_cast<int>(x) - static_cast<int>(y)};
+}
+
+CONSTCD11
+inline
+year
+operator+(const year& x, const years& y) NOEXCEPT
+{
+ return year{static_cast<int>(x) + y.count()};
+}
+
+CONSTCD11
+inline
+year
+operator+(const years& x, const year& y) NOEXCEPT
+{
+ return y + x;
+}
+
+CONSTCD11
+inline
+year
+operator-(const year& x, const years& y) NOEXCEPT
+{
+ return year{static_cast<int>(x) - y.count()};
+}
+
+template<class CharT, class Traits>
+inline
+std::basic_ostream<CharT, Traits>&
+operator<<(std::basic_ostream<CharT, Traits>& os, const year& y)
+{
+ date::detail::save_stream<CharT, Traits> _(os);
+ os.fill('0');
+ os.flags(std::ios::dec | std::ios::internal);
+ os.width(4 + (y < year{0}));
+ os << static_cast<int>(y);
+ return os;
+}
+
+// weekday
+
+CONSTCD11
+inline
+unsigned char
+weekday::weekday_from_days(int z) NOEXCEPT
+{
+ return static_cast<unsigned char>(static_cast<unsigned>(
+ z >= -4 ? (z+4) % 7 : (z+5) % 7 + 6));
+}
+
+CONSTCD11
+inline
+weekday::weekday(unsigned wd) NOEXCEPT
+ : wd_(static_cast<decltype(wd_)>(wd))
+ {}
+
+CONSTCD11
+inline
+weekday::weekday(const sys_days& dp) NOEXCEPT
+ : wd_(weekday_from_days(dp.time_since_epoch().count()))
+ {}
+
+CONSTCD11
+inline
+weekday::weekday(const local_days& dp) NOEXCEPT
+ : wd_(weekday_from_days(dp.time_since_epoch().count()))
+ {}
+
+CONSTCD14 inline weekday& weekday::operator++() NOEXCEPT {if (++wd_ == 7) wd_ = 0; return *this;}
+CONSTCD14 inline weekday weekday::operator++(int) NOEXCEPT {auto tmp(*this); ++(*this); return tmp;}
+CONSTCD14 inline weekday& weekday::operator--() NOEXCEPT {if (wd_-- == 0) wd_ = 6; return *this;}
+CONSTCD14 inline weekday weekday::operator--(int) NOEXCEPT {auto tmp(*this); --(*this); return tmp;}
+
+CONSTCD14
+inline
+weekday&
+weekday::operator+=(const days& d) NOEXCEPT
+{
+ *this = *this + d;
+ return *this;
+}
+
+CONSTCD14
+inline
+weekday&
+weekday::operator-=(const days& d) NOEXCEPT
+{
+ *this = *this - d;
+ return *this;
+}
+
+CONSTCD11
+inline
+weekday::operator unsigned() const NOEXCEPT
+{
+ return static_cast<unsigned>(wd_);
+}
+
+CONSTCD11 inline bool weekday::ok() const NOEXCEPT {return wd_ <= 6;}
+
+CONSTCD11
+inline
+bool
+operator==(const weekday& x, const weekday& y) NOEXCEPT
+{
+ return static_cast<unsigned>(x) == static_cast<unsigned>(y);
+}
+
+CONSTCD11
+inline
+bool
+operator!=(const weekday& x, const weekday& y) NOEXCEPT
+{
+ return !(x == y);
+}
+
+CONSTCD14
+inline
+days
+operator-(const weekday& x, const weekday& y) NOEXCEPT
+{
+ auto const diff = static_cast<unsigned>(x) - static_cast<unsigned>(y);
+ return days{diff <= 6 ? diff : diff + 7};
+}
+
+CONSTCD14
+inline
+weekday
+operator+(const weekday& x, const days& y) NOEXCEPT
+{
+ auto const wdu = static_cast<long long>(static_cast<unsigned>(x)) + y.count();
+ auto const wk = (wdu >= 0 ? wdu : wdu-6) / 7;
+ return weekday{static_cast<unsigned>(wdu - wk * 7)};
+}
+
+CONSTCD14
+inline
+weekday
+operator+(const days& x, const weekday& y) NOEXCEPT
+{
+ return y + x;
+}
+
+CONSTCD14
+inline
+weekday
+operator-(const weekday& x, const days& y) NOEXCEPT
+{
+ return x + -y;
+}
+
+template<class CharT, class Traits>
+inline
+std::basic_ostream<CharT, Traits>&
+operator<<(std::basic_ostream<CharT, Traits>& os, const weekday& wd)
+{
+ switch (static_cast<unsigned>(wd))
+ {
+ case 0:
+ os << "al-Aḥad";
+ break;
+ case 1:
+ os << "al-Ithnayn";
+ break;
+ case 2:
+ os << "ath-Thulāthā’";
+ break;
+ case 3:
+ os << "al-Arba‘ā’";
+ break;
+ case 4:
+ os << "al-Khamīs";
+ break;
+ case 5:
+ os << "al-Jum‘ah";
+ break;
+ case 6:
+ os << "as-Sabt";
+ break;
+ default:
+ os << static_cast<unsigned>(wd) << " is not a valid weekday";
+ break;
+ }
+ return os;
+}
+
+#if !defined(_MSC_VER) || (_MSC_VER >= 1900)
+inline namespace literals
+{
+
+CONSTCD11
+inline
+islamic::day
+operator "" _d(unsigned long long d) NOEXCEPT
+{
+ return islamic::day{static_cast<unsigned>(d)};
+}
+
+CONSTCD11
+inline
+islamic::year
+operator "" _y(unsigned long long y) NOEXCEPT
+{
+ return islamic::year(static_cast<int>(y));
+}
+#endif // !defined(_MSC_VER) || (_MSC_VER >= 1900)
+
+CONSTDATA islamic::last_spec last{};
+
+#if !defined(_MSC_VER) || (_MSC_VER >= 1900)
+} // inline namespace literals
+#endif
+
+// weekday_indexed
+
+CONSTCD11
+inline
+weekday
+weekday_indexed::weekday() const NOEXCEPT
+{
+ return islamic::weekday{static_cast<unsigned>(wd_)};
+}
+
+CONSTCD11 inline unsigned weekday_indexed::index() const NOEXCEPT {return index_;}
+
+CONSTCD11
+inline
+bool
+weekday_indexed::ok() const NOEXCEPT
+{
+ return weekday().ok() && 1 <= index_ && index_ <= 5;
+}
+
+CONSTCD11
+inline
+weekday_indexed::weekday_indexed(const islamic::weekday& wd, unsigned index) NOEXCEPT
+ : wd_(static_cast<decltype(wd_)>(static_cast<unsigned>(wd)))
+ , index_(static_cast<decltype(index_)>(index))
+ {}
+
+template<class CharT, class Traits>
+inline
+std::basic_ostream<CharT, Traits>&
+operator<<(std::basic_ostream<CharT, Traits>& os, const weekday_indexed& wdi)
+{
+ return os << wdi.weekday() << '[' << wdi.index() << ']';
+}
+
+CONSTCD11
+inline
+weekday_indexed
+weekday::operator[](unsigned index) const NOEXCEPT
+{
+ return {*this, index};
+}
+
+CONSTCD11
+inline
+bool
+operator==(const weekday_indexed& x, const weekday_indexed& y) NOEXCEPT
+{
+ return x.weekday() == y.weekday() && x.index() == y.index();
+}
+
+CONSTCD11
+inline
+bool
+operator!=(const weekday_indexed& x, const weekday_indexed& y) NOEXCEPT
+{
+ return !(x == y);
+}
+
+// weekday_last
+
+CONSTCD11 inline islamic::weekday weekday_last::weekday() const NOEXCEPT {return wd_;}
+CONSTCD11 inline bool weekday_last::ok() const NOEXCEPT {return wd_.ok();}
+CONSTCD11 inline weekday_last::weekday_last(const islamic::weekday& wd) NOEXCEPT : wd_(wd) {}
+
+CONSTCD11
+inline
+bool
+operator==(const weekday_last& x, const weekday_last& y) NOEXCEPT
+{
+ return x.weekday() == y.weekday();
+}
+
+CONSTCD11
+inline
+bool
+operator!=(const weekday_last& x, const weekday_last& y) NOEXCEPT
+{
+ return !(x == y);
+}
+
+template<class CharT, class Traits>
+inline
+std::basic_ostream<CharT, Traits>&
+operator<<(std::basic_ostream<CharT, Traits>& os, const weekday_last& wdl)
+{
+ return os << wdl.weekday() << "[last]";
+}
+
+CONSTCD11
+inline
+weekday_last
+weekday::operator[](last_spec) const NOEXCEPT
+{
+ return weekday_last{*this};
+}
+
+// year_month
+
+CONSTCD11
+inline
+year_month::year_month(const islamic::year& y, const islamic::month& m) NOEXCEPT
+ : y_(y)
+ , m_(m)
+ {}
+
+CONSTCD11 inline year year_month::year() const NOEXCEPT {return y_;}
+CONSTCD11 inline month year_month::month() const NOEXCEPT {return m_;}
+CONSTCD11 inline bool year_month::ok() const NOEXCEPT {return y_.ok() && m_.ok();}
+
+CONSTCD14
+inline
+year_month&
+year_month::operator+=(const months& dm) NOEXCEPT
+{
+ *this = *this + dm;
+ return *this;
+}
+
+CONSTCD14
+inline
+year_month&
+year_month::operator-=(const months& dm) NOEXCEPT
+{
+ *this = *this - dm;
+ return *this;
+}
+
+CONSTCD14
+inline
+year_month&
+year_month::operator+=(const years& dy) NOEXCEPT
+{
+ *this = *this + dy;
+ return *this;
+}
+
+CONSTCD14
+inline
+year_month&
+year_month::operator-=(const years& dy) NOEXCEPT
+{
+ *this = *this - dy;
+ return *this;
+}
+
+CONSTCD11
+inline
+bool
+operator==(const year_month& x, const year_month& y) NOEXCEPT
+{
+ return x.year() == y.year() && x.month() == y.month();
+}
+
+CONSTCD11
+inline
+bool
+operator!=(const year_month& x, const year_month& y) NOEXCEPT
+{
+ return !(x == y);
+}
+
+CONSTCD11
+inline
+bool
+operator<(const year_month& x, const year_month& y) NOEXCEPT
+{
+ return x.year() < y.year() ? true
+ : (x.year() > y.year() ? false
+ : (x.month() < y.month()));
+}
+
+CONSTCD11
+inline
+bool
+operator>(const year_month& x, const year_month& y) NOEXCEPT
+{
+ return y < x;
+}
+
+CONSTCD11
+inline
+bool
+operator<=(const year_month& x, const year_month& y) NOEXCEPT
+{
+ return !(y < x);
+}
+
+CONSTCD11
+inline
+bool
+operator>=(const year_month& x, const year_month& y) NOEXCEPT
+{
+ return !(x < y);
+}
+
+CONSTCD14
+inline
+year_month
+operator+(const year_month& ym, const months& dm) NOEXCEPT
+{
+ auto dmi = static_cast<int>(static_cast<unsigned>(ym.month())) - 1 + dm.count();
+ auto dy = (dmi >= 0 ? dmi : dmi-11) / 12;
+ dmi = dmi - dy * 12 + 1;
+ return (ym.year() + years(dy)) / month(static_cast<unsigned>(dmi));
+}
+
+CONSTCD14
+inline
+year_month
+operator+(const months& dm, const year_month& ym) NOEXCEPT
+{
+ return ym + dm;
+}
+
+CONSTCD14
+inline
+year_month
+operator-(const year_month& ym, const months& dm) NOEXCEPT
+{
+ return ym + -dm;
+}
+
+CONSTCD11
+inline
+months
+operator-(const year_month& x, const year_month& y) NOEXCEPT
+{
+ return (x.year() - y.year()) +
+ months(static_cast<unsigned>(x.month()) - static_cast<unsigned>(y.month()));
+}
+
+CONSTCD11
+inline
+year_month
+operator+(const year_month& ym, const years& dy) NOEXCEPT
+{
+ return (ym.year() + dy) / ym.month();
+}
+
+CONSTCD11
+inline
+year_month
+operator+(const years& dy, const year_month& ym) NOEXCEPT
+{
+ return ym + dy;
+}
+
+CONSTCD11
+inline
+year_month
+operator-(const year_month& ym, const years& dy) NOEXCEPT
+{
+ return ym + -dy;
+}
+
+template<class CharT, class Traits>
+inline
+std::basic_ostream<CharT, Traits>&
+operator<<(std::basic_ostream<CharT, Traits>& os, const year_month& ym)
+{
+ return os << ym.year() << '/' << ym.month();
+}
+
+// month_day
+
+CONSTCD11
+inline
+month_day::month_day(const islamic::month& m, const islamic::day& d) NOEXCEPT
+ : m_(m)
+ , d_(d)
+ {}
+
+CONSTCD11 inline islamic::month month_day::month() const NOEXCEPT {return m_;}
+CONSTCD11 inline islamic::day month_day::day() const NOEXCEPT {return d_;}
+
+CONSTCD14
+inline
+bool
+month_day::ok() const NOEXCEPT
+{
+ CONSTDATA islamic::day d[] =
+ {30_d, 29_d, 30_d, 29_d, 30_d, 29_d, 30_d, 29_d, 30_d, 29_d, 30_d, 30_d};
+ return m_.ok() && 1_d <= d_ && d_ <= d[static_cast<unsigned>(m_)-1];
+}
+
+CONSTCD11
+inline
+bool
+operator==(const month_day& x, const month_day& y) NOEXCEPT
+{
+ return x.month() == y.month() && x.day() == y.day();
+}
+
+CONSTCD11
+inline
+bool
+operator!=(const month_day& x, const month_day& y) NOEXCEPT
+{
+ return !(x == y);
+}
+
+CONSTCD11
+inline
+bool
+operator<(const month_day& x, const month_day& y) NOEXCEPT
+{
+ return x.month() < y.month() ? true
+ : (x.month() > y.month() ? false
+ : (x.day() < y.day()));
+}
+
+CONSTCD11
+inline
+bool
+operator>(const month_day& x, const month_day& y) NOEXCEPT
+{
+ return y < x;
+}
+
+CONSTCD11
+inline
+bool
+operator<=(const month_day& x, const month_day& y) NOEXCEPT
+{
+ return !(y < x);
+}
+
+CONSTCD11
+inline
+bool
+operator>=(const month_day& x, const month_day& y) NOEXCEPT
+{
+ return !(x < y);
+}
+
+template<class CharT, class Traits>
+inline
+std::basic_ostream<CharT, Traits>&
+operator<<(std::basic_ostream<CharT, Traits>& os, const month_day& md)
+{
+ return os << md.month() << '/' << md.day();
+}
+
+// month_day_last
+
+CONSTCD11 inline month month_day_last::month() const NOEXCEPT {return m_;}
+CONSTCD11 inline bool month_day_last::ok() const NOEXCEPT {return m_.ok();}
+CONSTCD11 inline month_day_last::month_day_last(const islamic::month& m) NOEXCEPT : m_(m) {}
+
+CONSTCD11
+inline
+bool
+operator==(const month_day_last& x, const month_day_last& y) NOEXCEPT
+{
+ return x.month() == y.month();
+}
+
+CONSTCD11
+inline
+bool
+operator!=(const month_day_last& x, const month_day_last& y) NOEXCEPT
+{
+ return !(x == y);
+}
+
+CONSTCD11
+inline
+bool
+operator<(const month_day_last& x, const month_day_last& y) NOEXCEPT
+{
+ return x.month() < y.month();
+}
+
+CONSTCD11
+inline
+bool
+operator>(const month_day_last& x, const month_day_last& y) NOEXCEPT
+{
+ return y < x;
+}
+
+CONSTCD11
+inline
+bool
+operator<=(const month_day_last& x, const month_day_last& y) NOEXCEPT
+{
+ return !(y < x);
+}
+
+CONSTCD11
+inline
+bool
+operator>=(const month_day_last& x, const month_day_last& y) NOEXCEPT
+{
+ return !(x < y);
+}
+
+template<class CharT, class Traits>
+inline
+std::basic_ostream<CharT, Traits>&
+operator<<(std::basic_ostream<CharT, Traits>& os, const month_day_last& mdl)
+{
+ return os << mdl.month() << "/last";
+}
+
+// month_weekday
+
+CONSTCD11
+inline
+month_weekday::month_weekday(const islamic::month& m,
+ const islamic::weekday_indexed& wdi) NOEXCEPT
+ : m_(m)
+ , wdi_(wdi)
+ {}
+
+CONSTCD11 inline month month_weekday::month() const NOEXCEPT {return m_;}
+
+CONSTCD11
+inline
+weekday_indexed
+month_weekday::weekday_indexed() const NOEXCEPT
+{
+ return wdi_;
+}
+
+CONSTCD11
+inline
+bool
+month_weekday::ok() const NOEXCEPT
+{
+ return m_.ok() && wdi_.ok();
+}
+
+CONSTCD11
+inline
+bool
+operator==(const month_weekday& x, const month_weekday& y) NOEXCEPT
+{
+ return x.month() == y.month() && x.weekday_indexed() == y.weekday_indexed();
+}
+
+CONSTCD11
+inline
+bool
+operator!=(const month_weekday& x, const month_weekday& y) NOEXCEPT
+{
+ return !(x == y);
+}
+
+template<class CharT, class Traits>
+inline
+std::basic_ostream<CharT, Traits>&
+operator<<(std::basic_ostream<CharT, Traits>& os, const month_weekday& mwd)
+{
+ return os << mwd.month() << '/' << mwd.weekday_indexed();
+}
+
+// month_weekday_last
+
+CONSTCD11
+inline
+month_weekday_last::month_weekday_last(const islamic::month& m,
+ const islamic::weekday_last& wdl) NOEXCEPT
+ : m_(m)
+ , wdl_(wdl)
+ {}
+
+CONSTCD11 inline month month_weekday_last::month() const NOEXCEPT {return m_;}
+
+CONSTCD11
+inline
+weekday_last
+month_weekday_last::weekday_last() const NOEXCEPT
+{
+ return wdl_;
+}
+
+CONSTCD11
+inline
+bool
+month_weekday_last::ok() const NOEXCEPT
+{
+ return m_.ok() && wdl_.ok();
+}
+
+CONSTCD11
+inline
+bool
+operator==(const month_weekday_last& x, const month_weekday_last& y) NOEXCEPT
+{
+ return x.month() == y.month() && x.weekday_last() == y.weekday_last();
+}
+
+CONSTCD11
+inline
+bool
+operator!=(const month_weekday_last& x, const month_weekday_last& y) NOEXCEPT
+{
+ return !(x == y);
+}
+
+template<class CharT, class Traits>
+inline
+std::basic_ostream<CharT, Traits>&
+operator<<(std::basic_ostream<CharT, Traits>& os, const month_weekday_last& mwdl)
+{
+ return os << mwdl.month() << '/' << mwdl.weekday_last();
+}
+
+// year_month_day_last
+
+CONSTCD11
+inline
+year_month_day_last::year_month_day_last(const islamic::year& y,
+ const islamic::month_day_last& mdl) NOEXCEPT
+ : y_(y)
+ , mdl_(mdl)
+ {}
+
+CONSTCD14
+inline
+year_month_day_last&
+year_month_day_last::operator+=(const months& m) NOEXCEPT
+{
+ *this = *this + m;
+ return *this;
+}
+
+CONSTCD14
+inline
+year_month_day_last&
+year_month_day_last::operator-=(const months& m) NOEXCEPT
+{
+ *this = *this - m;
+ return *this;
+}
+
+CONSTCD14
+inline
+year_month_day_last&
+year_month_day_last::operator+=(const years& y) NOEXCEPT
+{
+ *this = *this + y;
+ return *this;
+}
+
+CONSTCD14
+inline
+year_month_day_last&
+year_month_day_last::operator-=(const years& y) NOEXCEPT
+{
+ *this = *this - y;
+ return *this;
+}
+
+CONSTCD11 inline year year_month_day_last::year() const NOEXCEPT {return y_;}
+CONSTCD11 inline month year_month_day_last::month() const NOEXCEPT {return mdl_.month();}
+
+CONSTCD11
+inline
+month_day_last
+year_month_day_last::month_day_last() const NOEXCEPT
+{
+ return mdl_;
+}
+
+CONSTCD14
+inline
+day
+year_month_day_last::day() const NOEXCEPT
+{
+ CONSTDATA islamic::day d[] =
+ {30_d, 29_d, 30_d, 29_d, 30_d, 29_d, 30_d, 29_d, 30_d, 29_d, 30_d, 29_d};
+ return month() != islamic::month(12) || !y_.is_leap() ?
+ d[static_cast<unsigned>(month())-1] : 30_d;
+}
+
+CONSTCD14
+inline
+year_month_day_last::operator sys_days() const NOEXCEPT
+{
+ return sys_days(year()/month()/day());
+}
+
+CONSTCD14
+inline
+year_month_day_last::operator local_days() const NOEXCEPT
+{
+ return local_days(year()/month()/day());
+}
+
+CONSTCD11
+inline
+bool
+year_month_day_last::ok() const NOEXCEPT
+{
+ return y_.ok() && mdl_.ok();
+}
+
+CONSTCD11
+inline
+bool
+operator==(const year_month_day_last& x, const year_month_day_last& y) NOEXCEPT
+{
+ return x.year() == y.year() && x.month_day_last() == y.month_day_last();
+}
+
+CONSTCD11
+inline
+bool
+operator!=(const year_month_day_last& x, const year_month_day_last& y) NOEXCEPT
+{
+ return !(x == y);
+}
+
+CONSTCD11
+inline
+bool
+operator<(const year_month_day_last& x, const year_month_day_last& y) NOEXCEPT
+{
+ return x.year() < y.year() ? true
+ : (x.year() > y.year() ? false
+ : (x.month_day_last() < y.month_day_last()));
+}
+
+CONSTCD11
+inline
+bool
+operator>(const year_month_day_last& x, const year_month_day_last& y) NOEXCEPT
+{
+ return y < x;
+}
+
+CONSTCD11
+inline
+bool
+operator<=(const year_month_day_last& x, const year_month_day_last& y) NOEXCEPT
+{
+ return !(y < x);
+}
+
+CONSTCD11
+inline
+bool
+operator>=(const year_month_day_last& x, const year_month_day_last& y) NOEXCEPT
+{
+ return !(x < y);
+}
+
+template<class CharT, class Traits>
+inline
+std::basic_ostream<CharT, Traits>&
+operator<<(std::basic_ostream<CharT, Traits>& os, const year_month_day_last& ymdl)
+{
+ return os << ymdl.year() << '/' << ymdl.month_day_last();
+}
+
+CONSTCD14
+inline
+year_month_day_last
+operator+(const year_month_day_last& ymdl, const months& dm) NOEXCEPT
+{
+ return (ymdl.year() / ymdl.month() + dm) / last;
+}
+
+CONSTCD14
+inline
+year_month_day_last
+operator+(const months& dm, const year_month_day_last& ymdl) NOEXCEPT
+{
+ return ymdl + dm;
+}
+
+CONSTCD14
+inline
+year_month_day_last
+operator-(const year_month_day_last& ymdl, const months& dm) NOEXCEPT
+{
+ return ymdl + (-dm);
+}
+
+CONSTCD11
+inline
+year_month_day_last
+operator+(const year_month_day_last& ymdl, const years& dy) NOEXCEPT
+{
+ return {ymdl.year()+dy, ymdl.month_day_last()};
+}
+
+CONSTCD11
+inline
+year_month_day_last
+operator+(const years& dy, const year_month_day_last& ymdl) NOEXCEPT
+{
+ return ymdl + dy;
+}
+
+CONSTCD11
+inline
+year_month_day_last
+operator-(const year_month_day_last& ymdl, const years& dy) NOEXCEPT
+{
+ return ymdl + (-dy);
+}
+
+// year_month_day
+
+CONSTCD11
+inline
+year_month_day::year_month_day(const islamic::year& y, const islamic::month& m,
+ const islamic::day& d) NOEXCEPT
+ : y_(y)
+ , m_(m)
+ , d_(d)
+ {}
+
+CONSTCD14
+inline
+year_month_day::year_month_day(const year_month_day_last& ymdl) NOEXCEPT
+ : y_(ymdl.year())
+ , m_(ymdl.month())
+ , d_(ymdl.day())
+ {}
+
+CONSTCD14
+inline
+year_month_day::year_month_day(sys_days dp) NOEXCEPT
+ : year_month_day(from_days(dp.time_since_epoch()))
+ {}
+
+CONSTCD14
+inline
+year_month_day::year_month_day(local_days dp) NOEXCEPT
+ : year_month_day(from_days(dp.time_since_epoch()))
+ {}
+
+CONSTCD11 inline year year_month_day::year() const NOEXCEPT {return y_;}
+CONSTCD11 inline month year_month_day::month() const NOEXCEPT {return m_;}
+CONSTCD11 inline day year_month_day::day() const NOEXCEPT {return d_;}
+
+CONSTCD14
+inline
+year_month_day&
+year_month_day::operator+=(const months& m) NOEXCEPT
+{
+ *this = *this + m;
+ return *this;
+}
+
+CONSTCD14
+inline
+year_month_day&
+year_month_day::operator-=(const months& m) NOEXCEPT
+{
+ *this = *this - m;
+ return *this;
+}
+
+CONSTCD14
+inline
+year_month_day&
+year_month_day::operator+=(const years& y) NOEXCEPT
+{
+ *this = *this + y;
+ return *this;
+}
+
+CONSTCD14
+inline
+year_month_day&
+year_month_day::operator-=(const years& y) NOEXCEPT
+{
+ *this = *this - y;
+ return *this;
+}
+
+CONSTCD14
+inline
+days
+year_month_day::to_days() const NOEXCEPT
+{
+ static_assert(std::numeric_limits<unsigned>::digits >= 18,
+ "This algorithm has not been ported to a 16 bit unsigned integer");
+ static_assert(std::numeric_limits<int>::digits >= 20,
+ "This algorithm has not been ported to a 16 bit signed integer");
+ auto const y = static_cast<int>(y_) - 1;
+ auto const m = static_cast<unsigned>(m_);
+ auto const d = static_cast<unsigned>(d_);
+ auto const era = (y >= 0 ? y : y-29) / 30;
+ auto const yoe = static_cast<unsigned>(y - era * 30); // [0, 29]
+ auto const doy = 29*(m-1) + m/2 + d-1; // [0, 354]
+ auto const doe = yoe * 354 + (11*(yoe+1)+3)/30 + doy; // [0, 10630]
+ return days{era * 10631 + static_cast<int>(doe) - 492148};
+}
+
+CONSTCD14
+inline
+year_month_day::operator sys_days() const NOEXCEPT
+{
+ return sys_days{to_days()};
+}
+
+CONSTCD14
+inline
+year_month_day::operator local_days() const NOEXCEPT
+{
+ return local_days{to_days()};
+}
+
+CONSTCD14
+inline
+bool
+year_month_day::ok() const NOEXCEPT
+{
+ if (!(y_.ok() && m_.ok()))
+ return false;
+ return 1_d <= d_ && d_ <= (y_/m_/last).day();
+}
+
+CONSTCD11
+inline
+bool
+operator==(const year_month_day& x, const year_month_day& y) NOEXCEPT
+{
+ return x.year() == y.year() && x.month() == y.month() && x.day() == y.day();
+}
+
+CONSTCD11
+inline
+bool
+operator!=(const year_month_day& x, const year_month_day& y) NOEXCEPT
+{
+ return !(x == y);
+}
+
+CONSTCD11
+inline
+bool
+operator<(const year_month_day& x, const year_month_day& y) NOEXCEPT
+{
+ return x.year() < y.year() ? true
+ : (x.year() > y.year() ? false
+ : (x.month() < y.month() ? true
+ : (x.month() > y.month() ? false
+ : (x.day() < y.day()))));
+}
+
+CONSTCD11
+inline
+bool
+operator>(const year_month_day& x, const year_month_day& y) NOEXCEPT
+{
+ return y < x;
+}
+
+CONSTCD11
+inline
+bool
+operator<=(const year_month_day& x, const year_month_day& y) NOEXCEPT
+{
+ return !(y < x);
+}
+
+CONSTCD11
+inline
+bool
+operator>=(const year_month_day& x, const year_month_day& y) NOEXCEPT
+{
+ return !(x < y);
+}
+
+template<class CharT, class Traits>
+inline
+std::basic_ostream<CharT, Traits>&
+operator<<(std::basic_ostream<CharT, Traits>& os, const year_month_day& ymd)
+{
+ date::detail::save_stream<CharT, Traits> _(os);
+ os.fill('0');
+ os.flags(std::ios::dec | std::ios::right);
+ os << ymd.year() << '-';
+ os.width(2);
+ os << static_cast<unsigned>(ymd.month()) << '-';
+ os << ymd.day();
+ return os;
+}
+
+CONSTCD14
+inline
+year_month_day
+year_month_day::from_days(days dp) NOEXCEPT
+{
+ static_assert(std::numeric_limits<unsigned>::digits >= 18,
+ "This algorithm has not been ported to a 16 bit unsigned integer");
+ static_assert(std::numeric_limits<int>::digits >= 20,
+ "This algorithm has not been ported to a 16 bit signed integer");
+ auto const z = dp.count() + 492148;
+ auto const era = (z >= 0 ? z : z - 10630) / 10631;
+ auto const doe = static_cast<unsigned>(z - era * 10631); // [0, 10630]
+ auto const yoe = (30*doe + 10646)/10631 - 1; // [0, 29]
+ auto const y = static_cast<sys_days::rep>(yoe) + era * 30 + 1;
+ auto const doy = doe - (yoe * 354 + (11*(yoe+1)+3)/30); // [0, 354]
+ auto const m = (11*doy + 330) / 325; // [1, 12]
+ auto const d = doy - (29*(m-1) + m/2) + 1; // [1, 30]
+ return year_month_day{islamic::year{y}, islamic::month(m), islamic::day(d)};
+}
+
+CONSTCD14
+inline
+year_month_day
+operator+(const year_month_day& ymd, const months& dm) NOEXCEPT
+{
+ return (ymd.year() / ymd.month() + dm) / ymd.day();
+}
+
+CONSTCD14
+inline
+year_month_day
+operator+(const months& dm, const year_month_day& ymd) NOEXCEPT
+{
+ return ymd + dm;
+}
+
+CONSTCD14
+inline
+year_month_day
+operator-(const year_month_day& ymd, const months& dm) NOEXCEPT
+{
+ return ymd + (-dm);
+}
+
+CONSTCD11
+inline
+year_month_day
+operator+(const year_month_day& ymd, const years& dy) NOEXCEPT
+{
+ return (ymd.year() + dy) / ymd.month() / ymd.day();
+}
+
+CONSTCD11
+inline
+year_month_day
+operator+(const years& dy, const year_month_day& ymd) NOEXCEPT
+{
+ return ymd + dy;
+}
+
+CONSTCD11
+inline
+year_month_day
+operator-(const year_month_day& ymd, const years& dy) NOEXCEPT
+{
+ return ymd + (-dy);
+}
+
+// year_month_weekday
+
+CONSTCD11
+inline
+year_month_weekday::year_month_weekday(const islamic::year& y, const islamic::month& m,
+ const islamic::weekday_indexed& wdi)
+ NOEXCEPT
+ : y_(y)
+ , m_(m)
+ , wdi_(wdi)
+ {}
+
+CONSTCD14
+inline
+year_month_weekday::year_month_weekday(const sys_days& dp) NOEXCEPT
+ : year_month_weekday(from_days(dp.time_since_epoch()))
+ {}
+
+CONSTCD14
+inline
+year_month_weekday::year_month_weekday(const local_days& dp) NOEXCEPT
+ : year_month_weekday(from_days(dp.time_since_epoch()))
+ {}
+
+CONSTCD14
+inline
+year_month_weekday&
+year_month_weekday::operator+=(const months& m) NOEXCEPT
+{
+ *this = *this + m;
+ return *this;
+}
+
+CONSTCD14
+inline
+year_month_weekday&
+year_month_weekday::operator-=(const months& m) NOEXCEPT
+{
+ *this = *this - m;
+ return *this;
+}
+
+CONSTCD14
+inline
+year_month_weekday&
+year_month_weekday::operator+=(const years& y) NOEXCEPT
+{
+ *this = *this + y;
+ return *this;
+}
+
+CONSTCD14
+inline
+year_month_weekday&
+year_month_weekday::operator-=(const years& y) NOEXCEPT
+{
+ *this = *this - y;
+ return *this;
+}
+
+CONSTCD11 inline year year_month_weekday::year() const NOEXCEPT {return y_;}
+CONSTCD11 inline month year_month_weekday::month() const NOEXCEPT {return m_;}
+
+CONSTCD11
+inline
+weekday
+year_month_weekday::weekday() const NOEXCEPT
+{
+ return wdi_.weekday();
+}
+
+CONSTCD11
+inline
+unsigned
+year_month_weekday::index() const NOEXCEPT
+{
+ return wdi_.index();
+}
+
+CONSTCD11
+inline
+weekday_indexed
+year_month_weekday::weekday_indexed() const NOEXCEPT
+{
+ return wdi_;
+}
+
+CONSTCD14
+inline
+year_month_weekday::operator sys_days() const NOEXCEPT
+{
+ return sys_days{to_days()};
+}
+
+CONSTCD14
+inline
+year_month_weekday::operator local_days() const NOEXCEPT
+{
+ return local_days{to_days()};
+}
+
+CONSTCD14
+inline
+bool
+year_month_weekday::ok() const NOEXCEPT
+{
+ if (!y_.ok() || !m_.ok() || !wdi_.weekday().ok() || wdi_.index() < 1)
+ return false;
+ if (wdi_.index() <= 4)
+ return true;
+ auto d2 = wdi_.weekday() - islamic::weekday(y_/m_/1) + days((wdi_.index()-1)*7 + 1);
+ return static_cast<unsigned>(d2.count()) <= static_cast<unsigned>((y_/m_/last).day());
+}
+
+CONSTCD14
+inline
+year_month_weekday
+year_month_weekday::from_days(days d) NOEXCEPT
+{
+ sys_days dp{d};
+ auto const wd = islamic::weekday(dp);
+ auto const ymd = year_month_day(dp);
+ return {ymd.year(), ymd.month(), wd[(static_cast<unsigned>(ymd.day())-1)/7+1]};
+}
+
+CONSTCD14
+inline
+days
+year_month_weekday::to_days() const NOEXCEPT
+{
+ auto d = sys_days(y_/m_/1);
+ return (d + (wdi_.weekday() - islamic::weekday(d) + days{(wdi_.index()-1)*7})
+ ).time_since_epoch();
+}
+
+CONSTCD11
+inline
+bool
+operator==(const year_month_weekday& x, const year_month_weekday& y) NOEXCEPT
+{
+ return x.year() == y.year() && x.month() == y.month() &&
+ x.weekday_indexed() == y.weekday_indexed();
+}
+
+CONSTCD11
+inline
+bool
+operator!=(const year_month_weekday& x, const year_month_weekday& y) NOEXCEPT
+{
+ return !(x == y);
+}
+
+template<class CharT, class Traits>
+inline
+std::basic_ostream<CharT, Traits>&
+operator<<(std::basic_ostream<CharT, Traits>& os, const year_month_weekday& ymwdi)
+{
+ return os << ymwdi.year() << '/' << ymwdi.month()
+ << '/' << ymwdi.weekday_indexed();
+}
+
+CONSTCD14
+inline
+year_month_weekday
+operator+(const year_month_weekday& ymwd, const months& dm) NOEXCEPT
+{
+ return (ymwd.year() / ymwd.month() + dm) / ymwd.weekday_indexed();
+}
+
+CONSTCD14
+inline
+year_month_weekday
+operator+(const months& dm, const year_month_weekday& ymwd) NOEXCEPT
+{
+ return ymwd + dm;
+}
+
+CONSTCD14
+inline
+year_month_weekday
+operator-(const year_month_weekday& ymwd, const months& dm) NOEXCEPT
+{
+ return ymwd + (-dm);
+}
+
+CONSTCD11
+inline
+year_month_weekday
+operator+(const year_month_weekday& ymwd, const years& dy) NOEXCEPT
+{
+ return {ymwd.year()+dy, ymwd.month(), ymwd.weekday_indexed()};
+}
+
+CONSTCD11
+inline
+year_month_weekday
+operator+(const years& dy, const year_month_weekday& ymwd) NOEXCEPT
+{
+ return ymwd + dy;
+}
+
+CONSTCD11
+inline
+year_month_weekday
+operator-(const year_month_weekday& ymwd, const years& dy) NOEXCEPT
+{
+ return ymwd + (-dy);
+}
+
+// year_month_weekday_last
+
+CONSTCD11
+inline
+year_month_weekday_last::year_month_weekday_last(const islamic::year& y,
+ const islamic::month& m,
+ const islamic::weekday_last& wdl) NOEXCEPT
+ : y_(y)
+ , m_(m)
+ , wdl_(wdl)
+ {}
+
+CONSTCD14
+inline
+year_month_weekday_last&
+year_month_weekday_last::operator+=(const months& m) NOEXCEPT
+{
+ *this = *this + m;
+ return *this;
+}
+
+CONSTCD14
+inline
+year_month_weekday_last&
+year_month_weekday_last::operator-=(const months& m) NOEXCEPT
+{
+ *this = *this - m;
+ return *this;
+}
+
+CONSTCD14
+inline
+year_month_weekday_last&
+year_month_weekday_last::operator+=(const years& y) NOEXCEPT
+{
+ *this = *this + y;
+ return *this;
+}
+
+CONSTCD14
+inline
+year_month_weekday_last&
+year_month_weekday_last::operator-=(const years& y) NOEXCEPT
+{
+ *this = *this - y;
+ return *this;
+}
+
+CONSTCD11 inline year year_month_weekday_last::year() const NOEXCEPT {return y_;}
+CONSTCD11 inline month year_month_weekday_last::month() const NOEXCEPT {return m_;}
+
+CONSTCD11
+inline
+weekday
+year_month_weekday_last::weekday() const NOEXCEPT
+{
+ return wdl_.weekday();
+}
+
+CONSTCD11
+inline
+weekday_last
+year_month_weekday_last::weekday_last() const NOEXCEPT
+{
+ return wdl_;
+}
+
+CONSTCD14
+inline
+year_month_weekday_last::operator sys_days() const NOEXCEPT
+{
+ return sys_days{to_days()};
+}
+
+CONSTCD14
+inline
+year_month_weekday_last::operator local_days() const NOEXCEPT
+{
+ return local_days{to_days()};
+}
+
+CONSTCD11
+inline
+bool
+year_month_weekday_last::ok() const NOEXCEPT
+{
+ return y_.ok() && m_.ok() && wdl_.ok();
+}
+
+CONSTCD14
+inline
+days
+year_month_weekday_last::to_days() const NOEXCEPT
+{
+ auto const d = sys_days(y_/m_/last);
+ return (d - (islamic::weekday{d} - wdl_.weekday())).time_since_epoch();
+}
+
+CONSTCD11
+inline
+bool
+operator==(const year_month_weekday_last& x, const year_month_weekday_last& y) NOEXCEPT
+{
+ return x.year() == y.year() && x.month() == y.month() &&
+ x.weekday_last() == y.weekday_last();
+}
+
+CONSTCD11
+inline
+bool
+operator!=(const year_month_weekday_last& x, const year_month_weekday_last& y) NOEXCEPT
+{
+ return !(x == y);
+}
+
+template<class CharT, class Traits>
+inline
+std::basic_ostream<CharT, Traits>&
+operator<<(std::basic_ostream<CharT, Traits>& os, const year_month_weekday_last& ymwdl)
+{
+ return os << ymwdl.year() << '/' << ymwdl.month() << '/' << ymwdl.weekday_last();
+}
+
+CONSTCD14
+inline
+year_month_weekday_last
+operator+(const year_month_weekday_last& ymwdl, const months& dm) NOEXCEPT
+{
+ return (ymwdl.year() / ymwdl.month() + dm) / ymwdl.weekday_last();
+}
+
+CONSTCD14
+inline
+year_month_weekday_last
+operator+(const months& dm, const year_month_weekday_last& ymwdl) NOEXCEPT
+{
+ return ymwdl + dm;
+}
+
+CONSTCD14
+inline
+year_month_weekday_last
+operator-(const year_month_weekday_last& ymwdl, const months& dm) NOEXCEPT
+{
+ return ymwdl + (-dm);
+}
+
+CONSTCD11
+inline
+year_month_weekday_last
+operator+(const year_month_weekday_last& ymwdl, const years& dy) NOEXCEPT
+{
+ return {ymwdl.year()+dy, ymwdl.month(), ymwdl.weekday_last()};
+}
+
+CONSTCD11
+inline
+year_month_weekday_last
+operator+(const years& dy, const year_month_weekday_last& ymwdl) NOEXCEPT
+{
+ return ymwdl + dy;
+}
+
+CONSTCD11
+inline
+year_month_weekday_last
+operator-(const year_month_weekday_last& ymwdl, const years& dy) NOEXCEPT
+{
+ return ymwdl + (-dy);
+}
+
+// year_month from operator/()
+
+CONSTCD11
+inline
+year_month
+operator/(const year& y, const month& m) NOEXCEPT
+{
+ return {y, m};
+}
+
+CONSTCD11
+inline
+year_month
+operator/(const year& y, int m) NOEXCEPT
+{
+ return y / month(static_cast<unsigned>(m));
+}
+
+// month_day from operator/()
+
+CONSTCD11
+inline
+month_day
+operator/(const month& m, const day& d) NOEXCEPT
+{
+ return {m, d};
+}
+
+CONSTCD11
+inline
+month_day
+operator/(const day& d, const month& m) NOEXCEPT
+{
+ return m / d;
+}
+
+CONSTCD11
+inline
+month_day
+operator/(const month& m, int d) NOEXCEPT
+{
+ return m / day(static_cast<unsigned>(d));
+}
+
+CONSTCD11
+inline
+month_day
+operator/(int m, const day& d) NOEXCEPT
+{
+ return month(static_cast<unsigned>(m)) / d;
+}
+
+CONSTCD11 inline month_day operator/(const day& d, int m) NOEXCEPT {return m / d;}
+
+// month_day_last from operator/()
+
+CONSTCD11
+inline
+month_day_last
+operator/(const month& m, last_spec) NOEXCEPT
+{
+ return month_day_last{m};
+}
+
+CONSTCD11
+inline
+month_day_last
+operator/(last_spec, const month& m) NOEXCEPT
+{
+ return m/last;
+}
+
+CONSTCD11
+inline
+month_day_last
+operator/(int m, last_spec) NOEXCEPT
+{
+ return month(static_cast<unsigned>(m))/last;
+}
+
+CONSTCD11
+inline
+month_day_last
+operator/(last_spec, int m) NOEXCEPT
+{
+ return m/last;
+}
+
+// month_weekday from operator/()
+
+CONSTCD11
+inline
+month_weekday
+operator/(const month& m, const weekday_indexed& wdi) NOEXCEPT
+{
+ return {m, wdi};
+}
+
+CONSTCD11
+inline
+month_weekday
+operator/(const weekday_indexed& wdi, const month& m) NOEXCEPT
+{
+ return m / wdi;
+}
+
+CONSTCD11
+inline
+month_weekday
+operator/(int m, const weekday_indexed& wdi) NOEXCEPT
+{
+ return month(static_cast<unsigned>(m)) / wdi;
+}
+
+CONSTCD11
+inline
+month_weekday
+operator/(const weekday_indexed& wdi, int m) NOEXCEPT
+{
+ return m / wdi;
+}
+
+// month_weekday_last from operator/()
+
+CONSTCD11
+inline
+month_weekday_last
+operator/(const month& m, const weekday_last& wdl) NOEXCEPT
+{
+ return {m, wdl};
+}
+
+CONSTCD11
+inline
+month_weekday_last
+operator/(const weekday_last& wdl, const month& m) NOEXCEPT
+{
+ return m / wdl;
+}
+
+CONSTCD11
+inline
+month_weekday_last
+operator/(int m, const weekday_last& wdl) NOEXCEPT
+{
+ return month(static_cast<unsigned>(m)) / wdl;
+}
+
+CONSTCD11
+inline
+month_weekday_last
+operator/(const weekday_last& wdl, int m) NOEXCEPT
+{
+ return m / wdl;
+}
+
+// year_month_day from operator/()
+
+CONSTCD11
+inline
+year_month_day
+operator/(const year_month& ym, const day& d) NOEXCEPT
+{
+ return {ym.year(), ym.month(), d};
+}
+
+CONSTCD11
+inline
+year_month_day
+operator/(const year_month& ym, int d) NOEXCEPT
+{
+ return ym / day(static_cast<unsigned>(d));
+}
+
+CONSTCD11
+inline
+year_month_day
+operator/(const year& y, const month_day& md) NOEXCEPT
+{
+ return y / md.month() / md.day();
+}
+
+CONSTCD11
+inline
+year_month_day
+operator/(int y, const month_day& md) NOEXCEPT
+{
+ return year(y) / md;
+}
+
+CONSTCD11
+inline
+year_month_day
+operator/(const month_day& md, const year& y) NOEXCEPT
+{
+ return y / md;
+}
+
+CONSTCD11
+inline
+year_month_day
+operator/(const month_day& md, int y) NOEXCEPT
+{
+ return year(y) / md;
+}
+
+// year_month_day_last from operator/()
+
+CONSTCD11
+inline
+year_month_day_last
+operator/(const year_month& ym, last_spec) NOEXCEPT
+{
+ return {ym.year(), month_day_last{ym.month()}};
+}
+
+CONSTCD11
+inline
+year_month_day_last
+operator/(const year& y, const month_day_last& mdl) NOEXCEPT
+{
+ return {y, mdl};
+}
+
+CONSTCD11
+inline
+year_month_day_last
+operator/(int y, const month_day_last& mdl) NOEXCEPT
+{
+ return year(y) / mdl;
+}
+
+CONSTCD11
+inline
+year_month_day_last
+operator/(const month_day_last& mdl, const year& y) NOEXCEPT
+{
+ return y / mdl;
+}
+
+CONSTCD11
+inline
+year_month_day_last
+operator/(const month_day_last& mdl, int y) NOEXCEPT
+{
+ return year(y) / mdl;
+}
+
+// year_month_weekday from operator/()
+
+CONSTCD11
+inline
+year_month_weekday
+operator/(const year_month& ym, const weekday_indexed& wdi) NOEXCEPT
+{
+ return {ym.year(), ym.month(), wdi};
+}
+
+CONSTCD11
+inline
+year_month_weekday
+operator/(const year& y, const month_weekday& mwd) NOEXCEPT
+{
+ return {y, mwd.month(), mwd.weekday_indexed()};
+}
+
+CONSTCD11
+inline
+year_month_weekday
+operator/(int y, const month_weekday& mwd) NOEXCEPT
+{
+ return year(y) / mwd;
+}
+
+CONSTCD11
+inline
+year_month_weekday
+operator/(const month_weekday& mwd, const year& y) NOEXCEPT
+{
+ return y / mwd;
+}
+
+CONSTCD11
+inline
+year_month_weekday
+operator/(const month_weekday& mwd, int y) NOEXCEPT
+{
+ return year(y) / mwd;
+}
+
+// year_month_weekday_last from operator/()
+
+CONSTCD11
+inline
+year_month_weekday_last
+operator/(const year_month& ym, const weekday_last& wdl) NOEXCEPT
+{
+ return {ym.year(), ym.month(), wdl};
+}
+
+CONSTCD11
+inline
+year_month_weekday_last
+operator/(const year& y, const month_weekday_last& mwdl) NOEXCEPT
+{
+ return {y, mwdl.month(), mwdl.weekday_last()};
+}
+
+CONSTCD11
+inline
+year_month_weekday_last
+operator/(int y, const month_weekday_last& mwdl) NOEXCEPT
+{
+ return year(y) / mwdl;
+}
+
+CONSTCD11
+inline
+year_month_weekday_last
+operator/(const month_weekday_last& mwdl, const year& y) NOEXCEPT
+{
+ return y / mwdl;
+}
+
+CONSTCD11
+inline
+year_month_weekday_last
+operator/(const month_weekday_last& mwdl, int y) NOEXCEPT
+{
+ return year(y) / mwdl;
+}
+
+} // namespace islamic
+
+#endif // ISLAMIC_H
[04/10] nifi-minifi-cpp git commit: MINIFICPP-472 Added date
formatting EL functions
Posted by al...@apache.org.
http://git-wip-us.apache.org/repos/asf/nifi-minifi-cpp/blob/8777ab5f/thirdparty/date/include/date/tz.h
----------------------------------------------------------------------
diff --git a/thirdparty/date/include/date/tz.h b/thirdparty/date/include/date/tz.h
new file mode 100644
index 0000000..9840e7b
--- /dev/null
+++ b/thirdparty/date/include/date/tz.h
@@ -0,0 +1,2575 @@
+#ifndef TZ_H
+#define TZ_H
+
+// The MIT License (MIT)
+//
+// Copyright (c) 2015, 2016, 2017 Howard Hinnant
+// Copyright (c) 2017 Jiangang Zhuang
+// Copyright (c) 2017 Aaron Bishop
+// Copyright (c) 2017 Tomasz Kamiński
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in all
+// copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+// SOFTWARE.
+//
+// Our apologies. When the previous paragraph was written, lowercase had not yet
+// been invented (that would involve another several millennia of evolution).
+// We did not mean to shout.
+
+// Get more recent database at http://www.iana.org/time-zones
+
+// The notion of "current timezone" is something the operating system is expected to "just
+// know". How it knows this is system specific. It's often a value set by the user at OS
+// installation time and recorded by the OS somewhere. On Linux and Mac systems the current
+// timezone name is obtained by looking at the name or contents of a particular file on
+// disk. On Windows the current timezone name comes from the registry. In either method,
+// there is no guarantee that the "native" current timezone name obtained will match any
+// of the "Standard" names in this library's "database". On Linux, the names usually do
+// seem to match so mapping functions to map from native to "Standard" are typically not
+// required. On Windows, the names are never "Standard" so mapping is always required.
+// Technically any OS may use the mapping process but currently only Windows does use it.
+
+#ifndef USE_OS_TZDB
+# define USE_OS_TZDB 0
+#endif
+
+#ifndef HAS_REMOTE_API
+# if USE_OS_TZDB == 0
+# ifdef _WIN32
+# define HAS_REMOTE_API 0
+# else
+# define HAS_REMOTE_API 1
+# endif
+# else // HAS_REMOTE_API makes no since when using the OS timezone database
+# define HAS_REMOTE_API 0
+# endif
+#endif
+
+#ifdef __clang__
+# pragma clang diagnostic push
+# pragma clang diagnostic ignored "-Wconstant-logical-operand"
+#endif
+
+static_assert(!(USE_OS_TZDB && HAS_REMOTE_API),
+ "USE_OS_TZDB and HAS_REMOTE_API can not be used together");
+
+#ifdef __clang__
+# pragma clang diagnostic pop
+#endif
+
+#ifndef AUTO_DOWNLOAD
+# define AUTO_DOWNLOAD HAS_REMOTE_API
+#endif
+
+static_assert(HAS_REMOTE_API == 0 ? AUTO_DOWNLOAD == 0 : true,
+ "AUTO_DOWNLOAD can not be turned on without HAS_REMOTE_API");
+
+#ifndef USE_SHELL_API
+# define USE_SHELL_API 1
+#endif
+
+#if USE_OS_TZDB
+# ifdef _WIN32
+# error "USE_OS_TZDB can not be used on Windows"
+# endif
+# ifndef MISSING_LEAP_SECONDS
+# ifdef __APPLE__
+# define MISSING_LEAP_SECONDS 1
+# else
+# define MISSING_LEAP_SECONDS 0
+# endif
+# endif
+#else
+# define MISSING_LEAP_SECONDS 0
+#endif
+
+#ifndef HAS_DEDUCTION_GUIDES
+# if __cplusplus >= 201703
+# define HAS_DEDUCTION_GUIDES 1
+# else
+# define HAS_DEDUCTION_GUIDES 0
+# endif
+#endif // HAS_DEDUCTION_GUIDES
+
+#include "date.h"
+
+#if defined(_MSC_VER) && (_MSC_VER < 1900)
+#include "tz_private.h"
+#endif
+
+#include <algorithm>
+#include <atomic>
+#include <cassert>
+#include <chrono>
+#include <istream>
+#include <locale>
+#include <memory>
+#include <mutex>
+#include <ostream>
+#include <sstream>
+#include <stdexcept>
+#include <string>
+#include <type_traits>
+#include <utility>
+#include <vector>
+
+#ifdef _WIN32
+# ifdef DATE_BUILD_DLL
+# define DATE_API __declspec(dllexport)
+# elif defined(DATE_USE_DLL)
+# define DATE_API __declspec(dllimport)
+# else
+# define DATE_API
+# endif
+#else
+# ifdef DATE_BUILD_DLL
+# define DATE_API __attribute__ ((visibility ("default")))
+# else
+# define DATE_API
+# endif
+#endif
+
+namespace date
+{
+
+enum class choose {earliest, latest};
+
+namespace detail
+{
+ struct undocumented;
+}
+
+struct sys_info
+{
+ sys_seconds begin;
+ sys_seconds end;
+ std::chrono::seconds offset;
+ std::chrono::minutes save;
+ std::string abbrev;
+};
+
+template<class CharT, class Traits>
+std::basic_ostream<CharT, Traits>&
+operator<<(std::basic_ostream<CharT, Traits>& os, const sys_info& r)
+{
+ os << r.begin << '\n';
+ os << r.end << '\n';
+ os << make_time(r.offset) << "\n";
+ os << make_time(r.save) << "\n";
+ os << r.abbrev << '\n';
+ return os;
+}
+
+struct local_info
+{
+ enum {unique, nonexistent, ambiguous} result;
+ sys_info first;
+ sys_info second;
+};
+
+template<class CharT, class Traits>
+std::basic_ostream<CharT, Traits>&
+operator<<(std::basic_ostream<CharT, Traits>& os, const local_info& r)
+{
+ if (r.result == local_info::nonexistent)
+ os << "nonexistent between\n";
+ else if (r.result == local_info::ambiguous)
+ os << "ambiguous between\n";
+ os << r.first;
+ if (r.result != local_info::unique)
+ {
+ os << "and\n";
+ os << r.second;
+ }
+ return os;
+}
+
+class nonexistent_local_time
+ : public std::runtime_error
+{
+public:
+ template <class Duration>
+ nonexistent_local_time(local_time<Duration> tp, const local_info& i);
+
+private:
+ template <class Duration>
+ static
+ std::string
+ make_msg(local_time<Duration> tp, const local_info& i);
+};
+
+template <class Duration>
+inline
+nonexistent_local_time::nonexistent_local_time(local_time<Duration> tp,
+ const local_info& i)
+ : std::runtime_error(make_msg(tp, i))
+{
+}
+
+template <class Duration>
+std::string
+nonexistent_local_time::make_msg(local_time<Duration> tp, const local_info& i)
+{
+ assert(i.result == local_info::nonexistent);
+ std::ostringstream os;
+ os << tp << " is in a gap between\n"
+ << local_seconds{i.first.end.time_since_epoch()} + i.first.offset << ' '
+ << i.first.abbrev << " and\n"
+ << local_seconds{i.second.begin.time_since_epoch()} + i.second.offset << ' '
+ << i.second.abbrev
+ << " which are both equivalent to\n"
+ << i.first.end << " UTC";
+ return os.str();
+}
+
+class ambiguous_local_time
+ : public std::runtime_error
+{
+public:
+ template <class Duration>
+ ambiguous_local_time(local_time<Duration> tp, const local_info& i);
+
+private:
+ template <class Duration>
+ static
+ std::string
+ make_msg(local_time<Duration> tp, const local_info& i);
+};
+
+template <class Duration>
+inline
+ambiguous_local_time::ambiguous_local_time(local_time<Duration> tp, const local_info& i)
+ : std::runtime_error(make_msg(tp, i))
+{
+}
+
+template <class Duration>
+std::string
+ambiguous_local_time::make_msg(local_time<Duration> tp, const local_info& i)
+{
+ assert(i.result == local_info::ambiguous);
+ std::ostringstream os;
+ os << tp << " is ambiguous. It could be\n"
+ << tp << ' ' << i.first.abbrev << " == "
+ << tp - i.first.offset << " UTC or\n"
+ << tp << ' ' << i.second.abbrev << " == "
+ << tp - i.second.offset << " UTC";
+ return os.str();
+}
+
+class time_zone;
+
+#if HAS_STRING_VIEW
+DATE_API const time_zone* locate_zone(std::string_view tz_name);
+#else
+DATE_API const time_zone* locate_zone(const std::string& tz_name);
+#endif
+
+DATE_API const time_zone* current_zone();
+
+template <class T>
+struct zoned_traits
+{
+};
+
+template <>
+struct zoned_traits<const time_zone*>
+{
+ static
+ const time_zone*
+ default_zone()
+ {
+ return date::locate_zone("Etc/UTC");
+ }
+
+#if HAS_STRING_VIEW
+
+ static
+ const time_zone*
+ locate_zone(std::string_view name)
+ {
+ return date::locate_zone(name);
+ }
+
+#else // !HAS_STRING_VIEW
+
+ static
+ const time_zone*
+ locate_zone(const std::string& name)
+ {
+ return date::locate_zone(name);
+ }
+
+ static
+ const time_zone*
+ locate_zone(const char* name)
+ {
+ return date::locate_zone(name);
+ }
+
+#endif // !HAS_STRING_VIEW
+};
+
+template <class Duration, class TimeZonePtr>
+class zoned_time;
+
+template <class Duration1, class Duration2, class TimeZonePtr>
+bool
+operator==(const zoned_time<Duration1, TimeZonePtr>& x,
+ const zoned_time<Duration2, TimeZonePtr>& y);
+
+template <class Duration, class TimeZonePtr = const time_zone*>
+class zoned_time
+{
+public:
+ using duration = typename std::common_type<Duration, std::chrono::seconds>::type;
+
+private:
+ TimeZonePtr zone_;
+ sys_time<duration> tp_;
+
+public:
+#if !defined(_MSC_VER) || (_MSC_VER > 1900)
+ template <class T = TimeZonePtr,
+ class = decltype(zoned_traits<T>::default_zone())>
+#endif
+ zoned_time();
+
+#if !defined(_MSC_VER) || (_MSC_VER > 1900)
+ template <class T = TimeZonePtr,
+ class = decltype(zoned_traits<T>::default_zone())>
+#endif
+ zoned_time(const sys_time<Duration>& st);
+ explicit zoned_time(TimeZonePtr z);
+
+#if HAS_STRING_VIEW
+ template <class T = TimeZonePtr,
+ class = typename std::enable_if
+ <
+ std::is_constructible
+ <
+ zoned_time,
+ decltype(zoned_traits<T>::locate_zone(std::string_view()))
+ >::value
+ >::type>
+ explicit zoned_time(std::string_view name);
+#else
+#if !defined(_MSC_VER) || (_MSC_VER > 1900)
+ template <class T = TimeZonePtr,
+ class = typename std::enable_if
+ <
+ std::is_constructible
+ <
+ zoned_time,
+ decltype(zoned_traits<T>::locate_zone(std::string()))
+ >::value
+ >::type>
+#endif
+ explicit zoned_time(const std::string& name);
+#endif
+
+ template <class Duration2,
+ class = typename std::enable_if
+ <
+ std::is_convertible<sys_time<Duration2>,
+ sys_time<Duration>>::value
+ >::type>
+ zoned_time(const zoned_time<Duration2, TimeZonePtr>& zt) NOEXCEPT;
+
+ zoned_time(TimeZonePtr z, const sys_time<Duration>& st);
+
+#if !defined(_MSC_VER) || (_MSC_VER > 1900)
+ template <class T = TimeZonePtr,
+ class = typename std::enable_if
+ <
+ std::is_convertible
+ <
+ decltype(std::declval<T&>()->to_sys(local_time<Duration>{})),
+ sys_time<duration>
+ >::value
+ >::type>
+#endif
+ zoned_time(TimeZonePtr z, const local_time<Duration>& tp);
+
+#if !defined(_MSC_VER) || (_MSC_VER > 1900)
+ template <class T = TimeZonePtr,
+ class = typename std::enable_if
+ <
+ std::is_convertible
+ <
+ decltype(std::declval<T&>()->to_sys(local_time<Duration>{},
+ choose::earliest)),
+ sys_time<duration>
+ >::value
+ >::type>
+#endif
+ zoned_time(TimeZonePtr z, const local_time<Duration>& tp, choose c);
+
+ template <class Duration2, class TimeZonePtr2,
+ class = typename std::enable_if
+ <
+ std::is_convertible<sys_time<Duration2>,
+ sys_time<Duration>>::value
+ >::type>
+ zoned_time(TimeZonePtr z, const zoned_time<Duration2, TimeZonePtr2>& zt);
+
+ template <class Duration2, class TimeZonePtr2,
+ class = typename std::enable_if
+ <
+ std::is_convertible<sys_time<Duration2>,
+ sys_time<Duration>>::value
+ >::type>
+ zoned_time(TimeZonePtr z, const zoned_time<Duration2, TimeZonePtr2>& zt, choose);
+
+#if HAS_STRING_VIEW
+
+ template <class T = TimeZonePtr,
+ class = typename std::enable_if
+ <
+ std::is_constructible
+ <
+ zoned_time,
+ decltype(zoned_traits<T>::locate_zone(std::string_view())),
+ sys_time<Duration>
+ >::value
+ >::type>
+ zoned_time(std::string_view name, const sys_time<Duration>& st);
+
+ template <class T = TimeZonePtr,
+ class = typename std::enable_if
+ <
+ std::is_constructible
+ <
+ zoned_time,
+ decltype(zoned_traits<T>::locate_zone(std::string_view())),
+ local_time<Duration>
+ >::value
+ >::type>
+ zoned_time(std::string_view name, const local_time<Duration>& tp);
+
+ template <class T = TimeZonePtr,
+ class = typename std::enable_if
+ <
+ std::is_constructible
+ <
+ zoned_time,
+ decltype(zoned_traits<T>::locate_zone(std::string_view())),
+ local_time<Duration>,
+ choose
+ >::value
+ >::type>
+ zoned_time(std::string_view name, const local_time<Duration>& tp, choose c);
+
+ template <class T = TimeZonePtr,
+ class = typename std::enable_if
+ <
+ std::is_constructible
+ <
+ zoned_time,
+ decltype(zoned_traits<T>::locate_zone(std::string_view())),
+ zoned_time
+ >::value
+ >::type>
+ zoned_time(std::string_view name, const zoned_time& zt);
+
+ template <class T = TimeZonePtr,
+ class = typename std::enable_if
+ <
+ std::is_constructible
+ <
+ zoned_time,
+ decltype(zoned_traits<T>::locate_zone(std::string_view())),
+ zoned_time,
+ choose
+ >::value
+ >::type>
+ zoned_time(std::string_view name, const zoned_time& zt, choose);
+
+#else // !HAS_STRING_VIEW
+
+#if !defined(_MSC_VER) || (_MSC_VER > 1900)
+ template <class T = TimeZonePtr,
+ class = typename std::enable_if
+ <
+ std::is_constructible
+ <
+ zoned_time,
+ decltype(zoned_traits<T>::locate_zone(std::string())),
+ sys_time<Duration>
+ >::value
+ >::type>
+#endif
+ zoned_time(const std::string& name, const sys_time<Duration>& st);
+
+#if !defined(_MSC_VER) || (_MSC_VER > 1900)
+ template <class T = TimeZonePtr,
+ class = typename std::enable_if
+ <
+ std::is_constructible
+ <
+ zoned_time,
+ decltype(zoned_traits<T>::locate_zone(std::string())),
+ sys_time<Duration>
+ >::value
+ >::type>
+#endif
+ zoned_time(const char* name, const sys_time<Duration>& st);
+
+#if !defined(_MSC_VER) || (_MSC_VER > 1900)
+ template <class T = TimeZonePtr,
+ class = typename std::enable_if
+ <
+ std::is_constructible
+ <
+ zoned_time,
+ decltype(zoned_traits<T>::locate_zone(std::string())),
+ local_time<Duration>
+ >::value
+ >::type>
+#endif
+ zoned_time(const std::string& name, const local_time<Duration>& tp);
+
+#if !defined(_MSC_VER) || (_MSC_VER > 1900)
+ template <class T = TimeZonePtr,
+ class = typename std::enable_if
+ <
+ std::is_constructible
+ <
+ zoned_time,
+ decltype(zoned_traits<T>::locate_zone(std::string())),
+ local_time<Duration>
+ >::value
+ >::type>
+#endif
+ zoned_time(const char* name, const local_time<Duration>& tp);
+
+#if !defined(_MSC_VER) || (_MSC_VER > 1900)
+ template <class T = TimeZonePtr,
+ class = typename std::enable_if
+ <
+ std::is_constructible
+ <
+ zoned_time,
+ decltype(zoned_traits<T>::locate_zone(std::string())),
+ local_time<Duration>,
+ choose
+ >::value
+ >::type>
+#endif
+ zoned_time(const std::string& name, const local_time<Duration>& tp, choose c);
+
+#if !defined(_MSC_VER) || (_MSC_VER > 1900)
+ template <class T = TimeZonePtr,
+ class = typename std::enable_if
+ <
+ std::is_constructible
+ <
+ zoned_time,
+ decltype(zoned_traits<T>::locate_zone(std::string())),
+ local_time<Duration>,
+ choose
+ >::value
+ >::type>
+#endif
+ zoned_time(const char* name, const local_time<Duration>& tp, choose c);
+
+#if !defined(_MSC_VER) || (_MSC_VER > 1900)
+ template <class T = TimeZonePtr,
+ class = typename std::enable_if
+ <
+ std::is_constructible
+ <
+ zoned_time,
+ decltype(zoned_traits<T>::locate_zone(std::string())),
+ zoned_time
+ >::value
+ >::type>
+#endif
+ zoned_time(const std::string& name, const zoned_time& zt);
+
+#if !defined(_MSC_VER) || (_MSC_VER > 1900)
+ template <class T = TimeZonePtr,
+ class = typename std::enable_if
+ <
+ std::is_constructible
+ <
+ zoned_time,
+ decltype(zoned_traits<T>::locate_zone(std::string())),
+ zoned_time
+ >::value
+ >::type>
+#endif
+ zoned_time(const char* name, const zoned_time& zt);
+
+#if !defined(_MSC_VER) || (_MSC_VER > 1900)
+ template <class T = TimeZonePtr,
+ class = typename std::enable_if
+ <
+ std::is_constructible
+ <
+ zoned_time,
+ decltype(zoned_traits<T>::locate_zone(std::string())),
+ zoned_time,
+ choose
+ >::value
+ >::type>
+#endif
+ zoned_time(const std::string& name, const zoned_time& zt, choose);
+
+#if !defined(_MSC_VER) || (_MSC_VER > 1900)
+ template <class T = TimeZonePtr,
+ class = typename std::enable_if
+ <
+ std::is_constructible
+ <
+ zoned_time,
+ decltype(zoned_traits<T>::locate_zone(std::string())),
+ zoned_time,
+ choose
+ >::value
+ >::type>
+#endif
+ zoned_time(const char* name, const zoned_time& zt, choose);
+
+#endif // !HAS_STRING_VIEW
+
+ zoned_time& operator=(const sys_time<Duration>& st);
+ zoned_time& operator=(const local_time<Duration>& ut);
+
+ explicit operator sys_time<duration>() const;
+ explicit operator local_time<duration>() const;
+
+ TimeZonePtr get_time_zone() const;
+ local_time<duration> get_local_time() const;
+ sys_time<duration> get_sys_time() const;
+ sys_info get_info() const;
+
+ template <class Duration1, class Duration2, class TimeZonePtr1>
+ friend
+ bool
+ operator==(const zoned_time<Duration1, TimeZonePtr1>& x,
+ const zoned_time<Duration2, TimeZonePtr1>& y);
+
+ template <class CharT, class Traits, class Duration1, class TimeZonePtr1>
+ friend
+ std::basic_ostream<CharT, Traits>&
+ operator<<(std::basic_ostream<CharT, Traits>& os,
+ const zoned_time<Duration1, TimeZonePtr1>& t);
+
+private:
+ template <class D, class T> friend class zoned_time;
+};
+
+using zoned_seconds = zoned_time<std::chrono::seconds>;
+
+#if HAS_DEDUCTION_GUIDES
+
+zoned_time()
+ -> zoned_time<std::chrono::seconds>;
+
+template <class Duration>
+zoned_time(sys_time<Duration>)
+ -> zoned_time<std::common_type_t<Duration, std::chrono::seconds>>;
+
+template <class TimeZonePtr>
+zoned_time(TimeZonePtr)
+ -> zoned_time<std::chrono::seconds, TimeZonePtr>;
+
+template <class TimeZonePtr, class Duration>
+zoned_time(TimeZonePtr, sys_time<Duration>)
+ -> zoned_time<std::common_type_t<Duration, std::chrono::seconds>, TimeZonePtr>;
+
+template <class TimeZonePtr, class Duration>
+zoned_time(TimeZonePtr, local_time<Duration>, choose = choose::earliest)
+ -> zoned_time<std::common_type_t<Duration, std::chrono::seconds>, TimeZonePtr>;
+
+#if HAS_STRING_VIEW
+
+zoned_time(std::string_view)
+ -> zoned_time<std::chrono::seconds>;
+
+template <class Duration>
+zoned_time(std::string_view, sys_time<Duration>)
+ -> zoned_time<std::common_type_t<Duration, std::chrono::seconds>>;
+
+template <class Duration>
+zoned_time(std::string_view, local_time<Duration>, choose = choose::earliest)
+ -> zoned_time<std::common_type_t<Duration, std::chrono::seconds>>;
+
+#else // !HAS_STRING_VIEW
+
+zoned_time(std::string)
+ -> zoned_time<std::chrono::seconds>;
+
+template <class Duration>
+zoned_time(std::string, sys_time<Duration>)
+ -> zoned_time<std::common_type_t<Duration, std::chrono::seconds>>;
+
+template <class Duration>
+zoned_time(std::string, local_time<Duration>, choose = choose::earliest)
+ -> zoned_time<std::common_type_t<Duration, std::chrono::seconds>>;
+
+#endif // !HAS_STRING_VIEW
+
+template <class Duration>
+zoned_time(const char*, sys_time<Duration>)
+ -> zoned_time<std::common_type_t<Duration, std::chrono::seconds>>;
+
+template <class Duration>
+zoned_time(const char*, local_time<Duration>, choose = choose::earliest)
+ -> zoned_time<std::common_type_t<Duration, std::chrono::seconds>>;
+
+template <class Duration, class TimeZonePtr, class TimeZonePtr2>
+zoned_time(TimeZonePtr, zoned_time<Duration, TimeZonePtr2>, choose = choose::earliest)
+ -> zoned_time<Duration, TimeZonePtr>;
+
+#endif // HAS_DEDUCTION_GUIDES
+
+template <class Duration1, class Duration2, class TimeZonePtr>
+inline
+bool
+operator==(const zoned_time<Duration1, TimeZonePtr>& x,
+ const zoned_time<Duration2, TimeZonePtr>& y)
+{
+ return x.zone_ == y.zone_ && x.tp_ == y.tp_;
+}
+
+template <class Duration1, class Duration2, class TimeZonePtr>
+inline
+bool
+operator!=(const zoned_time<Duration1, TimeZonePtr>& x,
+ const zoned_time<Duration2, TimeZonePtr>& y)
+{
+ return !(x == y);
+}
+
+#if !defined(_MSC_VER) || (_MSC_VER >= 1900)
+
+namespace detail
+{
+# if USE_OS_TZDB
+ struct transition;
+ struct expanded_ttinfo;
+# else // !USE_OS_TZDB
+ struct zonelet;
+ class Rule;
+# endif // !USE_OS_TZDB
+}
+
+#endif // !defined(_MSC_VER) || (_MSC_VER >= 1900)
+
+class time_zone
+{
+private:
+ std::string name_;
+#if USE_OS_TZDB
+ std::vector<detail::transition> transitions_;
+ std::vector<detail::expanded_ttinfo> ttinfos_;
+#else // !USE_OS_TZDB
+ std::vector<detail::zonelet> zonelets_;
+#endif // !USE_OS_TZDB
+ std::unique_ptr<std::once_flag> adjusted_;
+
+public:
+#if !defined(_MSC_VER) || (_MSC_VER >= 1900)
+ time_zone(time_zone&&) = default;
+ time_zone& operator=(time_zone&&) = default;
+#else // defined(_MSC_VER) && (_MSC_VER < 1900)
+ time_zone(time_zone&& src);
+ time_zone& operator=(time_zone&& src);
+#endif // defined(_MSC_VER) && (_MSC_VER < 1900)
+
+ DATE_API explicit time_zone(const std::string& s, detail::undocumented);
+
+ const std::string& name() const NOEXCEPT;
+
+ template <class Duration> sys_info get_info(sys_time<Duration> st) const;
+ template <class Duration> local_info get_info(local_time<Duration> tp) const;
+
+ template <class Duration>
+ sys_time<typename std::common_type<Duration, std::chrono::seconds>::type>
+ to_sys(local_time<Duration> tp) const;
+
+ template <class Duration>
+ sys_time<typename std::common_type<Duration, std::chrono::seconds>::type>
+ to_sys(local_time<Duration> tp, choose z) const;
+
+ template <class Duration>
+ local_time<typename std::common_type<Duration, std::chrono::seconds>::type>
+ to_local(sys_time<Duration> tp) const;
+
+ friend bool operator==(const time_zone& x, const time_zone& y) NOEXCEPT;
+ friend bool operator< (const time_zone& x, const time_zone& y) NOEXCEPT;
+ friend DATE_API std::ostream& operator<<(std::ostream& os, const time_zone& z);
+
+#if !USE_OS_TZDB
+ DATE_API void add(const std::string& s);
+#endif // !USE_OS_TZDB
+
+private:
+ DATE_API sys_info get_info_impl(sys_seconds tp) const;
+ DATE_API local_info get_info_impl(local_seconds tp) const;
+
+ template <class Duration>
+ sys_time<typename std::common_type<Duration, std::chrono::seconds>::type>
+ to_sys_impl(local_time<Duration> tp, choose z, std::false_type) const;
+ template <class Duration>
+ sys_time<typename std::common_type<Duration, std::chrono::seconds>::type>
+ to_sys_impl(local_time<Duration> tp, choose, std::true_type) const;
+
+#if USE_OS_TZDB
+ DATE_API void init() const;
+ DATE_API void init_impl();
+ DATE_API sys_info
+ load_sys_info(std::vector<detail::transition>::const_iterator i) const;
+
+ template <class TimeType>
+ DATE_API void
+ load_data(std::istream& inf, std::int32_t tzh_leapcnt, std::int32_t tzh_timecnt,
+ std::int32_t tzh_typecnt, std::int32_t tzh_charcnt);
+#else // !USE_OS_TZDB
+ DATE_API sys_info get_info_impl(sys_seconds tp, int timezone) const;
+ DATE_API void adjust_infos(const std::vector<detail::Rule>& rules);
+ DATE_API void parse_info(std::istream& in);
+#endif // !USE_OS_TZDB
+};
+
+#if defined(_MSC_VER) && (_MSC_VER < 1900)
+
+inline
+time_zone::time_zone(time_zone&& src)
+ : name_(std::move(src.name_))
+ , zonelets_(std::move(src.zonelets_))
+ , adjusted_(std::move(src.adjusted_))
+ {}
+
+inline
+time_zone&
+time_zone::operator=(time_zone&& src)
+{
+ name_ = std::move(src.name_);
+ zonelets_ = std::move(src.zonelets_);
+ adjusted_ = std::move(src.adjusted_);
+ return *this;
+}
+
+#endif // defined(_MSC_VER) && (_MSC_VER < 1900)
+
+inline
+const std::string&
+time_zone::name() const NOEXCEPT
+{
+ return name_;
+}
+
+template <class Duration>
+inline
+sys_info
+time_zone::get_info(sys_time<Duration> st) const
+{
+ using namespace std::chrono;
+ return get_info_impl(date::floor<seconds>(st));
+}
+
+template <class Duration>
+inline
+local_info
+time_zone::get_info(local_time<Duration> tp) const
+{
+ using namespace std::chrono;
+ return get_info_impl(date::floor<seconds>(tp));
+}
+
+template <class Duration>
+inline
+sys_time<typename std::common_type<Duration, std::chrono::seconds>::type>
+time_zone::to_sys(local_time<Duration> tp) const
+{
+ return to_sys_impl(tp, choose{}, std::true_type{});
+}
+
+template <class Duration>
+inline
+sys_time<typename std::common_type<Duration, std::chrono::seconds>::type>
+time_zone::to_sys(local_time<Duration> tp, choose z) const
+{
+ return to_sys_impl(tp, z, std::false_type{});
+}
+
+template <class Duration>
+inline
+local_time<typename std::common_type<Duration, std::chrono::seconds>::type>
+time_zone::to_local(sys_time<Duration> tp) const
+{
+ using LT = local_time<typename std::common_type<Duration, std::chrono::seconds>::type>;
+ auto i = get_info(tp);
+ return LT{(tp + i.offset).time_since_epoch()};
+}
+
+inline bool operator==(const time_zone& x, const time_zone& y) NOEXCEPT {return x.name_ == y.name_;}
+inline bool operator< (const time_zone& x, const time_zone& y) NOEXCEPT {return x.name_ < y.name_;}
+
+inline bool operator!=(const time_zone& x, const time_zone& y) NOEXCEPT {return !(x == y);}
+inline bool operator> (const time_zone& x, const time_zone& y) NOEXCEPT {return y < x;}
+inline bool operator<=(const time_zone& x, const time_zone& y) NOEXCEPT {return !(y < x);}
+inline bool operator>=(const time_zone& x, const time_zone& y) NOEXCEPT {return !(x < y);}
+
+template <class Duration>
+sys_time<typename std::common_type<Duration, std::chrono::seconds>::type>
+time_zone::to_sys_impl(local_time<Duration> tp, choose z, std::false_type) const
+{
+ using namespace date;
+ using namespace std::chrono;
+ auto i = get_info(tp);
+ if (i.result == local_info::nonexistent)
+ {
+ return i.first.end;
+ }
+ else if (i.result == local_info::ambiguous)
+ {
+ if (z == choose::latest)
+ return sys_time<Duration>{tp.time_since_epoch()} - i.second.offset;
+ }
+ return sys_time<Duration>{tp.time_since_epoch()} - i.first.offset;
+}
+
+template <class Duration>
+sys_time<typename std::common_type<Duration, std::chrono::seconds>::type>
+time_zone::to_sys_impl(local_time<Duration> tp, choose, std::true_type) const
+{
+ using namespace date;
+ using namespace std::chrono;
+ auto i = get_info(tp);
+ if (i.result == local_info::nonexistent)
+ throw nonexistent_local_time(tp, i);
+ else if (i.result == local_info::ambiguous)
+ throw ambiguous_local_time(tp, i);
+ return sys_time<Duration>{tp.time_since_epoch()} - i.first.offset;
+}
+
+#if !USE_OS_TZDB
+
+class link
+{
+private:
+ std::string name_;
+ std::string target_;
+public:
+ DATE_API explicit link(const std::string& s);
+
+ const std::string& name() const {return name_;}
+ const std::string& target() const {return target_;}
+
+ friend bool operator==(const link& x, const link& y) {return x.name_ == y.name_;}
+ friend bool operator< (const link& x, const link& y) {return x.name_ < y.name_;}
+
+ friend DATE_API std::ostream& operator<<(std::ostream& os, const link& x);
+};
+
+inline bool operator!=(const link& x, const link& y) {return !(x == y);}
+inline bool operator> (const link& x, const link& y) {return y < x;}
+inline bool operator<=(const link& x, const link& y) {return !(y < x);}
+inline bool operator>=(const link& x, const link& y) {return !(x < y);}
+
+#endif // !USE_OS_TZDB
+
+#if !MISSING_LEAP_SECONDS
+
+class leap
+{
+private:
+ sys_seconds date_;
+
+public:
+#if USE_OS_TZDB
+ DATE_API explicit leap(const sys_seconds& s, detail::undocumented);
+#else
+ DATE_API explicit leap(const std::string& s, detail::undocumented);
+#endif
+
+ sys_seconds date() const {return date_;}
+
+ friend bool operator==(const leap& x, const leap& y) {return x.date_ == y.date_;}
+ friend bool operator< (const leap& x, const leap& y) {return x.date_ < y.date_;}
+
+ template <class Duration>
+ friend
+ bool
+ operator==(const leap& x, const sys_time<Duration>& y)
+ {
+ return x.date_ == y;
+ }
+
+ template <class Duration>
+ friend
+ bool
+ operator< (const leap& x, const sys_time<Duration>& y)
+ {
+ return x.date_ < y;
+ }
+
+ template <class Duration>
+ friend
+ bool
+ operator< (const sys_time<Duration>& x, const leap& y)
+ {
+ return x < y.date_;
+ }
+
+ friend DATE_API std::ostream& operator<<(std::ostream& os, const leap& x);
+};
+
+inline bool operator!=(const leap& x, const leap& y) {return !(x == y);}
+inline bool operator> (const leap& x, const leap& y) {return y < x;}
+inline bool operator<=(const leap& x, const leap& y) {return !(y < x);}
+inline bool operator>=(const leap& x, const leap& y) {return !(x < y);}
+
+template <class Duration>
+inline
+bool
+operator==(const sys_time<Duration>& x, const leap& y)
+{
+ return y == x;
+}
+
+template <class Duration>
+inline
+bool
+operator!=(const leap& x, const sys_time<Duration>& y)
+{
+ return !(x == y);
+}
+
+template <class Duration>
+inline
+bool
+operator!=(const sys_time<Duration>& x, const leap& y)
+{
+ return !(x == y);
+}
+
+template <class Duration>
+inline
+bool
+operator> (const leap& x, const sys_time<Duration>& y)
+{
+ return y < x;
+}
+
+template <class Duration>
+inline
+bool
+operator> (const sys_time<Duration>& x, const leap& y)
+{
+ return y < x;
+}
+
+template <class Duration>
+inline
+bool
+operator<=(const leap& x, const sys_time<Duration>& y)
+{
+ return !(y < x);
+}
+
+template <class Duration>
+inline
+bool
+operator<=(const sys_time<Duration>& x, const leap& y)
+{
+ return !(y < x);
+}
+
+template <class Duration>
+inline
+bool
+operator>=(const leap& x, const sys_time<Duration>& y)
+{
+ return !(x < y);
+}
+
+template <class Duration>
+inline
+bool
+operator>=(const sys_time<Duration>& x, const leap& y)
+{
+ return !(x < y);
+}
+
+#endif // !MISSING_LEAP_SECONDS
+
+#ifdef _WIN32
+
+namespace detail
+{
+
+// The time zone mapping is modelled after this data file:
+// http://unicode.org/repos/cldr/trunk/common/supplemental/windowsZones.xml
+// and the field names match the element names from the mapZone element
+// of windowsZones.xml.
+// The website displays this file here:
+// http://www.unicode.org/cldr/charts/latest/supplemental/zone_tzid.html
+// The html view is sorted before being displayed but is otherwise the same
+// There is a mapping between the os centric view (in this case windows)
+// the html displays uses and the generic view the xml file.
+// That mapping is this:
+// display column "windows" -> xml field "other".
+// display column "region" -> xml field "territory".
+// display column "tzid" -> xml field "type".
+// This structure uses the generic terminology because it could be
+// used to to support other os/native name conversions, not just windows,
+// and using the same generic names helps retain the connection to the
+// origin of the data that we are using.
+struct timezone_mapping
+{
+ timezone_mapping(const char* other, const char* territory, const char* type)
+ : other(other), territory(territory), type(type)
+ {
+ }
+ timezone_mapping() = default;
+ std::string other;
+ std::string territory;
+ std::string type;
+};
+
+} // detail
+
+#endif // _WIN32
+
+struct tzdb
+{
+ std::string version = "unknown";
+ std::vector<time_zone> zones;
+#if !USE_OS_TZDB
+ std::vector<link> links;
+#endif
+#if !MISSING_LEAP_SECONDS
+ std::vector<leap> leaps;
+#endif
+#if !USE_OS_TZDB
+ std::vector<detail::Rule> rules;
+#endif
+#ifdef _WIN32
+ std::vector<detail::timezone_mapping> mappings;
+#endif
+ tzdb* next = nullptr;
+
+ tzdb() = default;
+#if !defined(_MSC_VER) || (_MSC_VER >= 1900)
+ tzdb(tzdb&&) = default;
+ tzdb& operator=(tzdb&&) = default;
+#else // defined(_MSC_VER) && (_MSC_VER < 1900)
+ tzdb(tzdb&& src)
+ : version(std::move(src.version))
+ , zones(std::move(src.zones))
+ , links(std::move(src.links))
+ , leaps(std::move(src.leaps))
+ , rules(std::move(src.rules))
+ , mappings(std::move(src.mappings))
+ {}
+
+ tzdb& operator=(tzdb&& src)
+ {
+ version = std::move(src.version);
+ zones = std::move(src.zones);
+ links = std::move(src.links);
+ leaps = std::move(src.leaps);
+ rules = std::move(src.rules);
+ mappings = std::move(src.mappings);
+ return *this;
+ }
+#endif // defined(_MSC_VER) && (_MSC_VER < 1900)
+
+#if HAS_STRING_VIEW
+ const time_zone* locate_zone(std::string_view tz_name) const;
+#else
+ const time_zone* locate_zone(const std::string& tz_name) const;
+#endif
+ const time_zone* current_zone() const;
+};
+
+using TZ_DB = tzdb;
+
+DATE_API std::ostream&
+operator<<(std::ostream& os, const tzdb& db);
+
+DATE_API const tzdb& get_tzdb();
+
+class tzdb_list
+{
+ std::atomic<tzdb*> head_{nullptr};
+
+public:
+ ~tzdb_list();
+ tzdb_list() = default;
+ tzdb_list(tzdb_list&& x) noexcept;
+
+ const tzdb& front() const noexcept {return *head_;}
+ tzdb& front() noexcept {return *head_;}
+
+ class const_iterator;
+
+ const_iterator begin() const noexcept;
+ const_iterator end() const noexcept;
+
+ const_iterator cbegin() const noexcept;
+ const_iterator cend() const noexcept;
+
+ const_iterator erase_after(const_iterator p) noexcept;
+
+ struct undocumented_helper;
+private:
+ void push_front(tzdb* tzdb) noexcept;
+};
+
+class tzdb_list::const_iterator
+{
+ tzdb* p_ = nullptr;
+
+ explicit const_iterator(tzdb* p) noexcept : p_{p} {}
+public:
+ const_iterator() = default;
+
+ using iterator_category = std::forward_iterator_tag;
+ using value_type = tzdb;
+ using reference = const value_type&;
+ using pointer = const value_type*;
+ using difference_type = std::ptrdiff_t;
+
+ reference operator*() const noexcept {return *p_;}
+ pointer operator->() const noexcept {return p_;}
+
+ const_iterator& operator++() noexcept {p_ = p_->next; return *this;}
+ const_iterator operator++(int) noexcept {auto t = *this; ++(*this); return t;}
+
+ friend
+ bool
+ operator==(const const_iterator& x, const const_iterator& y) noexcept
+ {return x.p_ == y.p_;}
+
+ friend
+ bool
+ operator!=(const const_iterator& x, const const_iterator& y) noexcept
+ {return !(x == y);}
+
+ friend class tzdb_list;
+};
+
+inline
+tzdb_list::const_iterator
+tzdb_list::begin() const noexcept
+{
+ return const_iterator{head_};
+}
+
+inline
+tzdb_list::const_iterator
+tzdb_list::end() const noexcept
+{
+ return const_iterator{nullptr};
+}
+
+inline
+tzdb_list::const_iterator
+tzdb_list::cbegin() const noexcept
+{
+ return begin();
+}
+
+inline
+tzdb_list::const_iterator
+tzdb_list::cend() const noexcept
+{
+ return end();
+}
+
+DATE_API tzdb_list& get_tzdb_list();
+
+#if !USE_OS_TZDB
+
+DATE_API const tzdb& reload_tzdb();
+DATE_API void set_install(const std::string& install);
+
+#endif // !USE_OS_TZDB
+
+#if HAS_REMOTE_API
+
+DATE_API std::string remote_version();
+DATE_API bool remote_download(const std::string& version);
+DATE_API bool remote_install(const std::string& version);
+
+#endif
+
+// zoned_time
+
+namespace detail
+{
+
+template <class T>
+inline
+T*
+to_raw_pointer(T* p) noexcept
+{
+ return p;
+}
+
+template <class Pointer>
+inline
+auto
+to_raw_pointer(Pointer p) noexcept
+ -> decltype(detail::to_raw_pointer(p.operator->()))
+{
+ return detail::to_raw_pointer(p.operator->());
+}
+
+} // namespace detail
+
+template <class Duration, class TimeZonePtr>
+#if !defined(_MSC_VER) || (_MSC_VER > 1900)
+template <class T, class>
+#endif
+inline
+zoned_time<Duration, TimeZonePtr>::zoned_time()
+ : zone_(zoned_traits<TimeZonePtr>::default_zone())
+ {}
+
+template <class Duration, class TimeZonePtr>
+#if !defined(_MSC_VER) || (_MSC_VER > 1900)
+template <class T, class>
+#endif
+inline
+zoned_time<Duration, TimeZonePtr>::zoned_time(const sys_time<Duration>& st)
+ : zone_(zoned_traits<TimeZonePtr>::default_zone())
+ , tp_(st)
+ {}
+
+template <class Duration, class TimeZonePtr>
+inline
+zoned_time<Duration, TimeZonePtr>::zoned_time(TimeZonePtr z)
+ : zone_(std::move(z))
+ {assert(detail::to_raw_pointer(zone_) != nullptr);}
+
+#if HAS_STRING_VIEW
+
+template <class Duration, class TimeZonePtr>
+template <class, class>
+inline
+zoned_time<Duration, TimeZonePtr>::zoned_time(std::string_view name)
+ : zoned_time(zoned_traits<TimeZonePtr>::locate_zone(name))
+ {}
+
+#else // !HAS_STRING_VIEW
+
+template <class Duration, class TimeZonePtr>
+#if !defined(_MSC_VER) || (_MSC_VER > 1900)
+template <class T, class>
+#endif
+inline
+zoned_time<Duration, TimeZonePtr>::zoned_time(const std::string& name)
+ : zoned_time(zoned_traits<TimeZonePtr>::locate_zone(name))
+ {}
+
+#endif // !HAS_STRING_VIEW
+
+template <class Duration, class TimeZonePtr>
+template <class Duration2, class>
+inline
+zoned_time<Duration, TimeZonePtr>::zoned_time(const zoned_time<Duration2, TimeZonePtr>& zt) NOEXCEPT
+ : zone_(zt.zone_)
+ , tp_(zt.tp_)
+ {}
+
+template <class Duration, class TimeZonePtr>
+inline
+zoned_time<Duration, TimeZonePtr>::zoned_time(TimeZonePtr z, const sys_time<Duration>& st)
+ : zone_(std::move(z))
+ , tp_(st)
+ {}
+
+template <class Duration, class TimeZonePtr>
+#if !defined(_MSC_VER) || (_MSC_VER > 1900)
+template <class T, class>
+#endif
+inline
+zoned_time<Duration, TimeZonePtr>::zoned_time(TimeZonePtr z, const local_time<Duration>& t)
+ : zone_(std::move(z))
+ , tp_(zone_->to_sys(t))
+ {}
+
+template <class Duration, class TimeZonePtr>
+#if !defined(_MSC_VER) || (_MSC_VER > 1900)
+template <class T, class>
+#endif
+inline
+zoned_time<Duration, TimeZonePtr>::zoned_time(TimeZonePtr z, const local_time<Duration>& t,
+ choose c)
+ : zone_(std::move(z))
+ , tp_(zone_->to_sys(t, c))
+ {}
+
+template <class Duration, class TimeZonePtr>
+template <class Duration2, class TimeZonePtr2, class>
+inline
+zoned_time<Duration, TimeZonePtr>::zoned_time(TimeZonePtr z,
+ const zoned_time<Duration2, TimeZonePtr2>& zt)
+ : zone_(std::move(z))
+ , tp_(zt.tp_)
+ {}
+
+template <class Duration, class TimeZonePtr>
+template <class Duration2, class TimeZonePtr2, class>
+inline
+zoned_time<Duration, TimeZonePtr>::zoned_time(TimeZonePtr z,
+ const zoned_time<Duration2, TimeZonePtr2>& zt, choose)
+ : zoned_time(std::move(z), zt)
+ {}
+
+#if HAS_STRING_VIEW
+
+template <class Duration, class TimeZonePtr>
+template <class, class>
+inline
+zoned_time<Duration, TimeZonePtr>::zoned_time(std::string_view name,
+ const sys_time<Duration>& st)
+ : zoned_time(zoned_traits<TimeZonePtr>::locate_zone(name), st)
+ {}
+
+template <class Duration, class TimeZonePtr>
+template <class, class>
+inline
+zoned_time<Duration, TimeZonePtr>::zoned_time(std::string_view name,
+ const local_time<Duration>& t)
+ : zoned_time(zoned_traits<TimeZonePtr>::locate_zone(name), t)
+ {}
+
+template <class Duration, class TimeZonePtr>
+template <class, class>
+inline
+zoned_time<Duration, TimeZonePtr>::zoned_time(std::string_view name,
+ const local_time<Duration>& t, choose c)
+ : zoned_time(zoned_traits<TimeZonePtr>::locate_zone(name), t, c)
+ {}
+
+template <class Duration, class TimeZonePtr>
+template <class, class>
+inline
+zoned_time<Duration, TimeZonePtr>::zoned_time(std::string_view name, const zoned_time& zt)
+ : zoned_time(zoned_traits<TimeZonePtr>::locate_zone(name), zt)
+ {}
+
+template <class Duration, class TimeZonePtr>
+template <class, class>
+inline
+zoned_time<Duration, TimeZonePtr>::zoned_time(std::string_view name,
+ const zoned_time& zt, choose c)
+ : zoned_time(zoned_traits<TimeZonePtr>::locate_zone(name), zt, c)
+ {}
+
+#else // !HAS_STRING_VIEW
+
+template <class Duration, class TimeZonePtr>
+#if !defined(_MSC_VER) || (_MSC_VER > 1900)
+template <class T, class>
+#endif
+inline
+zoned_time<Duration, TimeZonePtr>::zoned_time(const std::string& name,
+ const sys_time<Duration>& st)
+ : zoned_time(zoned_traits<TimeZonePtr>::locate_zone(name), st)
+ {}
+
+template <class Duration, class TimeZonePtr>
+#if !defined(_MSC_VER) || (_MSC_VER > 1900)
+template <class T, class>
+#endif
+inline
+zoned_time<Duration, TimeZonePtr>::zoned_time(const char* name,
+ const sys_time<Duration>& st)
+ : zoned_time(zoned_traits<TimeZonePtr>::locate_zone(name), st)
+ {}
+
+template <class Duration, class TimeZonePtr>
+#if !defined(_MSC_VER) || (_MSC_VER > 1900)
+template <class T, class>
+#endif
+inline
+zoned_time<Duration, TimeZonePtr>::zoned_time(const std::string& name,
+ const local_time<Duration>& t)
+ : zoned_time(zoned_traits<TimeZonePtr>::locate_zone(name), t)
+ {}
+
+template <class Duration, class TimeZonePtr>
+#if !defined(_MSC_VER) || (_MSC_VER > 1900)
+template <class T, class>
+#endif
+inline
+zoned_time<Duration, TimeZonePtr>::zoned_time(const char* name,
+ const local_time<Duration>& t)
+ : zoned_time(zoned_traits<TimeZonePtr>::locate_zone(name), t)
+ {}
+
+template <class Duration, class TimeZonePtr>
+#if !defined(_MSC_VER) || (_MSC_VER > 1900)
+template <class T, class>
+#endif
+inline
+zoned_time<Duration, TimeZonePtr>::zoned_time(const std::string& name,
+ const local_time<Duration>& t, choose c)
+ : zoned_time(zoned_traits<TimeZonePtr>::locate_zone(name), t, c)
+ {}
+
+template <class Duration, class TimeZonePtr>
+#if !defined(_MSC_VER) || (_MSC_VER > 1900)
+template <class T, class>
+#endif
+inline
+zoned_time<Duration, TimeZonePtr>::zoned_time(const char* name,
+ const local_time<Duration>& t, choose c)
+ : zoned_time(zoned_traits<TimeZonePtr>::locate_zone(name), t, c)
+ {}
+
+template <class Duration, class TimeZonePtr>
+#if !defined(_MSC_VER) || (_MSC_VER > 1900)
+template <class T, class>
+#endif
+inline
+zoned_time<Duration, TimeZonePtr>::zoned_time(const std::string& name,
+ const zoned_time& zt)
+ : zoned_time(zoned_traits<TimeZonePtr>::locate_zone(name), zt)
+ {}
+
+template <class Duration, class TimeZonePtr>
+#if !defined(_MSC_VER) || (_MSC_VER > 1900)
+template <class T, class>
+#endif
+inline
+zoned_time<Duration, TimeZonePtr>::zoned_time(const char* name, const zoned_time& zt)
+ : zoned_time(zoned_traits<TimeZonePtr>::locate_zone(name), zt)
+ {}
+
+template <class Duration, class TimeZonePtr>
+#if !defined(_MSC_VER) || (_MSC_VER > 1900)
+template <class T, class>
+#endif
+inline
+zoned_time<Duration, TimeZonePtr>::zoned_time(const std::string& name,
+ const zoned_time& zt, choose c)
+ : zoned_time(zoned_traits<TimeZonePtr>::locate_zone(name), zt, c)
+ {}
+
+template <class Duration, class TimeZonePtr>
+#if !defined(_MSC_VER) || (_MSC_VER > 1900)
+template <class T, class>
+#endif
+inline
+zoned_time<Duration, TimeZonePtr>::zoned_time(const char* name,
+ const zoned_time& zt, choose c)
+ : zoned_time(zoned_traits<TimeZonePtr>::locate_zone(name), zt, c)
+ {}
+
+#endif // HAS_STRING_VIEW
+
+template <class Duration, class TimeZonePtr>
+inline
+zoned_time<Duration, TimeZonePtr>&
+zoned_time<Duration, TimeZonePtr>::operator=(const sys_time<Duration>& st)
+{
+ tp_ = st;
+ return *this;
+}
+
+template <class Duration, class TimeZonePtr>
+inline
+zoned_time<Duration, TimeZonePtr>&
+zoned_time<Duration, TimeZonePtr>::operator=(const local_time<Duration>& ut)
+{
+ tp_ = zone_->to_sys(ut);
+ return *this;
+}
+
+template <class Duration, class TimeZonePtr>
+inline
+zoned_time<Duration, TimeZonePtr>::operator local_time<typename zoned_time<Duration, TimeZonePtr>::duration>() const
+{
+ return get_local_time();
+}
+
+template <class Duration, class TimeZonePtr>
+inline
+zoned_time<Duration, TimeZonePtr>::operator sys_time<typename zoned_time<Duration, TimeZonePtr>::duration>() const
+{
+ return get_sys_time();
+}
+
+template <class Duration, class TimeZonePtr>
+inline
+TimeZonePtr
+zoned_time<Duration, TimeZonePtr>::get_time_zone() const
+{
+ return zone_;
+}
+
+template <class Duration, class TimeZonePtr>
+inline
+local_time<typename zoned_time<Duration, TimeZonePtr>::duration>
+zoned_time<Duration, TimeZonePtr>::get_local_time() const
+{
+ return zone_->to_local(tp_);
+}
+
+template <class Duration, class TimeZonePtr>
+inline
+sys_time<typename zoned_time<Duration, TimeZonePtr>::duration>
+zoned_time<Duration, TimeZonePtr>::get_sys_time() const
+{
+ return tp_;
+}
+
+template <class Duration, class TimeZonePtr>
+inline
+sys_info
+zoned_time<Duration, TimeZonePtr>::get_info() const
+{
+ return zone_->get_info(tp_);
+}
+
+// make_zoned_time
+
+inline
+zoned_time<std::chrono::seconds>
+make_zoned()
+{
+ return zoned_time<std::chrono::seconds>();
+}
+
+template <class Duration>
+inline
+zoned_time<typename std::common_type<Duration, std::chrono::seconds>::type>
+make_zoned(const sys_time<Duration>& tp)
+{
+ return zoned_time<typename std::common_type<Duration, std::chrono::seconds>::type>(tp);
+}
+
+template <class TimeZonePtr
+#if !defined(_MSC_VER) || (_MSC_VER > 1900)
+ , class = typename std::enable_if
+ <
+ std::is_class
+ <
+ typename std::decay
+ <
+ decltype(*detail::to_raw_pointer(std::declval<TimeZonePtr&>()))
+ >::type
+ >{}
+ >::type
+#endif
+ >
+inline
+zoned_time<std::chrono::seconds, TimeZonePtr>
+make_zoned(TimeZonePtr z)
+{
+ return zoned_time<std::chrono::seconds, TimeZonePtr>(std::move(z));
+}
+
+inline
+zoned_seconds
+make_zoned(const std::string& name)
+{
+ return zoned_seconds(name);
+}
+
+template <class Duration, class TimeZonePtr
+#if !defined(_MSC_VER) || (_MSC_VER > 1900)
+ , class = typename std::enable_if
+ <
+ std::is_class<typename std::decay<decltype(*std::declval<TimeZonePtr&>())>::type>{}
+ >::type
+#endif
+ >
+inline
+zoned_time<typename std::common_type<Duration, std::chrono::seconds>::type, TimeZonePtr>
+make_zoned(TimeZonePtr zone, const local_time<Duration>& tp)
+{
+ return zoned_time<typename std::common_type<Duration, std::chrono::seconds>::type,
+ TimeZonePtr>(std::move(zone), tp);
+}
+
+template <class Duration, class TimeZonePtr
+#if !defined(_MSC_VER) || (_MSC_VER > 1900)
+ , class = typename std::enable_if
+ <
+ std::is_class<typename std::decay<decltype(*std::declval<TimeZonePtr&>())>::type>{}
+ >::type
+#endif
+ >
+inline
+zoned_time<typename std::common_type<Duration, std::chrono::seconds>::type, TimeZonePtr>
+make_zoned(TimeZonePtr zone, const local_time<Duration>& tp, choose c)
+{
+ return zoned_time<typename std::common_type<Duration, std::chrono::seconds>::type,
+ TimeZonePtr>(std::move(zone), tp, c);
+}
+
+template <class Duration>
+inline
+zoned_time<typename std::common_type<Duration, std::chrono::seconds>::type>
+make_zoned(const std::string& name, const local_time<Duration>& tp)
+{
+ return zoned_time<typename std::common_type<Duration,
+ std::chrono::seconds>::type>(name, tp);
+}
+
+template <class Duration>
+inline
+zoned_time<typename std::common_type<Duration, std::chrono::seconds>::type>
+make_zoned(const std::string& name, const local_time<Duration>& tp, choose c)
+{
+ return zoned_time<typename std::common_type<Duration,
+ std::chrono::seconds>::type>(name, tp, c);
+}
+
+template <class Duration, class TimeZonePtr>
+inline
+zoned_time<Duration, TimeZonePtr>
+make_zoned(TimeZonePtr zone, const zoned_time<Duration, TimeZonePtr>& zt)
+{
+ return zoned_time<Duration, TimeZonePtr>(std::move(zone), zt);
+}
+
+template <class Duration, class TimeZonePtr>
+inline
+zoned_time<Duration, TimeZonePtr>
+make_zoned(const std::string& name, const zoned_time<Duration, TimeZonePtr>& zt)
+{
+ return zoned_time<Duration, TimeZonePtr>(name, zt);
+}
+
+template <class Duration, class TimeZonePtr>
+inline
+zoned_time<Duration, TimeZonePtr>
+make_zoned(TimeZonePtr zone, const zoned_time<Duration, TimeZonePtr>& zt, choose c)
+{
+ return zoned_time<Duration, TimeZonePtr>(std::move(zone), zt, c);
+}
+
+template <class Duration, class TimeZonePtr>
+inline
+zoned_time<Duration, TimeZonePtr>
+make_zoned(const std::string& name, const zoned_time<Duration, TimeZonePtr>& zt, choose c)
+{
+ return zoned_time<Duration, TimeZonePtr>(name, zt, c);
+}
+
+template <class Duration, class TimeZonePtr
+#if !defined(_MSC_VER) || (_MSC_VER > 1900)
+ , class = typename std::enable_if
+ <
+ std::is_class<typename std::decay<decltype(*std::declval<TimeZonePtr&>())>::type>{}
+ >::type
+#endif
+ >
+inline
+zoned_time<typename std::common_type<Duration, std::chrono::seconds>::type, TimeZonePtr>
+make_zoned(TimeZonePtr zone, const sys_time<Duration>& st)
+{
+ return zoned_time<typename std::common_type<Duration, std::chrono::seconds>::type,
+ TimeZonePtr>(std::move(zone), st);
+}
+
+template <class Duration>
+inline
+zoned_time<typename std::common_type<Duration, std::chrono::seconds>::type>
+make_zoned(const std::string& name, const sys_time<Duration>& st)
+{
+ return zoned_time<typename std::common_type<Duration,
+ std::chrono::seconds>::type>(name, st);
+}
+
+template <class CharT, class Traits, class Duration, class TimeZonePtr>
+std::basic_ostream<CharT, Traits>&
+to_stream(std::basic_ostream<CharT, Traits>& os, const CharT* fmt,
+ const zoned_time<Duration, TimeZonePtr>& tp)
+{
+ using duration = typename zoned_time<Duration, TimeZonePtr>::duration;
+ using LT = local_time<duration>;
+ auto const tz = tp.get_time_zone();
+ auto const st = tp.get_sys_time();
+ auto const info = tz->get_info(st);
+ return to_stream(os, fmt, LT{(st+info.offset).time_since_epoch()},
+ &info.abbrev, &info.offset);
+}
+
+template <class CharT, class Traits, class Duration, class TimeZonePtr>
+inline
+std::basic_ostream<CharT, Traits>&
+operator<<(std::basic_ostream<CharT, Traits>& os, const zoned_time<Duration, TimeZonePtr>& t)
+{
+ const CharT fmt[] = {'%', 'F', ' ', '%', 'T', ' ', '%', 'Z', CharT{}};
+ return to_stream(os, fmt, t);
+}
+
+#if !MISSING_LEAP_SECONDS
+
+class utc_clock
+{
+public:
+ using duration = std::chrono::system_clock::duration;
+ using rep = duration::rep;
+ using period = duration::period;
+ using time_point = std::chrono::time_point<utc_clock>;
+ static CONSTDATA bool is_steady = false;
+
+ static time_point now();
+
+ template<typename Duration>
+ static
+ std::chrono::time_point<std::chrono::system_clock, typename std::common_type<Duration, std::chrono::seconds>::type>
+ to_sys(const std::chrono::time_point<utc_clock, Duration>&);
+
+ template<typename Duration>
+ static
+ std::chrono::time_point<utc_clock, typename std::common_type<Duration, std::chrono::seconds>::type>
+ from_sys(const std::chrono::time_point<std::chrono::system_clock, Duration>&);
+};
+
+template <class Duration>
+ using utc_time = std::chrono::time_point<utc_clock, Duration>;
+
+using utc_seconds = utc_time<std::chrono::seconds>;
+
+template <class Duration>
+utc_time<typename std::common_type<Duration, std::chrono::seconds>::type>
+utc_clock::from_sys(const sys_time<Duration>& st)
+{
+ using namespace std::chrono;
+ using duration = typename std::common_type<Duration, seconds>::type;
+ auto const& leaps = get_tzdb().leaps;
+ auto const lt = std::upper_bound(leaps.begin(), leaps.end(), st);
+ return utc_time<duration>{st.time_since_epoch() + seconds{lt-leaps.begin()}};
+}
+
+// Return pair<is_leap_second, seconds{number_of_leap_seconds_since_1970}>
+// first is true if ut is during a leap second insertion, otherwise false.
+// If ut is during a leap second insertion, that leap second is included in the count
+template <class Duration>
+std::pair<bool, std::chrono::seconds>
+is_leap_second(date::utc_time<Duration> const& ut)
+{
+ using namespace date;
+ using namespace std::chrono;
+ using duration = typename std::common_type<Duration, seconds>::type;
+ auto const& leaps = get_tzdb().leaps;
+ auto tp = sys_time<duration>{ut.time_since_epoch()};
+ auto const lt = std::upper_bound(leaps.begin(), leaps.end(), tp);
+ auto ds = seconds{lt-leaps.begin()};
+ tp -= ds;
+ auto ls = false;
+ if (lt > leaps.begin())
+ {
+ if (tp < lt[-1])
+ {
+ if (tp >= lt[-1].date() - seconds{1})
+ ls = true;
+ else
+ --ds;
+ }
+ }
+ return {ls, ds};
+}
+
+template <class Duration>
+sys_time<typename std::common_type<Duration, std::chrono::seconds>::type>
+utc_clock::to_sys(const utc_time<Duration>& ut)
+{
+ using namespace std::chrono;
+ using duration = typename std::common_type<Duration, seconds>::type;
+ auto ls = is_leap_second(ut);
+ auto tp = sys_time<duration>{ut.time_since_epoch() - ls.second};
+ if (ls.first)
+ tp = floor<seconds>(tp) + seconds{1} - duration{1};
+ return tp;
+}
+
+inline
+utc_clock::time_point
+utc_clock::now()
+{
+ using namespace std::chrono;
+ return from_sys(system_clock::now());
+}
+
+template <class CharT, class Traits, class Duration>
+std::basic_ostream<CharT, Traits>&
+to_stream(std::basic_ostream<CharT, Traits>& os, const CharT* fmt,
+ const utc_time<Duration>& t)
+{
+ using namespace std;
+ using namespace std::chrono;
+ using CT = typename common_type<Duration, seconds>::type;
+ const string abbrev("UTC");
+ CONSTDATA seconds offset{0};
+ auto ls = is_leap_second(t);
+ auto tp = sys_time<CT>{t.time_since_epoch() - ls.second};
+ auto const sd = floor<days>(tp);
+ year_month_day ymd = sd;
+ auto time = make_time(tp - sys_seconds{sd});
+ time.seconds() += seconds{ls.first};
+ fields<CT> fds{ymd, time};
+ return to_stream(os, fmt, fds, &abbrev, &offset);
+}
+
+template <class CharT, class Traits, class Duration>
+std::basic_ostream<CharT, Traits>&
+operator<<(std::basic_ostream<CharT, Traits>& os, const utc_time<Duration>& t)
+{
+ const CharT fmt[] = {'%', 'F', ' ', '%', 'T', CharT{}};
+ return to_stream(os, fmt, t);
+}
+
+template <class Duration, class CharT, class Traits, class Alloc = std::allocator<CharT>>
+std::basic_istream<CharT, Traits>&
+from_stream(std::basic_istream<CharT, Traits>& is, const CharT* fmt,
+ utc_time<Duration>& tp, std::basic_string<CharT, Traits, Alloc>* abbrev = nullptr,
+ std::chrono::minutes* offset = nullptr)
+{
+ using namespace std;
+ using namespace std::chrono;
+ using CT = typename common_type<Duration, seconds>::type;
+ minutes offset_local{};
+ auto offptr = offset ? offset : &offset_local;
+ fields<CT> fds{};
+ from_stream(is, fmt, fds, abbrev, offptr);
+ if (!fds.ymd.ok())
+ is.setstate(ios::failbit);
+ if (!is.fail())
+ {
+ bool is_60_sec = fds.tod.seconds() == seconds{60};
+ if (is_60_sec)
+ fds.tod.seconds() -= seconds{1};
+ auto tmp = utc_clock::from_sys(sys_days(fds.ymd) - *offptr + fds.tod.to_duration());
+ if (is_60_sec)
+ tmp += seconds{1};
+ if (is_60_sec != is_leap_second(tmp).first || !fds.tod.in_conventional_range())
+ {
+ is.setstate(ios::failbit);
+ return is;
+ }
+ tp = time_point_cast<Duration>(tmp);
+ }
+ return is;
+}
+
+// tai_clock
+
+class tai_clock
+{
+public:
+ using duration = std::chrono::system_clock::duration;
+ using rep = duration::rep;
+ using period = duration::period;
+ using time_point = std::chrono::time_point<tai_clock>;
+ static const bool is_steady = false;
+
+ static time_point now();
+
+ template<typename Duration>
+ static
+ std::chrono::time_point<utc_clock, typename std::common_type<Duration, std::chrono::seconds>::type>
+ to_utc(const std::chrono::time_point<tai_clock, Duration>&) NOEXCEPT;
+
+ template<typename Duration>
+ static
+ std::chrono::time_point<tai_clock, typename std::common_type<Duration, std::chrono::seconds>::type>
+ from_utc(const std::chrono::time_point<utc_clock, Duration>&) NOEXCEPT;
+};
+
+template <class Duration>
+ using tai_time = std::chrono::time_point<tai_clock, Duration>;
+
+using tai_seconds = tai_time<std::chrono::seconds>;
+
+template <class Duration>
+inline
+utc_time<typename std::common_type<Duration, std::chrono::seconds>::type>
+tai_clock::to_utc(const tai_time<Duration>& t) NOEXCEPT
+{
+ using namespace std::chrono;
+ using duration = typename std::common_type<Duration, seconds>::type;
+ return utc_time<duration>{t.time_since_epoch()} -
+ (sys_days(year{1970}/jan/1) - sys_days(year{1958}/jan/1) + seconds{10});
+}
+
+template <class Duration>
+inline
+tai_time<typename std::common_type<Duration, std::chrono::seconds>::type>
+tai_clock::from_utc(const utc_time<Duration>& t) NOEXCEPT
+{
+ using namespace std::chrono;
+ using duration = typename std::common_type<Duration, seconds>::type;
+ return tai_time<duration>{t.time_since_epoch()} +
+ (sys_days(year{1970}/jan/1) - sys_days(year{1958}/jan/1) + seconds{10});
+}
+
+inline
+tai_clock::time_point
+tai_clock::now()
+{
+ using namespace std::chrono;
+ return from_utc(utc_clock::now());
+}
+
+template <class CharT, class Traits, class Duration>
+std::basic_ostream<CharT, Traits>&
+to_stream(std::basic_ostream<CharT, Traits>& os, const CharT* fmt,
+ const tai_time<Duration>& t)
+{
+ using namespace std;
+ using namespace std::chrono;
+ using CT = typename common_type<Duration, seconds>::type;
+ const string abbrev("TAI");
+ CONSTDATA seconds offset{0};
+ auto tp = sys_time<CT>{t.time_since_epoch()} -
+ seconds(sys_days(year{1970}/jan/1) - sys_days(year{1958}/jan/1));
+ auto const sd = floor<days>(tp);
+ year_month_day ymd = sd;
+ auto time = make_time(tp - sys_seconds{sd});
+ fields<CT> fds{ymd, time};
+ return to_stream(os, fmt, fds, &abbrev, &offset);
+}
+
+template <class CharT, class Traits, class Duration>
+std::basic_ostream<CharT, Traits>&
+operator<<(std::basic_ostream<CharT, Traits>& os, const tai_time<Duration>& t)
+{
+ const CharT fmt[] = {'%', 'F', ' ', '%', 'T', CharT{}};
+ return to_stream(os, fmt, t);
+}
+
+template <class Duration, class CharT, class Traits, class Alloc = std::allocator<CharT>>
+std::basic_istream<CharT, Traits>&
+from_stream(std::basic_istream<CharT, Traits>& is, const CharT* fmt,
+ tai_time<Duration>& tp,
+ std::basic_string<CharT, Traits, Alloc>* abbrev = nullptr,
+ std::chrono::minutes* offset = nullptr)
+{
+ using namespace std;
+ using namespace std::chrono;
+ using CT = typename common_type<Duration, seconds>::type;
+ minutes offset_local{};
+ auto offptr = offset ? offset : &offset_local;
+ fields<CT> fds{};
+ from_stream(is, fmt, fds, abbrev, offptr);
+ if (!fds.ymd.ok() || !fds.tod.in_conventional_range())
+ is.setstate(ios::failbit);
+ if (!is.fail())
+ tp = tai_time<Duration>{duration_cast<Duration>(
+ (sys_days(fds.ymd) +
+ (sys_days(year{1970}/jan/1) - sys_days(year{1958}/jan/1)) -
+ *offptr + fds.tod.to_duration()).time_since_epoch())};
+ return is;
+}
+
+// gps_clock
+
+class gps_clock
+{
+public:
+ using duration = std::chrono::system_clock::duration;
+ using rep = duration::rep;
+ using period = duration::period;
+ using time_point = std::chrono::time_point<gps_clock>;
+ static const bool is_steady = false;
+
+ static time_point now();
+
+ template<typename Duration>
+ static
+ std::chrono::time_point<utc_clock, typename std::common_type<Duration, std::chrono::seconds>::type>
+ to_utc(const std::chrono::time_point<gps_clock, Duration>&) NOEXCEPT;
+
+ template<typename Duration>
+ static
+ std::chrono::time_point<gps_clock, typename std::common_type<Duration, std::chrono::seconds>::type>
+ from_utc(const std::chrono::time_point<utc_clock, Duration>&) NOEXCEPT;
+
+};
+
+template <class Duration>
+ using gps_time = std::chrono::time_point<gps_clock, Duration>;
+
+using gps_seconds = gps_time<std::chrono::seconds>;
+
+template <class Duration>
+inline
+utc_time<typename std::common_type<Duration, std::chrono::seconds>::type>
+gps_clock::to_utc(const gps_time<Duration>& t) NOEXCEPT
+{
+ using namespace std::chrono;
+ using duration = typename std::common_type<Duration, seconds>::type;
+ return utc_time<duration>{t.time_since_epoch()} +
+ (sys_days(year{1980}/jan/sun[1]) - sys_days(year{1970}/jan/1) + seconds{9});
+}
+
+template <class Duration>
+inline
+gps_time<typename std::common_type<Duration, std::chrono::seconds>::type>
+gps_clock::from_utc(const utc_time<Duration>& t) NOEXCEPT
+{
+ using namespace std::chrono;
+ using duration = typename std::common_type<Duration, seconds>::type;
+ return gps_time<duration>{t.time_since_epoch()} -
+ (sys_days(year{1980}/jan/sun[1]) - sys_days(year{1970}/jan/1) + seconds{9});
+}
+
+inline
+gps_clock::time_point
+gps_clock::now()
+{
+ using namespace std::chrono;
+ return from_utc(utc_clock::now());
+}
+
+template <class CharT, class Traits, class Duration>
+std::basic_ostream<CharT, Traits>&
+to_stream(std::basic_ostream<CharT, Traits>& os, const CharT* fmt,
+ const gps_time<Duration>& t)
+{
+ using namespace std;
+ using namespace std::chrono;
+ using CT = typename common_type<Duration, seconds>::type;
+ const string abbrev("GPS");
+ CONSTDATA seconds offset{0};
+ auto tp = sys_time<CT>{t.time_since_epoch()} +
+ seconds(sys_days(year{1980}/jan/sun[1]) - sys_days(year{1970}/jan/1));
+ auto const sd = floor<days>(tp);
+ year_month_day ymd = sd;
+ auto time = make_time(tp - sys_seconds{sd});
+ fields<CT> fds{ymd, time};
+ return to_stream(os, fmt, fds, &abbrev, &offset);
+}
+
+template <class CharT, class Traits, class Duration>
+std::basic_ostream<CharT, Traits>&
+operator<<(std::basic_ostream<CharT, Traits>& os, const gps_time<Duration>& t)
+{
+ const CharT fmt[] = {'%', 'F', ' ', '%', 'T', CharT{}};
+ return to_stream(os, fmt, t);
+}
+
+template <class Duration, class CharT, class Traits, class Alloc = std::allocator<CharT>>
+std::basic_istream<CharT, Traits>&
+from_stream(std::basic_istream<CharT, Traits>& is, const CharT* fmt,
+ gps_time<Duration>& tp,
+ std::basic_string<CharT, Traits, Alloc>* abbrev = nullptr,
+ std::chrono::minutes* offset = nullptr)
+{
+ using namespace std;
+ using namespace std::chrono;
+ using CT = typename common_type<Duration, seconds>::type;
+ minutes offset_local{};
+ auto offptr = offset ? offset : &offset_local;
+ fields<CT> fds{};
+ from_stream(is, fmt, fds, abbrev, offptr);
+ if (!fds.ymd.ok() || !fds.tod.in_conventional_range())
+ is.setstate(ios::failbit);
+ if (!is.fail())
+ tp = gps_time<Duration>{duration_cast<Duration>(
+ (sys_days(fds.ymd) -
+ (sys_days(year{1980}/jan/sun[1]) - sys_days(year{1970}/jan/1)) -
+ *offptr + fds.tod.to_duration()).time_since_epoch())};
+ return is;
+}
+
+// clock_time_conversion
+
+template <class DstClock, class SrcClock>
+struct clock_time_conversion
+{};
+
+template <>
+struct clock_time_conversion<std::chrono::system_clock, std::chrono::system_clock>
+{
+ template <class Duration>
+ sys_time<Duration>
+ operator()(const sys_time<Duration>& st) const
+ {
+ return st;
+ }
+};
+
+template <>
+struct clock_time_conversion<utc_clock, utc_clock>
+{
+ template <class Duration>
+ utc_time<Duration>
+ operator()(const utc_time<Duration>& ut) const
+ {
+ return ut;
+ }
+};
+
+template <>
+struct clock_time_conversion<utc_clock, std::chrono::system_clock>
+{
+ template <class Duration>
+ utc_time<typename std::common_type<Duration, std::chrono::seconds>::type>
+ operator()(const sys_time<Duration>& st) const
+ {
+ return utc_clock::from_sys(st);
+ }
+};
+
+template <>
+struct clock_time_conversion<std::chrono::system_clock, utc_clock>
+{
+ template <class Duration>
+ sys_time<typename std::common_type<Duration, std::chrono::seconds>::type>
+ operator()(const utc_time<Duration>& ut) const
+ {
+ return utc_clock::to_sys(ut);
+ }
+};
+
+template <class Clock>
+struct clock_time_conversion<Clock, Clock>
+{
+ template <class Duration>
+ std::chrono::time_point<Clock, Duration>
+ operator()(const std::chrono::time_point<Clock, Duration>& tp) const
+ {
+ return tp;
+ }
+};
+
+namespace ctc_detail
+{
+
+template <class Clock, class Duration>
+ using time_point = std::chrono::time_point<Clock, Duration>;
+
+using std::declval;
+using std::chrono::system_clock;
+
+//Check if TimePoint is time for given clock,
+//if not emits hard error
+template <class Clock, class TimePoint>
+struct return_clock_time
+{
+ using clock_time_point = time_point<Clock, typename TimePoint::duration>;
+ using type = TimePoint;
+
+ static_assert(std::is_same<TimePoint, clock_time_point>::value,
+ "time point with appropariate clock shall be returned");
+};
+
+// Check if Clock has to_sys method accepting TimePoint with given duration const& and
+// returning sys_time. If so has nested type member equal to return type to_sys.
+template <class Clock, class Duration, class = void>
+struct return_to_sys
+{};
+
+template <class Clock, class Duration>
+struct return_to_sys
+ <
+ Clock, Duration,
+ decltype(Clock::to_sys(declval<time_point<Clock, Duration> const&>()), void())
+ >
+ : return_clock_time
+ <
+ system_clock,
+ decltype(Clock::to_sys(declval<time_point<Clock, Duration> const&>()))
+ >
+{};
+
+// Similiar to above
+template <class Clock, class Duration, class = void>
+struct return_from_sys
+{};
+
+template <class Clock, class Duration>
+struct return_from_sys
+ <
+ Clock, Duration,
+ decltype(Clock::from_sys(declval<time_point<system_clock, Duration> const&>()),
+ void())
+ >
+ : return_clock_time
+ <
+ Clock,
+ decltype(Clock::from_sys(declval<time_point<system_clock, Duration> const&>()))
+ >
+{};
+
+// Similiar to above
+template <class Clock, class Duration, class = void>
+struct return_to_utc
+{};
+
+template <class Clock, class Duration>
+struct return_to_utc
+ <
+ Clock, Duration,
+ decltype(Clock::to_utc(declval<time_point<Clock, Duration> const&>()), void())
+ >
+ : return_clock_time
+ <
+ utc_clock,
+ decltype(Clock::to_utc(declval<time_point<Clock, Duration> const&>()))>
+{};
+
+// Similiar to above
+template <class Clock, class Duration, class = void>
+struct return_from_utc
+{};
+
+template <class Clock, class Duration>
+struct return_from_utc
+ <
+ Clock, Duration,
+ decltype(Clock::from_utc(declval<time_point<utc_clock, Duration> const&>()),
+ void())
+ >
+ : return_clock_time
+ <
+ Clock,
+ decltype(Clock::from_utc(declval<time_point<utc_clock, Duration> const&>()))
+ >
+{};
+
+} // namespace ctc_detail
+
+template <class SrcClock>
+struct clock_time_conversion<std::chrono::system_clock, SrcClock>
+{
+ template <class Duration>
+ typename ctc_detail::return_to_sys<SrcClock, Duration>::type
+ operator()(const std::chrono::time_point<SrcClock, Duration>& tp) const
+ {
+ return SrcClock::to_sys(tp);
+ }
+};
+
+template <class DstClock>
+struct clock_time_conversion<DstClock, std::chrono::system_clock>
+{
+ template <class Duration>
+ typename ctc_detail::return_from_sys<DstClock, Duration>::type
+ operator()(const sys_time<Duration>& st) const
+ {
+ return DstClock::from_sys(st);
+ }
+};
+
+template <class SrcClock>
+struct clock_time_conversion<utc_clock, SrcClock>
+{
+ template <class Duration>
+ typename ctc_detail::return_to_utc<SrcClock, Duration>::type
+ operator()(const std::chrono::time_point<SrcClock, Duration>& tp) const
+ {
+ return SrcClock::to_utc(tp);
+ }
+};
+
+template <class DstClock>
+struct clock_time_conversion<DstClock, utc_clock>
+{
+ template <class Duration>
+ typename ctc_detail::return_from_utc<DstClock, Duration>::type
+ operator()(const utc_time<Duration>& ut) const
+ {
+ return DstClock::from_utc(ut);
+ }
+};
+
+namespace clock_cast_detail
+{
+
+template <class Clock, class Duration>
+ using time_point = std::chrono::time_point<Clock, Duration>;
+using std::chrono::system_clock;
+
+template <class DstClock, class SrcClock, class Duration>
+auto
+conv_clock(const time_point<SrcClock, Duration>& t)
+ -> decltype(std::declval<clock_time_conversion<DstClock, SrcClock>>()(t))
+{
+ return clock_time_conversion<DstClock, SrcClock>{}(t);
+}
+
+//direct trait conversion, 1st candidate
+template <class DstClock, class SrcClock, class Duration>
+auto
+cc_impl(const time_point<SrcClock, Duration>& t, const time_point<SrcClock, Duration>*)
+ -> decltype(conv_clock<DstClock>(t))
+{
+ return conv_clock<DstClock>(t);
+}
+
+//conversion through sys, 2nd candidate
+template <class DstClock, class SrcClock, class Duration>
+auto
+cc_impl(const time_point<SrcClock, Duration>& t, const void*)
+ -> decltype(conv_clock<DstClock>(conv_clock<system_clock>(t)))
+{
+ return conv_clock<DstClock>(conv_clock<system_clock>(t));
+}
+
+//conversion through utc, 2nd candidate
+template <class DstClock, class SrcClock, class Duration>
+auto
+cc_impl(const time_point<SrcClock, Duration>& t, const void*)
+ -> decltype(0, // MSVC_WORKAROUND
+ conv_clock<DstClock>(conv_clock<utc_clock>(t)))
+{
+ return conv_clock<DstClock>(conv_clock<utc_clock>(t));
+}
+
+//conversion through sys and utc, 3rd candidate
+template <class DstClock, class SrcClock, class Duration>
+auto
+cc_impl(const time_point<SrcClock, Duration>& t, ...)
+ -> decltype(conv_clock<DstClock>(conv_clock<utc_clock>(conv_clock<system_clock>(t))))
+{
+ return conv_clock<DstClock>(conv_clock<utc_clock>(conv_clock<system_clock>(t)));
+}
+
+//conversion through utc and sys, 3rd candidate
+template <class DstClock, class SrcClock, class Duration>
+auto
+cc_impl(const time_point<SrcClock, Duration>& t, ...)
+ -> decltype(0, // MSVC_WORKAROUND
+ conv_clock<DstClock>(conv_clock<system_clock>(conv_clock<utc_clock>(t))))
+{
+ return conv_clock<DstClock>(conv_clock<system_clock>(conv_clock<utc_clock>(t)));
+}
+
+} // namespace clock_cast_detail
+
+template <class DstClock, class SrcClock, class Duration>
+auto
+clock_cast(const std::chrono::time_point<SrcClock, Duration>& tp)
+ -> decltype(clock_cast_detail::cc_impl<DstClock>(tp, &tp))
+{
+ return clock_cast_detail::cc_impl<DstClock>(tp, &tp);
+}
+
+// Deprecated API
+
+template <class Duration>
+inline
+sys_time<typename std::common_type<Duration, std::chrono::seconds>::type>
+to_sys_time(const utc_time<Duration>& t)
+{
+ return utc_clock::to_sys(t);
+}
+
+template <class Duration>
+inline
+sys_time<typename std::common_type<Duration, std::chrono::seconds>::type>
+to_sys_time(const tai_time<Duration>& t)
+{
+ return utc_clock::to_sys(tai_clock::to_utc(t));
+}
+
+template <class Duration>
+inline
+sys_time<typename std::common_type<Duration, std::chrono::seconds>::type>
+to_sys_time(const gps_time<Duration>& t)
+{
+ return utc_clock::to_sys(gps_clock::to_utc(t));
+}
+
+
+template <class Duration>
+inline
+utc_time<typename std::common_type<Duration, std::chrono::seconds>::type>
+to_utc_time(const sys_time<Duration>& t)
+{
+ return utc_clock::from_sys(t);
+}
+
+template <class Duration>
+inline
+utc_time<typename std::common_type<Duration, std::chrono::seconds>::type>
+to_utc_time(const tai_time<Duration>& t)
+{
+ return tai_clock::to_utc(t);
+}
+
+template <class Duration>
+inline
+utc_time<typename std::common_type<Duration, std::chrono::seconds>::type>
+to_utc_time(const gps_time<Duration>& t)
+{
+ return gps_clock::to_utc(t);
+}
+
+
+template <class Duration>
+inline
+tai_time<typename std::common_type<Duration, std::chrono::seconds>::type>
+to_tai_time(const sys_time<Duration>& t)
+{
+ return tai_clock::from_utc(utc_clock::from_sys(t));
+}
+
+template <class Duration>
+inline
+tai_time<typename std::common_type<Duration, std::chrono::seconds>::type>
+to_tai_time(const utc_time<Duration>& t)
+{
+ return tai_clock::from_utc(t);
+}
+
+template <class Duration>
+inline
+tai_time<typename std::common_type<Duration, std::chrono::seconds>::type>
+to_tai_time(const gps_time<Duration>& t)
+{
+ return tai_clock::from_utc(gps_clock::to_utc(t));
+}
+
+
+template <class Duration>
+inline
+gps_time<typename std::common_type<Duration, std::chrono::seconds>::type>
+to_gps_time(const sys_time<Duration>& t)
+{
+ return gps_clock::from_utc(utc_clock::from_sys(t));
+}
+
+template <class Duration>
+inline
+gps_time<typename std::common_type<Duration, std::chrono::seconds>::type>
+to_gps_time(const utc_time<Duration>& t)
+{
+ return gps_clock::from_utc(t);
+}
+
+template <class Duration>
+inline
+gps_time<typename std::common_type<Duration, std::chrono::seconds>::type>
+to_gps_time(const tai_time<Duration>& t)
+{
+ return gps_clock::from_utc(tai_clock::to_utc(t));
+}
+
+#endif // !MISSING_LEAP_SECONDS
+
+} // namespace date
+
+#endif // TZ_H
[02/10] nifi-minifi-cpp git commit: MINIFICPP-472 Added date
formatting EL functions
Posted by al...@apache.org.
http://git-wip-us.apache.org/repos/asf/nifi-minifi-cpp/blob/8777ab5f/thirdparty/date/src/tz.cpp
----------------------------------------------------------------------
diff --git a/thirdparty/date/src/tz.cpp b/thirdparty/date/src/tz.cpp
new file mode 100644
index 0000000..f4a819b
--- /dev/null
+++ b/thirdparty/date/src/tz.cpp
@@ -0,0 +1,3788 @@
+// The MIT License (MIT)
+//
+// Copyright (c) 2015, 2016, 2017 Howard Hinnant
+// Copyright (c) 2015 Ville Voutilainen
+// Copyright (c) 2016 Alexander Kormanovsky
+// Copyright (c) 2016, 2017 Jiangang Zhuang
+// Copyright (c) 2017 Nicolas Veloz Savino
+// Copyright (c) 2017 Florian Dang
+// Copyright (c) 2017 Aaron Bishop
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in all
+// copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+// SOFTWARE.
+//
+// Our apologies. When the previous paragraph was written, lowercase had not yet
+// been invented (that would involve another several millennia of evolution).
+// We did not mean to shout.
+
+#ifdef _WIN32
+ // windows.h will be included directly and indirectly (e.g. by curl).
+ // We need to define these macros to prevent windows.h bringing in
+ // more than we need and do it early so windows.h doesn't get included
+ // without these macros having been defined.
+ // min/max macros interfere with the C++ versions.
+# ifndef NOMINMAX
+# define NOMINMAX
+# endif
+ // We don't need all that Windows has to offer.
+# ifndef WIN32_LEAN_AND_MEAN
+# define WIN32_LEAN_AND_MEAN
+# endif
+
+ // for wcstombs
+# ifndef _CRT_SECURE_NO_WARNINGS
+# define _CRT_SECURE_NO_WARNINGS
+# endif
+
+ // None of this happens with the MS SDK (at least VS14 which I tested), but:
+ // Compiling with mingw, we get "error: 'KF_FLAG_DEFAULT' was not declared in this scope."
+ // and error: 'SHGetKnownFolderPath' was not declared in this scope.".
+ // It seems when using mingw NTDDI_VERSION is undefined and that
+ // causes KNOWN_FOLDER_FLAG and the KF_ flags to not get defined.
+ // So we must define NTDDI_VERSION to get those flags on mingw.
+ // The docs say though here:
+ // https://msdn.microsoft.com/en-nz/library/windows/desktop/aa383745(v=vs.85).aspx
+ // that "If you define NTDDI_VERSION, you must also define _WIN32_WINNT."
+ // So we declare we require Vista or greater.
+# ifdef __MINGW32__
+
+# ifndef NTDDI_VERSION
+# define NTDDI_VERSION 0x06000000
+# define _WIN32_WINNT _WIN32_WINNT_VISTA
+# elif NTDDI_VERSION < 0x06000000
+# warning "If this fails to compile NTDDI_VERSION may be to low. See comments above."
+# endif
+ // But once we define the values above we then get this linker error:
+ // "tz.cpp:(.rdata$.refptr.FOLDERID_Downloads[.refptr.FOLDERID_Downloads]+0x0): "
+ // "undefined reference to `FOLDERID_Downloads'"
+ // which #include <initguid.h> cures see:
+ // https://support.microsoft.com/en-us/kb/130869
+# include <initguid.h>
+ // But with <initguid.h> included, the error moves on to:
+ // error: 'FOLDERID_Downloads' was not declared in this scope
+ // Which #include <knownfolders.h> cures.
+# include <knownfolders.h>
+
+# endif // __MINGW32__
+
+# include <windows.h>
+#endif // _WIN32
+
+#include "date/tz_private.h"
+
+#ifdef __APPLE__
+# include "date/ios.h"
+#else
+# define TARGET_OS_IPHONE 0
+#endif
+
+#if USE_OS_TZDB
+# include <dirent.h>
+#endif
+#include <algorithm>
+#include <cctype>
+#include <cstdlib>
+#include <cstring>
+#include <exception>
+#include <fstream>
+#include <iostream>
+#include <iterator>
+#include <memory>
+#if USE_OS_TZDB
+# include <queue>
+#endif
+#include <sstream>
+#include <string>
+#include <tuple>
+#include <vector>
+#include <sys/stat.h>
+
+// unistd.h is used on some platforms as part of the the means to get
+// the current time zone. On Win32 windows.h provides a means to do it.
+// gcc/mingw supports unistd.h on Win32 but MSVC does not.
+
+#ifdef _WIN32
+# include <io.h> // _unlink etc.
+
+# if defined(__clang__)
+ struct IUnknown; // fix for issue with static_cast<> in objbase.h
+ // (see https://github.com/philsquared/Catch/issues/690)
+# endif
+
+# include <shlobj.h> // CoTaskFree, ShGetKnownFolderPath etc.
+# if HAS_REMOTE_API
+# include <direct.h> // _mkdir
+# include <shellapi.h> // ShFileOperation etc.
+# endif // HAS_REMOTE_API
+#else // !_WIN32
+# include <unistd.h>
+# if !USE_OS_TZDB
+# include <wordexp.h>
+# endif
+# include <limits.h>
+# include <string.h>
+# if !USE_SHELL_API
+# include <sys/stat.h>
+# include <sys/fcntl.h>
+# include <dirent.h>
+# include <cstring>
+# include <sys/wait.h>
+# include <sys/types.h>
+# endif //!USE_SHELL_API
+#endif // !_WIN32
+
+
+#if HAS_REMOTE_API
+ // Note curl includes windows.h so we must include curl AFTER definitions of things
+ // that affect windows.h such as NOMINMAX.
+#if defined(_MSC_VER) && defined(SHORTENED_CURL_INCLUDE)
+ // For rmt_curl nuget package
+# include <curl.h>
+#else
+# include <curl/curl.h>
+#endif
+#endif
+
+#ifdef _WIN32
+static CONSTDATA char folder_delimiter = '\\';
+#else // !_WIN32
+static CONSTDATA char folder_delimiter = '/';
+#endif // !_WIN32
+
+#if defined(__GNUC__) && __GNUC__ < 5
+ // GCC 4.9 Bug 61489 Wrong warning with -Wmissing-field-initializers
+# pragma GCC diagnostic push
+# pragma GCC diagnostic ignored "-Wmissing-field-initializers"
+#endif // defined(__GNUC__) && __GNUC__ < 5
+
+#if !USE_OS_TZDB
+
+# ifdef _WIN32
+
+namespace
+{
+ struct task_mem_deleter
+ {
+ void operator()(wchar_t buf[])
+ {
+ if (buf != nullptr)
+ CoTaskMemFree(buf);
+ }
+ };
+ using co_task_mem_ptr = std::unique_ptr<wchar_t[], task_mem_deleter>;
+}
+
+// We might need to know certain locations even if not using the remote API,
+// so keep these routines out of that block for now.
+static
+std::string
+get_known_folder(const GUID& folderid)
+{
+ std::string folder;
+ PWSTR pfolder = nullptr;
+ HRESULT hr = SHGetKnownFolderPath(folderid, KF_FLAG_DEFAULT, nullptr, &pfolder);
+ if (SUCCEEDED(hr))
+ {
+ co_task_mem_ptr folder_ptr(pfolder);
+ folder = std::string(folder_ptr.get(), folder_ptr.get() + wcslen(folder_ptr.get()));
+ }
+ return folder;
+}
+
+// Usually something like "c:\Users\username\Downloads".
+static
+std::string
+get_download_folder()
+{
+ return get_known_folder(FOLDERID_Downloads);
+}
+
+# else // !_WIN32
+
+# if !defined(INSTALL) || HAS_REMOTE_API
+
+static
+std::string
+expand_path(std::string path)
+{
+# if TARGET_OS_IPHONE
+ return date::iOSUtils::get_tzdata_path();
+# else // !TARGET_OS_IPHONE
+ ::wordexp_t w{};
+ std::unique_ptr<::wordexp_t, void(*)(::wordexp_t*)> hold{&w, ::wordfree};
+ ::wordexp(path.c_str(), &w, 0);
+ if (w.we_wordc != 1)
+ throw std::runtime_error("Cannot expand path: " + path);
+ path = w.we_wordv[0];
+ return path;
+# endif // !TARGET_OS_IPHONE
+}
+
+static
+std::string
+get_download_folder()
+{
+ return expand_path("~/Downloads");
+}
+
+# endif // !defined(INSTALL) || HAS_REMOTE_API
+
+# endif // !_WIN32
+
+#endif // !USE_OS_TZDB
+
+namespace date
+{
+// +---------------------+
+// | Begin Configuration |
+// +---------------------+
+
+using namespace detail;
+
+#if !USE_OS_TZDB
+
+static
+std::string&
+access_install()
+{
+ static std::string install
+#ifndef INSTALL
+
+ = get_download_folder() + folder_delimiter + "tzdata";
+
+#else // !INSTALL
+
+# define STRINGIZEIMP(x) #x
+# define STRINGIZE(x) STRINGIZEIMP(x)
+
+ = STRINGIZE(INSTALL) + std::string(1, folder_delimiter) + "tzdata";
+
+ #undef STRINGIZEIMP
+ #undef STRINGIZE
+#endif // !INSTALL
+
+ return install;
+}
+
+void
+set_install(const std::string& s)
+{
+ access_install() = s;
+}
+
+static
+const std::string&
+get_install()
+{
+ static const std::string& ref = access_install();
+ return ref;
+}
+
+#if HAS_REMOTE_API
+static
+std::string
+get_download_gz_file(const std::string& version)
+{
+ auto file = get_install() + version + ".tar.gz";
+ return file;
+}
+#endif // HAS_REMOTE_API
+
+#endif // !USE_OS_TZDB
+
+// These can be used to reduce the range of the database to save memory
+CONSTDATA auto min_year = date::year::min();
+CONSTDATA auto max_year = date::year::max();
+
+CONSTDATA auto min_day = date::jan/1;
+CONSTDATA auto max_day = date::dec/31;
+
+#if USE_OS_TZDB
+
+CONSTCD14 const sys_seconds min_seconds = sys_days(min_year/min_day);
+
+#endif // USE_OS_TZDB
+
+#ifndef _WIN32
+
+static
+std::string
+discover_tz_dir()
+{
+ struct stat sb;
+ using namespace std;
+# ifndef __APPLE__
+ CONSTDATA auto tz_dir_default = "/usr/share/zoneinfo";
+ CONSTDATA auto tz_dir_buildroot = "/usr/share/zoneinfo/uclibc";
+
+ // Check special path which is valid for buildroot with uclibc builds
+ if(stat(tz_dir_buildroot, &sb) == 0 && S_ISDIR(sb.st_mode))
+ return tz_dir_buildroot;
+ else if(stat(tz_dir_default, &sb) == 0 && S_ISDIR(sb.st_mode))
+ return tz_dir_default;
+ else
+ throw runtime_error("discover_tz_dir failed to find zoneinfo\n");
+# else // __APPLE__
+# if TARGET_OS_IPHONE
+ return "/var/db/timezone/zoneinfo";
+# else
+ CONSTDATA auto timezone = "/etc/localtime";
+ if (!(lstat(timezone, &sb) == 0 && S_ISLNK(sb.st_mode) && sb.st_size > 0))
+ throw runtime_error("discover_tz_dir failed\n");
+ string result;
+ char rp[PATH_MAX+1] = {};
+ if (readlink(timezone, rp, sizeof(rp)-1) > 0)
+ result = string(rp);
+ else
+ throw system_error(errno, system_category(), "readlink() failed");
+ auto i = result.find("zoneinfo");
+ if (i == string::npos)
+ throw runtime_error("discover_tz_dir failed to find zoneinfo\n");
+ i = result.find('/', i);
+ if (i == string::npos)
+ throw runtime_error("discover_tz_dir failed to find '/'\n");
+ return result.substr(0, i);
+# endif
+# endif // __APPLE__
+}
+
+static
+const std::string&
+get_tz_dir()
+{
+ static const std::string tz_dir = discover_tz_dir();
+ return tz_dir;
+}
+
+#endif
+
+// +-------------------+
+// | End Configuration |
+// +-------------------+
+
+namespace detail
+{
+struct undocumented {explicit undocumented() = default;};
+}
+
+#ifndef _MSC_VER
+static_assert(min_year <= max_year, "Configuration error");
+#endif
+
+static std::unique_ptr<tzdb> init_tzdb();
+
+tzdb_list::~tzdb_list()
+{
+ const tzdb* ptr = head_;
+ head_ = nullptr;
+ while (ptr != nullptr)
+ {
+ auto next = ptr->next;
+ delete ptr;
+ ptr = next;
+ }
+}
+
+tzdb_list::tzdb_list(tzdb_list&& x) noexcept
+ : head_{x.head_.exchange(nullptr)}
+{
+}
+
+void
+tzdb_list::push_front(tzdb* tzdb) noexcept
+{
+ tzdb->next = head_;
+ head_ = tzdb;
+}
+
+tzdb_list::const_iterator
+tzdb_list::erase_after(const_iterator p) noexcept
+{
+ auto t = p.p_->next;
+ p.p_->next = p.p_->next->next;
+ delete t;
+ return ++p;
+}
+
+struct tzdb_list::undocumented_helper
+{
+ static void push_front(tzdb_list& db_list, tzdb* tzdb) noexcept
+ {
+ db_list.push_front(tzdb);
+ }
+};
+
+static
+tzdb_list
+create_tzdb()
+{
+ tzdb_list tz_db;
+ tzdb_list::undocumented_helper::push_front(tz_db, init_tzdb().release());
+ return tz_db;
+}
+
+tzdb_list&
+get_tzdb_list()
+{
+ static tzdb_list tz_db = create_tzdb();
+ return tz_db;
+}
+
+#if !USE_OS_TZDB
+
+#ifdef _WIN32
+
+static
+void
+sort_zone_mappings(std::vector<date::detail::timezone_mapping>& mappings)
+{
+ std::sort(mappings.begin(), mappings.end(),
+ [](const date::detail::timezone_mapping& lhs,
+ const date::detail::timezone_mapping& rhs)->bool
+ {
+ auto other_result = lhs.other.compare(rhs.other);
+ if (other_result < 0)
+ return true;
+ else if (other_result == 0)
+ {
+ auto territory_result = lhs.territory.compare(rhs.territory);
+ if (territory_result < 0)
+ return true;
+ else if (territory_result == 0)
+ {
+ if (lhs.type < rhs.type)
+ return true;
+ }
+ }
+ return false;
+ });
+}
+
+static
+bool
+native_to_standard_timezone_name(const std::string& native_tz_name,
+ std::string& standard_tz_name)
+{
+ // TOOD! Need be a case insensitive compare?
+ if (native_tz_name == "UTC")
+ {
+ standard_tz_name = "Etc/UTC";
+ return true;
+ }
+ standard_tz_name.clear();
+ // TODO! we can improve on linear search.
+ const auto& mappings = date::get_tzdb().mappings;
+ for (const auto& tzm : mappings)
+ {
+ if (tzm.other == native_tz_name)
+ {
+ standard_tz_name = tzm.type;
+ return true;
+ }
+ }
+ return false;
+}
+
+// Parse this XML file:
+// http://unicode.org/repos/cldr/trunk/common/supplemental/windowsZones.xml
+// The parsing method is designed to be simple and quick. It is not overly
+// forgiving of change but it should diagnose basic format issues.
+// See timezone_mapping structure for more info.
+static
+std::vector<detail::timezone_mapping>
+load_timezone_mappings_from_xml_file(const std::string& input_path)
+{
+ std::size_t line_num = 0;
+ std::vector<detail::timezone_mapping> mappings;
+ std::string line;
+
+ std::ifstream is(input_path);
+ if (!is.is_open())
+ {
+ // We don't emit file exceptions because that's an implementation detail.
+ std::string msg = "Error opening time zone mapping file \"";
+ msg += input_path;
+ msg += "\".";
+ throw std::runtime_error(msg);
+ }
+
+ auto error = [&input_path, &line_num](const char* info)
+ {
+ std::string msg = "Error loading time zone mapping file \"";
+ msg += input_path;
+ msg += "\" at line ";
+ msg += std::to_string(line_num);
+ msg += ": ";
+ msg += info;
+ throw std::runtime_error(msg);
+ };
+ // [optional space]a="b"
+ auto read_attribute = [&line, &error]
+ (const char* name, std::string& value, std::size_t startPos)
+ ->std::size_t
+ {
+ value.clear();
+ // Skip leading space before attribute name.
+ std::size_t spos = line.find_first_not_of(' ', startPos);
+ if (spos == std::string::npos)
+ spos = startPos;
+ // Assume everything up to next = is the attribute name
+ // and that an = will always delimit that.
+ std::size_t epos = line.find('=', spos);
+ if (epos == std::string::npos)
+ error("Expected \'=\' right after attribute name.");
+ std::size_t name_len = epos - spos;
+ // Expect the name we find matches the name we expect.
+ if (line.compare(spos, name_len, name) != 0)
+ {
+ std::string msg;
+ msg = "Expected attribute name \'";
+ msg += name;
+ msg += "\' around position ";
+ msg += std::to_string(spos);
+ msg += " but found something else.";
+ error(msg.c_str());
+ }
+ ++epos; // Skip the '=' that is after the attribute name.
+ spos = epos;
+ if (spos < line.length() && line[spos] == '\"')
+ ++spos; // Skip the quote that is before the attribute value.
+ else
+ {
+ std::string msg = "Expected '\"' to begin value of attribute \'";
+ msg += name;
+ msg += "\'.";
+ error(msg.c_str());
+ }
+ epos = line.find('\"', spos);
+ if (epos == std::string::npos)
+ {
+ std::string msg = "Expected '\"' to end value of attribute \'";
+ msg += name;
+ msg += "\'.";
+ error(msg.c_str());
+ }
+ // Extract everything in between the quotes. Note no escaping is done.
+ std::size_t value_len = epos - spos;
+ value.assign(line, spos, value_len);
+ ++epos; // Skip the quote that is after the attribute value;
+ return epos;
+ };
+
+ // Quick but not overly forgiving XML mapping file processing.
+ bool mapTimezonesOpenTagFound = false;
+ bool mapTimezonesCloseTagFound = false;
+ std::size_t mapZonePos = std::string::npos;
+ std::size_t mapTimezonesPos = std::string::npos;
+ CONSTDATA char mapTimeZonesOpeningTag[] = { "<mapTimezones " };
+ CONSTDATA char mapZoneOpeningTag[] = { "<mapZone " };
+ CONSTDATA std::size_t mapZoneOpeningTagLen = sizeof(mapZoneOpeningTag) /
+ sizeof(mapZoneOpeningTag[0]) - 1;
+ while (!mapTimezonesOpenTagFound)
+ {
+ std::getline(is, line);
+ ++line_num;
+ if (is.eof())
+ {
+ // If there is no mapTimezones tag is it an error?
+ // Perhaps if there are no mapZone mappings it might be ok for
+ // its parent mapTimezones element to be missing?
+ // We treat this as an error though on the assumption that if there
+ // really are no mappings we should still get a mapTimezones parent
+ // element but no mapZone elements inside. Assuming we must
+ // find something will hopefully at least catch more drastic formatting
+ // changes or errors than if we don't do this and assume nothing found.
+ error("Expected a mapTimezones opening tag.");
+ }
+ mapTimezonesPos = line.find(mapTimeZonesOpeningTag);
+ mapTimezonesOpenTagFound = (mapTimezonesPos != std::string::npos);
+ }
+
+ // NOTE: We could extract the version info that follows the opening
+ // mapTimezones tag and compare that to the version of other data we have.
+ // I would have expected them to be kept in synch but testing has shown
+ // it typically does not match anyway. So what's the point?
+ while (!mapTimezonesCloseTagFound)
+ {
+ std::ws(is);
+ std::getline(is, line);
+ ++line_num;
+ if (is.eof())
+ error("Expected a mapTimezones closing tag.");
+ if (line.empty())
+ continue;
+ mapZonePos = line.find(mapZoneOpeningTag);
+ if (mapZonePos != std::string::npos)
+ {
+ mapZonePos += mapZoneOpeningTagLen;
+ detail::timezone_mapping zm{};
+ std::size_t pos = read_attribute("other", zm.other, mapZonePos);
+ pos = read_attribute("territory", zm.territory, pos);
+ read_attribute("type", zm.type, pos);
+ mappings.push_back(std::move(zm));
+
+ continue;
+ }
+ mapTimezonesPos = line.find("</mapTimezones>");
+ mapTimezonesCloseTagFound = (mapTimezonesPos != std::string::npos);
+ if (!mapTimezonesCloseTagFound)
+ {
+ std::size_t commentPos = line.find("<!--");
+ if (commentPos == std::string::npos)
+ error("Unexpected mapping record found. A xml mapZone or comment "
+ "attribute or mapTimezones closing tag was expected.");
+ }
+ }
+
+ is.close();
+ return mappings;
+}
+
+#endif // _WIN32
+
+// Parsing helpers
+
+static
+std::string
+parse3(std::istream& in)
+{
+ std::string r(3, ' ');
+ ws(in);
+ r[0] = static_cast<char>(in.get());
+ r[1] = static_cast<char>(in.get());
+ r[2] = static_cast<char>(in.get());
+ return r;
+}
+
+static
+unsigned
+parse_dow(std::istream& in)
+{
+ CONSTDATA char*const dow_names[] =
+ {"Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"};
+ auto s = parse3(in);
+ auto dow = std::find(std::begin(dow_names), std::end(dow_names), s) - dow_names;
+ if (dow >= std::end(dow_names) - std::begin(dow_names))
+ throw std::runtime_error("oops: bad dow name: " + s);
+ return static_cast<unsigned>(dow);
+}
+
+static
+unsigned
+parse_month(std::istream& in)
+{
+ CONSTDATA char*const month_names[] =
+ {"Jan", "Feb", "Mar", "Apr", "May", "Jun",
+ "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"};
+ auto s = parse3(in);
+ auto m = std::find(std::begin(month_names), std::end(month_names), s) - month_names;
+ if (m >= std::end(month_names) - std::begin(month_names))
+ throw std::runtime_error("oops: bad month name: " + s);
+ return static_cast<unsigned>(++m);
+}
+
+static
+std::chrono::seconds
+parse_unsigned_time(std::istream& in)
+{
+ using namespace std::chrono;
+ int x;
+ in >> x;
+ auto r = seconds{hours{x}};
+ if (!in.eof() && in.peek() == ':')
+ {
+ in.get();
+ in >> x;
+ r += minutes{x};
+ if (!in.eof() && in.peek() == ':')
+ {
+ in.get();
+ in >> x;
+ r += seconds{x};
+ }
+ }
+ return r;
+}
+
+static
+std::chrono::seconds
+parse_signed_time(std::istream& in)
+{
+ ws(in);
+ auto sign = 1;
+ if (in.peek() == '-')
+ {
+ sign = -1;
+ in.get();
+ }
+ else if (in.peek() == '+')
+ in.get();
+ return sign * parse_unsigned_time(in);
+}
+
+// MonthDayTime
+
+detail::MonthDayTime::MonthDayTime(local_seconds tp, tz timezone)
+ : zone_(timezone)
+{
+ using namespace date;
+ const auto dp = date::floor<days>(tp);
+ const auto hms = make_time(tp - dp);
+ const auto ymd = year_month_day(dp);
+ u = ymd.month() / ymd.day();
+ h_ = hms.hours();
+ m_ = hms.minutes();
+ s_ = hms.seconds();
+}
+
+detail::MonthDayTime::MonthDayTime(const date::month_day& md, tz timezone)
+ : zone_(timezone)
+{
+ u = md;
+}
+
+date::day
+detail::MonthDayTime::day() const
+{
+ switch (type_)
+ {
+ case month_day:
+ return u.month_day_.day();
+ case month_last_dow:
+ return date::day{31};
+ case lteq:
+ case gteq:
+ break;
+ }
+ return u.month_day_weekday_.month_day_.day();
+}
+
+date::month
+detail::MonthDayTime::month() const
+{
+ switch (type_)
+ {
+ case month_day:
+ return u.month_day_.month();
+ case month_last_dow:
+ return u.month_weekday_last_.month();
+ case lteq:
+ case gteq:
+ break;
+ }
+ return u.month_day_weekday_.month_day_.month();
+}
+
+int
+detail::MonthDayTime::compare(date::year y, const MonthDayTime& x, date::year yx,
+ std::chrono::seconds offset, std::chrono::minutes prev_save) const
+{
+ if (zone_ != x.zone_)
+ {
+ auto dp0 = to_sys_days(y);
+ auto dp1 = x.to_sys_days(yx);
+ if (std::abs((dp0-dp1).count()) > 1)
+ return dp0 < dp1 ? -1 : 1;
+ if (zone_ == tz::local)
+ {
+ auto tp0 = to_time_point(y) - prev_save;
+ if (x.zone_ == tz::utc)
+ tp0 -= offset;
+ auto tp1 = x.to_time_point(yx);
+ return tp0 < tp1 ? -1 : tp0 == tp1 ? 0 : 1;
+ }
+ else if (zone_ == tz::standard)
+ {
+ auto tp0 = to_time_point(y);
+ auto tp1 = x.to_time_point(yx);
+ if (x.zone_ == tz::local)
+ tp1 -= prev_save;
+ else
+ tp0 -= offset;
+ return tp0 < tp1 ? -1 : tp0 == tp1 ? 0 : 1;
+ }
+ // zone_ == tz::utc
+ auto tp0 = to_time_point(y);
+ auto tp1 = x.to_time_point(yx);
+ if (x.zone_ == tz::local)
+ tp1 -= offset + prev_save;
+ else
+ tp1 -= offset;
+ return tp0 < tp1 ? -1 : tp0 == tp1 ? 0 : 1;
+ }
+ auto const t0 = to_time_point(y);
+ auto const t1 = x.to_time_point(yx);
+ return t0 < t1 ? -1 : t0 == t1 ? 0 : 1;
+}
+
+sys_seconds
+detail::MonthDayTime::to_sys(date::year y, std::chrono::seconds offset,
+ std::chrono::seconds save) const
+{
+ using namespace date;
+ using namespace std::chrono;
+ auto until_utc = to_time_point(y);
+ if (zone_ == tz::standard)
+ until_utc -= offset;
+ else if (zone_ == tz::local)
+ until_utc -= offset + save;
+ return until_utc;
+}
+
+detail::MonthDayTime::U&
+detail::MonthDayTime::U::operator=(const date::month_day& x)
+{
+ month_day_ = x;
+ return *this;
+}
+
+detail::MonthDayTime::U&
+detail::MonthDayTime::U::operator=(const date::month_weekday_last& x)
+{
+ month_weekday_last_ = x;
+ return *this;
+}
+
+detail::MonthDayTime::U&
+detail::MonthDayTime::U::operator=(const pair& x)
+{
+ month_day_weekday_ = x;
+ return *this;
+}
+
+date::sys_days
+detail::MonthDayTime::to_sys_days(date::year y) const
+{
+ using namespace std::chrono;
+ using namespace date;
+ switch (type_)
+ {
+ case month_day:
+ return sys_days(y/u.month_day_);
+ case month_last_dow:
+ return sys_days(y/u.month_weekday_last_);
+ case lteq:
+ {
+ auto const x = y/u.month_day_weekday_.month_day_;
+ auto const wd1 = weekday(static_cast<sys_days>(x));
+ auto const wd0 = u.month_day_weekday_.weekday_;
+ return sys_days(x) - (wd1-wd0);
+ }
+ case gteq:
+ break;
+ }
+ auto const x = y/u.month_day_weekday_.month_day_;
+ auto const wd1 = u.month_day_weekday_.weekday_;
+ auto const wd0 = weekday(static_cast<sys_days>(x));
+ return sys_days(x) + (wd1-wd0);
+}
+
+sys_seconds
+detail::MonthDayTime::to_time_point(date::year y) const
+{
+ // Add seconds first to promote to largest rep early to prevent overflow
+ return to_sys_days(y) + s_ + h_ + m_;
+}
+
+void
+detail::MonthDayTime::canonicalize(date::year y)
+{
+ using namespace std::chrono;
+ using namespace date;
+ switch (type_)
+ {
+ case month_day:
+ return;
+ case month_last_dow:
+ {
+ auto const ymd = year_month_day(sys_days(y/u.month_weekday_last_));
+ u.month_day_ = ymd.month()/ymd.day();
+ type_ = month_day;
+ return;
+ }
+ case lteq:
+ {
+ auto const x = y/u.month_day_weekday_.month_day_;
+ auto const wd1 = weekday(static_cast<sys_days>(x));
+ auto const wd0 = u.month_day_weekday_.weekday_;
+ auto const ymd = year_month_day(sys_days(x) - (wd1-wd0));
+ u.month_day_ = ymd.month()/ymd.day();
+ type_ = month_day;
+ return;
+ }
+ case gteq:
+ {
+ auto const x = y/u.month_day_weekday_.month_day_;
+ auto const wd1 = u.month_day_weekday_.weekday_;
+ auto const wd0 = weekday(static_cast<sys_days>(x));
+ auto const ymd = year_month_day(sys_days(x) + (wd1-wd0));
+ u.month_day_ = ymd.month()/ymd.day();
+ type_ = month_day;
+ return;
+ }
+ }
+}
+
+std::istream&
+detail::operator>>(std::istream& is, MonthDayTime& x)
+{
+ using namespace date;
+ using namespace std::chrono;
+ assert(((std::ios::failbit | std::ios::badbit) & is.exceptions()) ==
+ (std::ios::failbit | std::ios::badbit));
+ x = MonthDayTime{};
+ if (!is.eof() && ws(is) && !is.eof() && is.peek() != '#')
+ {
+ auto m = parse_month(is);
+ if (!is.eof() && ws(is) && !is.eof() && is.peek() != '#')
+ {
+ if (is.peek() == 'l')
+ {
+ for (int i = 0; i < 4; ++i)
+ is.get();
+ auto dow = parse_dow(is);
+ x.type_ = MonthDayTime::month_last_dow;
+ x.u = date::month(m)/weekday(dow)[last];
+ }
+ else if (std::isalpha(is.peek()))
+ {
+ auto dow = parse_dow(is);
+ char c{};
+ is >> c;
+ if (c == '<' || c == '>')
+ {
+ char c2{};
+ is >> c2;
+ if (c2 != '=')
+ throw std::runtime_error(std::string("bad operator: ") + c + c2);
+ int d;
+ is >> d;
+ if (d < 1 || d > 31)
+ throw std::runtime_error(std::string("bad operator: ") + c + c2
+ + std::to_string(d));
+ x.type_ = c == '<' ? MonthDayTime::lteq : MonthDayTime::gteq;
+ x.u = MonthDayTime::pair{ date::month(m) / d, date::weekday(dow) };
+ }
+ else
+ throw std::runtime_error(std::string("bad operator: ") + c);
+ }
+ else // if (std::isdigit(is.peek())
+ {
+ int d;
+ is >> d;
+ if (d < 1 || d > 31)
+ throw std::runtime_error(std::string("day of month: ")
+ + std::to_string(d));
+ x.type_ = MonthDayTime::month_day;
+ x.u = date::month(m)/d;
+ }
+ if (!is.eof() && ws(is) && !is.eof() && is.peek() != '#')
+ {
+ int t;
+ is >> t;
+ x.h_ = hours{t};
+ if (!is.eof() && is.peek() == ':')
+ {
+ is.get();
+ is >> t;
+ x.m_ = minutes{t};
+ if (!is.eof() && is.peek() == ':')
+ {
+ is.get();
+ is >> t;
+ x.s_ = seconds{t};
+ }
+ }
+ if (!is.eof() && std::isalpha(is.peek()))
+ {
+ char c;
+ is >> c;
+ switch (c)
+ {
+ case 's':
+ x.zone_ = tz::standard;
+ break;
+ case 'u':
+ x.zone_ = tz::utc;
+ break;
+ }
+ }
+ }
+ }
+ else
+ {
+ x.u = month{m}/1;
+ }
+ }
+ return is;
+}
+
+std::ostream&
+detail::operator<<(std::ostream& os, const MonthDayTime& x)
+{
+ switch (x.type_)
+ {
+ case MonthDayTime::month_day:
+ os << x.u.month_day_ << " ";
+ break;
+ case MonthDayTime::month_last_dow:
+ os << x.u.month_weekday_last_ << " ";
+ break;
+ case MonthDayTime::lteq:
+ os << x.u.month_day_weekday_.weekday_ << " on or before "
+ << x.u.month_day_weekday_.month_day_ << " ";
+ break;
+ case MonthDayTime::gteq:
+ if ((static_cast<unsigned>(x.day()) - 1) % 7 == 0)
+ {
+ os << (x.u.month_day_weekday_.month_day_.month() /
+ x.u.month_day_weekday_.weekday_[
+ (static_cast<unsigned>(x.day()) - 1)/7+1]) << " ";
+ }
+ else
+ {
+ os << x.u.month_day_weekday_.weekday_ << " on or after "
+ << x.u.month_day_weekday_.month_day_ << " ";
+ }
+ break;
+ }
+ os << date::make_time(x.s_ + x.h_ + x.m_);
+ if (x.zone_ == tz::utc)
+ os << "UTC ";
+ else if (x.zone_ == tz::standard)
+ os << "STD ";
+ else
+ os << " ";
+ return os;
+}
+
+// Rule
+
+detail::Rule::Rule(const std::string& s)
+{
+ try
+ {
+ using namespace date;
+ using namespace std::chrono;
+ std::istringstream in(s);
+ in.exceptions(std::ios::failbit | std::ios::badbit);
+ std::string word;
+ in >> word >> name_;
+ int x;
+ ws(in);
+ if (std::isalpha(in.peek()))
+ {
+ in >> word;
+ if (word == "min")
+ {
+ starting_year_ = year::min();
+ }
+ else
+ throw std::runtime_error("Didn't find expected word: " + word);
+ }
+ else
+ {
+ in >> x;
+ starting_year_ = year{x};
+ }
+ std::ws(in);
+ if (std::isalpha(in.peek()))
+ {
+ in >> word;
+ if (word == "only")
+ {
+ ending_year_ = starting_year_;
+ }
+ else if (word == "max")
+ {
+ ending_year_ = year::max();
+ }
+ else
+ throw std::runtime_error("Didn't find expected word: " + word);
+ }
+ else
+ {
+ in >> x;
+ ending_year_ = year{x};
+ }
+ in >> word; // TYPE (always "-")
+ assert(word == "-");
+ in >> starting_at_;
+ save_ = duration_cast<minutes>(parse_signed_time(in));
+ in >> abbrev_;
+ if (abbrev_ == "-")
+ abbrev_.clear();
+ assert(hours{-1} <= save_ && save_ <= hours{2});
+ }
+ catch (...)
+ {
+ std::cerr << s << '\n';
+ std::cerr << *this << '\n';
+ throw;
+ }
+}
+
+detail::Rule::Rule(const Rule& r, date::year starting_year, date::year ending_year)
+ : name_(r.name_)
+ , starting_year_(starting_year)
+ , ending_year_(ending_year)
+ , starting_at_(r.starting_at_)
+ , save_(r.save_)
+ , abbrev_(r.abbrev_)
+{
+}
+
+bool
+detail::operator==(const Rule& x, const Rule& y)
+{
+ if (std::tie(x.name_, x.save_, x.starting_year_, x.ending_year_) ==
+ std::tie(y.name_, y.save_, y.starting_year_, y.ending_year_))
+ return x.month() == y.month() && x.day() == y.day();
+ return false;
+}
+
+bool
+detail::operator<(const Rule& x, const Rule& y)
+{
+ using namespace std::chrono;
+ auto const xm = x.month();
+ auto const ym = y.month();
+ if (std::tie(x.name_, x.starting_year_, xm, x.ending_year_) <
+ std::tie(y.name_, y.starting_year_, ym, y.ending_year_))
+ return true;
+ if (std::tie(x.name_, x.starting_year_, xm, x.ending_year_) >
+ std::tie(y.name_, y.starting_year_, ym, y.ending_year_))
+ return false;
+ return x.day() < y.day();
+}
+
+bool
+detail::operator==(const Rule& x, const date::year& y)
+{
+ return x.starting_year_ <= y && y <= x.ending_year_;
+}
+
+bool
+detail::operator<(const Rule& x, const date::year& y)
+{
+ return x.ending_year_ < y;
+}
+
+bool
+detail::operator==(const date::year& x, const Rule& y)
+{
+ return y.starting_year_ <= x && x <= y.ending_year_;
+}
+
+bool
+detail::operator<(const date::year& x, const Rule& y)
+{
+ return x < y.starting_year_;
+}
+
+bool
+detail::operator==(const Rule& x, const std::string& y)
+{
+ return x.name() == y;
+}
+
+bool
+detail::operator<(const Rule& x, const std::string& y)
+{
+ return x.name() < y;
+}
+
+bool
+detail::operator==(const std::string& x, const Rule& y)
+{
+ return y.name() == x;
+}
+
+bool
+detail::operator<(const std::string& x, const Rule& y)
+{
+ return x < y.name();
+}
+
+std::ostream&
+detail::operator<<(std::ostream& os, const Rule& r)
+{
+ using namespace date;
+ using namespace std::chrono;
+ detail::save_stream<char> _(os);
+ os.fill(' ');
+ os.flags(std::ios::dec | std::ios::left);
+ os.width(15);
+ os << r.name_;
+ os << r.starting_year_ << " " << r.ending_year_ << " ";
+ os << r.starting_at_;
+ if (r.save_ >= minutes{0})
+ os << ' ';
+ os << date::make_time(r.save_) << " ";
+ os << r.abbrev_;
+ return os;
+}
+
+date::day
+detail::Rule::day() const
+{
+ return starting_at_.day();
+}
+
+date::month
+detail::Rule::month() const
+{
+ return starting_at_.month();
+}
+
+struct find_rule_by_name
+{
+ bool operator()(const Rule& x, const std::string& nm) const
+ {
+ return x.name() < nm;
+ }
+
+ bool operator()(const std::string& nm, const Rule& x) const
+ {
+ return nm < x.name();
+ }
+};
+
+bool
+detail::Rule::overlaps(const Rule& x, const Rule& y)
+{
+ // assume x.starting_year_ <= y.starting_year_;
+ if (!(x.starting_year_ <= y.starting_year_))
+ {
+ std::cerr << x << '\n';
+ std::cerr << y << '\n';
+ assert(x.starting_year_ <= y.starting_year_);
+ }
+ if (y.starting_year_ > x.ending_year_)
+ return false;
+ return !(x.starting_year_ == y.starting_year_ && x.ending_year_ == y.ending_year_);
+}
+
+void
+detail::Rule::split(std::vector<Rule>& rules, std::size_t i, std::size_t k, std::size_t& e)
+{
+ using namespace date;
+ using difference_type = std::vector<Rule>::iterator::difference_type;
+ // rules[i].starting_year_ <= rules[k].starting_year_ &&
+ // rules[i].ending_year_ >= rules[k].starting_year_ &&
+ // (rules[i].starting_year_ != rules[k].starting_year_ ||
+ // rules[i].ending_year_ != rules[k].ending_year_)
+ assert(rules[i].starting_year_ <= rules[k].starting_year_ &&
+ rules[i].ending_year_ >= rules[k].starting_year_ &&
+ (rules[i].starting_year_ != rules[k].starting_year_ ||
+ rules[i].ending_year_ != rules[k].ending_year_));
+ if (rules[i].starting_year_ == rules[k].starting_year_)
+ {
+ if (rules[k].ending_year_ < rules[i].ending_year_)
+ {
+ rules.insert(rules.begin() + static_cast<difference_type>(k+1),
+ Rule(rules[i], rules[k].ending_year_ + years{1},
+ std::move(rules[i].ending_year_)));
+ ++e;
+ rules[i].ending_year_ = rules[k].ending_year_;
+ }
+ else // rules[k].ending_year_ > rules[i].ending_year_
+ {
+ rules.insert(rules.begin() + static_cast<difference_type>(k+1),
+ Rule(rules[k], rules[i].ending_year_ + years{1},
+ std::move(rules[k].ending_year_)));
+ ++e;
+ rules[k].ending_year_ = rules[i].ending_year_;
+ }
+ }
+ else // rules[i].starting_year_ < rules[k].starting_year_
+ {
+ if (rules[k].ending_year_ < rules[i].ending_year_)
+ {
+ rules.insert(rules.begin() + static_cast<difference_type>(k),
+ Rule(rules[i], rules[k].starting_year_, rules[k].ending_year_));
+ ++k;
+ rules.insert(rules.begin() + static_cast<difference_type>(k+1),
+ Rule(rules[i], rules[k].ending_year_ + years{1},
+ std::move(rules[i].ending_year_)));
+ rules[i].ending_year_ = rules[k].starting_year_ - years{1};
+ e += 2;
+ }
+ else if (rules[k].ending_year_ > rules[i].ending_year_)
+ {
+ rules.insert(rules.begin() + static_cast<difference_type>(k),
+ Rule(rules[i], rules[k].starting_year_, rules[i].ending_year_));
+ ++k;
+ rules.insert(rules.begin() + static_cast<difference_type>(k+1),
+ Rule(rules[k], rules[i].ending_year_ + years{1},
+ std::move(rules[k].ending_year_)));
+ e += 2;
+ rules[k].ending_year_ = std::move(rules[i].ending_year_);
+ rules[i].ending_year_ = rules[k].starting_year_ - years{1};
+ }
+ else // rules[k].ending_year_ == rules[i].ending_year_
+ {
+ rules.insert(rules.begin() + static_cast<difference_type>(k),
+ Rule(rules[i], rules[k].starting_year_,
+ std::move(rules[i].ending_year_)));
+ ++k;
+ ++e;
+ rules[i].ending_year_ = rules[k].starting_year_ - years{1};
+ }
+ }
+}
+
+void
+detail::Rule::split_overlaps(std::vector<Rule>& rules, std::size_t i, std::size_t& e)
+{
+ using difference_type = std::vector<Rule>::iterator::difference_type;
+ auto j = i;
+ for (; i + 1 < e; ++i)
+ {
+ for (auto k = i + 1; k < e; ++k)
+ {
+ if (overlaps(rules[i], rules[k]))
+ {
+ split(rules, i, k, e);
+ std::sort(rules.begin() + static_cast<difference_type>(i),
+ rules.begin() + static_cast<difference_type>(e));
+ }
+ }
+ }
+ for (; j < e; ++j)
+ {
+ if (rules[j].starting_year() == rules[j].ending_year())
+ rules[j].starting_at_.canonicalize(rules[j].starting_year());
+ }
+}
+
+void
+detail::Rule::split_overlaps(std::vector<Rule>& rules)
+{
+ using difference_type = std::vector<Rule>::iterator::difference_type;
+ for (std::size_t i = 0; i < rules.size();)
+ {
+ auto e = static_cast<std::size_t>(std::upper_bound(
+ rules.cbegin()+static_cast<difference_type>(i), rules.cend(), rules[i].name(),
+ [](const std::string& nm, const Rule& x)
+ {
+ return nm < x.name();
+ }) - rules.cbegin());
+ split_overlaps(rules, i, e);
+ auto first_rule = rules.begin() + static_cast<difference_type>(i);
+ auto last_rule = rules.begin() + static_cast<difference_type>(e);
+ auto t = std::lower_bound(first_rule, last_rule, min_year);
+ if (t > first_rule+1)
+ {
+ if (t == last_rule || t->starting_year() >= min_year)
+ --t;
+ auto d = static_cast<std::size_t>(t - first_rule);
+ rules.erase(first_rule, t);
+ e -= d;
+ }
+ first_rule = rules.begin() + static_cast<difference_type>(i);
+ last_rule = rules.begin() + static_cast<difference_type>(e);
+ t = std::upper_bound(first_rule, last_rule, max_year);
+ if (t != last_rule)
+ {
+ auto d = static_cast<std::size_t>(last_rule - t);
+ rules.erase(t, last_rule);
+ e -= d;
+ }
+ i = e;
+ }
+ rules.shrink_to_fit();
+}
+
+// Find the rule that comes chronologically before Rule r. For multi-year rules,
+// y specifies which rules in r. For single year rules, y is assumed to be equal
+// to the year specified by r.
+// Returns a pointer to the chronologically previous rule, and the year within
+// that rule. If there is no previous rule, returns nullptr and year::min().
+// Preconditions:
+// r->starting_year() <= y && y <= r->ending_year()
+static
+std::pair<const Rule*, date::year>
+find_previous_rule(const Rule* r, date::year y)
+{
+ using namespace date;
+ auto const& rules = get_tzdb().rules;
+ if (y == r->starting_year())
+ {
+ if (r == &rules.front() || r->name() != r[-1].name())
+ std::terminate(); // never called with first rule
+ --r;
+ if (y == r->starting_year())
+ return {r, y};
+ return {r, r->ending_year()};
+ }
+ if (r == &rules.front() || r->name() != r[-1].name() ||
+ r[-1].starting_year() < r->starting_year())
+ {
+ while (r < &rules.back() && r->name() == r[1].name() &&
+ r->starting_year() == r[1].starting_year())
+ ++r;
+ return {r, --y};
+ }
+ --r;
+ return {r, y};
+}
+
+// Find the rule that comes chronologically after Rule r. For multi-year rules,
+// y specifies which rules in r. For single year rules, y is assumed to be equal
+// to the year specified by r.
+// Returns a pointer to the chronologically next rule, and the year within
+// that rule. If there is no next rule, return a pointer to a defaulted rule
+// and y+1.
+// Preconditions:
+// first <= r && r < last && r->starting_year() <= y && y <= r->ending_year()
+// [first, last) all have the same name
+static
+std::pair<const Rule*, date::year>
+find_next_rule(const Rule* first_rule, const Rule* last_rule, const Rule* r, date::year y)
+{
+ using namespace date;
+ if (y == r->ending_year())
+ {
+ if (r == last_rule-1)
+ return {nullptr, year::max()};
+ ++r;
+ if (y == r->ending_year())
+ return {r, y};
+ return {r, r->starting_year()};
+ }
+ if (r == last_rule-1 || r->ending_year() < r[1].ending_year())
+ {
+ while (r > first_rule && r->starting_year() == r[-1].starting_year())
+ --r;
+ return {r, ++y};
+ }
+ ++r;
+ return {r, y};
+}
+
+// Find the rule that comes chronologically after Rule r. For multi-year rules,
+// y specifies which rules in r. For single year rules, y is assumed to be equal
+// to the year specified by r.
+// Returns a pointer to the chronologically next rule, and the year within
+// that rule. If there is no next rule, return nullptr and year::max().
+// Preconditions:
+// r->starting_year() <= y && y <= r->ending_year()
+static
+std::pair<const Rule*, date::year>
+find_next_rule(const Rule* r, date::year y)
+{
+ using namespace date;
+ auto const& rules = get_tzdb().rules;
+ if (y == r->ending_year())
+ {
+ if (r == &rules.back() || r->name() != r[1].name())
+ return {nullptr, year::max()};
+ ++r;
+ if (y == r->ending_year())
+ return {r, y};
+ return {r, r->starting_year()};
+ }
+ if (r == &rules.back() || r->name() != r[1].name() ||
+ r->ending_year() < r[1].ending_year())
+ {
+ while (r > &rules.front() && r->name() == r[-1].name() &&
+ r->starting_year() == r[-1].starting_year())
+ --r;
+ return {r, ++y};
+ }
+ ++r;
+ return {r, y};
+}
+
+static
+const Rule*
+find_first_std_rule(const std::pair<const Rule*, const Rule*>& eqr)
+{
+ auto r = eqr.first;
+ auto ry = r->starting_year();
+ while (r->save() != std::chrono::minutes{0})
+ {
+ std::tie(r, ry) = find_next_rule(eqr.first, eqr.second, r, ry);
+ if (r == nullptr)
+ throw std::runtime_error("Could not find standard offset in rule "
+ + eqr.first->name());
+ }
+ return r;
+}
+
+static
+std::pair<const Rule*, date::year>
+find_rule_for_zone(const std::pair<const Rule*, const Rule*>& eqr,
+ const date::year& y, const std::chrono::seconds& offset,
+ const MonthDayTime& mdt)
+{
+ assert(eqr.first != nullptr);
+ assert(eqr.second != nullptr);
+
+ using namespace std::chrono;
+ using namespace date;
+ auto r = eqr.first;
+ auto ry = r->starting_year();
+ auto prev_save = minutes{0};
+ auto prev_year = year::min();
+ const Rule* prev_rule = nullptr;
+ while (r != nullptr)
+ {
+ if (mdt.compare(y, r->mdt(), ry, offset, prev_save) <= 0)
+ break;
+ prev_rule = r;
+ prev_year = ry;
+ prev_save = prev_rule->save();
+ std::tie(r, ry) = find_next_rule(eqr.first, eqr.second, r, ry);
+ }
+ return {prev_rule, prev_year};
+}
+
+static
+std::pair<const Rule*, date::year>
+find_rule_for_zone(const std::pair<const Rule*, const Rule*>& eqr,
+ const sys_seconds& tp_utc,
+ const local_seconds& tp_std,
+ const local_seconds& tp_loc)
+{
+ using namespace std::chrono;
+ using namespace date;
+ auto r = eqr.first;
+ auto ry = r->starting_year();
+ auto prev_save = minutes{0};
+ auto prev_year = year::min();
+ const Rule* prev_rule = nullptr;
+ while (r != nullptr)
+ {
+ bool found = false;
+ switch (r->mdt().zone())
+ {
+ case tz::utc:
+ found = tp_utc < r->mdt().to_time_point(ry);
+ break;
+ case tz::standard:
+ found = sys_seconds{tp_std.time_since_epoch()} < r->mdt().to_time_point(ry);
+ break;
+ case tz::local:
+ found = sys_seconds{tp_loc.time_since_epoch()} < r->mdt().to_time_point(ry);
+ break;
+ }
+ if (found)
+ break;
+ prev_rule = r;
+ prev_year = ry;
+ prev_save = prev_rule->save();
+ std::tie(r, ry) = find_next_rule(eqr.first, eqr.second, r, ry);
+ }
+ return {prev_rule, prev_year};
+}
+
+static
+sys_info
+find_rule(const std::pair<const Rule*, date::year>& first_rule,
+ const std::pair<const Rule*, date::year>& last_rule,
+ const date::year& y, const std::chrono::seconds& offset,
+ const MonthDayTime& mdt, const std::chrono::minutes& initial_save,
+ const std::string& initial_abbrev)
+{
+ using namespace std::chrono;
+ using namespace date;
+ auto r = first_rule.first;
+ auto ry = first_rule.second;
+ sys_info x{sys_days(year::min()/min_day), sys_days(year::max()/max_day),
+ seconds{0}, initial_save, initial_abbrev};
+ while (r != nullptr)
+ {
+ auto tr = r->mdt().to_sys(ry, offset, x.save);
+ auto tx = mdt.to_sys(y, offset, x.save);
+ // Find last rule where tx >= tr
+ if (tx <= tr || (r == last_rule.first && ry == last_rule.second))
+ {
+ if (tx < tr && r == first_rule.first && ry == first_rule.second)
+ {
+ x.end = r->mdt().to_sys(ry, offset, x.save);
+ break;
+ }
+ if (tx < tr)
+ {
+ std::tie(r, ry) = find_previous_rule(r, ry); // can't return nullptr for r
+ assert(r != nullptr);
+ }
+ // r != nullptr && tx >= tr (if tr were to be recomputed)
+ auto prev_save = initial_save;
+ if (!(r == first_rule.first && ry == first_rule.second))
+ prev_save = find_previous_rule(r, ry).first->save();
+ x.begin = r->mdt().to_sys(ry, offset, prev_save);
+ x.save = r->save();
+ x.abbrev = r->abbrev();
+ if (!(r == last_rule.first && ry == last_rule.second))
+ {
+ std::tie(r, ry) = find_next_rule(r, ry); // can't return nullptr for r
+ assert(r != nullptr);
+ x.end = r->mdt().to_sys(ry, offset, x.save);
+ }
+ else
+ x.end = sys_days(year::max()/max_day);
+ break;
+ }
+ x.save = r->save();
+ std::tie(r, ry) = find_next_rule(r, ry); // Can't return nullptr for r
+ assert(r != nullptr);
+ }
+ return x;
+}
+
+// zonelet
+
+detail::zonelet::~zonelet()
+{
+#if !defined(_MSC_VER) || (_MSC_VER >= 1900)
+ using minutes = std::chrono::minutes;
+ using string = std::string;
+ if (tag_ == has_save)
+ u.save_.~minutes();
+ else
+ u.rule_.~string();
+#endif
+}
+
+detail::zonelet::zonelet()
+{
+#if !defined(_MSC_VER) || (_MSC_VER >= 1900)
+ ::new(&u.rule_) std::string();
+#endif
+}
+
+detail::zonelet::zonelet(const zonelet& i)
+ : gmtoff_(i.gmtoff_)
+ , tag_(i.tag_)
+ , format_(i.format_)
+ , until_year_(i.until_year_)
+ , until_date_(i.until_date_)
+ , until_utc_(i.until_utc_)
+ , until_std_(i.until_std_)
+ , until_loc_(i.until_loc_)
+ , initial_save_(i.initial_save_)
+ , initial_abbrev_(i.initial_abbrev_)
+ , first_rule_(i.first_rule_)
+ , last_rule_(i.last_rule_)
+{
+#if !defined(_MSC_VER) || (_MSC_VER >= 1900)
+ if (tag_ == has_save)
+ ::new(&u.save_) std::chrono::minutes(i.u.save_);
+ else
+ ::new(&u.rule_) std::string(i.u.rule_);
+#else
+ if (tag_ == has_save)
+ u.save_ = i.u.save_;
+ else
+ u.rule_ = i.u.rule_;
+#endif
+}
+
+#endif // !USE_OS_TZDB
+
+// time_zone
+
+#if USE_OS_TZDB
+
+time_zone::time_zone(const std::string& s, detail::undocumented)
+ : name_(s)
+ , adjusted_(new std::once_flag{})
+{
+}
+
+enum class endian
+{
+ native = __BYTE_ORDER__,
+ little = __ORDER_LITTLE_ENDIAN__,
+ big = __ORDER_BIG_ENDIAN__
+};
+
+static
+inline
+std::uint32_t
+reverse_bytes(std::uint32_t i)
+{
+ return
+ (i & 0xff000000u) >> 24 |
+ (i & 0x00ff0000u) >> 8 |
+ (i & 0x0000ff00u) << 8 |
+ (i & 0x000000ffu) << 24;
+}
+
+static
+inline
+std::uint64_t
+reverse_bytes(std::uint64_t i)
+{
+ return
+ (i & 0xff00000000000000ull) >> 56 |
+ (i & 0x00ff000000000000ull) >> 40 |
+ (i & 0x0000ff0000000000ull) >> 24 |
+ (i & 0x000000ff00000000ull) >> 8 |
+ (i & 0x00000000ff000000ull) << 8 |
+ (i & 0x0000000000ff0000ull) << 24 |
+ (i & 0x000000000000ff00ull) << 40 |
+ (i & 0x00000000000000ffull) << 56;
+}
+
+template <class T>
+static
+inline
+void
+maybe_reverse_bytes(T&, std::false_type)
+{
+}
+
+static
+inline
+void
+maybe_reverse_bytes(std::int32_t& t, std::true_type)
+{
+ t = static_cast<std::int32_t>(reverse_bytes(static_cast<std::uint32_t>(t)));
+}
+
+static
+inline
+void
+maybe_reverse_bytes(std::int64_t& t, std::true_type)
+{
+ t = static_cast<std::int64_t>(reverse_bytes(static_cast<std::uint64_t>(t)));
+}
+
+template <class T>
+static
+inline
+void
+maybe_reverse_bytes(T& t)
+{
+ maybe_reverse_bytes(t, std::integral_constant<bool,
+ endian::native == endian::little>{});
+}
+
+static
+void
+load_header(std::istream& inf)
+{
+ // Read TZif
+ auto t = inf.get();
+ auto z = inf.get();
+ auto i = inf.get();
+ auto f = inf.get();
+#ifndef NDEBUG
+ assert(t == 'T');
+ assert(z == 'Z');
+ assert(i == 'i');
+ assert(f == 'f');
+#else
+ (void)t;
+ (void)z;
+ (void)i;
+ (void)f;
+#endif
+}
+
+static
+unsigned char
+load_version(std::istream& inf)
+{
+ // Read version
+ auto v = inf.get();
+ assert(v != EOF);
+ return static_cast<unsigned char>(v);
+}
+
+static
+void
+skip_reserve(std::istream& inf)
+{
+ inf.ignore(15);
+}
+
+static
+void
+load_counts(std::istream& inf,
+ std::int32_t& tzh_ttisgmtcnt, std::int32_t& tzh_ttisstdcnt,
+ std::int32_t& tzh_leapcnt, std::int32_t& tzh_timecnt,
+ std::int32_t& tzh_typecnt, std::int32_t& tzh_charcnt)
+{
+ // Read counts;
+ inf.read(reinterpret_cast<char*>(&tzh_ttisgmtcnt), 4);
+ maybe_reverse_bytes(tzh_ttisgmtcnt);
+ inf.read(reinterpret_cast<char*>(&tzh_ttisstdcnt), 4);
+ maybe_reverse_bytes(tzh_ttisstdcnt);
+ inf.read(reinterpret_cast<char*>(&tzh_leapcnt), 4);
+ maybe_reverse_bytes(tzh_leapcnt);
+ inf.read(reinterpret_cast<char*>(&tzh_timecnt), 4);
+ maybe_reverse_bytes(tzh_timecnt);
+ inf.read(reinterpret_cast<char*>(&tzh_typecnt), 4);
+ maybe_reverse_bytes(tzh_typecnt);
+ inf.read(reinterpret_cast<char*>(&tzh_charcnt), 4);
+ maybe_reverse_bytes(tzh_charcnt);
+}
+
+template <class TimeType>
+static
+std::vector<detail::transition>
+load_transitions(std::istream& inf, std::int32_t tzh_timecnt)
+{
+ // Read transitions
+ using namespace std::chrono;
+ std::vector<detail::transition> transitions;
+ transitions.reserve(static_cast<unsigned>(tzh_timecnt));
+ for (std::int32_t i = 0; i < tzh_timecnt; ++i)
+ {
+ TimeType t;
+ inf.read(reinterpret_cast<char*>(&t), sizeof(t));
+ maybe_reverse_bytes(t);
+ transitions.emplace_back(sys_seconds{seconds{t}});
+ if (transitions.back().timepoint < min_seconds)
+ transitions.back().timepoint = min_seconds;
+ }
+ return transitions;
+}
+
+static
+std::vector<std::uint8_t>
+load_indices(std::istream& inf, std::int32_t tzh_timecnt)
+{
+ // Read indices
+ std::vector<std::uint8_t> indices;
+ indices.reserve(static_cast<unsigned>(tzh_timecnt));
+ for (std::int32_t i = 0; i < tzh_timecnt; ++i)
+ {
+ std::uint8_t t;
+ inf.read(reinterpret_cast<char*>(&t), sizeof(t));
+ indices.emplace_back(t);
+ }
+ return indices;
+}
+
+static
+std::vector<ttinfo>
+load_ttinfo(std::istream& inf, std::int32_t tzh_typecnt)
+{
+ // Read ttinfo
+ std::vector<ttinfo> ttinfos;
+ ttinfos.reserve(static_cast<unsigned>(tzh_typecnt));
+ for (std::int32_t i = 0; i < tzh_typecnt; ++i)
+ {
+ ttinfo t;
+ inf.read(reinterpret_cast<char*>(&t), 6);
+ maybe_reverse_bytes(t.tt_gmtoff);
+ ttinfos.emplace_back(t);
+ }
+ return ttinfos;
+}
+
+static
+std::string
+load_abbreviations(std::istream& inf, std::int32_t tzh_charcnt)
+{
+ // Read abbreviations
+ std::string abbrev;
+ abbrev.resize(static_cast<unsigned>(tzh_charcnt), '\0');
+ inf.read(&abbrev[0], tzh_charcnt);
+ return abbrev;
+}
+
+#if !MISSING_LEAP_SECONDS
+
+template <class TimeType>
+static
+std::vector<leap>
+load_leaps(std::istream& inf, std::int32_t tzh_leapcnt)
+{
+ // Read tzh_leapcnt pairs
+ using namespace std::chrono;
+ std::vector<leap> leap_seconds;
+ leap_seconds.reserve(tzh_leapcnt);
+ for (std::int32_t i = 0; i < tzh_leapcnt; ++i)
+ {
+ TimeType t0;
+ std::int32_t t1;
+ inf.read(reinterpret_cast<char*>(&t0), sizeof(t0));
+ inf.read(reinterpret_cast<char*>(&t1), sizeof(t1));
+ maybe_reverse_bytes(t0);
+ maybe_reverse_bytes(t1);
+ leap_seconds.emplace_back(sys_seconds{seconds{t0 - (t1-1)}},
+ detail::undocumented{});
+ }
+ return leap_seconds;
+}
+
+template <class TimeType>
+static
+std::vector<leap>
+load_leap_data(std::istream& inf,
+ std::int32_t tzh_leapcnt, std::int32_t tzh_timecnt,
+ std::int32_t tzh_typecnt, std::int32_t tzh_charcnt)
+{
+ inf.ignore(tzh_timecnt*sizeof(TimeType) + tzh_timecnt + tzh_typecnt*6 + tzh_charcnt);
+ return load_leaps<TimeType>(inf, tzh_leapcnt);
+}
+
+static
+std::vector<leap>
+load_just_leaps(std::istream& inf)
+{
+ // Read tzh_leapcnt pairs
+ using namespace std::chrono;
+ load_header(inf);
+ auto v = load_version(inf);
+ std::int32_t tzh_ttisgmtcnt, tzh_ttisstdcnt, tzh_leapcnt,
+ tzh_timecnt, tzh_typecnt, tzh_charcnt;
+ skip_reserve(inf);
+ load_counts(inf, tzh_ttisgmtcnt, tzh_ttisstdcnt, tzh_leapcnt,
+ tzh_timecnt, tzh_typecnt, tzh_charcnt);
+ if (v == 0)
+ return load_leap_data<int32_t>(inf, tzh_leapcnt, tzh_timecnt, tzh_typecnt,
+ tzh_charcnt);
+#if !defined(NDEBUG)
+ inf.ignore((4+1)*tzh_timecnt + 6*tzh_typecnt + tzh_charcnt + 8*tzh_leapcnt +
+ tzh_ttisstdcnt + tzh_ttisgmtcnt);
+ load_header(inf);
+ auto v2 = load_version(inf);
+ assert(v == v2);
+ skip_reserve(inf);
+#else // defined(NDEBUG)
+ inf.ignore((4+1)*tzh_timecnt + 6*tzh_typecnt + tzh_charcnt + 8*tzh_leapcnt +
+ tzh_ttisstdcnt + tzh_ttisgmtcnt + (4+1+15));
+#endif // defined(NDEBUG)
+ load_counts(inf, tzh_ttisgmtcnt, tzh_ttisstdcnt, tzh_leapcnt,
+ tzh_timecnt, tzh_typecnt, tzh_charcnt);
+ return load_leap_data<int64_t>(inf, tzh_leapcnt, tzh_timecnt, tzh_typecnt,
+ tzh_charcnt);
+}
+
+#endif // !MISSING_LEAP_SECONDS
+
+template <class TimeType>
+void
+time_zone::load_data(std::istream& inf,
+ std::int32_t tzh_leapcnt, std::int32_t tzh_timecnt,
+ std::int32_t tzh_typecnt, std::int32_t tzh_charcnt)
+{
+ using namespace std::chrono;
+ transitions_ = load_transitions<TimeType>(inf, tzh_timecnt);
+ auto indices = load_indices(inf, tzh_timecnt);
+ auto infos = load_ttinfo(inf, tzh_typecnt);
+ auto abbrev = load_abbreviations(inf, tzh_charcnt);
+#if !MISSING_LEAP_SECONDS
+ auto& leap_seconds = get_tzdb_list().front().leaps;
+ if (leap_seconds.empty() && tzh_leapcnt > 0)
+ leap_seconds = load_leaps<TimeType>(inf, tzh_leapcnt);
+#endif
+ ttinfos_.reserve(infos.size());
+ for (auto& info : infos)
+ {
+ ttinfos_.push_back({seconds{info.tt_gmtoff},
+ abbrev.c_str() + info.tt_abbrind,
+ info.tt_isdst != 0});
+ }
+ auto i = 0u;
+ if (transitions_.empty() || transitions_.front().timepoint != min_seconds)
+ {
+ transitions_.emplace(transitions_.begin(), min_seconds);
+ auto tf = std::find_if(ttinfos_.begin(), ttinfos_.end(),
+ [](const expanded_ttinfo& ti)
+ {return ti.is_dst == 0;});
+ if (tf == ttinfos_.end())
+ tf = ttinfos_.begin();
+ transitions_[i].info = &*tf;
+ ++i;
+ }
+ for (auto j = 0u; i < transitions_.size(); ++i, ++j)
+ transitions_[i].info = ttinfos_.data() + indices[j];
+}
+
+void
+time_zone::init_impl()
+{
+ using namespace std;
+ using namespace std::chrono;
+ auto name = get_tz_dir() + ('/' + name_);
+ std::ifstream inf(name);
+ if (!inf.is_open())
+ throw std::runtime_error{"Unable to open " + name};
+ inf.exceptions(std::ios::failbit | std::ios::badbit);
+ load_header(inf);
+ auto v = load_version(inf);
+ std::int32_t tzh_ttisgmtcnt, tzh_ttisstdcnt, tzh_leapcnt,
+ tzh_timecnt, tzh_typecnt, tzh_charcnt;
+ skip_reserve(inf);
+ load_counts(inf, tzh_ttisgmtcnt, tzh_ttisstdcnt, tzh_leapcnt,
+ tzh_timecnt, tzh_typecnt, tzh_charcnt);
+ if (v == 0)
+ {
+ load_data<int32_t>(inf, tzh_leapcnt, tzh_timecnt, tzh_typecnt, tzh_charcnt);
+ }
+ else
+ {
+#if !defined(NDEBUG)
+ inf.ignore((4+1)*tzh_timecnt + 6*tzh_typecnt + tzh_charcnt + 8*tzh_leapcnt +
+ tzh_ttisstdcnt + tzh_ttisgmtcnt);
+ load_header(inf);
+ auto v2 = load_version(inf);
+ assert(v == v2);
+ skip_reserve(inf);
+#else // defined(NDEBUG)
+ inf.ignore((4+1)*tzh_timecnt + 6*tzh_typecnt + tzh_charcnt + 8*tzh_leapcnt +
+ tzh_ttisstdcnt + tzh_ttisgmtcnt + (4+1+15));
+#endif // defined(NDEBUG)
+ load_counts(inf, tzh_ttisgmtcnt, tzh_ttisstdcnt, tzh_leapcnt,
+ tzh_timecnt, tzh_typecnt, tzh_charcnt);
+ load_data<int64_t>(inf, tzh_leapcnt, tzh_timecnt, tzh_typecnt, tzh_charcnt);
+ }
+#if !MISSING_LEAP_SECONDS
+ if (tzh_leapcnt > 0)
+ {
+ auto& leap_seconds = get_tzdb_list().front().leaps;
+ auto itr = leap_seconds.begin();
+ auto l = itr->date();
+ seconds leap_count{0};
+ for (auto t = std::upper_bound(transitions_.begin(), transitions_.end(), l,
+ [](const sys_seconds& x, const transition& ct)
+ {
+ return x < ct.timepoint;
+ });
+ t != transitions_.end(); ++t)
+ {
+ while (t->timepoint >= l)
+ {
+ ++leap_count;
+ if (++itr == leap_seconds.end())
+ l = sys_days(max_year/max_day);
+ else
+ l = itr->date() + leap_count;
+ }
+ t->timepoint -= leap_count;
+ }
+ }
+#endif // !MISSING_LEAP_SECONDS
+ auto b = transitions_.begin();
+ auto i = transitions_.end();
+ if (i != b)
+ {
+ for (--i; i != b; --i)
+ {
+ if (i->info->offset == i[-1].info->offset &&
+ i->info->abbrev == i[-1].info->abbrev &&
+ i->info->is_dst == i[-1].info->is_dst)
+ i = transitions_.erase(i);
+ }
+ }
+}
+
+void
+time_zone::init() const
+{
+ std::call_once(*adjusted_, [this]() {const_cast<time_zone*>(this)->init_impl();});
+}
+
+sys_info
+time_zone::load_sys_info(std::vector<detail::transition>::const_iterator i) const
+{
+ using namespace std::chrono;
+ assert(!transitions_.empty());
+ assert(i != transitions_.begin());
+ sys_info r;
+ r.begin = i[-1].timepoint;
+ r.end = i != transitions_.end() ? i->timepoint :
+ sys_seconds(sys_days(year::max()/max_day));
+ r.offset = i[-1].info->offset;
+ r.save = i[-1].info->is_dst ? minutes{1} : minutes{0};
+ r.abbrev = i[-1].info->abbrev;
+ return r;
+}
+
+sys_info
+time_zone::get_info_impl(sys_seconds tp) const
+{
+ using namespace std;
+ init();
+ return load_sys_info(upper_bound(transitions_.begin(), transitions_.end(), tp,
+ [](const sys_seconds& x, const transition& t)
+ {
+ return x < t.timepoint;
+ }));
+}
+
+local_info
+time_zone::get_info_impl(local_seconds tp) const
+{
+ using namespace std::chrono;
+ init();
+ local_info i;
+ i.result = local_info::unique;
+ auto tr = upper_bound(transitions_.begin(), transitions_.end(), tp,
+ [](const local_seconds& x, const transition& t)
+ {
+ return sys_seconds{x.time_since_epoch()} -
+ t.info->offset < t.timepoint;
+ });
+ i.first = load_sys_info(tr);
+ auto tps = sys_seconds{(tp - i.first.offset).time_since_epoch()};
+ if (tps < i.first.begin + days{1} && tr != transitions_.begin())
+ {
+ i.second = load_sys_info(--tr);
+ tps = sys_seconds{(tp - i.second.offset).time_since_epoch()};
+ if (tps < i.second.end)
+ {
+ i.result = local_info::ambiguous;
+ std::swap(i.first, i.second);
+ }
+ else
+ {
+ i.second = {};
+ }
+ }
+ else if (tps >= i.first.end && tr != transitions_.end())
+ {
+ i.second = load_sys_info(++tr);
+ tps = sys_seconds{(tp - i.second.offset).time_since_epoch()};
+ if (tps < i.second.begin)
+ i.result = local_info::nonexistent;
+ else
+ i.second = {};
+ }
+ return i;
+}
+
+std::ostream&
+operator<<(std::ostream& os, const time_zone& z)
+{
+ using namespace std::chrono;
+ z.init();
+ os << z.name_ << '\n';
+ os << "Initially: ";
+ auto const& t = z.transitions_.front();
+ if (t.info->offset >= seconds{0})
+ os << '+';
+ os << make_time(t.info->offset);
+ if (t.info->is_dst > 0)
+ os << " daylight ";
+ else
+ os << " standard ";
+ os << t.info->abbrev << '\n';
+ for (auto i = std::next(z.transitions_.cbegin()); i < z.transitions_.cend(); ++i)
+ os << *i << '\n';
+ return os;
+}
+
+#if !MISSING_LEAP_SECONDS
+
+leap::leap(const sys_seconds& s, detail::undocumented)
+ : date_(s)
+{
+}
+
+#endif // !MISSING_LEAP_SECONDS
+
+#else // !USE_OS_TZDB
+
+time_zone::time_zone(const std::string& s, detail::undocumented)
+ : adjusted_(new std::once_flag{})
+{
+ try
+ {
+ using namespace date;
+ std::istringstream in(s);
+ in.exceptions(std::ios::failbit | std::ios::badbit);
+ std::string word;
+ in >> word >> name_;
+ parse_info(in);
+ }
+ catch (...)
+ {
+ std::cerr << s << '\n';
+ std::cerr << *this << '\n';
+ zonelets_.pop_back();
+ throw;
+ }
+}
+
+sys_info
+time_zone::get_info_impl(sys_seconds tp) const
+{
+ return get_info_impl(tp, static_cast<int>(tz::utc));
+}
+
+local_info
+time_zone::get_info_impl(local_seconds tp) const
+{
+ using namespace std::chrono;
+ local_info i{};
+ i.first = get_info_impl(sys_seconds{tp.time_since_epoch()}, static_cast<int>(tz::local));
+ auto tps = sys_seconds{(tp - i.first.offset).time_since_epoch()};
+ if (tps < i.first.begin)
+ {
+ i.second = std::move(i.first);
+ i.first = get_info_impl(i.second.begin - seconds{1}, static_cast<int>(tz::utc));
+ i.result = local_info::nonexistent;
+ }
+ else if (i.first.end - tps <= days{1})
+ {
+ i.second = get_info_impl(i.first.end, static_cast<int>(tz::utc));
+ tps = sys_seconds{(tp - i.second.offset).time_since_epoch()};
+ if (tps >= i.second.begin)
+ i.result = local_info::ambiguous;
+ else
+ i.second = {};
+ }
+ return i;
+}
+
+void
+time_zone::add(const std::string& s)
+{
+ try
+ {
+ std::istringstream in(s);
+ in.exceptions(std::ios::failbit | std::ios::badbit);
+ ws(in);
+ if (!in.eof() && in.peek() != '#')
+ parse_info(in);
+ }
+ catch (...)
+ {
+ std::cerr << s << '\n';
+ std::cerr << *this << '\n';
+ zonelets_.pop_back();
+ throw;
+ }
+}
+
+void
+time_zone::parse_info(std::istream& in)
+{
+ using namespace date;
+ using namespace std::chrono;
+ zonelets_.emplace_back();
+ auto& zonelet = zonelets_.back();
+ zonelet.gmtoff_ = parse_signed_time(in);
+ in >> zonelet.u.rule_;
+ if (zonelet.u.rule_ == "-")
+ zonelet.u.rule_.clear();
+ in >> zonelet.format_;
+ if (!in.eof())
+ ws(in);
+ if (in.eof() || in.peek() == '#')
+ {
+ zonelet.until_year_ = year::max();
+ zonelet.until_date_ = MonthDayTime(max_day, tz::utc);
+ }
+ else
+ {
+ int y;
+ in >> y;
+ zonelet.until_year_ = year{y};
+ in >> zonelet.until_date_;
+ zonelet.until_date_.canonicalize(zonelet.until_year_);
+ }
+ if ((zonelet.until_year_ < min_year) ||
+ (zonelets_.size() > 1 && zonelets_.end()[-2].until_year_ > max_year))
+ zonelets_.pop_back();
+}
+
+void
+time_zone::adjust_infos(const std::vector<Rule>& rules)
+{
+ using namespace std::chrono;
+ using namespace date;
+ const zonelet* prev_zonelet = nullptr;
+ for (auto& z : zonelets_)
+ {
+ std::pair<const Rule*, const Rule*> eqr{};
+ std::istringstream in;
+ in.exceptions(std::ios::failbit | std::ios::badbit);
+ // Classify info as rule-based, has save, or neither
+ if (!z.u.rule_.empty())
+ {
+ // Find out if this zonelet has a rule or a save
+ eqr = std::equal_range(rules.data(), rules.data() + rules.size(), z.u.rule_);
+ if (eqr.first == eqr.second)
+ {
+ // The rule doesn't exist. Assume this is a save
+ try
+ {
+ using namespace std::chrono;
+ using string = std::string;
+ in.str(z.u.rule_);
+ auto tmp = duration_cast<minutes>(parse_signed_time(in));
+#if !defined(_MSC_VER) || (_MSC_VER >= 1900)
+ z.u.rule_.~string();
+ z.tag_ = zonelet::has_save;
+ ::new(&z.u.save_) minutes(tmp);
+#else
+ z.u.rule_.clear();
+ z.tag_ = zonelet::has_save;
+ z.u.save_ = tmp;
+#endif
+ }
+ catch (...)
+ {
+ std::cerr << name_ << " : " << z.u.rule_ << '\n';
+ throw;
+ }
+ }
+ }
+ else
+ {
+ // This zone::zonelet has no rule and no save
+ z.tag_ = zonelet::is_empty;
+ }
+
+ minutes final_save{0};
+ if (z.tag_ == zonelet::has_save)
+ {
+ final_save = z.u.save_;
+ }
+ else if (z.tag_ == zonelet::has_rule)
+ {
+ z.last_rule_ = find_rule_for_zone(eqr, z.until_year_, z.gmtoff_,
+ z.until_date_);
+ if (z.last_rule_.first != nullptr)
+ final_save = z.last_rule_.first->save();
+ }
+ z.until_utc_ = z.until_date_.to_sys(z.until_year_, z.gmtoff_, final_save);
+ z.until_std_ = local_seconds{z.until_utc_.time_since_epoch()} + z.gmtoff_;
+ z.until_loc_ = z.until_std_ + final_save;
+
+ if (z.tag_ == zonelet::has_rule)
+ {
+ if (prev_zonelet != nullptr)
+ {
+ z.first_rule_ = find_rule_for_zone(eqr, prev_zonelet->until_utc_,
+ prev_zonelet->until_std_,
+ prev_zonelet->until_loc_);
+ if (z.first_rule_.first != nullptr)
+ {
+ z.initial_save_ = z.first_rule_.first->save();
+ z.initial_abbrev_ = z.first_rule_.first->abbrev();
+ if (z.first_rule_ != z.last_rule_)
+ {
+ z.first_rule_ = find_next_rule(eqr.first, eqr.second,
+ z.first_rule_.first,
+ z.first_rule_.second);
+ }
+ else
+ {
+ z.first_rule_ = std::make_pair(nullptr, year::min());
+ z.last_rule_ = std::make_pair(nullptr, year::max());
+ }
+ }
+ }
+ if (z.first_rule_.first == nullptr && z.last_rule_.first != nullptr)
+ {
+ z.first_rule_ = std::make_pair(eqr.first, eqr.first->starting_year());
+ z.initial_abbrev_ = find_first_std_rule(eqr)->abbrev();
+ }
+ }
+
+#ifndef NDEBUG
+ if (z.first_rule_.first == nullptr)
+ {
+ assert(z.first_rule_.second == year::min());
+ assert(z.last_rule_.first == nullptr);
+ assert(z.last_rule_.second == year::max());
+ }
+ else
+ {
+ assert(z.last_rule_.first != nullptr);
+ }
+#endif
+ prev_zonelet = &z;
+ }
+}
+
+static
+std::string
+format_abbrev(std::string format, const std::string& variable, std::chrono::seconds off,
+ std::chrono::minutes save)
+{
+ using namespace std::chrono;
+ auto k = format.find("%s");
+ if (k != std::string::npos)
+ {
+ format.replace(k, 2, variable);
+ }
+ else
+ {
+ k = format.find('/');
+ if (k != std::string::npos)
+ {
+ if (save == minutes{0})
+ format.erase(k);
+ else
+ format.erase(0, k+1);
+ }
+ else
+ {
+ k = format.find("%z");
+ if (k != std::string::npos)
+ {
+ std::string temp;
+ if (off < seconds{0})
+ {
+ temp = '-';
+ off = -off;
+ }
+ else
+ temp = '+';
+ auto h = date::floor<hours>(off);
+ off -= h;
+ if (h < hours{10})
+ temp += '0';
+ temp += std::to_string(h.count());
+ if (off > seconds{0})
+ {
+ auto m = date::floor<minutes>(off);
+ off -= m;
+ if (m < minutes{10})
+ temp += '0';
+ temp += std::to_string(m.count());
+ if (off > seconds{0})
+ {
+ if (off < seconds{10})
+ temp += '0';
+ temp += std::to_string(off.count());
+ }
+ }
+ format.replace(k, 2, temp);
+ }
+ }
+ }
+ return format;
+}
+
+sys_info
+time_zone::get_info_impl(sys_seconds tp, int tz_int) const
+{
+ using namespace std::chrono;
+ using namespace date;
+ tz timezone = static_cast<tz>(tz_int);
+ assert(timezone != tz::standard);
+ auto y = year_month_day(floor<days>(tp)).year();
+ if (y < min_year || y > max_year)
+ throw std::runtime_error("The year " + std::to_string(static_cast<int>(y)) +
+ " is out of range:[" + std::to_string(static_cast<int>(min_year)) + ", "
+ + std::to_string(static_cast<int>(max_year)) + "]");
+ std::call_once(*adjusted_,
+ [this]()
+ {
+ const_cast<time_zone*>(this)->adjust_infos(get_tzdb().rules);
+ });
+ auto i = std::upper_bound(zonelets_.begin(), zonelets_.end(), tp,
+ [timezone](sys_seconds t, const zonelet& zl)
+ {
+ return timezone == tz::utc ? t < zl.until_utc_ :
+ t < sys_seconds{zl.until_loc_.time_since_epoch()};
+ });
+
+ sys_info r{};
+ if (i != zonelets_.end())
+ {
+ if (i->tag_ == zonelet::has_save)
+ {
+ if (i != zonelets_.begin())
+ r.begin = i[-1].until_utc_;
+ else
+ r.begin = sys_days(year::min()/min_day);
+ r.end = i->until_utc_;
+ r.offset = i->gmtoff_ + i->u.save_;
+ r.save = i->u.save_;
+ }
+ else if (i->u.rule_.empty())
+ {
+ if (i != zonelets_.begin())
+ r.begin = i[-1].until_utc_;
+ else
+ r.begin = sys_days(year::min()/min_day);
+ r.end = i->until_utc_;
+ r.offset = i->gmtoff_;
+ }
+ else
+ {
+ r = find_rule(i->first_rule_, i->last_rule_, y, i->gmtoff_,
+ MonthDayTime(local_seconds{tp.time_since_epoch()}, timezone),
+ i->initial_save_, i->initial_abbrev_);
+ r.offset = i->gmtoff_ + r.save;
+ if (i != zonelets_.begin() && r.begin < i[-1].until_utc_)
+ r.begin = i[-1].until_utc_;
+ if (r.end > i->until_utc_)
+ r.end = i->until_utc_;
+ }
+ r.abbrev = format_abbrev(i->format_, r.abbrev, r.offset, r.save);
+ assert(r.begin < r.end);
+ }
+ return r;
+}
+
+std::ostream&
+operator<<(std::ostream& os, const time_zone& z)
+{
+ using namespace date;
+ using namespace std::chrono;
+ detail::save_stream<char> _(os);
+ os.fill(' ');
+ os.flags(std::ios::dec | std::ios::left);
+ std::call_once(*z.adjusted_,
+ [&z]()
+ {
+ const_cast<time_zone&>(z).adjust_infos(get_tzdb().rules);
+ });
+ os.width(35);
+ os << z.name_;
+ std::string indent;
+ for (auto const& s : z.zonelets_)
+ {
+ os << indent;
+ if (s.gmtoff_ >= seconds{0})
+ os << ' ';
+ os << make_time(s.gmtoff_) << " ";
+ os.width(15);
+ if (s.tag_ != zonelet::has_save)
+ os << s.u.rule_;
+ else
+ {
+ std::ostringstream tmp;
+ tmp << make_time(s.u.save_);
+ os << tmp.str();
+ }
+ os.width(8);
+ os << s.format_ << " ";
+ os << s.until_year_ << ' ' << s.until_date_;
+ os << " " << s.until_utc_ << " UTC";
+ os << " " << s.until_std_ << " STD";
+ os << " " << s.until_loc_;
+ os << " " << make_time(s.initial_save_);
+ os << " " << s.initial_abbrev_;
+ if (s.first_rule_.first != nullptr)
+ os << " {" << *s.first_rule_.first << ", " << s.first_rule_.second << '}';
+ else
+ os << " {" << "nullptr" << ", " << s.first_rule_.second << '}';
+ if (s.last_rule_.first != nullptr)
+ os << " {" << *s.last_rule_.first << ", " << s.last_rule_.second << '}';
+ else
+ os << " {" << "nullptr" << ", " << s.last_rule_.second << '}';
+ os << '\n';
+ if (indent.empty())
+ indent = std::string(35, ' ');
+ }
+ return os;
+}
+
+#endif // !USE_OS_TZDB
+
+#if !MISSING_LEAP_SECONDS
+
+std::ostream&
+operator<<(std::ostream& os, const leap& x)
+{
+ using namespace date;
+ return os << x.date_ << " +";
+}
+
+#endif // !MISSING_LEAP_SECONDS
+
+#if USE_OS_TZDB
+
+# ifdef __APPLE__
+static
+std::string
+get_version()
+{
+ using namespace std;
+ auto path = get_tz_dir() + string("/+VERSION");
+ ifstream in{path};
+ string version;
+ in >> version;
+ if (in.fail())
+ throw std::runtime_error("Unable to get Timezone database version from " + path);
+ return version;
+}
+# endif
+
+static
+std::unique_ptr<tzdb>
+init_tzdb()
+{
+ std::unique_ptr<tzdb> db(new tzdb);
+
+ //Iterate through folders
+ std::queue<std::string> subfolders;
+ subfolders.emplace(get_tz_dir());
+ struct dirent* d;
+ struct stat s;
+ while (!subfolders.empty())
+ {
+ auto dirname = std::move(subfolders.front());
+ subfolders.pop();
+ auto dir = opendir(dirname.c_str());
+ if (!dir)
+ continue;
+ while ((d = readdir(dir)) != nullptr)
+ {
+ // Ignore these files:
+ if (d->d_name[0] == '.' || // curdir, prevdir, hidden
+ memcmp(d->d_name, "posix", 5) == 0 || // starts with posix
+ strcmp(d->d_name, "Factory") == 0 ||
+ strcmp(d->d_name, "iso3166.tab") == 0 ||
+ strcmp(d->d_name, "right") == 0 ||
+ strcmp(d->d_name, "+VERSION") == 0 ||
+ strcmp(d->d_name, "zone.tab") == 0 ||
+ strcmp(d->d_name, "zone1970.tab") == 0 ||
+ strcmp(d->d_name, "leap-seconds.list") == 0 )
+ continue;
+ auto subname = dirname + folder_delimiter + d->d_name;
+ if(stat(subname.c_str(), &s) == 0)
+ {
+ if(S_ISDIR(s.st_mode))
+ {
+ if(!S_ISLNK(s.st_mode))
+ {
+ subfolders.push(subname);
+ }
+ }
+ else
+ {
+ db->zones.emplace_back(subname.substr(get_tz_dir().size()+1),
+ detail::undocumented{});
+ }
+ }
+ }
+ closedir(dir);
+ }
+ db->zones.shrink_to_fit();
+ std::sort(db->zones.begin(), db->zones.end());
+# if !MISSING_LEAP_SECONDS
+ std::ifstream in(get_tz_dir() + std::string(1, folder_delimiter) + "right/UTC",
+ std::ios_base::binary);
+ if (in)
+ {
+ in.exceptions(std::ios::failbit | std::ios::badbit);
+ db->leaps = load_just_leaps(in);
+ }
+ else
+ {
+ in.clear();
+ in.open(get_tz_dir() + std::string(1, folder_delimiter) +
+ "UTC", std::ios_base::binary);
+ if (!in)
+ throw std::runtime_error("Unable to extract leap second information");
+ in.exceptions(std::ios::failbit | std::ios::badbit);
+ db->leaps = load_just_leaps(in);
+ }
+# endif // !MISSING_LEAP_SECONDS
+# ifdef __APPLE__
+ db->version = get_version();
+# endif
+ return db;
+}
+
+#else // !USE_OS_TZDB
+
+// link
+
+link::link(const std::string& s)
+{
+ using namespace date;
+ std::istringstream in(s);
+ in.exceptions(std::ios::failbit | std::ios::badbit);
+ std::string word;
+ in >> word >> target_ >> name_;
+}
+
+std::ostream&
+operator<<(std::ostream& os, const link& x)
+{
+ using namespace date;
+ detail::save_stream<char> _(os);
+ os.fill(' ');
+ os.flags(std::ios::dec | std::ios::left);
+ os.width(35);
+ return os << x.name_ << " --> " << x.target_;
+}
+
+// leap
+
+leap::leap(const std::string& s, detail::undocumented)
+{
+ using namespace date;
+ std::istringstream in(s);
+ in.exceptions(std::ios::failbit | std::ios::badbit);
+ std::string word;
+ int y;
+ MonthDayTime date;
+ in >> word >> y >> date;
+ date_ = date.to_time_point(year(y));
+}
+
+static
+bool
+file_exists(const std::string& filename)
+{
+#ifdef _WIN32
+ return ::_access(filename.c_str(), 0) == 0;
+#else
+ return ::access(filename.c_str(), F_OK) == 0;
+#endif
+}
+
+#if HAS_REMOTE_API
+
+// CURL tools
+
+static
+int
+curl_global()
+{
+ if (::curl_global_init(CURL_GLOBAL_DEFAULT) != 0)
+ throw std::runtime_error("CURL global initialization failed");
+ return 0;
+}
+
+namespace
+{
+
+struct curl_deleter
+{
+ void operator()(CURL* p) const
+ {
+ ::curl_easy_cleanup(p);
+ }
+};
+
+} // unnamed namespace
+
+static
+std::unique_ptr<CURL, curl_deleter>
+curl_init()
+{
+ static const auto curl_is_now_initiailized = curl_global();
+ (void)curl_is_now_initiailized;
+ return std::unique_ptr<CURL, curl_deleter>{::curl_easy_init()};
+}
+
+static
+bool
+download_to_string(const std::string& url, std::string& str)
+{
+ str.clear();
+ auto curl = curl_init();
+ if (!curl)
+ return false;
+ std::string version;
+ curl_easy_setopt(curl.get(), CURLOPT_URL, url.c_str());
+ curl_write_callback write_cb = [](char* contents, std::size_t size, std::size_t nmemb,
+ void* userp) -> std::size_t
+ {
+ auto& userstr = *static_cast<std::string*>(userp);
+ auto realsize = size * nmemb;
+ userstr.append(contents, realsize);
+ return realsize;
+ };
+ curl_easy_setopt(curl.get(), CURLOPT_WRITEFUNCTION, write_cb);
+ curl_easy_setopt(curl.get(), CURLOPT_WRITEDATA, &str);
+ curl_easy_setopt(curl.get(), CURLOPT_SSL_VERIFYPEER, false);
+ auto res = curl_easy_perform(curl.get());
+ return (res == CURLE_OK);
+}
+
+namespace
+{
+ enum class download_file_options { binary, text };
+}
+
+static
+bool
+download_to_file(const std::string& url, const std::string& local_filename,
+ download_file_options opts)
+{
+ auto curl = curl_init();
+ if (!curl)
+ return false;
+ curl_easy_setopt(curl.get(), CURLOPT_URL, url.c_str());
+ curl_easy_setopt(curl.get(), CURLOPT_SSL_VERIFYPEER, false);
+ curl_write_callback write_cb = [](char* contents, std::size_t size, std::size_t nmemb,
+ void* userp) -> std::size_t
+ {
+ auto& of = *static_cast<std::ofstream*>(userp);
+ auto realsize = size * nmemb;
+ of.write(contents, static_cast<std::streamsize>(realsize));
+ return realsize;
+ };
+ curl_easy_setopt(curl.get(), CURLOPT_WRITEFUNCTION, write_cb);
+ decltype(curl_easy_perform(curl.get())) res;
+ {
+ std::ofstream of(local_filename,
+ opts == download_file_options::binary ?
+ std::ofstream::out | std::ofstream::binary :
+ std::ofstream::out);
+ of.exceptions(std::ios::badbit);
+ curl_easy_setopt(curl.get(), CURLOPT_WRITEDATA, &of);
+ res = curl_easy_perform(curl.get());
+ }
+ return res == CURLE_OK;
+}
+
+std::string
+remote_version()
+{
+ std::string version;
+ std::string str;
+ if (download_to_string("https://www.iana.org/time-zones", str))
+ {
+ CONSTDATA char db[] = "/time-zones/releases/tzdata";
+ CONSTDATA auto db_size = sizeof(db) - 1;
+ auto p = str.find(db, 0, db_size);
+ const int ver_str_len = 5;
+ if (p != std::string::npos && p + (db_size + ver_str_len) <= str.size())
+ version = str.substr(p + db_size, ver_str_len);
+ }
+ return version;
+}
+
+
+// TODO! Using system() create a process and a console window.
+// This is useful to see what errors may occur but is slow and distracting.
+// Consider implementing this functionality more directly, such as
+// using _mkdir and CreateProcess etc.
+// But use the current means now as matches Unix implementations and while
+// in proof of concept / testing phase.
+// TODO! Use <filesystem> eventually.
+static
+bool
+remove_folder_and_subfolders(const std::string& folder)
+{
+# ifdef _WIN32
+# if USE_SHELL_API
+ // Delete the folder contents by deleting the folder.
+ std::string cmd = "rd /s /q \"";
+ cmd += folder;
+ cmd += '\"';
+ return std::system(cmd.c_str()) == EXIT_SUCCESS;
+# else // !USE_SHELL_API
+ // Create a buffer containing the path to delete. It must be terminated
+ // by two nuls. Who designs these API's...
+ std::vector<char> from;
+ from.assign(folder.begin(), folder.end());
+ from.push_back('\0');
+ from.push_back('\0');
+ SHFILEOPSTRUCT fo{}; // Zero initialize.
+ fo.wFunc = FO_DELETE;
+ fo.pFrom = from.data();
+ fo.fFlags = FOF_NO_UI;
+ int ret = SHFileOperation(&fo);
+ if (ret == 0 && !fo.fAnyOperationsAborted)
+ return true;
+ return false;
+# endif // !USE_SHELL_API
+# else // !_WIN32
+# if USE_SHELL_API
+ return std::system(("rm -R " + folder).c_str()) == EXIT_SUCCESS;
+# else // !USE_SHELL_API
+ struct dir_deleter {
+
<TRUNCATED>
http://git-wip-us.apache.org/repos/asf/nifi-minifi-cpp/blob/8777ab5f/thirdparty/date/test_fail.sh
----------------------------------------------------------------------
diff --git a/thirdparty/date/test_fail.sh b/thirdparty/date/test_fail.sh
new file mode 100755
index 0000000..6562647
--- /dev/null
+++ b/thirdparty/date/test_fail.sh
@@ -0,0 +1,10 @@
+#!/bin/bash
+
+echo $1
+eval $1
+
+if [ $? -eq 0 ]; then
+ exit 0;
+fi
+exit 1;
+
[03/10] nifi-minifi-cpp git commit: MINIFICPP-472 Added date
formatting EL functions
Posted by al...@apache.org.
http://git-wip-us.apache.org/repos/asf/nifi-minifi-cpp/blob/8777ab5f/thirdparty/date/include/date/tz_private.h
----------------------------------------------------------------------
diff --git a/thirdparty/date/include/date/tz_private.h b/thirdparty/date/include/date/tz_private.h
new file mode 100644
index 0000000..1aaad8e
--- /dev/null
+++ b/thirdparty/date/include/date/tz_private.h
@@ -0,0 +1,318 @@
+#ifndef TZ_PRIVATE_H
+#define TZ_PRIVATE_H
+
+// The MIT License (MIT)
+//
+// Copyright (c) 2015, 2016 Howard Hinnant
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in all
+// copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+// SOFTWARE.
+//
+// Our apologies. When the previous paragraph was written, lowercase had not yet
+// been invented (that would involve another several millennia of evolution).
+// We did not mean to shout.
+
+#if !defined(_MSC_VER) || (_MSC_VER >= 1900)
+#include "tz.h"
+#else
+#include "date.h"
+#include <vector>
+#endif
+
+namespace date
+{
+
+namespace detail
+{
+
+#if !USE_OS_TZDB
+
+enum class tz {utc, local, standard};
+
+//forward declare to avoid warnings in gcc 6.2
+class MonthDayTime;
+std::istream& operator>>(std::istream& is, MonthDayTime& x);
+std::ostream& operator<<(std::ostream& os, const MonthDayTime& x);
+
+
+class MonthDayTime
+{
+private:
+ struct pair
+ {
+#if defined(_MSC_VER) && (_MSC_VER < 1900)
+ pair() : month_day_(date::jan / 1), weekday_(0U) {}
+
+ pair(const date::month_day& month_day, const date::weekday& weekday)
+ : month_day_(month_day), weekday_(weekday) {}
+#endif
+
+ date::month_day month_day_;
+ date::weekday weekday_;
+ };
+
+ enum Type {month_day, month_last_dow, lteq, gteq};
+
+ Type type_{month_day};
+
+#if !defined(_MSC_VER) || (_MSC_VER >= 1900)
+ union U
+#else
+ struct U
+#endif
+ {
+ date::month_day month_day_;
+ date::month_weekday_last month_weekday_last_;
+ pair month_day_weekday_;
+
+#if !defined(_MSC_VER) || (_MSC_VER >= 1900)
+ U() : month_day_{date::jan/1} {}
+#else
+ U() :
+ month_day_(date::jan/1),
+ month_weekday_last_(date::month(0U), date::weekday_last(date::weekday(0U)))
+ {}
+
+#endif // !defined(_MSC_VER) || (_MSC_VER >= 1900)
+
+ U& operator=(const date::month_day& x);
+ U& operator=(const date::month_weekday_last& x);
+ U& operator=(const pair& x);
+ } u;
+
+ std::chrono::hours h_{0};
+ std::chrono::minutes m_{0};
+ std::chrono::seconds s_{0};
+ tz zone_{tz::local};
+
+public:
+ MonthDayTime() = default;
+ MonthDayTime(local_seconds tp, tz timezone);
+ MonthDayTime(const date::month_day& md, tz timezone);
+
+ date::day day() const;
+ date::month month() const;
+ tz zone() const {return zone_;}
+
+ void canonicalize(date::year y);
+
+ sys_seconds
+ to_sys(date::year y, std::chrono::seconds offset, std::chrono::seconds save) const;
+ sys_days to_sys_days(date::year y) const;
+
+ sys_seconds to_time_point(date::year y) const;
+ int compare(date::year y, const MonthDayTime& x, date::year yx,
+ std::chrono::seconds offset, std::chrono::minutes prev_save) const;
+
+ friend std::istream& operator>>(std::istream& is, MonthDayTime& x);
+ friend std::ostream& operator<<(std::ostream& os, const MonthDayTime& x);
+};
+
+// A Rule specifies one or more set of datetimes without using an offset.
+// Multiple dates are specified with multiple years. The years in effect
+// go from starting_year_ to ending_year_, inclusive. starting_year_ <=
+// ending_year_. save_ is in effect for times from the specified time
+// onward, including the specified time. When the specified time is
+// local, it uses the save_ from the chronologically previous Rule, or if
+// there is none, 0.
+
+//forward declare to avoid warnings in gcc 6.2
+class Rule;
+bool operator==(const Rule& x, const Rule& y);
+bool operator<(const Rule& x, const Rule& y);
+bool operator==(const Rule& x, const date::year& y);
+bool operator<(const Rule& x, const date::year& y);
+bool operator==(const date::year& x, const Rule& y);
+bool operator<(const date::year& x, const Rule& y);
+bool operator==(const Rule& x, const std::string& y);
+bool operator<(const Rule& x, const std::string& y);
+bool operator==(const std::string& x, const Rule& y);
+bool operator<(const std::string& x, const Rule& y);
+std::ostream& operator<<(std::ostream& os, const Rule& r);
+
+class Rule
+{
+private:
+ std::string name_;
+ date::year starting_year_{0};
+ date::year ending_year_{0};
+ MonthDayTime starting_at_;
+ std::chrono::minutes save_{0};
+ std::string abbrev_;
+
+public:
+ Rule() = default;
+ explicit Rule(const std::string& s);
+ Rule(const Rule& r, date::year starting_year, date::year ending_year);
+
+ const std::string& name() const {return name_;}
+ const std::string& abbrev() const {return abbrev_;}
+
+ const MonthDayTime& mdt() const {return starting_at_;}
+ const date::year& starting_year() const {return starting_year_;}
+ const date::year& ending_year() const {return ending_year_;}
+ const std::chrono::minutes& save() const {return save_;}
+
+ static void split_overlaps(std::vector<Rule>& rules);
+
+ friend bool operator==(const Rule& x, const Rule& y);
+ friend bool operator<(const Rule& x, const Rule& y);
+ friend bool operator==(const Rule& x, const date::year& y);
+ friend bool operator<(const Rule& x, const date::year& y);
+ friend bool operator==(const date::year& x, const Rule& y);
+ friend bool operator<(const date::year& x, const Rule& y);
+ friend bool operator==(const Rule& x, const std::string& y);
+ friend bool operator<(const Rule& x, const std::string& y);
+ friend bool operator==(const std::string& x, const Rule& y);
+ friend bool operator<(const std::string& x, const Rule& y);
+
+ friend std::ostream& operator<<(std::ostream& os, const Rule& r);
+
+private:
+ date::day day() const;
+ date::month month() const;
+ static void split_overlaps(std::vector<Rule>& rules, std::size_t i, std::size_t& e);
+ static bool overlaps(const Rule& x, const Rule& y);
+ static void split(std::vector<Rule>& rules, std::size_t i, std::size_t k,
+ std::size_t& e);
+};
+
+inline bool operator!=(const Rule& x, const Rule& y) {return !(x == y);}
+inline bool operator> (const Rule& x, const Rule& y) {return y < x;}
+inline bool operator<=(const Rule& x, const Rule& y) {return !(y < x);}
+inline bool operator>=(const Rule& x, const Rule& y) {return !(x < y);}
+
+inline bool operator!=(const Rule& x, const date::year& y) {return !(x == y);}
+inline bool operator> (const Rule& x, const date::year& y) {return y < x;}
+inline bool operator<=(const Rule& x, const date::year& y) {return !(y < x);}
+inline bool operator>=(const Rule& x, const date::year& y) {return !(x < y);}
+
+inline bool operator!=(const date::year& x, const Rule& y) {return !(x == y);}
+inline bool operator> (const date::year& x, const Rule& y) {return y < x;}
+inline bool operator<=(const date::year& x, const Rule& y) {return !(y < x);}
+inline bool operator>=(const date::year& x, const Rule& y) {return !(x < y);}
+
+inline bool operator!=(const Rule& x, const std::string& y) {return !(x == y);}
+inline bool operator> (const Rule& x, const std::string& y) {return y < x;}
+inline bool operator<=(const Rule& x, const std::string& y) {return !(y < x);}
+inline bool operator>=(const Rule& x, const std::string& y) {return !(x < y);}
+
+inline bool operator!=(const std::string& x, const Rule& y) {return !(x == y);}
+inline bool operator> (const std::string& x, const Rule& y) {return y < x;}
+inline bool operator<=(const std::string& x, const Rule& y) {return !(y < x);}
+inline bool operator>=(const std::string& x, const Rule& y) {return !(x < y);}
+
+struct zonelet
+{
+ enum tag {has_rule, has_save, is_empty};
+
+ std::chrono::seconds gmtoff_;
+ tag tag_ = has_rule;
+
+#if !defined(_MSC_VER) || (_MSC_VER >= 1900)
+ union U
+#else
+ struct U
+#endif
+ {
+ std::string rule_;
+ std::chrono::minutes save_;
+
+ ~U() {}
+ U() {}
+ U(const U&) {}
+ U& operator=(const U&) = delete;
+ } u;
+
+ std::string format_;
+ date::year until_year_{0};
+ MonthDayTime until_date_;
+ sys_seconds until_utc_;
+ local_seconds until_std_;
+ local_seconds until_loc_;
+ std::chrono::minutes initial_save_{};
+ std::string initial_abbrev_;
+ std::pair<const Rule*, date::year> first_rule_{nullptr, date::year::min()};
+ std::pair<const Rule*, date::year> last_rule_{nullptr, date::year::max()};
+
+ ~zonelet();
+ zonelet();
+ zonelet(const zonelet& i);
+ zonelet& operator=(const zonelet&) = delete;
+};
+
+#else // USE_OS_TZDB
+
+struct ttinfo
+{
+ std::int32_t tt_gmtoff;
+ unsigned char tt_isdst;
+ unsigned char tt_abbrind;
+ unsigned char pad[2];
+};
+
+static_assert(sizeof(ttinfo) == 8, "");
+
+struct expanded_ttinfo
+{
+ std::chrono::seconds offset;
+ std::string abbrev;
+ bool is_dst;
+};
+
+struct transition
+{
+ sys_seconds timepoint;
+ const expanded_ttinfo* info;
+
+ transition(sys_seconds tp, const expanded_ttinfo* i = nullptr)
+ : timepoint(tp)
+ , info(i)
+ {}
+
+ friend
+ std::ostream&
+ operator<<(std::ostream& os, const transition& t)
+ {
+ using namespace date;
+ using namespace std::chrono;
+ using date::operator<<;
+ os << t.timepoint << "Z ";
+ if (t.info->offset >= seconds{0})
+ os << '+';
+ os << make_time(t.info->offset);
+ if (t.info->is_dst > 0)
+ os << " daylight ";
+ else
+ os << " standard ";
+ os << t.info->abbrev;
+ return os;
+ }
+};
+
+#endif // USE_OS_TZDB
+
+} // namespace detail
+
+} // namespace date
+
+#if defined(_MSC_VER) && (_MSC_VER < 1900)
+#include "tz.h"
+#endif
+
+#endif // TZ_PRIVATE_H
http://git-wip-us.apache.org/repos/asf/nifi-minifi-cpp/blob/8777ab5f/thirdparty/date/src/ios.mm
----------------------------------------------------------------------
diff --git a/thirdparty/date/src/ios.mm b/thirdparty/date/src/ios.mm
new file mode 100644
index 0000000..105e5c0
--- /dev/null
+++ b/thirdparty/date/src/ios.mm
@@ -0,0 +1,337 @@
+//
+// The MIT License (MIT)
+//
+// Copyright (c) 2016 Alexander Kormanovsky
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in all
+// copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+// SOFTWARE.
+//
+
+#include "ios.h"
+
+#if TARGET_OS_IPHONE
+
+#include <Foundation/Foundation.h>
+
+#include <fstream>
+#include <zlib.h>
+#include <sys/stat.h>
+
+#ifndef TAR_DEBUG
+# define TAR_DEBUG 0
+#endif
+
+#define INTERNAL_DIR "Library"
+#define TZDATA_DIR "tzdata"
+#define TARGZ_EXTENSION "tar.gz"
+
+#define TAR_BLOCK_SIZE 512
+#define TAR_TYPE_POSITION 156
+#define TAR_NAME_POSITION 0
+#define TAR_NAME_SIZE 100
+#define TAR_SIZE_POSITION 124
+#define TAR_SIZE_SIZE 12
+
+namespace date
+{
+ namespace iOSUtils
+ {
+
+ struct TarInfo
+ {
+ char objType;
+ std::string objName;
+ size_t realContentSize; // writable size without padding zeroes
+ size_t blocksContentSize; // adjusted size to 512 bytes blocks
+ bool success;
+ };
+
+ std::string convertCFStringRefPathToCStringPath(CFStringRef ref);
+ bool extractTzdata(CFURLRef homeUrl, CFURLRef archiveUrl, std::string destPath);
+ TarInfo getTarObjectInfo(std::ifstream &readStream);
+ std::string getTarObject(std::ifstream &readStream, int64_t size);
+ bool writeFile(const std::string &tzdataPath, const std::string &fileName,
+ const std::string &data, size_t realContentSize);
+
+ std::string
+ get_current_timezone()
+ {
+ CFTimeZoneRef tzRef = CFTimeZoneCopySystem();
+ CFStringRef tzNameRef = CFTimeZoneGetName(tzRef);
+ CFIndex bufferSize = CFStringGetLength(tzNameRef) + 1;
+ char buffer[bufferSize];
+
+ if (CFStringGetCString(tzNameRef, buffer, bufferSize, kCFStringEncodingUTF8))
+ {
+ CFRelease(tzRef);
+ return std::string(buffer);
+ }
+
+ CFRelease(tzRef);
+
+ return "";
+ }
+
+ std::string
+ get_tzdata_path()
+ {
+ CFURLRef homeUrlRef = CFCopyHomeDirectoryURL();
+ CFStringRef homePath = CFURLCopyPath(homeUrlRef);
+ std::string path(std::string(convertCFStringRefPathToCStringPath(homePath)) +
+ INTERNAL_DIR + "/" + TZDATA_DIR);
+ std::string result_path(std::string(convertCFStringRefPathToCStringPath(homePath)) +
+ INTERNAL_DIR);
+
+ if (access(path.c_str(), F_OK) == 0)
+ {
+#if TAR_DEBUG
+ printf("tzdata dir exists\n");
+#endif
+ CFRelease(homeUrlRef);
+ CFRelease(homePath);
+
+ return result_path;
+ }
+
+ CFBundleRef mainBundle = CFBundleGetMainBundle();
+ CFArrayRef paths = CFBundleCopyResourceURLsOfType(mainBundle, CFSTR(TARGZ_EXTENSION),
+ NULL);
+
+ if (CFArrayGetCount(paths) != 0)
+ {
+ // get archive path, assume there is no other tar.gz in bundle
+ CFURLRef archiveUrl = static_cast<CFURLRef>(CFArrayGetValueAtIndex(paths, 0));
+ CFStringRef archiveName = CFURLCopyPath(archiveUrl);
+ archiveUrl = CFBundleCopyResourceURL(mainBundle, archiveName, NULL, NULL);
+
+ extractTzdata(homeUrlRef, archiveUrl, path);
+
+ CFRelease(archiveUrl);
+ CFRelease(archiveName);
+ }
+
+ CFRelease(homeUrlRef);
+ CFRelease(homePath);
+ CFRelease(paths);
+
+ return result_path;
+ }
+
+ std::string
+ convertCFStringRefPathToCStringPath(CFStringRef ref)
+ {
+ CFIndex bufferSize = CFStringGetMaximumSizeOfFileSystemRepresentation(ref);
+ char *buffer = new char[bufferSize];
+ CFStringGetFileSystemRepresentation(ref, buffer, bufferSize);
+ auto result = std::string(buffer);
+ delete[] buffer;
+ return result;
+ }
+
+ bool
+ extractTzdata(CFURLRef homeUrl, CFURLRef archiveUrl, std::string destPath)
+ {
+ std::string TAR_TMP_PATH = "/tmp.tar";
+
+ CFStringRef homeStringRef = CFURLCopyPath(homeUrl);
+ auto homePath = convertCFStringRefPathToCStringPath(homeStringRef);
+ CFRelease(homeStringRef);
+
+ CFStringRef archiveStringRef = CFURLCopyPath(archiveUrl);
+ auto archivePath = convertCFStringRefPathToCStringPath(archiveStringRef);
+ CFRelease(archiveStringRef);
+
+ // create Library path
+ auto libraryPath = homePath + INTERNAL_DIR;
+
+ // create tzdata path
+ auto tzdataPath = libraryPath + "/" + TZDATA_DIR;
+
+ // -- replace %20 with " "
+ const std::string search = "%20";
+ const std::string replacement = " ";
+ size_t pos = 0;
+
+ while ((pos = archivePath.find(search, pos)) != std::string::npos) {
+ archivePath.replace(pos, search.length(), replacement);
+ pos += replacement.length();
+ }
+
+ gzFile tarFile = gzopen(archivePath.c_str(), "rb");
+
+ // create tar unpacking path
+ auto tarPath = libraryPath + TAR_TMP_PATH;
+
+ // create tzdata directory
+ mkdir(destPath.c_str(), S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH);
+
+ // ======= extract tar ========
+
+ std::ofstream os(tarPath.c_str(), std::ofstream::out | std::ofstream::app);
+ unsigned int bufferLength = 1024 * 256; // 256Kb
+ unsigned char *buffer = (unsigned char *)malloc(bufferLength);
+ bool success = true;
+
+ while (true)
+ {
+ int readBytes = gzread(tarFile, buffer, bufferLength);
+
+ if (readBytes > 0)
+ {
+ os.write((char *) &buffer[0], readBytes);
+ }
+ else
+ if (readBytes == 0)
+ {
+ break;
+ }
+ else
+ if (readBytes == -1)
+ {
+ printf("decompression failed\n");
+ success = false;
+ break;
+ }
+ else
+ {
+ printf("unexpected zlib state\n");
+ success = false;
+ break;
+ }
+ }
+
+ os.close();
+ free(buffer);
+ gzclose(tarFile);
+
+ if (!success)
+ {
+ remove(tarPath.c_str());
+ return false;
+ }
+
+ // ======== extract files =========
+
+ uint64_t location = 0; // Position in the file
+
+ // get file size
+ struct stat stat_buf;
+ int res = stat(tarPath.c_str(), &stat_buf);
+ if (res != 0)
+ {
+ printf("error file size\n");
+ remove(tarPath.c_str());
+ return false;
+ }
+ int64_t tarSize = stat_buf.st_size;
+
+ // create read stream
+ std::ifstream is(tarPath.c_str(), std::ifstream::in | std::ifstream::binary);
+
+ // process files
+ while (location < tarSize)
+ {
+ TarInfo info = getTarObjectInfo(is);
+
+ if (!info.success || info.realContentSize == 0)
+ {
+ break; // something wrong or all files are read
+ }
+
+ switch (info.objType)
+ {
+ case '0': // file
+ case '\0': //
+ {
+ std::string obj = getTarObject(is, info.blocksContentSize);
+#if TAR_DEBUG
+ size += info.realContentSize;
+ printf("#%i %s file size %lld written total %ld from %lld\n", ++count,
+ info.objName.c_str(), info.realContentSize, size, tarSize);
+#endif
+ writeFile(tzdataPath, info.objName, obj, info.realContentSize);
+ location += info.blocksContentSize;
+
+ break;
+ }
+ }
+ }
+
+ remove(tarPath.c_str());
+
+ return true;
+ }
+
+ TarInfo
+ getTarObjectInfo(std::ifstream &readStream)
+ {
+ int64_t length = TAR_BLOCK_SIZE;
+ char buffer[length];
+ char type;
+ char name[TAR_NAME_SIZE + 1];
+ char sizeBuf[TAR_SIZE_SIZE + 1];
+
+ readStream.read(buffer, length);
+
+ memcpy(&type, &buffer[TAR_TYPE_POSITION], 1);
+
+ memset(&name, '\0', TAR_NAME_SIZE + 1);
+ memcpy(&name, &buffer[TAR_NAME_POSITION], TAR_NAME_SIZE);
+
+ memset(&sizeBuf, '\0', TAR_SIZE_SIZE + 1);
+ memcpy(&sizeBuf, &buffer[TAR_SIZE_POSITION], TAR_SIZE_SIZE);
+ size_t realSize = strtol(sizeBuf, NULL, 8);
+ size_t blocksSize = realSize + (TAR_BLOCK_SIZE - (realSize % TAR_BLOCK_SIZE));
+
+ return {type, std::string(name), realSize, blocksSize, true};
+ }
+
+ std::string
+ getTarObject(std::ifstream &readStream, int64_t size)
+ {
+ char buffer[size];
+ readStream.read(buffer, size);
+ return std::string(buffer);
+ }
+
+ bool
+ writeFile(const std::string &tzdataPath, const std::string &fileName, const std::string &data,
+ size_t realContentSize)
+ {
+ std::ofstream os(tzdataPath + "/" + fileName, std::ofstream::out | std::ofstream::binary);
+
+ if (!os) {
+ return false;
+ }
+
+ // trim empty space
+ char trimmedData[realContentSize + 1];
+ memset(&trimmedData, '\0', realContentSize);
+ memcpy(&trimmedData, data.c_str(), realContentSize);
+
+ // write
+ os.write(trimmedData, realContentSize);
+ os.close();
+
+ return true;
+ }
+
+ } // namespace iOSUtils
+} // namespace date
+
+#endif // TARGET_OS_IPHONE
[10/10] nifi-minifi-cpp git commit: MINIFICPP-472 Added date
formatting EL functions
Posted by al...@apache.org.
MINIFICPP-472 Added date formatting EL functions
This closes #315.
Signed-off-by: Aldrin Piri <al...@apache.org>
Project: http://git-wip-us.apache.org/repos/asf/nifi-minifi-cpp/repo
Commit: http://git-wip-us.apache.org/repos/asf/nifi-minifi-cpp/commit/8777ab5f
Tree: http://git-wip-us.apache.org/repos/asf/nifi-minifi-cpp/tree/8777ab5f
Diff: http://git-wip-us.apache.org/repos/asf/nifi-minifi-cpp/diff/8777ab5f
Branch: refs/heads/master
Commit: 8777ab5f02cfc33e533fd9784b8721dcc5e348e7
Parents: 02f1823
Author: Andrew I. Christianson <an...@andyic.org>
Authored: Mon Apr 30 15:41:17 2018 -0400
Committer: Aldrin Piri <al...@apache.org>
Committed: Fri May 18 20:06:12 2018 -0400
----------------------------------------------------------------------
EXPRESSIONS.md | 91 +-
LICENSE | 34 +
extensions/expression-language/CMakeLists.txt | 5 +
extensions/expression-language/Expression.cpp | 48 +
extensions/expression-language/common/Value.h | 4 +
.../impl/expression/Expression.h | 7 +
.../ExpressionLanguageTests.cpp | 42 +
thirdparty/date/.gitignore | 194 +
thirdparty/date/CMakeLists.txt | 164 +
thirdparty/date/LICENSE.txt | 31 +
thirdparty/date/README.md | 58 +
thirdparty/date/compile_fail.sh | 16 +
thirdparty/date/include/date/chrono_io.h | 34 +
thirdparty/date/include/date/date.h | 8022 ++++++++++++++++++
thirdparty/date/include/date/ios.h | 50 +
thirdparty/date/include/date/islamic.h | 3031 +++++++
thirdparty/date/include/date/iso_week.h | 1745 ++++
thirdparty/date/include/date/julian.h | 3046 +++++++
thirdparty/date/include/date/ptz.h | 592 ++
thirdparty/date/include/date/tz.h | 2575 ++++++
thirdparty/date/include/date/tz_private.h | 318 +
thirdparty/date/src/ios.mm | 337 +
thirdparty/date/src/tz.cpp | 3788 +++++++++
thirdparty/date/test_fail.sh | 10 +
24 files changed, 24236 insertions(+), 6 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/nifi-minifi-cpp/blob/8777ab5f/EXPRESSIONS.md
----------------------------------------------------------------------
diff --git a/EXPRESSIONS.md b/EXPRESSIONS.md
index 1056900..79b9e0c 100644
--- a/EXPRESSIONS.md
+++ b/EXPRESSIONS.md
@@ -236,6 +236,12 @@ token, filename.
- [`join`](#join)
- [`count`](#count)
+### Date Manipulation
+
+- [`format`](#format)
+- [`toDate`](#todate)
+- [`now`](#now)
+
## Planned Features
### Searching
@@ -249,12 +255,6 @@ token, filename.
- `unescapeHtml3`
- `unescapeHtml4`
-### Date Manipulation
-
-- `format`
-- `toDate`
-- `now`
-
### Subjectless Functions
- `nextInt`
@@ -1820,3 +1820,82 @@ consider the following examples:
| `${allDelineatedValues(${number_list}, ","):count()}` | `5` |
| `${allAttributes("abc", "non-existent-attr", "xyz"):count()}` | `2` |
| `${allMatchingAttributes(".*"):length():gt(10):count()}` | `2` |
+
+### format
+
+**Description**: Formats a number as a date/time according to the format
+specified by the argument. The argument must be a String that is a valid
+strftime format. The Subject is expected to be a Number that represents the
+number of milliseconds since Midnight GMT on January 1, 1970. The number will
+be evaluated using the local time zone unless specified in the second optional
+argument.
+
+**Subject Type**: Number
+
+**Arguments**:
+
+| Argument | Description |
+| - | - |
+| format | The format to use in the strftime syntax |
+| time zone | Optional argument that specifies the time zone to use from the IANA Time Zone Database (e.g. 'America/New_York') |
+
+**Return Type**: String
+
+**Examples**:
+
+If the attribute "time" has the value "1420058163264", then the following
+Expressions will yield the following results:
+
+| Expression | Value |
+| - | - |
+| `${time:format("%Y/%m/%d %H:%M:%S", "GMT")}` | `2014/12/31 20:36:03` |
+| `${time:format("%Y", "America/Los_Angeles")}` | `2014` |
+
+### toDate
+
+**Description**: Converts a String into a date represented by the number of
+milliseconds since the UNIX epoch, based on the format specified by the
+argument. The argument must be a String that is a valid strftime syntax. The
+Subject is expected to be a String that is formatted according the argument.
+The date will be evaluated using the local time zone unless specified in the
+second optional argument.
+
+**Subject Type**: String
+
+| format | The format to use in the strftime syntax |
+| time zone | Optional argument that specifies the time zone to use when parsing the subject, from the IANA Time Zone Database (e.g. 'America/New_York') |
+
+**Return Type**: Number
+
+**Examples**:
+
+If the attribute "year" has the value "2014" and the attribute "time" has the
+value "2014/12/31 15:36:03.264Z", then the Expression `${year:toDate('%Y',
+'GMT')}` will return a date with a value representing Midnight GMT on January
+1, 2014. The Expression `${time:toDate("%Y/%m/%d %H:%M:%S", "GMT")} will result
+in a date for 15:36:03 GMT on December 31, 2014.
+
+Often, this function is used in conjunction with the format function to change
+the format of a date/time. For example, if the attribute "date" has the value
+"12-24-2014" and we want to change the format to "2014/12/24", we can do so by
+chaining together the two functions:
+`${date:toDate('%m-%d-%Y'):format('%Y/%m/%d')}`.
+
+### now
+
+**Description**: Returns the current date and time as a Date data type object.
+
+**Subject Type**: String
+
+**Arguments**: No arguments
+
+**Return Type**: Number
+
+**Examples**:
+
+| Expression | Value |
+| - | - |
+| `${now()}` | `Count of milliseconds since the UNIX epoch` |
+| `${now():minus(86400000)` | `A number presenting the time 24 hours ago` |
+| `${now():format('Y')}` | `The current year` |
+| `${now():minus(86400000):format('%a')}` | `The day of the week that was yesterday, as a 3-letter abbreviation (For example, Wed)` |
http://git-wip-us.apache.org/repos/asf/nifi-minifi-cpp/blob/8777ab5f/LICENSE
----------------------------------------------------------------------
diff --git a/LICENSE b/LICENSE
index 3374acd..dfa1e2b 100644
--- a/LICENSE
+++ b/LICENSE
@@ -1284,6 +1284,40 @@ Except as contained in this notice, the name of a copyright holder shall not be
used in advertising or otherwise to promote the sale, use or other dealings in
this Software without prior written authorization of the copyright holder.
+This product bundles date which is available under a MIT license:
+
+The source code in this project is released using the MIT License. There is no
+global license for the project because each file is licensed individually with
+different author names and/or dates.
+
+If you contribute to this project, please add your name to the license of each
+file you modify. If you have already contributed to this project and forgot to
+add your name to the license, please feel free to submit a new P/R to add your
+name to the license in each file you modified.
+
+For convenience, here is a copy of the MIT license found in each file except
+without author names or dates:
+
+The MIT License (MIT)
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
+
This product bundles RapidJSON:
Tencent is pleased to support the open source community by making RapidJSON available.
http://git-wip-us.apache.org/repos/asf/nifi-minifi-cpp/blob/8777ab5f/extensions/expression-language/CMakeLists.txt
----------------------------------------------------------------------
diff --git a/extensions/expression-language/CMakeLists.txt b/extensions/expression-language/CMakeLists.txt
index d16b7d2..1b44302 100644
--- a/extensions/expression-language/CMakeLists.txt
+++ b/extensions/expression-language/CMakeLists.txt
@@ -41,6 +41,9 @@ add_flex_bison_dependency(el-scanner el-parser)
include_directories(../../libminifi/include ../../libminifi/include/core ../../thirdparty/spdlog-20170710/include ../../thirdparty/concurrentqueue ../../thirdparty/yaml-cpp-yaml-cpp-0.5.3/include ${CIVET_THIRDPARTY_ROOT}/include ../../thirdparty/)
include_directories(common)
include_directories(impl)
+include_directories(../../thirdparty/date/include)
+
+add_subdirectory(../../thirdparty/date ${CMAKE_CURRENT_BINARY_DIR}/date)
file(GLOB SOURCES "*.cpp")
@@ -53,6 +56,8 @@ if(CMAKE_THREAD_LIBS_INIT)
target_link_libraries(minifi-expression-language-extensions "${CMAKE_THREAD_LIBS_INIT}")
endif()
+target_link_libraries(minifi-expression-language-extensions ${LIBMINIFI} tz)
+
find_package(UUID REQUIRED)
target_link_libraries(minifi-expression-language-extensions ${LIBMINIFI} ${UUID_LIBRARIES})
find_package(CURL REQUIRED)
http://git-wip-us.apache.org/repos/asf/nifi-minifi-cpp/blob/8777ab5f/extensions/expression-language/Expression.cpp
----------------------------------------------------------------------
diff --git a/extensions/expression-language/Expression.cpp b/extensions/expression-language/Expression.cpp
index 6c5b5b0..80c9440 100644
--- a/extensions/expression-language/Expression.cpp
+++ b/extensions/expression-language/Expression.cpp
@@ -34,6 +34,10 @@
#include "base64.h"
#include "Driver.h"
+#ifdef EXPRESSION_LANGUAGE_USE_DATE
+#include "date/tz.h"
+#endif // EXPRESSION_LANGUAGE_USE_DATE
+
namespace org {
namespace apache {
namespace nifi {
@@ -1274,6 +1278,42 @@ Value expr_escapeCsv(const std::vector<Value> &args) {
return Value(result);
}
+#ifdef EXPRESSION_LANGUAGE_USE_DATE
+
+Value expr_format(const std::vector<Value> &args) {
+ std::chrono::milliseconds dur(args[0].asUnsignedLong());
+ std::chrono::time_point<std::chrono::system_clock> dt(dur);
+ auto zone = date::current_zone();
+ if (args.size() > 2) {
+ zone = date::locate_zone(args[2].asString());
+ }
+ auto t = date::make_zoned(zone, dt);
+ std::stringstream result_s;
+ result_s << date::format(args[1].asString(), t);
+ return Value(result_s.str());
+}
+
+Value expr_toDate(const std::vector<Value> &args) {
+ auto arg_0 = args[0].asString();
+ std::istringstream arg_s{arg_0};
+ date::sys_time<std::chrono::milliseconds> t;
+ arg_s >> date::parse(args[1].asString(), t);
+ auto zone = date::current_zone();
+ if (args.size() > 2) {
+ zone = date::locate_zone(args[2].asString());
+ }
+ auto utc = date::locate_zone("UTC");
+ auto utct = date::make_zoned(utc, t);
+ auto zt = date::make_zoned(zone, utct.get_local_time());
+ return Value(std::chrono::duration_cast<std::chrono::milliseconds>(zt.get_sys_time().time_since_epoch()).count());
+}
+
+#endif // EXPRESSION_LANGUAGE_USE_DATE
+
+Value expr_now(const std::vector<Value> &args) {
+ return Value(std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::system_clock::now().time_since_epoch()).count());
+}
+
Value expr_unescapeCsv(const std::vector<Value> &args) {
auto result = args[0].asString();
@@ -2209,6 +2249,14 @@ Expression make_dynamic_function(const std::string &function_name,
return make_count(function_name, args);
} else if (function_name == "join") {
return make_join(function_name, args);
+#ifdef EXPRESSION_LANGUAGE_USE_DATE
+ } else if (function_name == "format") {
+ return make_dynamic_function_incomplete<expr_format>(function_name, args, 1);
+ } else if (function_name == "toDate") {
+ return make_dynamic_function_incomplete<expr_toDate>(function_name, args, 1);
+#endif // EXPRESSION_LANGUAGE_USE_DATE
+ } else if (function_name == "now") {
+ return make_dynamic_function_incomplete<expr_now>(function_name, args, 0);
} else {
std::string msg("Unknown expression function: ");
msg.append(function_name);
http://git-wip-us.apache.org/repos/asf/nifi-minifi-cpp/blob/8777ab5f/extensions/expression-language/common/Value.h
----------------------------------------------------------------------
diff --git a/extensions/expression-language/common/Value.h b/extensions/expression-language/common/Value.h
index 1c4ec43..d71517b 100644
--- a/extensions/expression-language/common/Value.h
+++ b/extensions/expression-language/common/Value.h
@@ -183,6 +183,10 @@ class Value {
return unsigned_long_val_;
} else if (is_string_) {
return std::stoul(string_val_);
+ } else if (is_signed_long_) {
+ return signed_long_val_;
+ } else if (is_long_double_) {
+ return long_double_val_;
} else {
return 0.0;
}
http://git-wip-us.apache.org/repos/asf/nifi-minifi-cpp/blob/8777ab5f/extensions/expression-language/impl/expression/Expression.h
----------------------------------------------------------------------
diff --git a/extensions/expression-language/impl/expression/Expression.h b/extensions/expression-language/impl/expression/Expression.h
index b7bf676..15f7558 100644
--- a/extensions/expression-language/impl/expression/Expression.h
+++ b/extensions/expression-language/impl/expression/Expression.h
@@ -25,6 +25,13 @@
#undef EXPRESSION_LANGUAGE_USE_REGEX
#endif
+#define EXPRESSION_LANGUAGE_USE_DATE
+
+// Disable date in EL for incompatible compilers
+#if __GNUC__ < 5
+#undef EXPRESSION_LANGUAGE_USE_DATE
+#endif
+
#include <Value.h>
#include <core/FlowFile.h>
http://git-wip-us.apache.org/repos/asf/nifi-minifi-cpp/blob/8777ab5f/libminifi/test/expression-language-tests/ExpressionLanguageTests.cpp
----------------------------------------------------------------------
diff --git a/libminifi/test/expression-language-tests/ExpressionLanguageTests.cpp b/libminifi/test/expression-language-tests/ExpressionLanguageTests.cpp
index 232deb4..f6e143e 100644
--- a/libminifi/test/expression-language-tests/ExpressionLanguageTests.cpp
+++ b/libminifi/test/expression-language-tests/ExpressionLanguageTests.cpp
@@ -16,6 +16,8 @@
* limitations under the License.
*/
+#include <time.h>
+
#include <memory>
#include <string>
@@ -1209,6 +1211,46 @@ TEST_CASE("Encode Decode URL", "[expressionEncodeDecodeURL]") { // NOLINT
REQUIRE("some value with spaces" == expr({flow_file_a}).asString());
}
+#ifdef EXPRESSION_LANGUAGE_USE_DATE
+
+TEST_CASE("Parse Date", "[expressionParseDate]") { // NOLINT
+ auto expr = expression::compile("${message:toDate('%Y/%m/%d', 'America/Los_Angeles')}");
+
+ auto flow_file_a = std::make_shared<MockFlowFile>();
+ flow_file_a->addAttribute("message", "2014/04/30");
+ REQUIRE("1398841200000" == expr({flow_file_a}).asString());
+}
+
+TEST_CASE("Format Date", "[expressionFormatDate]") { // NOLINT
+ auto expr = expression::compile("${message:format('%m-%d-%Y', 'GMT')}");
+
+ auto flow_file_a = std::make_shared<MockFlowFile>();
+ flow_file_a->addAttribute("message", "1394755200000");
+ REQUIRE("03-14-2014" == expr({flow_file_a}).asString());
+}
+
+TEST_CASE("Reformat Date", "[expressionReformatDate]") { // NOLINT
+ auto expr = expression::compile("${message:toDate('%Y/%m/%d', 'GMT'):format('%m-%d-%Y', 'America/New_York')}");
+
+ auto flow_file_a = std::make_shared<MockFlowFile>();
+ flow_file_a->addAttribute("message", "2014/03/14");
+ REQUIRE("03-13-2014" == expr({flow_file_a}).asString());
+}
+
+TEST_CASE("Now Date", "[expressionNowDate]") { // NOLINT
+ auto expr = expression::compile("${now():format('%Y')}");
+
+ auto flow_file_a = std::make_shared<MockFlowFile>();
+ flow_file_a->addAttribute("message", "2014/03/14");
+ time_t t = time(nullptr);
+ struct tm lt;
+ localtime_r(&t, <);
+
+ REQUIRE((lt.tm_year + 1900) == expr({flow_file_a}).asUnsignedLong());
+}
+
+#endif // EXPRESSION_LANGUAGE_USE_DATE
+
TEST_CASE("IP", "[expressionIP]") { // NOLINT
auto expr = expression::compile("${ip()}");
http://git-wip-us.apache.org/repos/asf/nifi-minifi-cpp/blob/8777ab5f/thirdparty/date/.gitignore
----------------------------------------------------------------------
diff --git a/thirdparty/date/.gitignore b/thirdparty/date/.gitignore
new file mode 100644
index 0000000..e88e3be
--- /dev/null
+++ b/thirdparty/date/.gitignore
@@ -0,0 +1,194 @@
+#ignore thumbnails created by windows
+Thumbs.db
+#Ignore files build by Visual Studio
+*.obj
+*.exe
+*.pdb
+*.user
+*.aps
+*.pch
+*.vspscc
+*_i.c
+*_p.c
+*.ncb
+*.suo
+*.tlb
+*.tlh
+*.bak
+*.cache
+*.ilk
+*.log
+[Bb]in
+[Dd]ebug*/
+*.lib
+*.sbr
+obj/
+[Rr]elease*/
+_ReSharper*/
+[Tt]est[Rr]esult*
+.idea/
+*.opensdf
+## Ignore Visual Studio temporary files, build results, and
+## files generated by popular Visual Studio add-ons.
+# User-specific files
+*.suo
+*.user
+*.userosscache
+*.sln.docstates
+# User-specific folders
+*.sln.ide/
+# Build results
+[Dd]ebug/
+[Dd]ebugPublic/
+[Rr]elease/
+[Rr]eleases/
+x64/
+x86/
+build/
+bld/
+[Bb]in/
+[Oo]bj/
+# Roslyn cache directories
+*.ide/
+# MSTest test Results
+[Tt]est[Rr]esult*/
+[Bb]uild[Ll]og.*
+#NUNIT
+*.VisualState.xml
+TestResult.xml
+# Build Results of an ATL Project
+[Dd]ebugPS/
+[Rr]eleasePS/
+dlldata.c
+*_i.c
+*_p.c
+*_i.h
+*.ilk
+*.meta
+*.obj
+*.pch
+*.pdb
+*.pgc
+*.pgd
+*.rsp
+*.sbr
+*.tlb
+*.tli
+*.tlh
+*.tmp
+*.tmp_proj
+*.log
+*.vspscc
+*.vssscc
+.builds
+*.pidb
+*.svclog
+*.scc
+# Chutzpah Test files
+_Chutzpah*
+# Visual C++ cache files
+ipch/
+*.aps
+*.ncb
+*.opensdf
+*.sdf
+*.cachefile
+# Visual Studio profiler
+*.psess
+*.vsp
+*.vspx
+# TFS 2012 Local Workspace
+$tf/
+# Guidance Automation Toolkit
+*.gpState
+# ReSharper is a .NET coding add-in
+_ReSharper*/
+*.[Rr]e[Ss]harper
+*.DotSettings.user
+# JustCode is a .NET coding addin-in
+.JustCode
+# TeamCity is a build add-in
+_TeamCity*
+# DotCover is a Code Coverage Tool
+*.dotCover
+# NCrunch
+_NCrunch_*
+.*crunch*.local.xml
+# MightyMoose
+*.mm.*
+AutoTest.Net/
+# Web workbench (sass)
+.sass-cache/
+# Installshield output folder
+[Ee]xpress/
+# DocProject is a documentation generator add-in
+DocProject/buildhelp/
+DocProject/Help/*.HxT
+DocProject/Help/*.HxC
+DocProject/Help/*.hhc
+DocProject/Help/*.hhk
+DocProject/Help/*.hhp
+DocProject/Help/Html2
+DocProject/Help/html
+# Click-Once directory
+publish/
+# Publish Web Output
+*.[Pp]ublish.xml
+*.azurePubxml
+# TODO: Comment the next line if you want to checkin your web deploy settings
+# but database connection strings (with potential passwords) will be unencrypted
+*.pubxml
+*.publishproj
+# NuGet Packages
+*.nupkg
+# The packages folder can be ignored because of Package Restore
+**/packages/*
+# except build/, which is used as an MSBuild target.
+!**/packages/build/
+# If using the old MSBuild-Integrated Package Restore, uncomment this:
+#!**/packages/repositories.config
+# Windows Azure Build Output
+csx/
+*.build.csdef
+# Windows Store app package directory
+AppPackages/
+# Others
+sql/
+*.Cache
+ClientBin/
+[Ss]tyle[Cc]op.*
+~$*
+*~
+*.dbmdl
+*.dbproj.schemaview
+*.pfx
+*.publishsettings
+node_modules/
+bower_components/
+# RIA/Silverlight projects
+Generated_Code/
+# Backup & report files from converting an old project file
+# to a newer Visual Studio version. Backup files are not needed,
+# because we have git ;-)
+_UpgradeReport_Files/
+Backup*/
+UpgradeLog*.XML
+UpgradeLog*.htm
+# SQL Server files
+*.mdf
+*.ldf
+# Business Intelligence projects
+*.rdl.data
+*.bim.layout
+*.bim_*.settings
+# Microsoft Fakes
+FakesAssemblies/
+*.suo
+*.vcxproj.filters
+*.npp
+CMakeFiles/*
+nbproject/*
+*.cd
+*.cd
+a.out
+cmake-build-debug/*
http://git-wip-us.apache.org/repos/asf/nifi-minifi-cpp/blob/8777ab5f/thirdparty/date/CMakeLists.txt
----------------------------------------------------------------------
diff --git a/thirdparty/date/CMakeLists.txt b/thirdparty/date/CMakeLists.txt
new file mode 100644
index 0000000..683ddce
--- /dev/null
+++ b/thirdparty/date/CMakeLists.txt
@@ -0,0 +1,164 @@
+cmake_minimum_required( VERSION 3.1.0 )
+
+project( date_prj )
+
+include( GNUInstallDirs )
+
+find_package( Threads REQUIRED )
+
+# Override by setting on CMake command line.
+set( CMAKE_CXX_STANDARD 14 CACHE STRING "The C++ standard whose features are requested.")
+
+option( USE_SYSTEM_TZ_DB "Use the operating system's timezone database" OFF )
+option( USE_TZ_DB_IN_DOT "Save the timezone database in the current folder" OFF )
+option( BUILD_SHARED_LIBS "Build a shared version of library" OFF )
+option( ENABLE_DATE_TESTING "Enable unit tests" ON )
+
+function( print_option OPT )
+ if ( NOT DEFINED PRINT_OPTION_CURR_${OPT} OR ( NOT PRINT_OPTION_CURR_${OPT} STREQUAL ${OPT} ) )
+ set( PRINT_OPTION_CURR_${OPT} ${${OPT}} CACHE BOOL "" )
+ mark_as_advanced(PRINT_OPTION_CURR_${OPT})
+ message( "# date: ${OPT} ${${OPT}}" )
+ endif( )
+endfunction( )
+
+print_option( USE_SYSTEM_TZ_DB )
+print_option( USE_TZ_DB_IN_DOT )
+print_option( BUILD_SHARED_LIBS )
+print_option( ENABLE_DATE_TESTING )
+
+set( HEADER_FOLDER "include" )
+set( SOURCE_FOLDER "src" )
+set( TEST_FOLDER "test" )
+
+# This is needed so IDE's live MSVC show header files
+set( HEADER_FILES
+ ${HEADER_FOLDER}/date/chrono_io.h
+ ${HEADER_FOLDER}/date/date.h
+ ${HEADER_FOLDER}/date/ios.h
+ ${HEADER_FOLDER}/date/islamic.h
+ ${HEADER_FOLDER}/date/iso_week.h
+ ${HEADER_FOLDER}/date/julian.h
+ ${HEADER_FOLDER}/date/tz.h
+ ${HEADER_FOLDER}/date/tz_private.h
+)
+
+add_library( tz ${HEADER_FILES} ${SOURCE_FOLDER}/tz.cpp )
+
+if( USE_SYSTEM_TZ_DB )
+ target_compile_definitions( tz PRIVATE -DUSE_AUTOLOAD=0 )
+ target_compile_definitions( tz PRIVATE -DHAS_REMOTE_API=0 )
+ # cannot set USE_OS_TZDB to 1 on Windows
+ if( NOT WIN32 )
+ target_compile_definitions( tz PUBLIC -DUSE_OS_TZDB=1 )
+ endif( )
+else( )
+ target_compile_definitions( tz PRIVATE -DUSE_AUTOLOAD=1 )
+ target_compile_definitions( tz PRIVATE -DHAS_REMOTE_API=1 )
+ target_compile_definitions( tz PUBLIC -DUSE_OS_TZDB=0 )
+ find_package( CURL REQUIRED )
+ include_directories( SYSTEM ${CURL_INCLUDE_DIRS} )
+ set( OPTIONAL_LIBRARIES ${CURL_LIBRARIES} )
+endif( )
+
+if( USE_TZ_DB_IN_DOT )
+ target_compile_definitions( tz PRIVATE -DINSTALL=. )
+endif( )
+
+target_link_libraries( tz ${CMAKE_THREAD_LIBS_INIT} ${OPTIONAL_LIBRARIES} )
+
+# add include folders to the library and targets that consume it
+target_include_directories(tz PUBLIC
+ $<BUILD_INTERFACE:
+ ${CMAKE_CURRENT_SOURCE_DIR}/${HEADER_FOLDER}
+ >
+ $<INSTALL_INTERFACE:
+ include
+ >
+)
+
+add_library(date_interface INTERFACE) # an interface (not a library), to enable automatic include_directory (for when just date.h, but not "tz.h and its lib" are needed)
+
+# add include folders to the INTERFACE and targets that consume it
+target_include_directories(date_interface INTERFACE
+ "$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>"
+ $<INSTALL_INTERFACE:include>
+)
+
+if(WIN32 AND NOT CYGWIN)
+ set(DEF_INSTALL_CMAKE_DIR CMake)
+else()
+ set(DEF_INSTALL_CMAKE_DIR ${CMAKE_INSTALL_LIBDIR}/cmake/date)
+endif()
+
+install( TARGETS date_interface EXPORT dateConfig )
+install( EXPORT dateConfig DESTINATION ${DEF_INSTALL_CMAKE_DIR} )
+install( TARGETS tz
+ ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}
+ LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
+ RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}) # This is for Windows
+install( DIRECTORY ${HEADER_FOLDER}/ DESTINATION include/ )
+
+if ( ENABLE_DATE_TESTING )
+
+ enable_testing( )
+
+ add_custom_target( testit COMMAND ${CMAKE_CTEST_COMMAND} )
+
+ add_dependencies( testit tz )
+ function( add_pass_tests TEST_GLOB TEST_PREFIX )
+ file( GLOB_RECURSE FILENAMES ${TEST_GLOB} )
+ include_directories( "${HEADER_FOLDER}/date" )
+
+ foreach( TEST_FILE ${FILENAMES} )
+ get_filename_component( TEST_NAME ${TEST_FILE} NAME_WE )
+ get_filename_component( TEST_EXT ${TEST_FILE} EXT )
+ if( NOT ${TEST_EXT} STREQUAL ".fail.cpp" )
+ set( PREFIX "${TEST_PREFIX}_pass_${TEST_NAME}" )
+ set( BIN_NAME ${PREFIX}_bin )
+ set( TST_NAME ${PREFIX}_test )
+ add_executable( ${BIN_NAME} EXCLUDE_FROM_ALL ${TEST_FILE} )
+ add_test( ${TST_NAME} ${BIN_NAME} )
+ target_link_libraries( ${BIN_NAME} tz )
+ add_dependencies( testit ${BIN_NAME} )
+ endif( )
+ endforeach( )
+ endfunction( )
+
+ function( add_fail_tests TEST_GLOB TEST_PREFIX )
+ file( GLOB_RECURSE FILENAMES ${TEST_GLOB} )
+
+ foreach( TEST_FILE ${FILENAMES} )
+ get_filename_component( TEST_NAME ${TEST_FILE} NAME_WE )
+ get_filename_component( TEST_EXT ${TEST_FILE} EXT )
+
+ set( TEST_TYPE "_fail" )
+
+ set( PREFIX "${TEST_PREFIX}_fail_${TEST_NAME}" )
+ set( BIN_NAME ${PREFIX}_bin )
+ set( TST_NAME ${PREFIX}_test )
+
+ #target_compile_definitions( ${BIN_NAME} PRIVATE ${TST_NAME} )
+ set( TEST_BIN_NAME ${CMAKE_BINARY_DIR}/${BIN_NAME} )
+ add_custom_target( ${BIN_NAME}
+ COMMAND ${PROJECT_SOURCE_DIR}/compile_fail.sh ${TEST_BIN_NAME} ${CMAKE_CXX_COMPILER} -std=c++14 -L${CMAKE_BINARY_DIR}/ -ltz -I${PROJECT_SOURCE_DIR}/${HEADER_FOLDER}/date -o ${BIN_NAME} ${TEST_FILE}
+ WORKING_DIRECTORY ${CMAKE_BINARY_DIR}
+ COMMENT ${TST_NAME}
+ )
+ add_test( ${TST_NAME} "${PROJECT_SOURCE_DIR}/test_fail.sh" ${CMAKE_BINARY_DIR}/${BIN_NAME} WORKING_DIRECTORY "${PROJECT_SOURCE_DIR}/" )
+ #set_tests_properties( ${TST_NAME} PROPERTIES WILL_FAIL TRUE)
+ add_dependencies( testit ${BIN_NAME} )
+ endforeach( )
+ endfunction( )
+
+ file( GLOB children RELATIVE "${PROJECT_SOURCE_DIR}/${TEST_FOLDER}" "${PROJECT_SOURCE_DIR}/${TEST_FOLDER}/*" )
+ foreach( child ${children} )
+ if( IS_DIRECTORY "${PROJECT_SOURCE_DIR}/${TEST_FOLDER}/${child}" )
+ set( CUR_FOLDER "${PROJECT_SOURCE_DIR}/${TEST_FOLDER}/${child}" )
+ add_pass_tests( "${CUR_FOLDER}/*.cpp" ${child} )
+ if( NOT WIN32 )
+ add_fail_tests( "${CUR_FOLDER}/*.fail.cpp" ${child} )
+ endif( )
+ endif( )
+ endforeach( )
+endif( )
http://git-wip-us.apache.org/repos/asf/nifi-minifi-cpp/blob/8777ab5f/thirdparty/date/LICENSE.txt
----------------------------------------------------------------------
diff --git a/thirdparty/date/LICENSE.txt b/thirdparty/date/LICENSE.txt
new file mode 100644
index 0000000..79ea069
--- /dev/null
+++ b/thirdparty/date/LICENSE.txt
@@ -0,0 +1,31 @@
+The source code in this project is released using the MIT License. There is no
+global license for the project because each file is licensed individually with
+different author names and/or dates.
+
+If you contribute to this project, please add your name to the license of each
+file you modify. If you have already contributed to this project and forgot to
+add your name to the license, please feel free to submit a new P/R to add your
+name to the license in each file you modified.
+
+For convenience, here is a copy of the MIT license found in each file except
+without author names or dates:
+
+The MIT License (MIT)
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
http://git-wip-us.apache.org/repos/asf/nifi-minifi-cpp/blob/8777ab5f/thirdparty/date/README.md
----------------------------------------------------------------------
diff --git a/thirdparty/date/README.md b/thirdparty/date/README.md
new file mode 100644
index 0000000..580d20d
--- /dev/null
+++ b/thirdparty/date/README.md
@@ -0,0 +1,58 @@
+# Date
+
+[](https://gitter.im/HowardHinnant/date?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
+
+---
+
+**[Try it out on wandbox!](https://wandbox.org/permlink/vqwMyTphHJv5iXX7)**
+
+## Summary
+
+This is actually several separate C++11/C++14/C++17 libraries:
+
+1. `"date.h"` is a header-only library which builds upon `<chrono>`. It adds some new `duration` types, and new `time_point` types. It also adds "field" types such as `year_month_day` which is a struct `{year, month, day}`. And it provides convenient means to convert between the "field" types and the `time_point` types.
+
+ * Documentation: http://howardhinnant.github.io/date/date.html
+ * Video: https://www.youtube.com/watch?v=tzyGjOm8AKo
+ * Slides: http://schd.ws/hosted_files/cppcon2015/43/hinnant_dates.pdf
+
+1. `"tz.h"` / `"tz.cpp"` are a timezone library built on top of the `"date.h"` library. This timezone library is a complete parser of the IANA timezone database. It provides for an easy way to access all of the data in this database, using the types from `"date.h"` and `<chrono>`. The IANA database also includes data on leap seconds, and this library provides utilities to compute with that information as well.
+
+ * Documentation: http://howardhinnant.github.io/date/tz.html
+ * Video: https://www.youtube.com/watch?v=Vwd3pduVGKY
+ * Slides: http://schd.ws/hosted_files/cppcon2016/0f/Welcome%20To%20The%20Time%20Zone%20-%20Howard%20Hinnant%20-%20CppCon%202016.pdf
+
+1. `"iso_week.h"` is a header-only library built on top of the `"date.h"` library which implements the ISO week date calendar.
+
+ * Documentation: http://howardhinnant.github.io/date/iso_week.html
+
+1. `"julian.h"` is a header-only library built on top of the `"date.h"` library which implements a proleptic Julian calendar which is fully interoperable with everything above.
+
+ * Documentation: http://howardhinnant.github.io/date/julian.html
+
+1. `"islamic.h"` is a header-only library built on top of the `"date.h"` library which implements a proleptic Islamic calendar which is fully interoperable with everything above.
+
+ * Documentation: http://howardhinnant.github.io/date/islamic.html
+
+## Standardization
+
+Slightly modified versions of `"date.h"` and `"tz.h"` were voted into the C++20 working draft at the Jacksonville FL meeting on 2018-03-17:
+
+* http://howardhinnant.github.io/date/d0355r7.html
+
+## Build & Test
+
+You will need [CMake](https://cmake.org/) and a recent C++ compiler. Here follows a guide of how to build and test using the CMake Makefile generator.
+
+```bash
+mkdir build
+cd build
+cmake ../
+cmake --build . --target testit # Consider '-- -j4' for multithreading
+```
+## Projects using this library
+
+* www.safe.com
+* www.webtoolkit.eu/wt
+
+If you would like your project (or product) on this list, just let me know.
http://git-wip-us.apache.org/repos/asf/nifi-minifi-cpp/blob/8777ab5f/thirdparty/date/compile_fail.sh
----------------------------------------------------------------------
diff --git a/thirdparty/date/compile_fail.sh b/thirdparty/date/compile_fail.sh
new file mode 100755
index 0000000..60cf6b9
--- /dev/null
+++ b/thirdparty/date/compile_fail.sh
@@ -0,0 +1,16 @@
+#!/bin/bash
+export TEST_BIN_NAME=$1
+#echo "Building ${TEST_BIN_NAME}"
+shift 1
+export BUILD_COMMAND=$@
+#echo "Build command: ${BUILD_COMMAND}"
+eval ${BUILD_COMMAND} >/dev/null 2>/dev/null
+
+if [ $? -eq 0 ]; then
+ echo -ne "#!/bin/bash\nexit 1;" > ${TEST_BIN_NAME}
+else
+ echo -ne "#!/bin/bash\nexit 0;" > ${TEST_BIN_NAME}
+fi
+chmod u+x ${TEST_BIN_NAME}
+exit 0;
+
http://git-wip-us.apache.org/repos/asf/nifi-minifi-cpp/blob/8777ab5f/thirdparty/date/include/date/chrono_io.h
----------------------------------------------------------------------
diff --git a/thirdparty/date/include/date/chrono_io.h b/thirdparty/date/include/date/chrono_io.h
new file mode 100644
index 0000000..21be404
--- /dev/null
+++ b/thirdparty/date/include/date/chrono_io.h
@@ -0,0 +1,34 @@
+#ifndef CHRONO_IO_H
+#define CHRONO_IO_H
+
+// The MIT License (MIT)
+//
+// Copyright (c) 2016, 2017 Howard Hinnant
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in all
+// copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+// SOFTWARE.
+//
+// Our apologies. When the previous paragraph was written, lowercase had not yet
+// been invented (that would involve another several millennia of evolution).
+// We did not mean to shout.
+
+// This functionality has moved to "date.h"
+
+#include "date.h"
+
+#endif // CHRONO_IO_H
[07/10] nifi-minifi-cpp git commit: MINIFICPP-472 Added date
formatting EL functions
Posted by al...@apache.org.
http://git-wip-us.apache.org/repos/asf/nifi-minifi-cpp/blob/8777ab5f/thirdparty/date/include/date/iso_week.h
----------------------------------------------------------------------
diff --git a/thirdparty/date/include/date/iso_week.h b/thirdparty/date/include/date/iso_week.h
new file mode 100644
index 0000000..5bbeb0c
--- /dev/null
+++ b/thirdparty/date/include/date/iso_week.h
@@ -0,0 +1,1745 @@
+#ifndef ISO_WEEK_H
+#define ISO_WEEK_H
+
+// The MIT License (MIT)
+//
+// Copyright (c) 2015, 2016, 2017 Howard Hinnant
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in all
+// copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+// SOFTWARE.
+
+#include "date.h"
+
+#include <climits>
+
+namespace iso_week
+{
+
+// y/wn/wd
+// wn/wd/y
+// wd/wn/y
+
+using days = date::days;
+using weeks = date::weeks;
+using years = date::years;
+
+// time_point
+
+using sys_days = date::sys_days;
+using local_days = date::local_days;
+
+// types
+
+struct last_week
+{
+ explicit last_week() = default;
+};
+
+class weekday;
+class weeknum;
+class year;
+
+class year_weeknum;
+class year_lastweek;
+class weeknum_weekday;
+class lastweek_weekday;
+
+class year_weeknum_weekday;
+class year_lastweek_weekday;
+
+// date composition operators
+
+CONSTCD11 year_weeknum operator/(const year& y, const weeknum& wn) NOEXCEPT;
+CONSTCD11 year_weeknum operator/(const year& y, int wn) NOEXCEPT;
+
+CONSTCD11 year_lastweek operator/(const year& y, last_week wn) NOEXCEPT;
+
+CONSTCD11 weeknum_weekday operator/(const weeknum& wn, const weekday& wd) NOEXCEPT;
+CONSTCD11 weeknum_weekday operator/(const weeknum& wn, int wd) NOEXCEPT;
+CONSTCD11 weeknum_weekday operator/(const weekday& wd, const weeknum& wn) NOEXCEPT;
+CONSTCD11 weeknum_weekday operator/(const weekday& wd, int wn) NOEXCEPT;
+
+CONSTCD11 lastweek_weekday operator/(const last_week& wn, const weekday& wd) NOEXCEPT;
+CONSTCD11 lastweek_weekday operator/(const last_week& wn, int wd) NOEXCEPT;
+CONSTCD11 lastweek_weekday operator/(const weekday& wd, const last_week& wn) NOEXCEPT;
+
+CONSTCD11 year_weeknum_weekday operator/(const year_weeknum& ywn, const weekday& wd) NOEXCEPT;
+CONSTCD11 year_weeknum_weekday operator/(const year_weeknum& ywn, int wd) NOEXCEPT;
+CONSTCD11 year_weeknum_weekday operator/(const weeknum_weekday& wnwd, const year& y) NOEXCEPT;
+CONSTCD11 year_weeknum_weekday operator/(const weeknum_weekday& wnwd, int y) NOEXCEPT;
+
+CONSTCD11 year_lastweek_weekday operator/(const year_lastweek& ylw, const weekday& wd) NOEXCEPT;
+CONSTCD11 year_lastweek_weekday operator/(const year_lastweek& ylw, int wd) NOEXCEPT;
+
+CONSTCD11 year_lastweek_weekday operator/(const lastweek_weekday& lwwd, const year& y) NOEXCEPT;
+CONSTCD11 year_lastweek_weekday operator/(const lastweek_weekday& lwwd, int y) NOEXCEPT;
+
+// weekday
+
+class weekday
+{
+ unsigned char wd_;
+public:
+ explicit CONSTCD11 weekday(unsigned wd) NOEXCEPT;
+ CONSTCD11 weekday(date::weekday wd) NOEXCEPT;
+ explicit weekday(int) = delete;
+ CONSTCD11 weekday(const sys_days& dp) NOEXCEPT;
+ CONSTCD11 explicit weekday(const local_days& dp) NOEXCEPT;
+
+ weekday& operator++() NOEXCEPT;
+ weekday operator++(int) NOEXCEPT;
+ weekday& operator--() NOEXCEPT;
+ weekday operator--(int) NOEXCEPT;
+
+ weekday& operator+=(const days& d) NOEXCEPT;
+ weekday& operator-=(const days& d) NOEXCEPT;
+
+ CONSTCD11 explicit operator unsigned() const NOEXCEPT;
+ CONSTCD11 operator date::weekday() const NOEXCEPT;
+ CONSTCD11 bool ok() const NOEXCEPT;
+
+private:
+ static CONSTCD11 unsigned char weekday_from_days(int z) NOEXCEPT;
+ static CONSTCD11 unsigned char to_iso_encoding(unsigned char) NOEXCEPT;
+ static CONSTCD11 unsigned from_iso_encoding(unsigned) NOEXCEPT;
+};
+
+CONSTCD11 bool operator==(const weekday& x, const weekday& y) NOEXCEPT;
+CONSTCD11 bool operator!=(const weekday& x, const weekday& y) NOEXCEPT;
+
+CONSTCD14 weekday operator+(const weekday& x, const days& y) NOEXCEPT;
+CONSTCD14 weekday operator+(const days& x, const weekday& y) NOEXCEPT;
+CONSTCD14 weekday operator-(const weekday& x, const days& y) NOEXCEPT;
+CONSTCD14 days operator-(const weekday& x, const weekday& y) NOEXCEPT;
+
+template<class CharT, class Traits>
+std::basic_ostream<CharT, Traits>&
+operator<<(std::basic_ostream<CharT, Traits>& os, const weekday& wd);
+
+// year
+
+class year
+{
+ short y_;
+
+public:
+ explicit CONSTCD11 year(int y) NOEXCEPT;
+
+ year& operator++() NOEXCEPT;
+ year operator++(int) NOEXCEPT;
+ year& operator--() NOEXCEPT;
+ year operator--(int) NOEXCEPT;
+
+ year& operator+=(const years& y) NOEXCEPT;
+ year& operator-=(const years& y) NOEXCEPT;
+
+ CONSTCD11 explicit operator int() const NOEXCEPT;
+ CONSTCD11 bool ok() const NOEXCEPT;
+
+ static CONSTCD11 year min() NOEXCEPT;
+ static CONSTCD11 year max() NOEXCEPT;
+};
+
+CONSTCD11 bool operator==(const year& x, const year& y) NOEXCEPT;
+CONSTCD11 bool operator!=(const year& x, const year& y) NOEXCEPT;
+CONSTCD11 bool operator< (const year& x, const year& y) NOEXCEPT;
+CONSTCD11 bool operator> (const year& x, const year& y) NOEXCEPT;
+CONSTCD11 bool operator<=(const year& x, const year& y) NOEXCEPT;
+CONSTCD11 bool operator>=(const year& x, const year& y) NOEXCEPT;
+
+CONSTCD11 year operator+(const year& x, const years& y) NOEXCEPT;
+CONSTCD11 year operator+(const years& x, const year& y) NOEXCEPT;
+CONSTCD11 year operator-(const year& x, const years& y) NOEXCEPT;
+CONSTCD11 years operator-(const year& x, const year& y) NOEXCEPT;
+
+template<class CharT, class Traits>
+std::basic_ostream<CharT, Traits>&
+operator<<(std::basic_ostream<CharT, Traits>& os, const year& y);
+
+// weeknum
+
+class weeknum
+{
+ unsigned char wn_;
+
+public:
+ explicit CONSTCD11 weeknum(unsigned wn) NOEXCEPT;
+
+ weeknum& operator++() NOEXCEPT;
+ weeknum operator++(int) NOEXCEPT;
+ weeknum& operator--() NOEXCEPT;
+ weeknum operator--(int) NOEXCEPT;
+
+ weeknum& operator+=(const weeks& y) NOEXCEPT;
+ weeknum& operator-=(const weeks& y) NOEXCEPT;
+
+ CONSTCD11 explicit operator unsigned() const NOEXCEPT;
+ CONSTCD11 bool ok() const NOEXCEPT;
+};
+
+CONSTCD11 bool operator==(const weeknum& x, const weeknum& y) NOEXCEPT;
+CONSTCD11 bool operator!=(const weeknum& x, const weeknum& y) NOEXCEPT;
+CONSTCD11 bool operator< (const weeknum& x, const weeknum& y) NOEXCEPT;
+CONSTCD11 bool operator> (const weeknum& x, const weeknum& y) NOEXCEPT;
+CONSTCD11 bool operator<=(const weeknum& x, const weeknum& y) NOEXCEPT;
+CONSTCD11 bool operator>=(const weeknum& x, const weeknum& y) NOEXCEPT;
+
+CONSTCD11 weeknum operator+(const weeknum& x, const weeks& y) NOEXCEPT;
+CONSTCD11 weeknum operator+(const weeks& x, const weeknum& y) NOEXCEPT;
+CONSTCD11 weeknum operator-(const weeknum& x, const weeks& y) NOEXCEPT;
+CONSTCD11 weeks operator-(const weeknum& x, const weeknum& y) NOEXCEPT;
+
+template<class CharT, class Traits>
+std::basic_ostream<CharT, Traits>&
+operator<<(std::basic_ostream<CharT, Traits>& os, const weeknum& wn);
+
+// year_weeknum
+
+class year_weeknum
+{
+ iso_week::year y_;
+ iso_week::weeknum wn_;
+
+public:
+ CONSTCD11 year_weeknum(const iso_week::year& y, const iso_week::weeknum& wn) NOEXCEPT;
+
+ CONSTCD11 iso_week::year year() const NOEXCEPT;
+ CONSTCD11 iso_week::weeknum weeknum() const NOEXCEPT;
+
+ year_weeknum& operator+=(const years& dy) NOEXCEPT;
+ year_weeknum& operator-=(const years& dy) NOEXCEPT;
+
+ CONSTCD11 bool ok() const NOEXCEPT;
+};
+
+CONSTCD11 bool operator==(const year_weeknum& x, const year_weeknum& y) NOEXCEPT;
+CONSTCD11 bool operator!=(const year_weeknum& x, const year_weeknum& y) NOEXCEPT;
+CONSTCD11 bool operator< (const year_weeknum& x, const year_weeknum& y) NOEXCEPT;
+CONSTCD11 bool operator> (const year_weeknum& x, const year_weeknum& y) NOEXCEPT;
+CONSTCD11 bool operator<=(const year_weeknum& x, const year_weeknum& y) NOEXCEPT;
+CONSTCD11 bool operator>=(const year_weeknum& x, const year_weeknum& y) NOEXCEPT;
+
+CONSTCD11 year_weeknum operator+(const year_weeknum& ym, const years& dy) NOEXCEPT;
+CONSTCD11 year_weeknum operator+(const years& dy, const year_weeknum& ym) NOEXCEPT;
+CONSTCD11 year_weeknum operator-(const year_weeknum& ym, const years& dy) NOEXCEPT;
+
+template<class CharT, class Traits>
+std::basic_ostream<CharT, Traits>&
+operator<<(std::basic_ostream<CharT, Traits>& os, const year_weeknum& ym);
+
+// year_lastweek
+
+class year_lastweek
+{
+ iso_week::year y_;
+
+public:
+ CONSTCD11 explicit year_lastweek(const iso_week::year& y) NOEXCEPT;
+
+ CONSTCD11 iso_week::year year() const NOEXCEPT;
+ CONSTCD14 iso_week::weeknum weeknum() const NOEXCEPT;
+
+ year_lastweek& operator+=(const years& dy) NOEXCEPT;
+ year_lastweek& operator-=(const years& dy) NOEXCEPT;
+
+ CONSTCD11 bool ok() const NOEXCEPT;
+};
+
+CONSTCD11 bool operator==(const year_lastweek& x, const year_lastweek& y) NOEXCEPT;
+CONSTCD11 bool operator!=(const year_lastweek& x, const year_lastweek& y) NOEXCEPT;
+CONSTCD11 bool operator< (const year_lastweek& x, const year_lastweek& y) NOEXCEPT;
+CONSTCD11 bool operator> (const year_lastweek& x, const year_lastweek& y) NOEXCEPT;
+CONSTCD11 bool operator<=(const year_lastweek& x, const year_lastweek& y) NOEXCEPT;
+CONSTCD11 bool operator>=(const year_lastweek& x, const year_lastweek& y) NOEXCEPT;
+
+CONSTCD11 year_lastweek operator+(const year_lastweek& ym, const years& dy) NOEXCEPT;
+CONSTCD11 year_lastweek operator+(const years& dy, const year_lastweek& ym) NOEXCEPT;
+CONSTCD11 year_lastweek operator-(const year_lastweek& ym, const years& dy) NOEXCEPT;
+
+template<class CharT, class Traits>
+std::basic_ostream<CharT, Traits>&
+operator<<(std::basic_ostream<CharT, Traits>& os, const year_lastweek& ym);
+
+// weeknum_weekday
+
+class weeknum_weekday
+{
+ iso_week::weeknum wn_;
+ iso_week::weekday wd_;
+
+public:
+ CONSTCD11 weeknum_weekday(const iso_week::weeknum& wn,
+ const iso_week::weekday& wd) NOEXCEPT;
+
+ CONSTCD11 iso_week::weeknum weeknum() const NOEXCEPT;
+ CONSTCD11 iso_week::weekday weekday() const NOEXCEPT;
+
+ CONSTCD14 bool ok() const NOEXCEPT;
+};
+
+CONSTCD11 bool operator==(const weeknum_weekday& x, const weeknum_weekday& y) NOEXCEPT;
+CONSTCD11 bool operator!=(const weeknum_weekday& x, const weeknum_weekday& y) NOEXCEPT;
+CONSTCD11 bool operator< (const weeknum_weekday& x, const weeknum_weekday& y) NOEXCEPT;
+CONSTCD11 bool operator> (const weeknum_weekday& x, const weeknum_weekday& y) NOEXCEPT;
+CONSTCD11 bool operator<=(const weeknum_weekday& x, const weeknum_weekday& y) NOEXCEPT;
+CONSTCD11 bool operator>=(const weeknum_weekday& x, const weeknum_weekday& y) NOEXCEPT;
+
+template<class CharT, class Traits>
+std::basic_ostream<CharT, Traits>&
+operator<<(std::basic_ostream<CharT, Traits>& os, const weeknum_weekday& md);
+
+// lastweek_weekday
+
+class lastweek_weekday
+{
+ iso_week::weekday wd_;
+
+public:
+ CONSTCD11 explicit lastweek_weekday(const iso_week::weekday& wd) NOEXCEPT;
+
+ CONSTCD11 iso_week::weekday weekday() const NOEXCEPT;
+
+ CONSTCD14 bool ok() const NOEXCEPT;
+};
+
+CONSTCD11 bool operator==(const lastweek_weekday& x, const lastweek_weekday& y) NOEXCEPT;
+CONSTCD11 bool operator!=(const lastweek_weekday& x, const lastweek_weekday& y) NOEXCEPT;
+CONSTCD11 bool operator< (const lastweek_weekday& x, const lastweek_weekday& y) NOEXCEPT;
+CONSTCD11 bool operator> (const lastweek_weekday& x, const lastweek_weekday& y) NOEXCEPT;
+CONSTCD11 bool operator<=(const lastweek_weekday& x, const lastweek_weekday& y) NOEXCEPT;
+CONSTCD11 bool operator>=(const lastweek_weekday& x, const lastweek_weekday& y) NOEXCEPT;
+
+template<class CharT, class Traits>
+std::basic_ostream<CharT, Traits>&
+operator<<(std::basic_ostream<CharT, Traits>& os, const lastweek_weekday& md);
+
+// year_lastweek_weekday
+
+class year_lastweek_weekday
+{
+ iso_week::year y_;
+ iso_week::weekday wd_;
+
+public:
+ CONSTCD11 year_lastweek_weekday(const iso_week::year& y,
+ const iso_week::weekday& wd) NOEXCEPT;
+
+ year_lastweek_weekday& operator+=(const years& y) NOEXCEPT;
+ year_lastweek_weekday& operator-=(const years& y) NOEXCEPT;
+
+ CONSTCD11 iso_week::year year() const NOEXCEPT;
+ CONSTCD14 iso_week::weeknum weeknum() const NOEXCEPT;
+ CONSTCD11 iso_week::weekday weekday() const NOEXCEPT;
+
+ CONSTCD14 operator sys_days() const NOEXCEPT;
+ CONSTCD14 explicit operator local_days() const NOEXCEPT;
+ CONSTCD11 bool ok() const NOEXCEPT;
+};
+
+CONSTCD11 bool operator==(const year_lastweek_weekday& x, const year_lastweek_weekday& y) NOEXCEPT;
+CONSTCD11 bool operator!=(const year_lastweek_weekday& x, const year_lastweek_weekday& y) NOEXCEPT;
+CONSTCD11 bool operator< (const year_lastweek_weekday& x, const year_lastweek_weekday& y) NOEXCEPT;
+CONSTCD11 bool operator> (const year_lastweek_weekday& x, const year_lastweek_weekday& y) NOEXCEPT;
+CONSTCD11 bool operator<=(const year_lastweek_weekday& x, const year_lastweek_weekday& y) NOEXCEPT;
+CONSTCD11 bool operator>=(const year_lastweek_weekday& x, const year_lastweek_weekday& y) NOEXCEPT;
+
+CONSTCD11 year_lastweek_weekday operator+(const year_lastweek_weekday& ywnwd, const years& y) NOEXCEPT;
+CONSTCD11 year_lastweek_weekday operator+(const years& y, const year_lastweek_weekday& ywnwd) NOEXCEPT;
+CONSTCD11 year_lastweek_weekday operator-(const year_lastweek_weekday& ywnwd, const years& y) NOEXCEPT;
+
+template<class CharT, class Traits>
+std::basic_ostream<CharT, Traits>&
+operator<<(std::basic_ostream<CharT, Traits>& os, const year_lastweek_weekday& ywnwd);
+
+// class year_weeknum_weekday
+
+class year_weeknum_weekday
+{
+ iso_week::year y_;
+ iso_week::weeknum wn_;
+ iso_week::weekday wd_;
+
+public:
+ CONSTCD11 year_weeknum_weekday(const iso_week::year& y, const iso_week::weeknum& wn,
+ const iso_week::weekday& wd) NOEXCEPT;
+ CONSTCD14 year_weeknum_weekday(const year_lastweek_weekday& ylwwd) NOEXCEPT;
+ CONSTCD14 year_weeknum_weekday(const sys_days& dp) NOEXCEPT;
+ CONSTCD14 explicit year_weeknum_weekday(const local_days& dp) NOEXCEPT;
+
+ year_weeknum_weekday& operator+=(const years& y) NOEXCEPT;
+ year_weeknum_weekday& operator-=(const years& y) NOEXCEPT;
+
+ CONSTCD11 iso_week::year year() const NOEXCEPT;
+ CONSTCD11 iso_week::weeknum weeknum() const NOEXCEPT;
+ CONSTCD11 iso_week::weekday weekday() const NOEXCEPT;
+
+ CONSTCD14 operator sys_days() const NOEXCEPT;
+ CONSTCD14 explicit operator local_days() const NOEXCEPT;
+ CONSTCD14 bool ok() const NOEXCEPT;
+
+private:
+ static CONSTCD14 year_weeknum_weekday from_days(days dp) NOEXCEPT;
+};
+
+CONSTCD11 bool operator==(const year_weeknum_weekday& x, const year_weeknum_weekday& y) NOEXCEPT;
+CONSTCD11 bool operator!=(const year_weeknum_weekday& x, const year_weeknum_weekday& y) NOEXCEPT;
+CONSTCD11 bool operator< (const year_weeknum_weekday& x, const year_weeknum_weekday& y) NOEXCEPT;
+CONSTCD11 bool operator> (const year_weeknum_weekday& x, const year_weeknum_weekday& y) NOEXCEPT;
+CONSTCD11 bool operator<=(const year_weeknum_weekday& x, const year_weeknum_weekday& y) NOEXCEPT;
+CONSTCD11 bool operator>=(const year_weeknum_weekday& x, const year_weeknum_weekday& y) NOEXCEPT;
+
+CONSTCD11 year_weeknum_weekday operator+(const year_weeknum_weekday& ywnwd, const years& y) NOEXCEPT;
+CONSTCD11 year_weeknum_weekday operator+(const years& y, const year_weeknum_weekday& ywnwd) NOEXCEPT;
+CONSTCD11 year_weeknum_weekday operator-(const year_weeknum_weekday& ywnwd, const years& y) NOEXCEPT;
+
+template<class CharT, class Traits>
+std::basic_ostream<CharT, Traits>&
+operator<<(std::basic_ostream<CharT, Traits>& os, const year_weeknum_weekday& ywnwd);
+
+//----------------+
+// Implementation |
+//----------------+
+
+// weekday
+
+CONSTCD11
+inline
+unsigned char
+weekday::to_iso_encoding(unsigned char z) NOEXCEPT
+{
+ return z != 0 ? z : (unsigned char)7;
+}
+
+CONSTCD11
+inline
+unsigned
+weekday::from_iso_encoding(unsigned z) NOEXCEPT
+{
+ return z != 7 ? z : 0u;
+}
+
+CONSTCD11
+inline
+unsigned char
+weekday::weekday_from_days(int z) NOEXCEPT
+{
+ return to_iso_encoding(static_cast<unsigned char>(static_cast<unsigned>(
+ z >= -4 ? (z+4) % 7 : (z+5) % 7 + 6)));
+}
+
+CONSTCD11
+inline
+weekday::weekday(unsigned wd) NOEXCEPT
+ : wd_(static_cast<decltype(wd_)>(wd))
+ {}
+
+CONSTCD11
+inline
+weekday::weekday(date::weekday wd) NOEXCEPT
+ : wd_(to_iso_encoding(static_cast<unsigned>(wd)))
+ {}
+
+CONSTCD11
+inline
+weekday::weekday(const sys_days& dp) NOEXCEPT
+ : wd_(weekday_from_days(dp.time_since_epoch().count()))
+ {}
+
+CONSTCD11
+inline
+weekday::weekday(const local_days& dp) NOEXCEPT
+ : wd_(weekday_from_days(dp.time_since_epoch().count()))
+ {}
+
+inline weekday& weekday::operator++() NOEXCEPT {if (++wd_ == 8) wd_ = 1; return *this;}
+inline weekday weekday::operator++(int) NOEXCEPT {auto tmp(*this); ++(*this); return tmp;}
+inline weekday& weekday::operator--() NOEXCEPT {if (wd_-- == 1) wd_ = 7; return *this;}
+inline weekday weekday::operator--(int) NOEXCEPT {auto tmp(*this); --(*this); return tmp;}
+
+inline
+weekday&
+weekday::operator+=(const days& d) NOEXCEPT
+{
+ *this = *this + d;
+ return *this;
+}
+
+inline
+weekday&
+weekday::operator-=(const days& d) NOEXCEPT
+{
+ *this = *this - d;
+ return *this;
+}
+
+CONSTCD11
+inline
+weekday::operator unsigned() const NOEXCEPT
+{
+ return wd_;
+}
+
+CONSTCD11
+inline
+weekday::operator date::weekday() const NOEXCEPT
+{
+ return date::weekday{from_iso_encoding(unsigned{wd_})};
+}
+
+CONSTCD11 inline bool weekday::ok() const NOEXCEPT {return 1 <= wd_ && wd_ <= 7;}
+
+CONSTCD11
+inline
+bool
+operator==(const weekday& x, const weekday& y) NOEXCEPT
+{
+ return static_cast<unsigned>(x) == static_cast<unsigned>(y);
+}
+
+CONSTCD11
+inline
+bool
+operator!=(const weekday& x, const weekday& y) NOEXCEPT
+{
+ return !(x == y);
+}
+
+CONSTCD14
+inline
+days
+operator-(const weekday& x, const weekday& y) NOEXCEPT
+{
+ auto const diff = static_cast<unsigned>(x) - static_cast<unsigned>(y);
+ return days{diff <= 6 ? diff : diff + 7};
+}
+
+CONSTCD14
+inline
+weekday
+operator+(const weekday& x, const days& y) NOEXCEPT
+{
+ auto const wdu = static_cast<long long>(static_cast<unsigned>(x) - 1u) + y.count();
+ auto const wk = (wdu >= 0 ? wdu : wdu-6) / 7;
+ return weekday{static_cast<unsigned>(wdu - wk * 7) + 1u};
+}
+
+CONSTCD14
+inline
+weekday
+operator+(const days& x, const weekday& y) NOEXCEPT
+{
+ return y + x;
+}
+
+CONSTCD14
+inline
+weekday
+operator-(const weekday& x, const days& y) NOEXCEPT
+{
+ return x + -y;
+}
+
+template<class CharT, class Traits>
+inline
+std::basic_ostream<CharT, Traits>&
+operator<<(std::basic_ostream<CharT, Traits>& os, const weekday& wd)
+{
+ switch (static_cast<unsigned>(wd))
+ {
+ case 7:
+ os << "Sun";
+ break;
+ case 1:
+ os << "Mon";
+ break;
+ case 2:
+ os << "Tue";
+ break;
+ case 3:
+ os << "Wed";
+ break;
+ case 4:
+ os << "Thu";
+ break;
+ case 5:
+ os << "Fri";
+ break;
+ case 6:
+ os << "Sat";
+ break;
+ default:
+ os << static_cast<unsigned>(wd) << " is not a valid weekday";
+ break;
+ }
+ return os;
+}
+
+// year
+
+CONSTCD11 inline year::year(int y) NOEXCEPT : y_(static_cast<decltype(y_)>(y)) {}
+inline year& year::operator++() NOEXCEPT {++y_; return *this;}
+inline year year::operator++(int) NOEXCEPT {auto tmp(*this); ++(*this); return tmp;}
+inline year& year::operator--() NOEXCEPT {--y_; return *this;}
+inline year year::operator--(int) NOEXCEPT {auto tmp(*this); --(*this); return tmp;}
+inline year& year::operator+=(const years& y) NOEXCEPT {*this = *this + y; return *this;}
+inline year& year::operator-=(const years& y) NOEXCEPT {*this = *this - y; return *this;}
+
+CONSTCD11 inline year::operator int() const NOEXCEPT {return y_;}
+CONSTCD11 inline bool year::ok() const NOEXCEPT {return min() <= *this && *this <= max();}
+
+CONSTCD11
+inline
+year
+year::min() NOEXCEPT
+{
+ using namespace std::chrono;
+ static_assert(sizeof(seconds)*CHAR_BIT >= 41, "seconds may overflow");
+ static_assert(sizeof(hours)*CHAR_BIT >= 30, "hours may overflow");
+ return sizeof(minutes)*CHAR_BIT < 34 ?
+ year{1970} + duration_cast<years>(minutes::min()) :
+ year{std::numeric_limits<short>::min()};
+}
+
+CONSTCD11
+inline
+year
+year::max() NOEXCEPT
+{
+ using namespace std::chrono;
+ static_assert(sizeof(seconds)*CHAR_BIT >= 41, "seconds may overflow");
+ static_assert(sizeof(hours)*CHAR_BIT >= 30, "hours may overflow");
+ return sizeof(minutes)*CHAR_BIT < 34 ?
+ year{1969} + duration_cast<years>(minutes::max()) :
+ year{std::numeric_limits<short>::max()};
+}
+
+CONSTCD11
+inline
+bool
+operator==(const year& x, const year& y) NOEXCEPT
+{
+ return static_cast<int>(x) == static_cast<int>(y);
+}
+
+CONSTCD11
+inline
+bool
+operator!=(const year& x, const year& y) NOEXCEPT
+{
+ return !(x == y);
+}
+
+CONSTCD11
+inline
+bool
+operator<(const year& x, const year& y) NOEXCEPT
+{
+ return static_cast<int>(x) < static_cast<int>(y);
+}
+
+CONSTCD11
+inline
+bool
+operator>(const year& x, const year& y) NOEXCEPT
+{
+ return y < x;
+}
+
+CONSTCD11
+inline
+bool
+operator<=(const year& x, const year& y) NOEXCEPT
+{
+ return !(y < x);
+}
+
+CONSTCD11
+inline
+bool
+operator>=(const year& x, const year& y) NOEXCEPT
+{
+ return !(x < y);
+}
+
+CONSTCD11
+inline
+years
+operator-(const year& x, const year& y) NOEXCEPT
+{
+ return years{static_cast<int>(x) - static_cast<int>(y)};
+}
+
+CONSTCD11
+inline
+year
+operator+(const year& x, const years& y) NOEXCEPT
+{
+ return year{static_cast<int>(x) + y.count()};
+}
+
+CONSTCD11
+inline
+year
+operator+(const years& x, const year& y) NOEXCEPT
+{
+ return y + x;
+}
+
+CONSTCD11
+inline
+year
+operator-(const year& x, const years& y) NOEXCEPT
+{
+ return year{static_cast<int>(x) - y.count()};
+}
+
+template<class CharT, class Traits>
+inline
+std::basic_ostream<CharT, Traits>&
+operator<<(std::basic_ostream<CharT, Traits>& os, const year& y)
+{
+ date::detail::save_stream<CharT, Traits> _(os);
+ os.fill('0');
+ os.flags(std::ios::dec | std::ios::internal);
+ os.width(4 + (y < year{0}));
+ os << static_cast<int>(y);
+ return os;
+}
+
+#if !defined(_MSC_VER) || (_MSC_VER >= 1900)
+inline namespace literals
+{
+
+CONSTCD11
+inline
+iso_week::year
+operator "" _y(unsigned long long y) NOEXCEPT
+{
+ return iso_week::year(static_cast<int>(y));
+}
+
+CONSTCD11
+inline
+iso_week::weeknum
+operator "" _w(unsigned long long wn) NOEXCEPT
+{
+ return iso_week::weeknum(static_cast<unsigned>(wn));
+}
+
+#endif // !defined(_MSC_VER) || (_MSC_VER >= 1900)
+
+CONSTDATA iso_week::last_week last{};
+
+CONSTDATA iso_week::weekday sun{7u};
+CONSTDATA iso_week::weekday mon{1u};
+CONSTDATA iso_week::weekday tue{2u};
+CONSTDATA iso_week::weekday wed{3u};
+CONSTDATA iso_week::weekday thu{4u};
+CONSTDATA iso_week::weekday fri{5u};
+CONSTDATA iso_week::weekday sat{6u};
+
+#if !defined(_MSC_VER) || (_MSC_VER >= 1900)
+} // inline namespace literals
+#endif
+
+// weeknum
+
+CONSTCD11
+inline
+weeknum::weeknum(unsigned wn) NOEXCEPT
+ : wn_(static_cast<decltype(wn_)>(wn))
+ {}
+
+inline weeknum& weeknum::operator++() NOEXCEPT {++wn_; return *this;}
+inline weeknum weeknum::operator++(int) NOEXCEPT {auto tmp(*this); ++(*this); return tmp;}
+inline weeknum& weeknum::operator--() NOEXCEPT {--wn_; return *this;}
+inline weeknum weeknum::operator--(int) NOEXCEPT {auto tmp(*this); --(*this); return tmp;}
+
+inline
+weeknum&
+weeknum::operator+=(const weeks& y) NOEXCEPT
+{
+ *this = *this + y;
+ return *this;
+}
+
+inline
+weeknum&
+weeknum::operator-=(const weeks& y) NOEXCEPT
+{
+ *this = *this - y;
+ return *this;
+}
+
+CONSTCD11 inline weeknum::operator unsigned() const NOEXCEPT {return wn_;}
+CONSTCD11 inline bool weeknum::ok() const NOEXCEPT {return 1 <= wn_ && wn_ <= 53;}
+
+CONSTCD11
+inline
+bool
+operator==(const weeknum& x, const weeknum& y) NOEXCEPT
+{
+ return static_cast<unsigned>(x) == static_cast<unsigned>(y);
+}
+
+CONSTCD11
+inline
+bool
+operator!=(const weeknum& x, const weeknum& y) NOEXCEPT
+{
+ return !(x == y);
+}
+
+CONSTCD11
+inline
+bool
+operator<(const weeknum& x, const weeknum& y) NOEXCEPT
+{
+ return static_cast<unsigned>(x) < static_cast<unsigned>(y);
+}
+
+CONSTCD11
+inline
+bool
+operator>(const weeknum& x, const weeknum& y) NOEXCEPT
+{
+ return y < x;
+}
+
+CONSTCD11
+inline
+bool
+operator<=(const weeknum& x, const weeknum& y) NOEXCEPT
+{
+ return !(y < x);
+}
+
+CONSTCD11
+inline
+bool
+operator>=(const weeknum& x, const weeknum& y) NOEXCEPT
+{
+ return !(x < y);
+}
+
+CONSTCD11
+inline
+weeks
+operator-(const weeknum& x, const weeknum& y) NOEXCEPT
+{
+ return weeks{static_cast<weeks::rep>(static_cast<unsigned>(x)) -
+ static_cast<weeks::rep>(static_cast<unsigned>(y))};
+}
+
+CONSTCD11
+inline
+weeknum
+operator+(const weeknum& x, const weeks& y) NOEXCEPT
+{
+ return weeknum{static_cast<unsigned>(x) + static_cast<unsigned>(y.count())};
+}
+
+CONSTCD11
+inline
+weeknum
+operator+(const weeks& x, const weeknum& y) NOEXCEPT
+{
+ return y + x;
+}
+
+CONSTCD11
+inline
+weeknum
+operator-(const weeknum& x, const weeks& y) NOEXCEPT
+{
+ return x + -y;
+}
+
+template<class CharT, class Traits>
+inline
+std::basic_ostream<CharT, Traits>&
+operator<<(std::basic_ostream<CharT, Traits>& os, const weeknum& wn)
+{
+ date::detail::save_stream<CharT, Traits> _(os);
+ os << 'W';
+ os.fill('0');
+ os.flags(std::ios::dec | std::ios::right);
+ os.width(2);
+ os << static_cast<unsigned>(wn);
+ return os;
+}
+
+// year_weeknum
+
+CONSTCD11
+inline
+year_weeknum::year_weeknum(const iso_week::year& y, const iso_week::weeknum& wn) NOEXCEPT
+ : y_(y)
+ , wn_(wn)
+ {}
+
+CONSTCD11 inline year year_weeknum::year() const NOEXCEPT {return y_;}
+CONSTCD11 inline weeknum year_weeknum::weeknum() const NOEXCEPT {return wn_;}
+CONSTCD11 inline bool year_weeknum::ok() const NOEXCEPT
+{
+ return y_.ok() && 1u <= static_cast<unsigned>(wn_) && wn_ <= (y_/last).weeknum();
+}
+
+inline
+year_weeknum&
+year_weeknum::operator+=(const years& dy) NOEXCEPT
+{
+ *this = *this + dy;
+ return *this;
+}
+
+inline
+year_weeknum&
+year_weeknum::operator-=(const years& dy) NOEXCEPT
+{
+ *this = *this - dy;
+ return *this;
+}
+
+CONSTCD11
+inline
+bool
+operator==(const year_weeknum& x, const year_weeknum& y) NOEXCEPT
+{
+ return x.year() == y.year() && x.weeknum() == y.weeknum();
+}
+
+CONSTCD11
+inline
+bool
+operator!=(const year_weeknum& x, const year_weeknum& y) NOEXCEPT
+{
+ return !(x == y);
+}
+
+CONSTCD11
+inline
+bool
+operator<(const year_weeknum& x, const year_weeknum& y) NOEXCEPT
+{
+ return x.year() < y.year() ? true
+ : (x.year() > y.year() ? false
+ : (x.weeknum() < y.weeknum()));
+}
+
+CONSTCD11
+inline
+bool
+operator>(const year_weeknum& x, const year_weeknum& y) NOEXCEPT
+{
+ return y < x;
+}
+
+CONSTCD11
+inline
+bool
+operator<=(const year_weeknum& x, const year_weeknum& y) NOEXCEPT
+{
+ return !(y < x);
+}
+
+CONSTCD11
+inline
+bool
+operator>=(const year_weeknum& x, const year_weeknum& y) NOEXCEPT
+{
+ return !(x < y);
+}
+
+CONSTCD11
+inline
+year_weeknum
+operator+(const year_weeknum& ym, const years& dy) NOEXCEPT
+{
+ return (ym.year() + dy) / ym.weeknum();
+}
+
+CONSTCD11
+inline
+year_weeknum
+operator+(const years& dy, const year_weeknum& ym) NOEXCEPT
+{
+ return ym + dy;
+}
+
+CONSTCD11
+inline
+year_weeknum
+operator-(const year_weeknum& ym, const years& dy) NOEXCEPT
+{
+ return ym + -dy;
+}
+
+template<class CharT, class Traits>
+inline
+std::basic_ostream<CharT, Traits>&
+operator<<(std::basic_ostream<CharT, Traits>& os, const year_weeknum& ywn)
+{
+ return os << ywn.year() << '-' << ywn.weeknum();
+}
+
+
+// year_lastweek
+
+CONSTCD11
+inline
+year_lastweek::year_lastweek(const iso_week::year& y) NOEXCEPT
+ : y_(y)
+ {}
+
+CONSTCD11 inline year year_lastweek::year() const NOEXCEPT {return y_;}
+
+CONSTCD14
+inline
+weeknum
+year_lastweek::weeknum() const NOEXCEPT
+{
+ const auto y = date::year{static_cast<int>(y_)};
+ const auto s0 = sys_days((y-years{1})/12/date::thu[date::last]);
+ const auto s1 = sys_days(y/12/date::thu[date::last]);
+ return iso_week::weeknum(static_cast<unsigned>(date::trunc<weeks>(s1-s0).count()));
+}
+
+CONSTCD11 inline bool year_lastweek::ok() const NOEXCEPT {return y_.ok();}
+
+inline
+year_lastweek&
+year_lastweek::operator+=(const years& dy) NOEXCEPT
+{
+ *this = *this + dy;
+ return *this;
+}
+
+inline
+year_lastweek&
+year_lastweek::operator-=(const years& dy) NOEXCEPT
+{
+ *this = *this - dy;
+ return *this;
+}
+
+CONSTCD11
+inline
+bool
+operator==(const year_lastweek& x, const year_lastweek& y) NOEXCEPT
+{
+ return x.year() == y.year();
+}
+
+CONSTCD11
+inline
+bool
+operator!=(const year_lastweek& x, const year_lastweek& y) NOEXCEPT
+{
+ return !(x == y);
+}
+
+CONSTCD11
+inline
+bool
+operator<(const year_lastweek& x, const year_lastweek& y) NOEXCEPT
+{
+ return x.year() < y.year();
+}
+
+CONSTCD11
+inline
+bool
+operator>(const year_lastweek& x, const year_lastweek& y) NOEXCEPT
+{
+ return y < x;
+}
+
+CONSTCD11
+inline
+bool
+operator<=(const year_lastweek& x, const year_lastweek& y) NOEXCEPT
+{
+ return !(y < x);
+}
+
+CONSTCD11
+inline
+bool
+operator>=(const year_lastweek& x, const year_lastweek& y) NOEXCEPT
+{
+ return !(x < y);
+}
+
+CONSTCD11
+inline
+year_lastweek
+operator+(const year_lastweek& ym, const years& dy) NOEXCEPT
+{
+ return year_lastweek{ym.year() + dy};
+}
+
+CONSTCD11
+inline
+year_lastweek
+operator+(const years& dy, const year_lastweek& ym) NOEXCEPT
+{
+ return ym + dy;
+}
+
+CONSTCD11
+inline
+year_lastweek
+operator-(const year_lastweek& ym, const years& dy) NOEXCEPT
+{
+ return ym + -dy;
+}
+
+template<class CharT, class Traits>
+inline
+std::basic_ostream<CharT, Traits>&
+operator<<(std::basic_ostream<CharT, Traits>& os, const year_lastweek& ywn)
+{
+ return os << ywn.year() << "-W last";
+}
+
+// weeknum_weekday
+
+CONSTCD11
+inline
+weeknum_weekday::weeknum_weekday(const iso_week::weeknum& wn,
+ const iso_week::weekday& wd) NOEXCEPT
+ : wn_(wn)
+ , wd_(wd)
+ {}
+
+CONSTCD11 inline weeknum weeknum_weekday::weeknum() const NOEXCEPT {return wn_;}
+CONSTCD11 inline weekday weeknum_weekday::weekday() const NOEXCEPT {return wd_;}
+
+CONSTCD14
+inline
+bool
+weeknum_weekday::ok() const NOEXCEPT
+{
+ return wn_.ok() && wd_.ok();
+}
+
+CONSTCD11
+inline
+bool
+operator==(const weeknum_weekday& x, const weeknum_weekday& y) NOEXCEPT
+{
+ return x.weeknum() == y.weeknum() && x.weekday() == y.weekday();
+}
+
+CONSTCD11
+inline
+bool
+operator!=(const weeknum_weekday& x, const weeknum_weekday& y) NOEXCEPT
+{
+ return !(x == y);
+}
+
+CONSTCD11
+inline
+bool
+operator<(const weeknum_weekday& x, const weeknum_weekday& y) NOEXCEPT
+{
+ return x.weeknum() < y.weeknum() ? true
+ : (x.weeknum() > y.weeknum() ? false
+ : (static_cast<unsigned>(x.weekday()) < static_cast<unsigned>(y.weekday())));
+}
+
+CONSTCD11
+inline
+bool
+operator>(const weeknum_weekday& x, const weeknum_weekday& y) NOEXCEPT
+{
+ return y < x;
+}
+
+CONSTCD11
+inline
+bool
+operator<=(const weeknum_weekday& x, const weeknum_weekday& y) NOEXCEPT
+{
+ return !(y < x);
+}
+
+CONSTCD11
+inline
+bool
+operator>=(const weeknum_weekday& x, const weeknum_weekday& y) NOEXCEPT
+{
+ return !(x < y);
+}
+
+template<class CharT, class Traits>
+inline
+std::basic_ostream<CharT, Traits>&
+operator<<(std::basic_ostream<CharT, Traits>& os, const weeknum_weekday& md)
+{
+ return os << md.weeknum() << '-' << md.weekday();
+}
+
+// lastweek_weekday
+
+CONSTCD11
+inline
+lastweek_weekday::lastweek_weekday(const iso_week::weekday& wd) NOEXCEPT
+ : wd_(wd)
+ {}
+
+CONSTCD11 inline weekday lastweek_weekday::weekday() const NOEXCEPT {return wd_;}
+
+CONSTCD14
+inline
+bool
+lastweek_weekday::ok() const NOEXCEPT
+{
+ return wd_.ok();
+}
+
+CONSTCD11
+inline
+bool
+operator==(const lastweek_weekday& x, const lastweek_weekday& y) NOEXCEPT
+{
+ return x.weekday() == y.weekday();
+}
+
+CONSTCD11
+inline
+bool
+operator!=(const lastweek_weekday& x, const lastweek_weekday& y) NOEXCEPT
+{
+ return !(x == y);
+}
+
+CONSTCD11
+inline
+bool
+operator<(const lastweek_weekday& x, const lastweek_weekday& y) NOEXCEPT
+{
+ return static_cast<unsigned>(x.weekday()) < static_cast<unsigned>(y.weekday());
+}
+
+CONSTCD11
+inline
+bool
+operator>(const lastweek_weekday& x, const lastweek_weekday& y) NOEXCEPT
+{
+ return y < x;
+}
+
+CONSTCD11
+inline
+bool
+operator<=(const lastweek_weekday& x, const lastweek_weekday& y) NOEXCEPT
+{
+ return !(y < x);
+}
+
+CONSTCD11
+inline
+bool
+operator>=(const lastweek_weekday& x, const lastweek_weekday& y) NOEXCEPT
+{
+ return !(x < y);
+}
+
+template<class CharT, class Traits>
+inline
+std::basic_ostream<CharT, Traits>&
+operator<<(std::basic_ostream<CharT, Traits>& os, const lastweek_weekday& md)
+{
+ return os << "W last-" << md.weekday();
+}
+
+// year_lastweek_weekday
+
+CONSTCD11
+inline
+year_lastweek_weekday::year_lastweek_weekday(const iso_week::year& y,
+ const iso_week::weekday& wd) NOEXCEPT
+ : y_(y)
+ , wd_(wd)
+ {}
+
+inline
+year_lastweek_weekday&
+year_lastweek_weekday::operator+=(const years& y) NOEXCEPT
+{
+ *this = *this + y;
+ return *this;
+}
+
+inline
+year_lastweek_weekday&
+year_lastweek_weekday::operator-=(const years& y) NOEXCEPT
+{
+ *this = *this - y;
+ return *this;
+}
+
+CONSTCD11 inline year year_lastweek_weekday::year() const NOEXCEPT {return y_;}
+
+CONSTCD14
+inline
+weeknum
+year_lastweek_weekday::weeknum() const NOEXCEPT
+{
+ return (y_ / last).weeknum();
+}
+
+CONSTCD11 inline weekday year_lastweek_weekday::weekday() const NOEXCEPT {return wd_;}
+
+CONSTCD14
+inline
+year_lastweek_weekday::operator sys_days() const NOEXCEPT
+{
+ return sys_days(date::year{static_cast<int>(y_)}/date::dec/date::thu[date::last])
+ + (sun - thu) - (sun - wd_);
+}
+
+CONSTCD14
+inline
+year_lastweek_weekday::operator local_days() const NOEXCEPT
+{
+ return local_days(date::year{static_cast<int>(y_)}/date::dec/date::thu[date::last])
+ + (sun - thu) - (sun - wd_);
+}
+
+CONSTCD11
+inline
+bool
+year_lastweek_weekday::ok() const NOEXCEPT
+{
+ return y_.ok() && wd_.ok();
+}
+
+CONSTCD11
+inline
+bool
+operator==(const year_lastweek_weekday& x, const year_lastweek_weekday& y) NOEXCEPT
+{
+ return x.year() == y.year() && x.weekday() == y.weekday();
+}
+
+CONSTCD11
+inline
+bool
+operator!=(const year_lastweek_weekday& x, const year_lastweek_weekday& y) NOEXCEPT
+{
+ return !(x == y);
+}
+
+CONSTCD11
+inline
+bool
+operator<(const year_lastweek_weekday& x, const year_lastweek_weekday& y) NOEXCEPT
+{
+ return x.year() < y.year() ? true
+ : (x.year() > y.year() ? false
+ : (static_cast<unsigned>(x.weekday()) < static_cast<unsigned>(y.weekday())));
+}
+
+CONSTCD11
+inline
+bool
+operator>(const year_lastweek_weekday& x, const year_lastweek_weekday& y) NOEXCEPT
+{
+ return y < x;
+}
+
+CONSTCD11
+inline
+bool
+operator<=(const year_lastweek_weekday& x, const year_lastweek_weekday& y) NOEXCEPT
+{
+ return !(y < x);
+}
+
+CONSTCD11
+inline
+bool
+operator>=(const year_lastweek_weekday& x, const year_lastweek_weekday& y) NOEXCEPT
+{
+ return !(x < y);
+}
+
+CONSTCD11
+inline
+year_lastweek_weekday
+operator+(const year_lastweek_weekday& ywnwd, const years& y) NOEXCEPT
+{
+ return (ywnwd.year() + y) / last / ywnwd.weekday();
+}
+
+CONSTCD11
+inline
+year_lastweek_weekday
+operator+(const years& y, const year_lastweek_weekday& ywnwd) NOEXCEPT
+{
+ return ywnwd + y;
+}
+
+CONSTCD11
+inline
+year_lastweek_weekday
+operator-(const year_lastweek_weekday& ywnwd, const years& y) NOEXCEPT
+{
+ return ywnwd + -y;
+}
+
+template<class CharT, class Traits>
+inline
+std::basic_ostream<CharT, Traits>&
+operator<<(std::basic_ostream<CharT, Traits>& os, const year_lastweek_weekday& ywnwd)
+{
+ return os << ywnwd.year() << "-W last-" << ywnwd.weekday();
+}
+
+// year_weeknum_weekday
+
+CONSTCD11
+inline
+year_weeknum_weekday::year_weeknum_weekday(const iso_week::year& y,
+ const iso_week::weeknum& wn,
+ const iso_week::weekday& wd) NOEXCEPT
+ : y_(y)
+ , wn_(wn)
+ , wd_(wd)
+ {}
+
+CONSTCD14
+inline
+year_weeknum_weekday::year_weeknum_weekday(const year_lastweek_weekday& ylwwd) NOEXCEPT
+ : y_(ylwwd.year())
+ , wn_(ylwwd.weeknum())
+ , wd_(ylwwd.weekday())
+ {}
+
+CONSTCD14
+inline
+year_weeknum_weekday::year_weeknum_weekday(const sys_days& dp) NOEXCEPT
+ : year_weeknum_weekday(from_days(dp.time_since_epoch()))
+ {}
+
+CONSTCD14
+inline
+year_weeknum_weekday::year_weeknum_weekday(const local_days& dp) NOEXCEPT
+ : year_weeknum_weekday(from_days(dp.time_since_epoch()))
+ {}
+
+inline
+year_weeknum_weekday&
+year_weeknum_weekday::operator+=(const years& y) NOEXCEPT
+{
+ *this = *this + y;
+ return *this;
+}
+
+inline
+year_weeknum_weekday&
+year_weeknum_weekday::operator-=(const years& y) NOEXCEPT
+{
+ *this = *this - y;
+ return *this;
+}
+
+CONSTCD11 inline year year_weeknum_weekday::year() const NOEXCEPT {return y_;}
+CONSTCD11 inline weeknum year_weeknum_weekday::weeknum() const NOEXCEPT {return wn_;}
+CONSTCD11 inline weekday year_weeknum_weekday::weekday() const NOEXCEPT {return wd_;}
+
+CONSTCD14
+inline
+year_weeknum_weekday::operator sys_days() const NOEXCEPT
+{
+ return sys_days(date::year{static_cast<int>(y_)-1}/date::dec/date::thu[date::last])
+ + (date::mon - date::thu) + weeks{static_cast<unsigned>(wn_)-1} + (wd_ - mon);
+}
+
+CONSTCD14
+inline
+year_weeknum_weekday::operator local_days() const NOEXCEPT
+{
+ return local_days(date::year{static_cast<int>(y_)-1}/date::dec/date::thu[date::last])
+ + (date::mon - date::thu) + weeks{static_cast<unsigned>(wn_)-1} + (wd_ - mon);
+}
+
+CONSTCD14
+inline
+bool
+year_weeknum_weekday::ok() const NOEXCEPT
+{
+ return y_.ok() && wd_.ok() && iso_week::weeknum{1u} <= wn_ && wn_ <= year_lastweek{y_}.weeknum();
+}
+
+CONSTCD14
+inline
+year_weeknum_weekday
+year_weeknum_weekday::from_days(days d) NOEXCEPT
+{
+ const auto dp = sys_days{d};
+ const auto wd = iso_week::weekday{dp};
+ auto y = date::year_month_day{dp + days{3}}.year();
+ auto start = sys_days((y - date::years{1})/date::dec/date::thu[date::last]) + (mon-thu);
+ if (dp < start)
+ {
+ --y;
+ start = sys_days((y - date::years{1})/date::dec/date::thu[date::last]) + (mon-thu);
+ }
+ const auto wn = iso_week::weeknum(
+ static_cast<unsigned>(date::trunc<weeks>(dp - start).count() + 1));
+ return {iso_week::year(static_cast<int>(y)), wn, wd};
+}
+
+CONSTCD11
+inline
+bool
+operator==(const year_weeknum_weekday& x, const year_weeknum_weekday& y) NOEXCEPT
+{
+ return x.year() == y.year() && x.weeknum() == y.weeknum() && x.weekday() == y.weekday();
+}
+
+CONSTCD11
+inline
+bool
+operator!=(const year_weeknum_weekday& x, const year_weeknum_weekday& y) NOEXCEPT
+{
+ return !(x == y);
+}
+
+CONSTCD11
+inline
+bool
+operator<(const year_weeknum_weekday& x, const year_weeknum_weekday& y) NOEXCEPT
+{
+ return x.year() < y.year() ? true
+ : (x.year() > y.year() ? false
+ : (x.weeknum() < y.weeknum() ? true
+ : (x.weeknum() > y.weeknum() ? false
+ : (static_cast<unsigned>(x.weekday()) < static_cast<unsigned>(y.weekday())))));
+}
+
+CONSTCD11
+inline
+bool
+operator>(const year_weeknum_weekday& x, const year_weeknum_weekday& y) NOEXCEPT
+{
+ return y < x;
+}
+
+CONSTCD11
+inline
+bool
+operator<=(const year_weeknum_weekday& x, const year_weeknum_weekday& y) NOEXCEPT
+{
+ return !(y < x);
+}
+
+CONSTCD11
+inline
+bool
+operator>=(const year_weeknum_weekday& x, const year_weeknum_weekday& y) NOEXCEPT
+{
+ return !(x < y);
+}
+
+CONSTCD11
+inline
+year_weeknum_weekday
+operator+(const year_weeknum_weekday& ywnwd, const years& y) NOEXCEPT
+{
+ return (ywnwd.year() + y) / ywnwd.weeknum() / ywnwd.weekday();
+}
+
+CONSTCD11
+inline
+year_weeknum_weekday
+operator+(const years& y, const year_weeknum_weekday& ywnwd) NOEXCEPT
+{
+ return ywnwd + y;
+}
+
+CONSTCD11
+inline
+year_weeknum_weekday
+operator-(const year_weeknum_weekday& ywnwd, const years& y) NOEXCEPT
+{
+ return ywnwd + -y;
+}
+
+template<class CharT, class Traits>
+inline
+std::basic_ostream<CharT, Traits>&
+operator<<(std::basic_ostream<CharT, Traits>& os, const year_weeknum_weekday& ywnwd)
+{
+ return os << ywnwd.year() << '-' << ywnwd.weeknum() << '-' << ywnwd.weekday();
+}
+
+// date composition operators
+
+CONSTCD11
+inline
+year_weeknum
+operator/(const year& y, const weeknum& wn) NOEXCEPT
+{
+ return {y, wn};
+}
+
+CONSTCD11
+inline
+year_weeknum
+operator/(const year& y, int wn) NOEXCEPT
+{
+ return y/weeknum(static_cast<unsigned>(wn));
+}
+
+CONSTCD11
+inline
+year_lastweek
+operator/(const year& y, last_week) NOEXCEPT
+{
+ return year_lastweek{y};
+}
+
+CONSTCD11
+inline
+weeknum_weekday
+operator/(const weeknum& wn, const weekday& wd) NOEXCEPT
+{
+ return {wn, wd};
+}
+
+CONSTCD11
+inline
+weeknum_weekday
+operator/(const weeknum& wn, int wd) NOEXCEPT
+{
+ return wn/weekday{static_cast<unsigned>(wd)};
+}
+
+CONSTCD11
+inline
+weeknum_weekday
+operator/(const weekday& wd, const weeknum& wn) NOEXCEPT
+{
+ return wn/wd;
+}
+
+CONSTCD11
+inline
+weeknum_weekday
+operator/(const weekday& wd, int wn) NOEXCEPT
+{
+ return weeknum{static_cast<unsigned>(wn)}/wd;
+}
+
+CONSTCD11
+inline
+lastweek_weekday
+operator/(const last_week&, const weekday& wd) NOEXCEPT
+{
+ return lastweek_weekday{wd};
+}
+
+CONSTCD11
+inline
+lastweek_weekday
+operator/(const last_week& wn, int wd) NOEXCEPT
+{
+ return wn / weekday{static_cast<unsigned>(wd)};
+}
+
+CONSTCD11
+inline
+lastweek_weekday
+operator/(const weekday& wd, const last_week& wn) NOEXCEPT
+{
+ return wn / wd;
+}
+
+CONSTCD11
+inline
+year_weeknum_weekday
+operator/(const year_weeknum& ywn, const weekday& wd) NOEXCEPT
+{
+ return {ywn.year(), ywn.weeknum(), wd};
+}
+
+CONSTCD11
+inline
+year_weeknum_weekday
+operator/(const year_weeknum& ywn, int wd) NOEXCEPT
+{
+ return ywn / weekday(static_cast<unsigned>(wd));
+}
+
+CONSTCD11
+inline
+year_weeknum_weekday
+operator/(const weeknum_weekday& wnwd, const year& y) NOEXCEPT
+{
+ return {y, wnwd.weeknum(), wnwd.weekday()};
+}
+
+CONSTCD11
+inline
+year_weeknum_weekday
+operator/(const weeknum_weekday& wnwd, int y) NOEXCEPT
+{
+ return wnwd / year{y};
+}
+
+CONSTCD11
+inline
+year_lastweek_weekday
+operator/(const year_lastweek& ylw, const weekday& wd) NOEXCEPT
+{
+ return {ylw.year(), wd};
+}
+
+CONSTCD11
+inline
+year_lastweek_weekday
+operator/(const year_lastweek& ylw, int wd) NOEXCEPT
+{
+ return ylw / weekday(static_cast<unsigned>(wd));
+}
+
+CONSTCD11
+inline
+year_lastweek_weekday
+operator/(const lastweek_weekday& lwwd, const year& y) NOEXCEPT
+{
+ return {y, lwwd.weekday()};
+}
+
+CONSTCD11
+inline
+year_lastweek_weekday
+operator/(const lastweek_weekday& lwwd, int y) NOEXCEPT
+{
+ return lwwd / year{y};
+}
+
+} // namespace iso_week
+
+#endif // ISO_WEEK_H
[09/10] nifi-minifi-cpp git commit: MINIFICPP-472 Added date
formatting EL functions
Posted by al...@apache.org.
http://git-wip-us.apache.org/repos/asf/nifi-minifi-cpp/blob/8777ab5f/thirdparty/date/include/date/date.h
----------------------------------------------------------------------
diff --git a/thirdparty/date/include/date/date.h b/thirdparty/date/include/date/date.h
new file mode 100644
index 0000000..cb115a9
--- /dev/null
+++ b/thirdparty/date/include/date/date.h
@@ -0,0 +1,8022 @@
+#ifndef DATE_H
+#define DATE_H
+
+// The MIT License (MIT)
+//
+// Copyright (c) 2015, 2016, 2017 Howard Hinnant
+// Copyright (c) 2016 Adrian Colomitchi
+// Copyright (c) 2017 Florian Dang
+// Copyright (c) 2017 Paul Thompson
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in all
+// copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+// SOFTWARE.
+//
+// Our apologies. When the previous paragraph was written, lowercase had not yet
+// been invented (that would involve another several millennia of evolution).
+// We did not mean to shout.
+
+#ifndef HAS_STRING_VIEW
+# if __cplusplus >= 201703
+# define HAS_STRING_VIEW 1
+# else
+# define HAS_STRING_VIEW 0
+# endif
+#endif // HAS_STRING_VIEW
+
+#include <cassert>
+#include <algorithm>
+#include <cctype>
+#include <chrono>
+#include <climits>
+#if !(__cplusplus >= 201402)
+# include <cmath>
+#endif
+#include <cstddef>
+#include <cstdint>
+#include <cstdlib>
+#include <ctime>
+#include <ios>
+#include <istream>
+#include <iterator>
+#include <limits>
+#include <locale>
+#include <memory>
+#include <ostream>
+#include <ratio>
+#include <sstream>
+#include <stdexcept>
+#include <string>
+#if HAS_STRING_VIEW
+# include <string_view>
+#endif
+#include <utility>
+#include <type_traits>
+
+#ifdef __GNUC__
+# pragma GCC diagnostic push
+# pragma GCC diagnostic ignored "-Wpedantic"
+# if __GNUC__ < 5
+ // GCC 4.9 Bug 61489 Wrong warning with -Wmissing-field-initializers
+# pragma GCC diagnostic ignored "-Wmissing-field-initializers"
+# endif
+#endif
+
+namespace date
+{
+
+//---------------+
+// Configuration |
+//---------------+
+
+#ifndef ONLY_C_LOCALE
+# define ONLY_C_LOCALE 0
+#endif
+
+#if defined(_MSC_VER) && (!defined(__clang__) || (_MSC_VER < 1910))
+// MSVC
+# if _MSC_VER < 1910
+// before VS2017
+# define CONSTDATA const
+# define CONSTCD11
+# define CONSTCD14
+# define NOEXCEPT _NOEXCEPT
+# else
+// VS2017 and later
+# define CONSTDATA constexpr const
+# define CONSTCD11 constexpr
+# define CONSTCD14 constexpr
+# define NOEXCEPT noexcept
+# endif
+
+#elif defined(__SUNPRO_CC) && __SUNPRO_CC <= 0x5150
+// Oracle Developer Studio 12.6 and earlier
+# define CONSTDATA constexpr const
+# define CONSTCD11 constexpr
+# define CONSTCD14
+# define NOEXCEPT noexcept
+
+#elif __cplusplus >= 201402
+// C++14
+# define CONSTDATA constexpr const
+# define CONSTCD11 constexpr
+# define CONSTCD14 constexpr
+# define NOEXCEPT noexcept
+#else
+// C++11
+# define CONSTDATA constexpr const
+# define CONSTCD11 constexpr
+# define CONSTCD14
+# define NOEXCEPT noexcept
+#endif
+
+#ifndef HAS_VOID_T
+# if __cplusplus >= 201703
+# define HAS_VOID_T 1
+# else
+# define HAS_VOID_T 0
+# endif
+#endif // HAS_VOID_T
+
+// Protect from Oracle sun macro
+#ifdef sun
+# undef sun
+#endif
+
+//-----------+
+// Interface |
+//-----------+
+
+// durations
+
+using days = std::chrono::duration
+ <int, std::ratio_multiply<std::ratio<24>, std::chrono::hours::period>>;
+
+using weeks = std::chrono::duration
+ <int, std::ratio_multiply<std::ratio<7>, days::period>>;
+
+using years = std::chrono::duration
+ <int, std::ratio_multiply<std::ratio<146097, 400>, days::period>>;
+
+using months = std::chrono::duration
+ <int, std::ratio_divide<years::period, std::ratio<12>>>;
+
+// time_point
+
+template <class Duration>
+ using sys_time = std::chrono::time_point<std::chrono::system_clock, Duration>;
+
+using sys_days = sys_time<days>;
+using sys_seconds = sys_time<std::chrono::seconds>;
+
+struct local_t {};
+
+template <class Duration>
+ using local_time = std::chrono::time_point<local_t, Duration>;
+
+using local_seconds = local_time<std::chrono::seconds>;
+using local_days = local_time<days>;
+
+// types
+
+struct last_spec
+{
+ explicit last_spec() = default;
+};
+
+class day;
+class month;
+class year;
+
+class weekday;
+class weekday_indexed;
+class weekday_last;
+
+class month_day;
+class month_day_last;
+class month_weekday;
+class month_weekday_last;
+
+class year_month;
+
+class year_month_day;
+class year_month_day_last;
+class year_month_weekday;
+class year_month_weekday_last;
+
+// date composition operators
+
+CONSTCD11 year_month operator/(const year& y, const month& m) NOEXCEPT;
+CONSTCD11 year_month operator/(const year& y, int m) NOEXCEPT;
+
+CONSTCD11 month_day operator/(const day& d, const month& m) NOEXCEPT;
+CONSTCD11 month_day operator/(const day& d, int m) NOEXCEPT;
+CONSTCD11 month_day operator/(const month& m, const day& d) NOEXCEPT;
+CONSTCD11 month_day operator/(const month& m, int d) NOEXCEPT;
+CONSTCD11 month_day operator/(int m, const day& d) NOEXCEPT;
+
+CONSTCD11 month_day_last operator/(const month& m, last_spec) NOEXCEPT;
+CONSTCD11 month_day_last operator/(int m, last_spec) NOEXCEPT;
+CONSTCD11 month_day_last operator/(last_spec, const month& m) NOEXCEPT;
+CONSTCD11 month_day_last operator/(last_spec, int m) NOEXCEPT;
+
+CONSTCD11 month_weekday operator/(const month& m, const weekday_indexed& wdi) NOEXCEPT;
+CONSTCD11 month_weekday operator/(int m, const weekday_indexed& wdi) NOEXCEPT;
+CONSTCD11 month_weekday operator/(const weekday_indexed& wdi, const month& m) NOEXCEPT;
+CONSTCD11 month_weekday operator/(const weekday_indexed& wdi, int m) NOEXCEPT;
+
+CONSTCD11 month_weekday_last operator/(const month& m, const weekday_last& wdl) NOEXCEPT;
+CONSTCD11 month_weekday_last operator/(int m, const weekday_last& wdl) NOEXCEPT;
+CONSTCD11 month_weekday_last operator/(const weekday_last& wdl, const month& m) NOEXCEPT;
+CONSTCD11 month_weekday_last operator/(const weekday_last& wdl, int m) NOEXCEPT;
+
+CONSTCD11 year_month_day operator/(const year_month& ym, const day& d) NOEXCEPT;
+CONSTCD11 year_month_day operator/(const year_month& ym, int d) NOEXCEPT;
+CONSTCD11 year_month_day operator/(const year& y, const month_day& md) NOEXCEPT;
+CONSTCD11 year_month_day operator/(int y, const month_day& md) NOEXCEPT;
+CONSTCD11 year_month_day operator/(const month_day& md, const year& y) NOEXCEPT;
+CONSTCD11 year_month_day operator/(const month_day& md, int y) NOEXCEPT;
+
+CONSTCD11
+ year_month_day_last operator/(const year_month& ym, last_spec) NOEXCEPT;
+CONSTCD11
+ year_month_day_last operator/(const year& y, const month_day_last& mdl) NOEXCEPT;
+CONSTCD11
+ year_month_day_last operator/(int y, const month_day_last& mdl) NOEXCEPT;
+CONSTCD11
+ year_month_day_last operator/(const month_day_last& mdl, const year& y) NOEXCEPT;
+CONSTCD11
+ year_month_day_last operator/(const month_day_last& mdl, int y) NOEXCEPT;
+
+CONSTCD11
+year_month_weekday
+operator/(const year_month& ym, const weekday_indexed& wdi) NOEXCEPT;
+
+CONSTCD11
+year_month_weekday
+operator/(const year& y, const month_weekday& mwd) NOEXCEPT;
+
+CONSTCD11
+year_month_weekday
+operator/(int y, const month_weekday& mwd) NOEXCEPT;
+
+CONSTCD11
+year_month_weekday
+operator/(const month_weekday& mwd, const year& y) NOEXCEPT;
+
+CONSTCD11
+year_month_weekday
+operator/(const month_weekday& mwd, int y) NOEXCEPT;
+
+CONSTCD11
+year_month_weekday_last
+operator/(const year_month& ym, const weekday_last& wdl) NOEXCEPT;
+
+CONSTCD11
+year_month_weekday_last
+operator/(const year& y, const month_weekday_last& mwdl) NOEXCEPT;
+
+CONSTCD11
+year_month_weekday_last
+operator/(int y, const month_weekday_last& mwdl) NOEXCEPT;
+
+CONSTCD11
+year_month_weekday_last
+operator/(const month_weekday_last& mwdl, const year& y) NOEXCEPT;
+
+CONSTCD11
+year_month_weekday_last
+operator/(const month_weekday_last& mwdl, int y) NOEXCEPT;
+
+// Detailed interface
+
+// day
+
+class day
+{
+ unsigned char d_;
+
+public:
+ day() = default;
+ explicit CONSTCD11 day(unsigned d) NOEXCEPT;
+
+ CONSTCD14 day& operator++() NOEXCEPT;
+ CONSTCD14 day operator++(int) NOEXCEPT;
+ CONSTCD14 day& operator--() NOEXCEPT;
+ CONSTCD14 day operator--(int) NOEXCEPT;
+
+ CONSTCD14 day& operator+=(const days& d) NOEXCEPT;
+ CONSTCD14 day& operator-=(const days& d) NOEXCEPT;
+
+ CONSTCD11 explicit operator unsigned() const NOEXCEPT;
+ CONSTCD11 bool ok() const NOEXCEPT;
+};
+
+CONSTCD11 bool operator==(const day& x, const day& y) NOEXCEPT;
+CONSTCD11 bool operator!=(const day& x, const day& y) NOEXCEPT;
+CONSTCD11 bool operator< (const day& x, const day& y) NOEXCEPT;
+CONSTCD11 bool operator> (const day& x, const day& y) NOEXCEPT;
+CONSTCD11 bool operator<=(const day& x, const day& y) NOEXCEPT;
+CONSTCD11 bool operator>=(const day& x, const day& y) NOEXCEPT;
+
+CONSTCD11 day operator+(const day& x, const days& y) NOEXCEPT;
+CONSTCD11 day operator+(const days& x, const day& y) NOEXCEPT;
+CONSTCD11 day operator-(const day& x, const days& y) NOEXCEPT;
+CONSTCD11 days operator-(const day& x, const day& y) NOEXCEPT;
+
+template<class CharT, class Traits>
+std::basic_ostream<CharT, Traits>&
+operator<<(std::basic_ostream<CharT, Traits>& os, const day& d);
+
+// month
+
+class month
+{
+ unsigned char m_;
+
+public:
+ month() = default;
+ explicit CONSTCD11 month(unsigned m) NOEXCEPT;
+
+ CONSTCD14 month& operator++() NOEXCEPT;
+ CONSTCD14 month operator++(int) NOEXCEPT;
+ CONSTCD14 month& operator--() NOEXCEPT;
+ CONSTCD14 month operator--(int) NOEXCEPT;
+
+ CONSTCD14 month& operator+=(const months& m) NOEXCEPT;
+ CONSTCD14 month& operator-=(const months& m) NOEXCEPT;
+
+ CONSTCD11 explicit operator unsigned() const NOEXCEPT;
+ CONSTCD11 bool ok() const NOEXCEPT;
+};
+
+CONSTCD11 bool operator==(const month& x, const month& y) NOEXCEPT;
+CONSTCD11 bool operator!=(const month& x, const month& y) NOEXCEPT;
+CONSTCD11 bool operator< (const month& x, const month& y) NOEXCEPT;
+CONSTCD11 bool operator> (const month& x, const month& y) NOEXCEPT;
+CONSTCD11 bool operator<=(const month& x, const month& y) NOEXCEPT;
+CONSTCD11 bool operator>=(const month& x, const month& y) NOEXCEPT;
+
+CONSTCD14 month operator+(const month& x, const months& y) NOEXCEPT;
+CONSTCD14 month operator+(const months& x, const month& y) NOEXCEPT;
+CONSTCD14 month operator-(const month& x, const months& y) NOEXCEPT;
+CONSTCD14 months operator-(const month& x, const month& y) NOEXCEPT;
+
+template<class CharT, class Traits>
+std::basic_ostream<CharT, Traits>&
+operator<<(std::basic_ostream<CharT, Traits>& os, const month& m);
+
+// year
+
+class year
+{
+ short y_;
+
+public:
+ year() = default;
+ explicit CONSTCD11 year(int y) NOEXCEPT;
+
+ CONSTCD14 year& operator++() NOEXCEPT;
+ CONSTCD14 year operator++(int) NOEXCEPT;
+ CONSTCD14 year& operator--() NOEXCEPT;
+ CONSTCD14 year operator--(int) NOEXCEPT;
+
+ CONSTCD14 year& operator+=(const years& y) NOEXCEPT;
+ CONSTCD14 year& operator-=(const years& y) NOEXCEPT;
+
+ CONSTCD11 year operator-() const NOEXCEPT;
+ CONSTCD11 year operator+() const NOEXCEPT;
+
+ CONSTCD11 bool is_leap() const NOEXCEPT;
+
+ CONSTCD11 explicit operator int() const NOEXCEPT;
+ CONSTCD11 bool ok() const NOEXCEPT;
+
+ static CONSTCD11 year min() NOEXCEPT;
+ static CONSTCD11 year max() NOEXCEPT;
+};
+
+CONSTCD11 bool operator==(const year& x, const year& y) NOEXCEPT;
+CONSTCD11 bool operator!=(const year& x, const year& y) NOEXCEPT;
+CONSTCD11 bool operator< (const year& x, const year& y) NOEXCEPT;
+CONSTCD11 bool operator> (const year& x, const year& y) NOEXCEPT;
+CONSTCD11 bool operator<=(const year& x, const year& y) NOEXCEPT;
+CONSTCD11 bool operator>=(const year& x, const year& y) NOEXCEPT;
+
+CONSTCD11 year operator+(const year& x, const years& y) NOEXCEPT;
+CONSTCD11 year operator+(const years& x, const year& y) NOEXCEPT;
+CONSTCD11 year operator-(const year& x, const years& y) NOEXCEPT;
+CONSTCD11 years operator-(const year& x, const year& y) NOEXCEPT;
+
+template<class CharT, class Traits>
+std::basic_ostream<CharT, Traits>&
+operator<<(std::basic_ostream<CharT, Traits>& os, const year& y);
+
+// weekday
+
+class weekday
+{
+ unsigned char wd_;
+public:
+ weekday() = default;
+ explicit CONSTCD11 weekday(unsigned wd) NOEXCEPT;
+ CONSTCD11 weekday(const sys_days& dp) NOEXCEPT;
+ CONSTCD11 explicit weekday(const local_days& dp) NOEXCEPT;
+
+ CONSTCD14 weekday& operator++() NOEXCEPT;
+ CONSTCD14 weekday operator++(int) NOEXCEPT;
+ CONSTCD14 weekday& operator--() NOEXCEPT;
+ CONSTCD14 weekday operator--(int) NOEXCEPT;
+
+ CONSTCD14 weekday& operator+=(const days& d) NOEXCEPT;
+ CONSTCD14 weekday& operator-=(const days& d) NOEXCEPT;
+
+ CONSTCD11 explicit operator unsigned() const NOEXCEPT;
+ CONSTCD11 bool ok() const NOEXCEPT;
+
+ CONSTCD11 weekday_indexed operator[](unsigned index) const NOEXCEPT;
+ CONSTCD11 weekday_last operator[](last_spec) const NOEXCEPT;
+
+private:
+ static CONSTCD11 unsigned char weekday_from_days(int z) NOEXCEPT;
+};
+
+CONSTCD11 bool operator==(const weekday& x, const weekday& y) NOEXCEPT;
+CONSTCD11 bool operator!=(const weekday& x, const weekday& y) NOEXCEPT;
+
+CONSTCD14 weekday operator+(const weekday& x, const days& y) NOEXCEPT;
+CONSTCD14 weekday operator+(const days& x, const weekday& y) NOEXCEPT;
+CONSTCD14 weekday operator-(const weekday& x, const days& y) NOEXCEPT;
+CONSTCD14 days operator-(const weekday& x, const weekday& y) NOEXCEPT;
+
+template<class CharT, class Traits>
+std::basic_ostream<CharT, Traits>&
+operator<<(std::basic_ostream<CharT, Traits>& os, const weekday& wd);
+
+// weekday_indexed
+
+class weekday_indexed
+{
+ unsigned char wd_ : 4;
+ unsigned char index_ : 4;
+
+public:
+ weekday_indexed() = default;
+ CONSTCD11 weekday_indexed(const date::weekday& wd, unsigned index) NOEXCEPT;
+
+ CONSTCD11 date::weekday weekday() const NOEXCEPT;
+ CONSTCD11 unsigned index() const NOEXCEPT;
+ CONSTCD11 bool ok() const NOEXCEPT;
+};
+
+CONSTCD11 bool operator==(const weekday_indexed& x, const weekday_indexed& y) NOEXCEPT;
+CONSTCD11 bool operator!=(const weekday_indexed& x, const weekday_indexed& y) NOEXCEPT;
+
+template<class CharT, class Traits>
+std::basic_ostream<CharT, Traits>&
+operator<<(std::basic_ostream<CharT, Traits>& os, const weekday_indexed& wdi);
+
+// weekday_last
+
+class weekday_last
+{
+ date::weekday wd_;
+
+public:
+ explicit CONSTCD11 weekday_last(const date::weekday& wd) NOEXCEPT;
+
+ CONSTCD11 date::weekday weekday() const NOEXCEPT;
+ CONSTCD11 bool ok() const NOEXCEPT;
+};
+
+CONSTCD11 bool operator==(const weekday_last& x, const weekday_last& y) NOEXCEPT;
+CONSTCD11 bool operator!=(const weekday_last& x, const weekday_last& y) NOEXCEPT;
+
+template<class CharT, class Traits>
+std::basic_ostream<CharT, Traits>&
+operator<<(std::basic_ostream<CharT, Traits>& os, const weekday_last& wdl);
+
+// year_month
+
+class year_month
+{
+ date::year y_;
+ date::month m_;
+
+public:
+ year_month() = default;
+ CONSTCD11 year_month(const date::year& y, const date::month& m) NOEXCEPT;
+
+ CONSTCD11 date::year year() const NOEXCEPT;
+ CONSTCD11 date::month month() const NOEXCEPT;
+
+ CONSTCD14 year_month& operator+=(const months& dm) NOEXCEPT;
+ CONSTCD14 year_month& operator-=(const months& dm) NOEXCEPT;
+ CONSTCD14 year_month& operator+=(const years& dy) NOEXCEPT;
+ CONSTCD14 year_month& operator-=(const years& dy) NOEXCEPT;
+
+ CONSTCD11 bool ok() const NOEXCEPT;
+};
+
+CONSTCD11 bool operator==(const year_month& x, const year_month& y) NOEXCEPT;
+CONSTCD11 bool operator!=(const year_month& x, const year_month& y) NOEXCEPT;
+CONSTCD11 bool operator< (const year_month& x, const year_month& y) NOEXCEPT;
+CONSTCD11 bool operator> (const year_month& x, const year_month& y) NOEXCEPT;
+CONSTCD11 bool operator<=(const year_month& x, const year_month& y) NOEXCEPT;
+CONSTCD11 bool operator>=(const year_month& x, const year_month& y) NOEXCEPT;
+
+CONSTCD14 year_month operator+(const year_month& ym, const months& dm) NOEXCEPT;
+CONSTCD14 year_month operator+(const months& dm, const year_month& ym) NOEXCEPT;
+CONSTCD14 year_month operator-(const year_month& ym, const months& dm) NOEXCEPT;
+
+CONSTCD11 months operator-(const year_month& x, const year_month& y) NOEXCEPT;
+CONSTCD11 year_month operator+(const year_month& ym, const years& dy) NOEXCEPT;
+CONSTCD11 year_month operator+(const years& dy, const year_month& ym) NOEXCEPT;
+CONSTCD11 year_month operator-(const year_month& ym, const years& dy) NOEXCEPT;
+
+template<class CharT, class Traits>
+std::basic_ostream<CharT, Traits>&
+operator<<(std::basic_ostream<CharT, Traits>& os, const year_month& ym);
+
+// month_day
+
+class month_day
+{
+ date::month m_;
+ date::day d_;
+
+public:
+ month_day() = default;
+ CONSTCD11 month_day(const date::month& m, const date::day& d) NOEXCEPT;
+
+ CONSTCD11 date::month month() const NOEXCEPT;
+ CONSTCD11 date::day day() const NOEXCEPT;
+
+ CONSTCD14 bool ok() const NOEXCEPT;
+};
+
+CONSTCD11 bool operator==(const month_day& x, const month_day& y) NOEXCEPT;
+CONSTCD11 bool operator!=(const month_day& x, const month_day& y) NOEXCEPT;
+CONSTCD11 bool operator< (const month_day& x, const month_day& y) NOEXCEPT;
+CONSTCD11 bool operator> (const month_day& x, const month_day& y) NOEXCEPT;
+CONSTCD11 bool operator<=(const month_day& x, const month_day& y) NOEXCEPT;
+CONSTCD11 bool operator>=(const month_day& x, const month_day& y) NOEXCEPT;
+
+template<class CharT, class Traits>
+std::basic_ostream<CharT, Traits>&
+operator<<(std::basic_ostream<CharT, Traits>& os, const month_day& md);
+
+// month_day_last
+
+class month_day_last
+{
+ date::month m_;
+
+public:
+ CONSTCD11 explicit month_day_last(const date::month& m) NOEXCEPT;
+
+ CONSTCD11 date::month month() const NOEXCEPT;
+ CONSTCD11 bool ok() const NOEXCEPT;
+};
+
+CONSTCD11 bool operator==(const month_day_last& x, const month_day_last& y) NOEXCEPT;
+CONSTCD11 bool operator!=(const month_day_last& x, const month_day_last& y) NOEXCEPT;
+CONSTCD11 bool operator< (const month_day_last& x, const month_day_last& y) NOEXCEPT;
+CONSTCD11 bool operator> (const month_day_last& x, const month_day_last& y) NOEXCEPT;
+CONSTCD11 bool operator<=(const month_day_last& x, const month_day_last& y) NOEXCEPT;
+CONSTCD11 bool operator>=(const month_day_last& x, const month_day_last& y) NOEXCEPT;
+
+template<class CharT, class Traits>
+std::basic_ostream<CharT, Traits>&
+operator<<(std::basic_ostream<CharT, Traits>& os, const month_day_last& mdl);
+
+// month_weekday
+
+class month_weekday
+{
+ date::month m_;
+ date::weekday_indexed wdi_;
+public:
+ CONSTCD11 month_weekday(const date::month& m,
+ const date::weekday_indexed& wdi) NOEXCEPT;
+
+ CONSTCD11 date::month month() const NOEXCEPT;
+ CONSTCD11 date::weekday_indexed weekday_indexed() const NOEXCEPT;
+
+ CONSTCD11 bool ok() const NOEXCEPT;
+};
+
+CONSTCD11 bool operator==(const month_weekday& x, const month_weekday& y) NOEXCEPT;
+CONSTCD11 bool operator!=(const month_weekday& x, const month_weekday& y) NOEXCEPT;
+
+template<class CharT, class Traits>
+std::basic_ostream<CharT, Traits>&
+operator<<(std::basic_ostream<CharT, Traits>& os, const month_weekday& mwd);
+
+// month_weekday_last
+
+class month_weekday_last
+{
+ date::month m_;
+ date::weekday_last wdl_;
+
+public:
+ CONSTCD11 month_weekday_last(const date::month& m,
+ const date::weekday_last& wd) NOEXCEPT;
+
+ CONSTCD11 date::month month() const NOEXCEPT;
+ CONSTCD11 date::weekday_last weekday_last() const NOEXCEPT;
+
+ CONSTCD11 bool ok() const NOEXCEPT;
+};
+
+CONSTCD11
+ bool operator==(const month_weekday_last& x, const month_weekday_last& y) NOEXCEPT;
+CONSTCD11
+ bool operator!=(const month_weekday_last& x, const month_weekday_last& y) NOEXCEPT;
+
+template<class CharT, class Traits>
+std::basic_ostream<CharT, Traits>&
+operator<<(std::basic_ostream<CharT, Traits>& os, const month_weekday_last& mwdl);
+
+// class year_month_day
+
+class year_month_day
+{
+ date::year y_;
+ date::month m_;
+ date::day d_;
+
+public:
+ year_month_day() = default;
+ CONSTCD11 year_month_day(const date::year& y, const date::month& m,
+ const date::day& d) NOEXCEPT;
+ CONSTCD14 year_month_day(const year_month_day_last& ymdl) NOEXCEPT;
+
+ CONSTCD14 year_month_day(sys_days dp) NOEXCEPT;
+ CONSTCD14 explicit year_month_day(local_days dp) NOEXCEPT;
+
+ CONSTCD14 year_month_day& operator+=(const months& m) NOEXCEPT;
+ CONSTCD14 year_month_day& operator-=(const months& m) NOEXCEPT;
+ CONSTCD14 year_month_day& operator+=(const years& y) NOEXCEPT;
+ CONSTCD14 year_month_day& operator-=(const years& y) NOEXCEPT;
+
+ CONSTCD11 date::year year() const NOEXCEPT;
+ CONSTCD11 date::month month() const NOEXCEPT;
+ CONSTCD11 date::day day() const NOEXCEPT;
+
+ CONSTCD14 operator sys_days() const NOEXCEPT;
+ CONSTCD14 explicit operator local_days() const NOEXCEPT;
+ CONSTCD14 bool ok() const NOEXCEPT;
+
+private:
+ static CONSTCD14 year_month_day from_days(days dp) NOEXCEPT;
+ CONSTCD14 days to_days() const NOEXCEPT;
+};
+
+CONSTCD11 bool operator==(const year_month_day& x, const year_month_day& y) NOEXCEPT;
+CONSTCD11 bool operator!=(const year_month_day& x, const year_month_day& y) NOEXCEPT;
+CONSTCD11 bool operator< (const year_month_day& x, const year_month_day& y) NOEXCEPT;
+CONSTCD11 bool operator> (const year_month_day& x, const year_month_day& y) NOEXCEPT;
+CONSTCD11 bool operator<=(const year_month_day& x, const year_month_day& y) NOEXCEPT;
+CONSTCD11 bool operator>=(const year_month_day& x, const year_month_day& y) NOEXCEPT;
+
+CONSTCD14 year_month_day operator+(const year_month_day& ymd, const months& dm) NOEXCEPT;
+CONSTCD14 year_month_day operator+(const months& dm, const year_month_day& ymd) NOEXCEPT;
+CONSTCD14 year_month_day operator-(const year_month_day& ymd, const months& dm) NOEXCEPT;
+CONSTCD11 year_month_day operator+(const year_month_day& ymd, const years& dy) NOEXCEPT;
+CONSTCD11 year_month_day operator+(const years& dy, const year_month_day& ymd) NOEXCEPT;
+CONSTCD11 year_month_day operator-(const year_month_day& ymd, const years& dy) NOEXCEPT;
+
+template<class CharT, class Traits>
+std::basic_ostream<CharT, Traits>&
+operator<<(std::basic_ostream<CharT, Traits>& os, const year_month_day& ymd);
+
+// year_month_day_last
+
+class year_month_day_last
+{
+ date::year y_;
+ date::month_day_last mdl_;
+
+public:
+ CONSTCD11 year_month_day_last(const date::year& y,
+ const date::month_day_last& mdl) NOEXCEPT;
+
+ CONSTCD14 year_month_day_last& operator+=(const months& m) NOEXCEPT;
+ CONSTCD14 year_month_day_last& operator-=(const months& m) NOEXCEPT;
+ CONSTCD14 year_month_day_last& operator+=(const years& y) NOEXCEPT;
+ CONSTCD14 year_month_day_last& operator-=(const years& y) NOEXCEPT;
+
+ CONSTCD11 date::year year() const NOEXCEPT;
+ CONSTCD11 date::month month() const NOEXCEPT;
+ CONSTCD11 date::month_day_last month_day_last() const NOEXCEPT;
+ CONSTCD14 date::day day() const NOEXCEPT;
+
+ CONSTCD14 operator sys_days() const NOEXCEPT;
+ CONSTCD14 explicit operator local_days() const NOEXCEPT;
+ CONSTCD11 bool ok() const NOEXCEPT;
+};
+
+CONSTCD11
+ bool operator==(const year_month_day_last& x, const year_month_day_last& y) NOEXCEPT;
+CONSTCD11
+ bool operator!=(const year_month_day_last& x, const year_month_day_last& y) NOEXCEPT;
+CONSTCD11
+ bool operator< (const year_month_day_last& x, const year_month_day_last& y) NOEXCEPT;
+CONSTCD11
+ bool operator> (const year_month_day_last& x, const year_month_day_last& y) NOEXCEPT;
+CONSTCD11
+ bool operator<=(const year_month_day_last& x, const year_month_day_last& y) NOEXCEPT;
+CONSTCD11
+ bool operator>=(const year_month_day_last& x, const year_month_day_last& y) NOEXCEPT;
+
+CONSTCD14
+year_month_day_last
+operator+(const year_month_day_last& ymdl, const months& dm) NOEXCEPT;
+
+CONSTCD14
+year_month_day_last
+operator+(const months& dm, const year_month_day_last& ymdl) NOEXCEPT;
+
+CONSTCD11
+year_month_day_last
+operator+(const year_month_day_last& ymdl, const years& dy) NOEXCEPT;
+
+CONSTCD11
+year_month_day_last
+operator+(const years& dy, const year_month_day_last& ymdl) NOEXCEPT;
+
+CONSTCD14
+year_month_day_last
+operator-(const year_month_day_last& ymdl, const months& dm) NOEXCEPT;
+
+CONSTCD11
+year_month_day_last
+operator-(const year_month_day_last& ymdl, const years& dy) NOEXCEPT;
+
+template<class CharT, class Traits>
+std::basic_ostream<CharT, Traits>&
+operator<<(std::basic_ostream<CharT, Traits>& os, const year_month_day_last& ymdl);
+
+// year_month_weekday
+
+class year_month_weekday
+{
+ date::year y_;
+ date::month m_;
+ date::weekday_indexed wdi_;
+
+public:
+ year_month_weekday() = default;
+ CONSTCD11 year_month_weekday(const date::year& y, const date::month& m,
+ const date::weekday_indexed& wdi) NOEXCEPT;
+ CONSTCD14 year_month_weekday(const sys_days& dp) NOEXCEPT;
+ CONSTCD14 explicit year_month_weekday(const local_days& dp) NOEXCEPT;
+
+ CONSTCD14 year_month_weekday& operator+=(const months& m) NOEXCEPT;
+ CONSTCD14 year_month_weekday& operator-=(const months& m) NOEXCEPT;
+ CONSTCD14 year_month_weekday& operator+=(const years& y) NOEXCEPT;
+ CONSTCD14 year_month_weekday& operator-=(const years& y) NOEXCEPT;
+
+ CONSTCD11 date::year year() const NOEXCEPT;
+ CONSTCD11 date::month month() const NOEXCEPT;
+ CONSTCD11 date::weekday weekday() const NOEXCEPT;
+ CONSTCD11 unsigned index() const NOEXCEPT;
+ CONSTCD11 date::weekday_indexed weekday_indexed() const NOEXCEPT;
+
+ CONSTCD14 operator sys_days() const NOEXCEPT;
+ CONSTCD14 explicit operator local_days() const NOEXCEPT;
+ CONSTCD14 bool ok() const NOEXCEPT;
+
+private:
+ static CONSTCD14 year_month_weekday from_days(days dp) NOEXCEPT;
+ CONSTCD14 days to_days() const NOEXCEPT;
+};
+
+CONSTCD11
+ bool operator==(const year_month_weekday& x, const year_month_weekday& y) NOEXCEPT;
+CONSTCD11
+ bool operator!=(const year_month_weekday& x, const year_month_weekday& y) NOEXCEPT;
+
+CONSTCD14
+year_month_weekday
+operator+(const year_month_weekday& ymwd, const months& dm) NOEXCEPT;
+
+CONSTCD14
+year_month_weekday
+operator+(const months& dm, const year_month_weekday& ymwd) NOEXCEPT;
+
+CONSTCD11
+year_month_weekday
+operator+(const year_month_weekday& ymwd, const years& dy) NOEXCEPT;
+
+CONSTCD11
+year_month_weekday
+operator+(const years& dy, const year_month_weekday& ymwd) NOEXCEPT;
+
+CONSTCD14
+year_month_weekday
+operator-(const year_month_weekday& ymwd, const months& dm) NOEXCEPT;
+
+CONSTCD11
+year_month_weekday
+operator-(const year_month_weekday& ymwd, const years& dy) NOEXCEPT;
+
+template<class CharT, class Traits>
+std::basic_ostream<CharT, Traits>&
+operator<<(std::basic_ostream<CharT, Traits>& os, const year_month_weekday& ymwdi);
+
+// year_month_weekday_last
+
+class year_month_weekday_last
+{
+ date::year y_;
+ date::month m_;
+ date::weekday_last wdl_;
+
+public:
+ CONSTCD11 year_month_weekday_last(const date::year& y, const date::month& m,
+ const date::weekday_last& wdl) NOEXCEPT;
+
+ CONSTCD14 year_month_weekday_last& operator+=(const months& m) NOEXCEPT;
+ CONSTCD14 year_month_weekday_last& operator-=(const months& m) NOEXCEPT;
+ CONSTCD14 year_month_weekday_last& operator+=(const years& y) NOEXCEPT;
+ CONSTCD14 year_month_weekday_last& operator-=(const years& y) NOEXCEPT;
+
+ CONSTCD11 date::year year() const NOEXCEPT;
+ CONSTCD11 date::month month() const NOEXCEPT;
+ CONSTCD11 date::weekday weekday() const NOEXCEPT;
+ CONSTCD11 date::weekday_last weekday_last() const NOEXCEPT;
+
+ CONSTCD14 operator sys_days() const NOEXCEPT;
+ CONSTCD14 explicit operator local_days() const NOEXCEPT;
+ CONSTCD11 bool ok() const NOEXCEPT;
+
+private:
+ CONSTCD14 days to_days() const NOEXCEPT;
+};
+
+CONSTCD11
+bool
+operator==(const year_month_weekday_last& x, const year_month_weekday_last& y) NOEXCEPT;
+
+CONSTCD11
+bool
+operator!=(const year_month_weekday_last& x, const year_month_weekday_last& y) NOEXCEPT;
+
+CONSTCD14
+year_month_weekday_last
+operator+(const year_month_weekday_last& ymwdl, const months& dm) NOEXCEPT;
+
+CONSTCD14
+year_month_weekday_last
+operator+(const months& dm, const year_month_weekday_last& ymwdl) NOEXCEPT;
+
+CONSTCD11
+year_month_weekday_last
+operator+(const year_month_weekday_last& ymwdl, const years& dy) NOEXCEPT;
+
+CONSTCD11
+year_month_weekday_last
+operator+(const years& dy, const year_month_weekday_last& ymwdl) NOEXCEPT;
+
+CONSTCD14
+year_month_weekday_last
+operator-(const year_month_weekday_last& ymwdl, const months& dm) NOEXCEPT;
+
+CONSTCD11
+year_month_weekday_last
+operator-(const year_month_weekday_last& ymwdl, const years& dy) NOEXCEPT;
+
+template<class CharT, class Traits>
+std::basic_ostream<CharT, Traits>&
+operator<<(std::basic_ostream<CharT, Traits>& os, const year_month_weekday_last& ymwdl);
+
+#if !defined(_MSC_VER) || (_MSC_VER >= 1900)
+inline namespace literals
+{
+
+CONSTCD11 date::day operator "" _d(unsigned long long d) NOEXCEPT;
+CONSTCD11 date::year operator "" _y(unsigned long long y) NOEXCEPT;
+
+// CONSTDATA date::month jan{1};
+// CONSTDATA date::month feb{2};
+// CONSTDATA date::month mar{3};
+// CONSTDATA date::month apr{4};
+// CONSTDATA date::month may{5};
+// CONSTDATA date::month jun{6};
+// CONSTDATA date::month jul{7};
+// CONSTDATA date::month aug{8};
+// CONSTDATA date::month sep{9};
+// CONSTDATA date::month oct{10};
+// CONSTDATA date::month nov{11};
+// CONSTDATA date::month dec{12};
+//
+// CONSTDATA date::weekday sun{0u};
+// CONSTDATA date::weekday mon{1u};
+// CONSTDATA date::weekday tue{2u};
+// CONSTDATA date::weekday wed{3u};
+// CONSTDATA date::weekday thu{4u};
+// CONSTDATA date::weekday fri{5u};
+// CONSTDATA date::weekday sat{6u};
+
+} // inline namespace literals
+#endif // !defined(_MSC_VER) || (_MSC_VER >= 1900)
+
+#if HAS_VOID_T
+
+template <class T, class = std::void_t<>>
+struct is_clock
+ : std::false_type
+{};
+
+template <class T>
+struct is_clock<T, std::void_t<decltype(T::now()), typename T::rep, typename T::period,
+ typename T::duration, typename T::time_point,
+ decltype(T::is_steady)>>
+ : std::true_type
+{};
+
+#endif // HAS_VOID_T
+
+//----------------+
+// Implementation |
+//----------------+
+
+// utilities
+namespace detail {
+
+template<class CharT, class Traits = std::char_traits<CharT>>
+class save_stream
+{
+ std::basic_ostream<CharT, Traits>& os_;
+ CharT fill_;
+ std::ios::fmtflags flags_;
+ std::locale loc_;
+
+public:
+ ~save_stream()
+ {
+ os_.fill(fill_);
+ os_.flags(flags_);
+ os_.imbue(loc_);
+ }
+
+ save_stream(const save_stream&) = delete;
+ save_stream& operator=(const save_stream&) = delete;
+
+ explicit save_stream(std::basic_ostream<CharT, Traits>& os)
+ : os_(os)
+ , fill_(os.fill())
+ , flags_(os.flags())
+ , loc_(os.getloc())
+ {}
+};
+
+template <class T>
+struct choose_trunc_type
+{
+ static const int digits = std::numeric_limits<T>::digits;
+ using type = typename std::conditional
+ <
+ digits < 32,
+ std::int32_t,
+ typename std::conditional
+ <
+ digits < 64,
+ std::int64_t,
+#ifdef __SIZEOF_INT128__
+ __int128
+#else
+ std::int64_t
+#endif
+ >::type
+ >::type;
+};
+
+template <class T>
+CONSTCD11
+inline
+typename std::enable_if
+<
+ !std::chrono::treat_as_floating_point<T>::value,
+ T
+>::type
+trunc(T t) NOEXCEPT
+{
+ return t;
+}
+
+template <class T>
+CONSTCD14
+inline
+typename std::enable_if
+<
+ std::chrono::treat_as_floating_point<T>::value,
+ T
+>::type
+trunc(T t) NOEXCEPT
+{
+ using namespace std;
+ using I = typename choose_trunc_type<T>::type;
+ CONSTDATA auto digits = numeric_limits<T>::digits;
+ static_assert(digits < numeric_limits<I>::digits, "");
+ CONSTDATA auto max = I{1} << (digits-1);
+ CONSTDATA auto min = -max;
+ const auto negative = t < T{0};
+ if (min <= t && t <= max && t != 0 && t == t)
+ {
+ t = static_cast<T>(static_cast<I>(t));
+ if (t == 0 && negative)
+ t = -t;
+ }
+ return t;
+}
+
+template <std::intmax_t Xp, std::intmax_t Yp>
+struct static_gcd
+{
+ static const std::intmax_t value = static_gcd<Yp, Xp % Yp>::value;
+};
+
+template <std::intmax_t Xp>
+struct static_gcd<Xp, 0>
+{
+ static const std::intmax_t value = Xp;
+};
+
+template <>
+struct static_gcd<0, 0>
+{
+ static const std::intmax_t value = 1;
+};
+
+template <class R1, class R2>
+struct no_overflow
+{
+private:
+ static const std::intmax_t gcd_n1_n2 = static_gcd<R1::num, R2::num>::value;
+ static const std::intmax_t gcd_d1_d2 = static_gcd<R1::den, R2::den>::value;
+ static const std::intmax_t n1 = R1::num / gcd_n1_n2;
+ static const std::intmax_t d1 = R1::den / gcd_d1_d2;
+ static const std::intmax_t n2 = R2::num / gcd_n1_n2;
+ static const std::intmax_t d2 = R2::den / gcd_d1_d2;
+ static const std::intmax_t max = -((std::intmax_t(1) <<
+ (sizeof(std::intmax_t) * CHAR_BIT - 1)) + 1);
+
+ template <std::intmax_t Xp, std::intmax_t Yp, bool overflow>
+ struct mul // overflow == false
+ {
+ static const std::intmax_t value = Xp * Yp;
+ };
+
+ template <std::intmax_t Xp, std::intmax_t Yp>
+ struct mul<Xp, Yp, true>
+ {
+ static const std::intmax_t value = 1;
+ };
+
+public:
+ static const bool value = (n1 <= max / d2) && (n2 <= max / d1);
+ typedef std::ratio<mul<n1, d2, !value>::value,
+ mul<n2, d1, !value>::value> type;
+};
+
+} // detail
+
+// trunc towards zero
+template <class To, class Rep, class Period>
+CONSTCD11
+inline
+typename std::enable_if
+<
+ detail::no_overflow<Period, typename To::period>::value,
+ To
+>::type
+trunc(const std::chrono::duration<Rep, Period>& d)
+{
+ return To{detail::trunc(std::chrono::duration_cast<To>(d).count())};
+}
+
+template <class To, class Rep, class Period>
+CONSTCD11
+inline
+typename std::enable_if
+<
+ !detail::no_overflow<Period, typename To::period>::value,
+ To
+>::type
+trunc(const std::chrono::duration<Rep, Period>& d)
+{
+ using namespace std::chrono;
+ using rep = typename std::common_type<Rep, typename To::rep>::type;
+ return To{detail::trunc(duration_cast<To>(duration_cast<duration<rep>>(d)).count())};
+}
+
+#ifndef HAS_CHRONO_ROUNDING
+# if defined(_MSC_FULL_VER) && (_MSC_FULL_VER >= 190023918 || (_MSC_FULL_VER >= 190000000 && defined (__clang__)))
+# define HAS_CHRONO_ROUNDING 1
+# elif defined(__cpp_lib_chrono) && __cplusplus > 201402 && __cpp_lib_chrono >= 201510
+# define HAS_CHRONO_ROUNDING 1
+# elif defined(_LIBCPP_VERSION) && __cplusplus > 201402 && _LIBCPP_VERSION >= 3800
+# define HAS_CHRONO_ROUNDING 1
+# else
+# define HAS_CHRONO_ROUNDING 0
+# endif
+#endif // HAS_CHRONO_ROUNDING
+
+#if HAS_CHRONO_ROUNDING == 0
+
+// round down
+template <class To, class Rep, class Period>
+CONSTCD14
+inline
+typename std::enable_if
+<
+ detail::no_overflow<Period, typename To::period>::value,
+ To
+>::type
+floor(const std::chrono::duration<Rep, Period>& d)
+{
+ auto t = trunc<To>(d);
+ if (t > d)
+ return t - To{1};
+ return t;
+}
+
+template <class To, class Rep, class Period>
+CONSTCD14
+inline
+typename std::enable_if
+<
+ !detail::no_overflow<Period, typename To::period>::value,
+ To
+>::type
+floor(const std::chrono::duration<Rep, Period>& d)
+{
+ using namespace std::chrono;
+ using rep = typename std::common_type<Rep, typename To::rep>::type;
+ return floor<To>(floor<duration<rep>>(d));
+}
+
+// round to nearest, to even on tie
+template <class To, class Rep, class Period>
+CONSTCD14
+inline
+To
+round(const std::chrono::duration<Rep, Period>& d)
+{
+ auto t0 = floor<To>(d);
+ auto t1 = t0 + To{1};
+ if (t1 == To{0} && t0 < To{0})
+ t1 = -t1;
+ auto diff0 = d - t0;
+ auto diff1 = t1 - d;
+ if (diff0 == diff1)
+ {
+ if (t0 - trunc<To>(t0/2)*2 == To{0})
+ return t0;
+ return t1;
+ }
+ if (diff0 < diff1)
+ return t0;
+ return t1;
+}
+
+// round up
+template <class To, class Rep, class Period>
+CONSTCD14
+inline
+To
+ceil(const std::chrono::duration<Rep, Period>& d)
+{
+ auto t = trunc<To>(d);
+ if (t < d)
+ return t + To{1};
+ return t;
+}
+
+template <class Rep, class Period,
+ class = typename std::enable_if
+ <
+ std::numeric_limits<Rep>::is_signed
+ >::type>
+CONSTCD11
+std::chrono::duration<Rep, Period>
+abs(std::chrono::duration<Rep, Period> d)
+{
+ return d >= d.zero() ? d : -d;
+}
+
+// round down
+template <class To, class Clock, class FromDuration>
+CONSTCD11
+inline
+std::chrono::time_point<Clock, To>
+floor(const std::chrono::time_point<Clock, FromDuration>& tp)
+{
+ using std::chrono::time_point;
+ return time_point<Clock, To>{date::floor<To>(tp.time_since_epoch())};
+}
+
+// round to nearest, to even on tie
+template <class To, class Clock, class FromDuration>
+CONSTCD11
+inline
+std::chrono::time_point<Clock, To>
+round(const std::chrono::time_point<Clock, FromDuration>& tp)
+{
+ using std::chrono::time_point;
+ return time_point<Clock, To>{round<To>(tp.time_since_epoch())};
+}
+
+// round up
+template <class To, class Clock, class FromDuration>
+CONSTCD11
+inline
+std::chrono::time_point<Clock, To>
+ceil(const std::chrono::time_point<Clock, FromDuration>& tp)
+{
+ using std::chrono::time_point;
+ return time_point<Clock, To>{ceil<To>(tp.time_since_epoch())};
+}
+
+#else // HAS_CHRONO_ROUNDING == 1
+
+using std::chrono::floor;
+using std::chrono::ceil;
+using std::chrono::round;
+using std::chrono::abs;
+
+#endif // HAS_CHRONO_ROUNDING
+
+// trunc towards zero
+template <class To, class Clock, class FromDuration>
+CONSTCD11
+inline
+std::chrono::time_point<Clock, To>
+trunc(const std::chrono::time_point<Clock, FromDuration>& tp)
+{
+ using std::chrono::time_point;
+ return time_point<Clock, To>{trunc<To>(tp.time_since_epoch())};
+}
+
+// day
+
+CONSTCD11 inline day::day(unsigned d) NOEXCEPT : d_(static_cast<unsigned char>(d)) {}
+CONSTCD14 inline day& day::operator++() NOEXCEPT {++d_; return *this;}
+CONSTCD14 inline day day::operator++(int) NOEXCEPT {auto tmp(*this); ++(*this); return tmp;}
+CONSTCD14 inline day& day::operator--() NOEXCEPT {--d_; return *this;}
+CONSTCD14 inline day day::operator--(int) NOEXCEPT {auto tmp(*this); --(*this); return tmp;}
+CONSTCD14 inline day& day::operator+=(const days& d) NOEXCEPT {*this = *this + d; return *this;}
+CONSTCD14 inline day& day::operator-=(const days& d) NOEXCEPT {*this = *this - d; return *this;}
+CONSTCD11 inline day::operator unsigned() const NOEXCEPT {return d_;}
+CONSTCD11 inline bool day::ok() const NOEXCEPT {return 1 <= d_ && d_ <= 31;}
+
+CONSTCD11
+inline
+bool
+operator==(const day& x, const day& y) NOEXCEPT
+{
+ return static_cast<unsigned>(x) == static_cast<unsigned>(y);
+}
+
+CONSTCD11
+inline
+bool
+operator!=(const day& x, const day& y) NOEXCEPT
+{
+ return !(x == y);
+}
+
+CONSTCD11
+inline
+bool
+operator<(const day& x, const day& y) NOEXCEPT
+{
+ return static_cast<unsigned>(x) < static_cast<unsigned>(y);
+}
+
+CONSTCD11
+inline
+bool
+operator>(const day& x, const day& y) NOEXCEPT
+{
+ return y < x;
+}
+
+CONSTCD11
+inline
+bool
+operator<=(const day& x, const day& y) NOEXCEPT
+{
+ return !(y < x);
+}
+
+CONSTCD11
+inline
+bool
+operator>=(const day& x, const day& y) NOEXCEPT
+{
+ return !(x < y);
+}
+
+CONSTCD11
+inline
+days
+operator-(const day& x, const day& y) NOEXCEPT
+{
+ return days{static_cast<days::rep>(static_cast<unsigned>(x)
+ - static_cast<unsigned>(y))};
+}
+
+CONSTCD11
+inline
+day
+operator+(const day& x, const days& y) NOEXCEPT
+{
+ return day{static_cast<unsigned>(x) + static_cast<unsigned>(y.count())};
+}
+
+CONSTCD11
+inline
+day
+operator+(const days& x, const day& y) NOEXCEPT
+{
+ return y + x;
+}
+
+CONSTCD11
+inline
+day
+operator-(const day& x, const days& y) NOEXCEPT
+{
+ return x + -y;
+}
+
+template<class CharT, class Traits>
+inline
+std::basic_ostream<CharT, Traits>&
+operator<<(std::basic_ostream<CharT, Traits>& os, const day& d)
+{
+ detail::save_stream<CharT, Traits> _(os);
+ os.fill('0');
+ os.flags(std::ios::dec | std::ios::right);
+ os.width(2);
+ os << static_cast<unsigned>(d);
+ if (!d.ok())
+ os << " is not a valid day";
+ return os;
+}
+
+// month
+
+CONSTCD11 inline month::month(unsigned m) NOEXCEPT : m_(static_cast<decltype(m_)>(m)) {}
+CONSTCD14 inline month& month::operator++() NOEXCEPT {*this += months{1}; return *this;}
+CONSTCD14 inline month month::operator++(int) NOEXCEPT {auto tmp(*this); ++(*this); return tmp;}
+CONSTCD14 inline month& month::operator--() NOEXCEPT {*this -= months{1}; return *this;}
+CONSTCD14 inline month month::operator--(int) NOEXCEPT {auto tmp(*this); --(*this); return tmp;}
+
+CONSTCD14
+inline
+month&
+month::operator+=(const months& m) NOEXCEPT
+{
+ *this = *this + m;
+ return *this;
+}
+
+CONSTCD14
+inline
+month&
+month::operator-=(const months& m) NOEXCEPT
+{
+ *this = *this - m;
+ return *this;
+}
+
+CONSTCD11 inline month::operator unsigned() const NOEXCEPT {return m_;}
+CONSTCD11 inline bool month::ok() const NOEXCEPT {return 1 <= m_ && m_ <= 12;}
+
+CONSTCD11
+inline
+bool
+operator==(const month& x, const month& y) NOEXCEPT
+{
+ return static_cast<unsigned>(x) == static_cast<unsigned>(y);
+}
+
+CONSTCD11
+inline
+bool
+operator!=(const month& x, const month& y) NOEXCEPT
+{
+ return !(x == y);
+}
+
+CONSTCD11
+inline
+bool
+operator<(const month& x, const month& y) NOEXCEPT
+{
+ return static_cast<unsigned>(x) < static_cast<unsigned>(y);
+}
+
+CONSTCD11
+inline
+bool
+operator>(const month& x, const month& y) NOEXCEPT
+{
+ return y < x;
+}
+
+CONSTCD11
+inline
+bool
+operator<=(const month& x, const month& y) NOEXCEPT
+{
+ return !(y < x);
+}
+
+CONSTCD11
+inline
+bool
+operator>=(const month& x, const month& y) NOEXCEPT
+{
+ return !(x < y);
+}
+
+CONSTCD14
+inline
+months
+operator-(const month& x, const month& y) NOEXCEPT
+{
+ auto const d = static_cast<unsigned>(x) - static_cast<unsigned>(y);
+ return months(d <= 11 ? d : d + 12);
+}
+
+CONSTCD14
+inline
+month
+operator+(const month& x, const months& y) NOEXCEPT
+{
+ auto const mu = static_cast<long long>(static_cast<unsigned>(x)) + (y.count() - 1);
+ auto const yr = (mu >= 0 ? mu : mu-11) / 12;
+ return month{static_cast<unsigned>(mu - yr * 12 + 1)};
+}
+
+CONSTCD14
+inline
+month
+operator+(const months& x, const month& y) NOEXCEPT
+{
+ return y + x;
+}
+
+CONSTCD14
+inline
+month
+operator-(const month& x, const months& y) NOEXCEPT
+{
+ return x + -y;
+}
+
+template<class CharT, class Traits>
+inline
+std::basic_ostream<CharT, Traits>&
+operator<<(std::basic_ostream<CharT, Traits>& os, const month& m)
+{
+ if (m.ok())
+ {
+ CharT fmt[] = {'%', 'b', 0};
+ os << format(os.getloc(), fmt, m);
+ }
+ else
+ os << static_cast<unsigned>(m) << " is not a valid month";
+ return os;
+}
+
+// year
+
+CONSTCD11 inline year::year(int y) NOEXCEPT : y_(static_cast<decltype(y_)>(y)) {}
+CONSTCD14 inline year& year::operator++() NOEXCEPT {++y_; return *this;}
+CONSTCD14 inline year year::operator++(int) NOEXCEPT {auto tmp(*this); ++(*this); return tmp;}
+CONSTCD14 inline year& year::operator--() NOEXCEPT {--y_; return *this;}
+CONSTCD14 inline year year::operator--(int) NOEXCEPT {auto tmp(*this); --(*this); return tmp;}
+CONSTCD14 inline year& year::operator+=(const years& y) NOEXCEPT {*this = *this + y; return *this;}
+CONSTCD14 inline year& year::operator-=(const years& y) NOEXCEPT {*this = *this - y; return *this;}
+CONSTCD11 inline year year::operator-() const NOEXCEPT {return year{-y_};}
+CONSTCD11 inline year year::operator+() const NOEXCEPT {return *this;}
+
+CONSTCD11
+inline
+bool
+year::is_leap() const NOEXCEPT
+{
+ return y_ % 4 == 0 && (y_ % 100 != 0 || y_ % 400 == 0);
+}
+
+CONSTCD11 inline year::operator int() const NOEXCEPT {return y_;}
+
+CONSTCD11
+inline
+bool
+year::ok() const NOEXCEPT
+{
+ return y_ != std::numeric_limits<short>::min();
+}
+
+CONSTCD11
+inline
+year
+year::min() NOEXCEPT
+{
+ return year{-32767};
+}
+
+CONSTCD11
+inline
+year
+year::max() NOEXCEPT
+{
+ return year{32767};
+}
+
+CONSTCD11
+inline
+bool
+operator==(const year& x, const year& y) NOEXCEPT
+{
+ return static_cast<int>(x) == static_cast<int>(y);
+}
+
+CONSTCD11
+inline
+bool
+operator!=(const year& x, const year& y) NOEXCEPT
+{
+ return !(x == y);
+}
+
+CONSTCD11
+inline
+bool
+operator<(const year& x, const year& y) NOEXCEPT
+{
+ return static_cast<int>(x) < static_cast<int>(y);
+}
+
+CONSTCD11
+inline
+bool
+operator>(const year& x, const year& y) NOEXCEPT
+{
+ return y < x;
+}
+
+CONSTCD11
+inline
+bool
+operator<=(const year& x, const year& y) NOEXCEPT
+{
+ return !(y < x);
+}
+
+CONSTCD11
+inline
+bool
+operator>=(const year& x, const year& y) NOEXCEPT
+{
+ return !(x < y);
+}
+
+CONSTCD11
+inline
+years
+operator-(const year& x, const year& y) NOEXCEPT
+{
+ return years{static_cast<int>(x) - static_cast<int>(y)};
+}
+
+CONSTCD11
+inline
+year
+operator+(const year& x, const years& y) NOEXCEPT
+{
+ return year{static_cast<int>(x) + y.count()};
+}
+
+CONSTCD11
+inline
+year
+operator+(const years& x, const year& y) NOEXCEPT
+{
+ return y + x;
+}
+
+CONSTCD11
+inline
+year
+operator-(const year& x, const years& y) NOEXCEPT
+{
+ return year{static_cast<int>(x) - y.count()};
+}
+
+template<class CharT, class Traits>
+inline
+std::basic_ostream<CharT, Traits>&
+operator<<(std::basic_ostream<CharT, Traits>& os, const year& y)
+{
+ detail::save_stream<CharT, Traits> _(os);
+ os.fill('0');
+ os.flags(std::ios::dec | std::ios::internal);
+ os.width(4 + (y < year{0}));
+ os << static_cast<int>(y);
+ if (!y.ok())
+ os << " is not a valid year";
+ return os;
+}
+
+// weekday
+
+CONSTCD11
+inline
+unsigned char
+weekday::weekday_from_days(int z) NOEXCEPT
+{
+ return static_cast<unsigned char>(static_cast<unsigned>(
+ z >= -4 ? (z+4) % 7 : (z+5) % 7 + 6));
+}
+
+CONSTCD11
+inline
+weekday::weekday(unsigned wd) NOEXCEPT
+ : wd_(static_cast<decltype(wd_)>(wd))
+ {}
+
+CONSTCD11
+inline
+weekday::weekday(const sys_days& dp) NOEXCEPT
+ : wd_(weekday_from_days(dp.time_since_epoch().count()))
+ {}
+
+CONSTCD11
+inline
+weekday::weekday(const local_days& dp) NOEXCEPT
+ : wd_(weekday_from_days(dp.time_since_epoch().count()))
+ {}
+
+CONSTCD14 inline weekday& weekday::operator++() NOEXCEPT {*this += days{1}; return *this;}
+CONSTCD14 inline weekday weekday::operator++(int) NOEXCEPT {auto tmp(*this); ++(*this); return tmp;}
+CONSTCD14 inline weekday& weekday::operator--() NOEXCEPT {*this -= days{1}; return *this;}
+CONSTCD14 inline weekday weekday::operator--(int) NOEXCEPT {auto tmp(*this); --(*this); return tmp;}
+
+CONSTCD14
+inline
+weekday&
+weekday::operator+=(const days& d) NOEXCEPT
+{
+ *this = *this + d;
+ return *this;
+}
+
+CONSTCD14
+inline
+weekday&
+weekday::operator-=(const days& d) NOEXCEPT
+{
+ *this = *this - d;
+ return *this;
+}
+
+CONSTCD11
+inline
+weekday::operator unsigned() const NOEXCEPT
+{
+ return static_cast<unsigned>(wd_);
+}
+
+CONSTCD11 inline bool weekday::ok() const NOEXCEPT {return wd_ <= 6;}
+
+CONSTCD11
+inline
+bool
+operator==(const weekday& x, const weekday& y) NOEXCEPT
+{
+ return static_cast<unsigned>(x) == static_cast<unsigned>(y);
+}
+
+CONSTCD11
+inline
+bool
+operator!=(const weekday& x, const weekday& y) NOEXCEPT
+{
+ return !(x == y);
+}
+
+CONSTCD14
+inline
+days
+operator-(const weekday& x, const weekday& y) NOEXCEPT
+{
+ auto const diff = static_cast<unsigned>(x) - static_cast<unsigned>(y);
+ return days{diff <= 6 ? diff : diff + 7};
+}
+
+CONSTCD14
+inline
+weekday
+operator+(const weekday& x, const days& y) NOEXCEPT
+{
+ auto const wdu = static_cast<long long>(static_cast<unsigned>(x)) + y.count();
+ auto const wk = (wdu >= 0 ? wdu : wdu-6) / 7;
+ return weekday{static_cast<unsigned>(wdu - wk * 7)};
+}
+
+CONSTCD14
+inline
+weekday
+operator+(const days& x, const weekday& y) NOEXCEPT
+{
+ return y + x;
+}
+
+CONSTCD14
+inline
+weekday
+operator-(const weekday& x, const days& y) NOEXCEPT
+{
+ return x + -y;
+}
+
+template<class CharT, class Traits>
+inline
+std::basic_ostream<CharT, Traits>&
+operator<<(std::basic_ostream<CharT, Traits>& os, const weekday& wd)
+{
+ if (wd.ok())
+ {
+ CharT fmt[] = {'%', 'a', 0};
+ os << format(fmt, wd);
+ }
+ else
+ os << static_cast<unsigned>(wd) << " is not a valid weekday";
+ return os;
+}
+
+#if !defined(_MSC_VER) || (_MSC_VER >= 1900)
+inline namespace literals
+{
+
+CONSTCD11
+inline
+date::day
+operator "" _d(unsigned long long d) NOEXCEPT
+{
+ return date::day{static_cast<unsigned>(d)};
+}
+
+CONSTCD11
+inline
+date::year
+operator "" _y(unsigned long long y) NOEXCEPT
+{
+ return date::year(static_cast<int>(y));
+}
+#endif // !defined(_MSC_VER) || (_MSC_VER >= 1900)
+
+CONSTDATA date::last_spec last{};
+
+CONSTDATA date::month jan{1};
+CONSTDATA date::month feb{2};
+CONSTDATA date::month mar{3};
+CONSTDATA date::month apr{4};
+CONSTDATA date::month may{5};
+CONSTDATA date::month jun{6};
+CONSTDATA date::month jul{7};
+CONSTDATA date::month aug{8};
+CONSTDATA date::month sep{9};
+CONSTDATA date::month oct{10};
+CONSTDATA date::month nov{11};
+CONSTDATA date::month dec{12};
+
+CONSTDATA date::weekday sun{0u};
+CONSTDATA date::weekday mon{1u};
+CONSTDATA date::weekday tue{2u};
+CONSTDATA date::weekday wed{3u};
+CONSTDATA date::weekday thu{4u};
+CONSTDATA date::weekday fri{5u};
+CONSTDATA date::weekday sat{6u};
+
+#if !defined(_MSC_VER) || (_MSC_VER >= 1900)
+} // inline namespace literals
+#endif
+
+CONSTDATA date::month January{1};
+CONSTDATA date::month February{2};
+CONSTDATA date::month March{3};
+CONSTDATA date::month April{4};
+CONSTDATA date::month May{5};
+CONSTDATA date::month June{6};
+CONSTDATA date::month July{7};
+CONSTDATA date::month August{8};
+CONSTDATA date::month September{9};
+CONSTDATA date::month October{10};
+CONSTDATA date::month November{11};
+CONSTDATA date::month December{12};
+
+CONSTDATA date::weekday Sunday{0u};
+CONSTDATA date::weekday Monday{1u};
+CONSTDATA date::weekday Tuesday{2u};
+CONSTDATA date::weekday Wednesday{3u};
+CONSTDATA date::weekday Thursday{4u};
+CONSTDATA date::weekday Friday{5u};
+CONSTDATA date::weekday Saturday{6u};
+
+// weekday_indexed
+
+CONSTCD11
+inline
+weekday
+weekday_indexed::weekday() const NOEXCEPT
+{
+ return date::weekday{static_cast<unsigned>(wd_)};
+}
+
+CONSTCD11 inline unsigned weekday_indexed::index() const NOEXCEPT {return index_;}
+
+CONSTCD11
+inline
+bool
+weekday_indexed::ok() const NOEXCEPT
+{
+ return weekday().ok() && 1 <= index_ && index_ <= 5;
+}
+
+#ifdef __GNUC__
+# pragma GCC diagnostic push
+# pragma GCC diagnostic ignored "-Wconversion"
+#endif // __GNUC__
+
+CONSTCD11
+inline
+weekday_indexed::weekday_indexed(const date::weekday& wd, unsigned index) NOEXCEPT
+ : wd_(static_cast<decltype(wd_)>(static_cast<unsigned>(wd)))
+ , index_(static_cast<decltype(index_)>(index))
+ {}
+
+#ifdef __GNUC__
+# pragma GCC diagnostic pop
+#endif // __GNUC__
+
+template<class CharT, class Traits>
+inline
+std::basic_ostream<CharT, Traits>&
+operator<<(std::basic_ostream<CharT, Traits>& os, const weekday_indexed& wdi)
+{
+ os << wdi.weekday() << '[' << wdi.index();
+ if (!(1 <= wdi.index() && wdi.index() <= 5))
+ os << " is not a valid index";
+ os << ']';
+ return os;
+}
+
+CONSTCD11
+inline
+weekday_indexed
+weekday::operator[](unsigned index) const NOEXCEPT
+{
+ return {*this, index};
+}
+
+CONSTCD11
+inline
+bool
+operator==(const weekday_indexed& x, const weekday_indexed& y) NOEXCEPT
+{
+ return x.weekday() == y.weekday() && x.index() == y.index();
+}
+
+CONSTCD11
+inline
+bool
+operator!=(const weekday_indexed& x, const weekday_indexed& y) NOEXCEPT
+{
+ return !(x == y);
+}
+
+// weekday_last
+
+CONSTCD11 inline date::weekday weekday_last::weekday() const NOEXCEPT {return wd_;}
+CONSTCD11 inline bool weekday_last::ok() const NOEXCEPT {return wd_.ok();}
+CONSTCD11 inline weekday_last::weekday_last(const date::weekday& wd) NOEXCEPT : wd_(wd) {}
+
+CONSTCD11
+inline
+bool
+operator==(const weekday_last& x, const weekday_last& y) NOEXCEPT
+{
+ return x.weekday() == y.weekday();
+}
+
+CONSTCD11
+inline
+bool
+operator!=(const weekday_last& x, const weekday_last& y) NOEXCEPT
+{
+ return !(x == y);
+}
+
+template<class CharT, class Traits>
+inline
+std::basic_ostream<CharT, Traits>&
+operator<<(std::basic_ostream<CharT, Traits>& os, const weekday_last& wdl)
+{
+ return os << wdl.weekday() << "[last]";
+}
+
+CONSTCD11
+inline
+weekday_last
+weekday::operator[](last_spec) const NOEXCEPT
+{
+ return weekday_last{*this};
+}
+
+// year_month
+
+CONSTCD11
+inline
+year_month::year_month(const date::year& y, const date::month& m) NOEXCEPT
+ : y_(y)
+ , m_(m)
+ {}
+
+CONSTCD11 inline year year_month::year() const NOEXCEPT {return y_;}
+CONSTCD11 inline month year_month::month() const NOEXCEPT {return m_;}
+CONSTCD11 inline bool year_month::ok() const NOEXCEPT {return y_.ok() && m_.ok();}
+
+CONSTCD14
+inline
+year_month&
+year_month::operator+=(const months& dm) NOEXCEPT
+{
+ *this = *this + dm;
+ return *this;
+}
+
+CONSTCD14
+inline
+year_month&
+year_month::operator-=(const months& dm) NOEXCEPT
+{
+ *this = *this - dm;
+ return *this;
+}
+
+CONSTCD14
+inline
+year_month&
+year_month::operator+=(const years& dy) NOEXCEPT
+{
+ *this = *this + dy;
+ return *this;
+}
+
+CONSTCD14
+inline
+year_month&
+year_month::operator-=(const years& dy) NOEXCEPT
+{
+ *this = *this - dy;
+ return *this;
+}
+
+CONSTCD11
+inline
+bool
+operator==(const year_month& x, const year_month& y) NOEXCEPT
+{
+ return x.year() == y.year() && x.month() == y.month();
+}
+
+CONSTCD11
+inline
+bool
+operator!=(const year_month& x, const year_month& y) NOEXCEPT
+{
+ return !(x == y);
+}
+
+CONSTCD11
+inline
+bool
+operator<(const year_month& x, const year_month& y) NOEXCEPT
+{
+ return x.year() < y.year() ? true
+ : (x.year() > y.year() ? false
+ : (x.month() < y.month()));
+}
+
+CONSTCD11
+inline
+bool
+operator>(const year_month& x, const year_month& y) NOEXCEPT
+{
+ return y < x;
+}
+
+CONSTCD11
+inline
+bool
+operator<=(const year_month& x, const year_month& y) NOEXCEPT
+{
+ return !(y < x);
+}
+
+CONSTCD11
+inline
+bool
+operator>=(const year_month& x, const year_month& y) NOEXCEPT
+{
+ return !(x < y);
+}
+
+CONSTCD14
+inline
+year_month
+operator+(const year_month& ym, const months& dm) NOEXCEPT
+{
+ auto dmi = static_cast<int>(static_cast<unsigned>(ym.month())) - 1 + dm.count();
+ auto dy = (dmi >= 0 ? dmi : dmi-11) / 12;
+ dmi = dmi - dy * 12 + 1;
+ return (ym.year() + years(dy)) / month(static_cast<unsigned>(dmi));
+}
+
+CONSTCD14
+inline
+year_month
+operator+(const months& dm, const year_month& ym) NOEXCEPT
+{
+ return ym + dm;
+}
+
+CONSTCD14
+inline
+year_month
+operator-(const year_month& ym, const months& dm) NOEXCEPT
+{
+ return ym + -dm;
+}
+
+CONSTCD11
+inline
+months
+operator-(const year_month& x, const year_month& y) NOEXCEPT
+{
+ return (x.year() - y.year()) +
+ months(static_cast<unsigned>(x.month()) - static_cast<unsigned>(y.month()));
+}
+
+CONSTCD11
+inline
+year_month
+operator+(const year_month& ym, const years& dy) NOEXCEPT
+{
+ return (ym.year() + dy) / ym.month();
+}
+
+CONSTCD11
+inline
+year_month
+operator+(const years& dy, const year_month& ym) NOEXCEPT
+{
+ return ym + dy;
+}
+
+CONSTCD11
+inline
+year_month
+operator-(const year_month& ym, const years& dy) NOEXCEPT
+{
+ return ym + -dy;
+}
+
+template<class CharT, class Traits>
+inline
+std::basic_ostream<CharT, Traits>&
+operator<<(std::basic_ostream<CharT, Traits>& os, const year_month& ym)
+{
+ return os << ym.year() << '/' << ym.month();
+}
+
+// month_day
+
+CONSTCD11
+inline
+month_day::month_day(const date::month& m, const date::day& d) NOEXCEPT
+ : m_(m)
+ , d_(d)
+ {}
+
+CONSTCD11 inline date::month month_day::month() const NOEXCEPT {return m_;}
+CONSTCD11 inline date::day month_day::day() const NOEXCEPT {return d_;}
+
+CONSTCD14
+inline
+bool
+month_day::ok() const NOEXCEPT
+{
+ CONSTDATA date::day d[] =
+ {
+ date::day(31), date::day(29), date::day(31),
+ date::day(30), date::day(31), date::day(30),
+ date::day(31), date::day(31), date::day(30),
+ date::day(31), date::day(30), date::day(31)
+ };
+ return m_.ok() && date::day{1} <= d_ && d_ <= d[static_cast<unsigned>(m_)-1];
+}
+
+CONSTCD11
+inline
+bool
+operator==(const month_day& x, const month_day& y) NOEXCEPT
+{
+ return x.month() == y.month() && x.day() == y.day();
+}
+
+CONSTCD11
+inline
+bool
+operator!=(const month_day& x, const month_day& y) NOEXCEPT
+{
+ return !(x == y);
+}
+
+CONSTCD11
+inline
+bool
+operator<(const month_day& x, const month_day& y) NOEXCEPT
+{
+ return x.month() < y.month() ? true
+ : (x.month() > y.month() ? false
+ : (x.day() < y.day()));
+}
+
+CONSTCD11
+inline
+bool
+operator>(const month_day& x, const month_day& y) NOEXCEPT
+{
+ return y < x;
+}
+
+CONSTCD11
+inline
+bool
+operator<=(const month_day& x, const month_day& y) NOEXCEPT
+{
+ return !(y < x);
+}
+
+CONSTCD11
+inline
+bool
+operator>=(const month_day& x, const month_day& y) NOEXCEPT
+{
+ return !(x < y);
+}
+
+template<class CharT, class Traits>
+inline
+std::basic_ostream<CharT, Traits>&
+operator<<(std::basic_ostream<CharT, Traits>& os, const month_day& md)
+{
+ return os << md.month() << '/' << md.day();
+}
+
+// month_day_last
+
+CONSTCD11 inline month month_day_last::month() const NOEXCEPT {return m_;}
+CONSTCD11 inline bool month_day_last::ok() const NOEXCEPT {return m_.ok();}
+CONSTCD11 inline month_day_last::month_day_last(const date::month& m) NOEXCEPT : m_(m) {}
+
+CONSTCD11
+inline
+bool
+operator==(const month_day_last& x, const month_day_last& y) NOEXCEPT
+{
+ return x.month() == y.month();
+}
+
+CONSTCD11
+inline
+bool
+operator!=(const month_day_last& x, const month_day_last& y) NOEXCEPT
+{
+ return !(x == y);
+}
+
+CONSTCD11
+inline
+bool
+operator<(const month_day_last& x, const month_day_last& y) NOEXCEPT
+{
+ return x.month() < y.month();
+}
+
+CONSTCD11
+inline
+bool
+operator>(const month_day_last& x, const month_day_last& y) NOEXCEPT
+{
+ return y < x;
+}
+
+CONSTCD11
+inline
+bool
+operator<=(const month_day_last& x, const month_day_last& y) NOEXCEPT
+{
+ return !(y < x);
+}
+
+CONSTCD11
+inline
+bool
+operator>=(const month_day_last& x, const month_day_last& y) NOEXCEPT
+{
+ return !(x < y);
+}
+
+template<class CharT, class Traits>
+inline
+std::basic_ostream<CharT, Traits>&
+operator<<(std::basic_ostream<CharT, Traits>& os, const month_day_last& mdl)
+{
+ return os << mdl.month() << "/last";
+}
+
+// month_weekday
+
+CONSTCD11
+inline
+month_weekday::month_weekday(const date::month& m,
+ const date::weekday_indexed& wdi) NOEXCEPT
+ : m_(m)
+ , wdi_(wdi)
+ {}
+
+CONSTCD11 inline month month_weekday::month() const NOEXCEPT {return m_;}
+
+CONSTCD11
+inline
+weekday_indexed
+month_weekday::weekday_indexed() const NOEXCEPT
+{
+ return wdi_;
+}
+
+CONSTCD11
+inline
+bool
+month_weekday::ok() const NOEXCEPT
+{
+ return m_.ok() && wdi_.ok();
+}
+
+CONSTCD11
+inline
+bool
+operator==(const month_weekday& x, const month_weekday& y) NOEXCEPT
+{
+ return x.month() == y.month() && x.weekday_indexed() == y.weekday_indexed();
+}
+
+CONSTCD11
+inline
+bool
+operator!=(const month_weekday& x, const month_weekday& y) NOEXCEPT
+{
+ return !(x == y);
+}
+
+template<class CharT, class Traits>
+inline
+std::basic_ostream<CharT, Traits>&
+operator<<(std::basic_ostream<CharT, Traits>& os, const month_weekday& mwd)
+{
+ return os << mwd.month() << '/' << mwd.weekday_indexed();
+}
+
+// month_weekday_last
+
+CONSTCD11
+inline
+month_weekday_last::month_weekday_last(const date::month& m,
+ const date::weekday_last& wdl) NOEXCEPT
+ : m_(m)
+ , wdl_(wdl)
+ {}
+
+CONSTCD11 inline month month_weekday_last::month() const NOEXCEPT {return m_;}
+
+CONSTCD11
+inline
+weekday_last
+month_weekday_last::weekday_last() const NOEXCEPT
+{
+ return wdl_;
+}
+
+CONSTCD11
+inline
+bool
+month_weekday_last::ok() const NOEXCEPT
+{
+ return m_.ok() && wdl_.ok();
+}
+
+CONSTCD11
+inline
+bool
+operator==(const month_weekday_last& x, const month_weekday_last& y) NOEXCEPT
+{
+ return x.month() == y.month() && x.weekday_last() == y.weekday_last();
+}
+
+CONSTCD11
+inline
+bool
+operator!=(const month_weekday_last& x, const month_weekday_last& y) NOEXCEPT
+{
+ return !(x == y);
+}
+
+template<class CharT, class Traits>
+inline
+std::basic_ostream<CharT, Traits>&
+operator<<(std::basic_ostream<CharT, Traits>& os, const month_weekday_last& mwdl)
+{
+ return os << mwdl.month() << '/' << mwdl.weekday_last();
+}
+
+// year_month_day_last
+
+CONSTCD11
+inline
+year_month_day_last::year_month_day_last(const date::year& y,
+ const date::month_day_last& mdl) NOEXCEPT
+ : y_(y)
+ , mdl_(mdl)
+ {}
+
+CONSTCD14
+inline
+year_month_day_last&
+year_month_day_last::operator+=(const months& m) NOEXCEPT
+{
+ *this = *this + m;
+ return *this;
+}
+
+CONSTCD14
+inline
+year_month_day_last&
+year_month_day_last::operator-=(const months& m) NOEXCEPT
+{
+ *this = *this - m;
+ return *this;
+}
+
+CONSTCD14
+inline
+year_month_day_last&
+year_month_day_last::operator+=(const years& y) NOEXCEPT
+{
+ *this = *this + y;
+ return *this;
+}
+
+CONSTCD14
+inline
+year_month_day_last&
+year_month_day_last::operator-=(const years& y) NOEXCEPT
+{
+ *this = *this - y;
+ return *this;
+}
+
+CONSTCD11 inline year year_month_day_last::year() const NOEXCEPT {return y_;}
+CONSTCD11 inline month year_month_day_last::month() const NOEXCEPT {return mdl_.month();}
+
+CONSTCD11
+inline
+month_day_last
+year_month_day_last::month_day_last() const NOEXCEPT
+{
+ return mdl_;
+}
+
+CONSTCD14
+inline
+day
+year_month_day_last::day() const NOEXCEPT
+{
+ CONSTDATA date::day d[] =
+ {
+ date::day(31), date::day(28), date::day(31),
+ date::day(30), date::day(31), date::day(30),
+ date::day(31), date::day(31), date::day(30),
+ date::day(31), date::day(30), date::day(31)
+ };
+ return month() != feb || !y_.is_leap() ?
+ d[static_cast<unsigned>(month()) - 1] : date::day{29};
+}
+
+CONSTCD14
+inline
+year_month_day_last::operator sys_days() const NOEXCEPT
+{
+ return sys_days(year()/month()/day());
+}
+
+CONSTCD14
+inline
+year_month_day_last::operator local_days() const NOEXCEPT
+{
+ return local_days(year()/month()/day());
+}
+
+CONSTCD11
+inline
+bool
+year_month_day_last::ok() const NOEXCEPT
+{
+ return y_.ok() && mdl_.ok();
+}
+
+CONSTCD11
+inline
+bool
+operator==(const year_month_day_last& x, const year_month_day_last& y) NOEXCEPT
+{
+ return x.year() == y.year() && x.month_day_last() == y.month_day_last();
+}
+
+CONSTCD11
+inline
+bool
+operator!=(const year_month_day_last& x, const year_month_day_last& y) NOEXCEPT
+{
+ return !(x == y);
+}
+
+CONSTCD11
+inline
+bool
+operator<(const year_month_day_last& x, const year_month_day_last& y) NOEXCEPT
+{
+ return x.year() < y.year() ? true
+ : (x.year() > y.year() ? false
+ : (x.month_day_last() < y.month_day_last()));
+}
+
+CONSTCD11
+inline
+bool
+operator>(const year_month_day_last& x, const year_month_day_last& y) NOEXCEPT
+{
+ return y < x;
+}
+
+CONSTCD11
+inline
+bool
+operator<=(const year_month_day_last& x, const year_month_day_last& y) NOEXCEPT
+{
+ return !(y < x);
+}
+
+CONSTCD11
+inline
+bool
+operator>=(const year_month_day_last& x, const year_month_day_last& y) NOEXCEPT
+{
+ return !(x < y);
+}
+
+template<class CharT, class Traits>
+inline
+std::basic_ostream<CharT, Traits>&
+operator<<(std::basic_ostream<CharT, Traits>& os, const year_month_day_last& ymdl)
+{
+ return os << ymdl.year() << '/' << ymdl.month_day_last();
+}
+
+CONSTCD14
+inline
+year_month_day_last
+operator+(const year_month_day_last& ymdl, const months& dm) NOEXCEPT
+{
+ return (ymdl.year() / ymdl.month() + dm) / last;
+}
+
+CONSTCD14
+inline
+year_month_day_last
+operator+(const months& dm, const year_month_day_last& ymdl) NOEXCEPT
+{
+ return ymdl + dm;
+}
+
+CONSTCD14
+inline
+year_month_day_last
+operator-(const year_month_day_last& ymdl, const months& dm) NOEXCEPT
+{
+ return ymdl + (-dm);
+}
+
+CONSTCD11
+inline
+year_month_day_last
+operator+(const year_month_day_last& ymdl, const years& dy) NOEXCEPT
+{
+ return {ymdl.year()+dy, ymdl.month_day_last()};
+}
+
+CONSTCD11
+inline
+year_month_day_last
+operator+(const years& dy, const year_month_day_last& ymdl) NOEXCEPT
+{
+ return ymdl + dy;
+}
+
+CONSTCD11
+inline
+year_month_day_last
+operator-(const year_month_day_last& ymdl, const years& dy) NOEXCEPT
+{
+ return ymdl + (-dy);
+}
+
+// year_month_day
+
+CONSTCD11
+inline
+year_month_day::year_month_day(const date::year& y, const date::month& m,
+ const date::day& d) NOEXCEPT
+ : y_(y)
+ , m_(m)
+ , d_(d)
+ {}
+
+CONSTCD14
+inline
+year_month_day::year_month_day(const year_month_day_last& ymdl) NOEXCEPT
+ : y_(ymdl.year())
+ , m_(ymdl.month())
+ , d_(ymdl.day())
+ {}
+
+CONSTCD14
+inline
+year_month_day::year_month_day(sys_days dp) NOEXCEPT
+ : year_month_day(from_days(dp.time_since_epoch()))
+ {}
+
+CONSTCD14
+inline
+year_month_day::year_month_day(local_days dp) NOEXCEPT
+ : year_month_day(from_days(dp.time_since_epoch()))
+ {}
+
+CONSTCD11 inline year year_month_day::year() const NOEXCEPT {return y_;}
+CONSTCD11 inline month year_month_day::month() const NOEXCEPT {return m_;}
+CONSTCD11 inline day year_month_day::day() const NOEXCEPT {return d_;}
+
+CONSTCD14
+inline
+year_month_day&
+year_month_day::operator+=(const months& m) NOEXCEPT
+{
+ *this = *this + m;
+ return *this;
+}
+
+CONSTCD14
+inline
+year_month_day&
+year_month_day::operator-=(const months& m) NOEXCEPT
+{
+ *this = *this - m;
+ return *this;
+}
+
+CONSTCD14
+inline
+year_month_day&
+year_month_day::operator+=(const years& y) NOEXCEPT
+{
+ *this = *this + y;
+ return *this;
+}
+
+CONSTCD14
+inline
+year_month_day&
+year_month_day::operator-=(const years& y) NOEXCEPT
+{
+ *this = *this - y;
+ return *this;
+}
+
+CONSTCD14
+inline
+days
+year_month_day::to_days() const NOEXCEPT
+{
+ static_assert(std::numeric_limits<unsigned>::digits >= 18,
+ "This algorithm has not been ported to a 16 bit unsigned integer");
+ static_assert(std::numeric_limits<int>::digits >= 20,
+ "This algorithm has not been ported to a 16 bit signed integer");
+ auto const y = static_cast<int>(y_) - (m_ <= feb);
+ auto const m = static_cast<unsigned>(m_);
+ auto const d = static_cast<unsigned>(d_);
+ auto const era = (y >= 0 ? y : y-399) / 400;
+ auto const yoe = static_cast<unsigned>(y - era * 400); // [0, 399]
+ auto const doy = (153*(m > 2 ? m-3 : m+9) + 2)/5 + d-1; // [0, 365]
+ auto const doe = yoe * 365 + yoe/4 - yoe/100 + doy; // [0, 146096]
+ return days{era * 146097 + static_cast<int>(doe) - 719468};
+}
+
+CONSTCD14
+inline
+year_month_day::operator sys_days() const NOEXCEPT
+{
+ return sys_days{to_days()};
+}
+
+CONSTCD14
+inline
+year_month_day::operator local_days() const NOEXCEPT
+{
+ return local_days{to_days()};
+}
+
+CONSTCD14
+inline
+bool
+year_month_day::ok() const NOEXCEPT
+{
+ if (!(y_.ok() && m_.ok()))
+ return false;
+ return date::day{1} <= d_ && d_ <= (y_ / m_ / last).day();
+}
+
+CONSTCD11
+inline
+bool
+operator==(const year_month_day& x, const year_month_day& y) NOEXCEPT
+{
+ return x.year() == y.year() && x.month() == y.month() && x.day() == y.day();
+}
+
+CONSTCD11
+inline
+bool
+operator!=(const year_month_day& x, const year_month_day& y) NOEXCEPT
+{
+ return !(x == y);
+}
+
+CONSTCD11
+inline
+bool
+operator<(const year_month_day& x, const year_month_day& y) NOEXCEPT
+{
+ return x.year() < y.year() ? true
+ : (x.year() > y.year() ? false
+ : (x.month() < y.month() ? true
+ : (x.month() > y.month() ? false
+ : (x.day() < y.day()))));
+}
+
+CONSTCD11
+inline
+bool
+operator>(const year_month_day& x, const year_month_day& y) NOEXCEPT
+{
+ return y < x;
+}
+
+CONSTCD11
+inline
+bool
+operator<=(const year_month_day& x, const year_month_day& y) NOEXCEPT
+{
+ return !(y < x);
+}
+
+CONSTCD11
+inline
+bool
+operator>=(const year_month_day& x, const year_month_day& y) NOEXCEPT
+{
+ return !(x < y);
+}
+
+template<class CharT, class Traits>
+inline
+std::basic_ostream<CharT, Traits>&
+operator<<(std::basic_ostream<CharT, Traits>& os, const year_month_day& ymd)
+{
+ detail::save_stream<CharT, Traits> _(os);
+ os.fill('0');
+ os.flags(std::ios::dec | std::ios::right);
+ os << ymd.year() << '-';
+ os.width(2);
+ os << static_cast<unsigned>(ymd.month()) << '-';
+ os << ymd.day();
+ if (!ymd.ok())
+ os << " is not a valid date";
+ return os;
+}
+
+CONSTCD14
+inline
+year_month_day
+year_month_day::from_days(days dp) NOEXCEPT
+{
+ static_assert(std::numeric_limits<unsigned>::digits >= 18,
+ "This algorithm has not been ported to a 16 bit unsigned integer");
+ static_assert(std::numeric_limits<int>::digits >= 20,
+ "This algorithm has not been ported to a 16 bit signed integer");
+ auto const z = dp.count() + 719468;
+ auto const era = (z >= 0 ? z : z - 146096) / 146097;
+ auto const doe = static_cast<unsigned>(z - era * 146097); // [0, 146096]
+ auto const yoe = (doe - doe/1460 + doe/36524 - doe/146096) / 365; // [0, 399]
+ auto const y = static_cast<days::rep>(yoe) + era * 400;
+ auto const doy = doe - (365*yoe + yoe/4 - yoe/100); // [0, 365]
+ auto const mp = (5*doy + 2)/153; // [0, 11]
+ auto const d = doy - (153*mp+2)/5 + 1; // [1, 31]
+ auto const m = mp < 10 ? mp+3 : mp-9; // [1, 12]
+ return year_month_day{date::year{y + (m <= 2)}, date::month(m), date::day(d)};
+}
+
+CONSTCD14
+inline
+year_month_day
+operator+(const year_month_day& ymd, const months& dm) NOEXCEPT
+{
+ return (ymd.year() / ymd.month() + dm) / ymd.day();
+}
+
+CONSTCD14
+inline
+year_month_day
+operator+(const months& dm, const year_month_day& ymd) NOEXCEPT
+{
+ return ymd + dm;
+}
+
+CONSTCD14
+inline
+year_month_day
+operator-(const year_month_day& ymd, const months& dm) NOEXCEPT
+{
+ return ymd + (-dm);
+}
+
+CONSTCD11
+inline
+year_month_day
+operator+(const year_month_day& ymd, const years& dy) NOEXCEPT
+{
+ return (ymd.year() + dy) / ymd.month() / ymd.day();
+}
+
+CONSTCD11
+inline
+year_month_day
+operator+(const years& dy, const year_month_day& ymd) NOEXCEPT
+{
+ return ymd + dy;
+}
+
+CONSTCD11
+inline
+year_month_day
+operator-(const year_month_day& ymd, const years& dy) NOEXCEPT
+{
+ return ymd + (-dy);
+}
+
+// year_month_weekday
+
+CONSTCD11
+inline
+year_month_weekday::year_month_weekday(const date::year& y, const date::month& m,
+ const date::weekday_indexed& wdi)
+ NOEXCEPT
+ : y_(y)
+ , m_(m)
+ , wdi_(wdi)
+ {}
+
+CONSTCD14
+inline
+year_month_weekday::year_month_weekday(const sys_days& dp) NOEXCEPT
+ : year_month_weekday(from_days(dp.time_since_epoch()))
+ {}
+
+CONSTCD14
+inline
+year_month_weekday::year_month_weekday(const local_days& dp) NOEXCEPT
+ : year_month_weekday(from_days(dp.time_since_epoch()))
+ {}
+
+CONSTCD14
+inline
+year_month_weekday&
+year_month_weekday::operator+=(const months& m) NOEXCEPT
+{
+ *this = *this + m;
+ return *this;
+}
+
+CONSTCD14
+inline
+year_month_weekday&
+year_month_weekday::operator-=(const months& m) NOEXCEPT
+{
+ *this = *this - m;
+ return *this;
+}
+
+CONSTCD14
+inline
+year_month_weekday&
+year_month_weekday::operator+=(const years& y) NOEXCEPT
+{
+ *this = *this + y;
+ return *this;
+}
+
+CONSTCD14
+inline
+year_month_weekday&
+year_month_weekday::operator-=(const years& y) NOEXCEPT
+{
+ *this = *this - y;
+ return *this;
+}
+
+CONSTCD11 inline year year_month_weekday::year() const NOEXCEPT {return y_;}
+CONSTCD11 inline month year_month_weekday::month() const NOEXCEPT {return m_;}
+
+CONSTCD11
+inline
+weekday
+year_month_weekday::weekday() const NOEXCEPT
+{
+ return wdi_.weekday();
+}
+
+CONSTCD11
+inline
+unsigned
+year_month_weekday::index() const NOEXCEPT
+{
+ return wdi_.index();
+}
+
+CONSTCD11
+inline
+weekday_indexed
+year_month_weekday::weekday_indexed() const NOEXCEPT
+{
+ return wdi_;
+}
+
+CONSTCD14
+inline
+year_month_weekday::operator sys_days() const NOEXCEPT
+{
+ return sys_days{to_days()};
+}
+
+CONSTCD14
+inline
+year_month_weekday::operator local_days() const NOEXCEPT
+{
+ return local_days{to_days()};
+}
+
+CONSTCD14
+inline
+bool
+year_month_weekday::ok() const NOEXCEPT
+{
+ if (!y_.ok() || !m_.ok() || !wdi_.weekday().ok() || wdi_.index() < 1)
+ return false;
+ if (wdi_.index() <= 4)
+ return true;
+ auto d2 = wdi_.weekday() - date::weekday(static_cast<sys_days>(y_/m_/1)) + days((wdi_.index()-1)*7 + 1);
+ return static_cast<unsigned>(d2.count()) <= static_cast<unsigned>((y_/m_/last).day());
+}
+
+CONSTCD14
+inline
+year_month_weekday
+year_month_weekday::from_days(days d) NOEXCEPT
+{
+ sys_days dp{d};
+ auto const wd = date::weekday(dp);
+ auto const ymd = year_month_day(dp);
+ return {ymd.year(), ymd.month(), wd[(static_cast<unsigned>(ymd.day())-1)/7+1]};
+}
+
+CONSTCD14
+inline
+days
+year_month_weekday::to_days() const NOEXCEPT
+{
+ auto d = sys_days(y_/m_/1);
+ return (d + (wdi_.weekday() - date::weekday(d) + days{(wdi_.index()-1)*7})
+ ).time_since_epoch();
+}
+
+CONSTCD11
+inline
+bool
+operator==(const year_month_weekday& x, const year_month_weekday& y) NOEXCEPT
+{
+ return x.year() == y.year() && x.month() == y.month() &&
+ x.weekday_indexed() == y.weekday_indexed();
+}
+
+CONSTCD11
+inline
+bool
+operator!=(const year_month_weekday& x, const year_month_weekday& y) NOEXCEPT
+{
+ return !(x == y);
+}
+
+template<class CharT, class Traits>
+inline
+std::basic_ostream<CharT, Traits>&
+operator<<(std::basic_ostream<CharT, Traits>& os, const year_month_weekday& ymwdi)
+{
+ return os << ymwdi.year() << '/' << ymwdi.month()
+ << '/' << ymwdi.weekday_indexed();
+}
+
+CONSTCD14
+inline
+year_month_weekday
+operator+(const year_month_weekday& ymwd, const months& dm) NOEXCEPT
+{
+ return (ymwd.year() / ymwd.month() + dm) / ymwd.weekday_indexed();
+}
+
+CONSTCD14
+inline
+year_month_weekday
+operator+(const months& dm, const year_month_weekday& ymwd) NOEXCEPT
+{
+ return ymwd + dm;
+}
+
+CONSTCD14
+inline
+year_month_weekday
+operator-(const year_month_weekday& ymwd, const months& dm) NOEXCEPT
+{
+ return ymwd + (-dm);
+}
+
+CONSTCD11
+inline
+year_month_weekday
+operator+(const year_month_weekday& ymwd, const years& dy) NOEXCEPT
+{
+ return {ymwd.year()+dy, ymwd.month(), ymwd.weekday_indexed()};
+}
+
+CONSTCD11
+inline
+year_month_weekday
+operator+(const years& dy, const year_month_weekday& ymwd) NOEXCEPT
+{
+ return ymwd + dy;
+}
+
+CONSTCD11
+inline
+year_month_weekday
+operator-(const year_month_weekday& ymwd, const years& dy) NOEXCEPT
+{
+ return ymwd + (-dy);
+}
+
+// year_month_weekday_last
+
+CONSTCD11
+inline
+year_month_weekday_last::year_month_weekday_last(const date::year& y,
+ const date::month& m,
+ const date::weekday_last& wdl) NOEXCEPT
+ : y_(y)
+ , m_(m)
+ , wdl_(wdl)
+ {}
+
+CONSTCD14
+inline
+year_month_weekday_last&
+year_month_weekday_last::operator+=(const months& m) NOEXCEPT
+{
+ *this = *this + m;
+ return *this;
+}
+
+CONSTCD14
+inline
+year_month_weekday_last&
+year_month_weekday_last::operator-=(const months& m) NOEXCEPT
+{
+ *this = *this - m;
+ return *this;
+}
+
+CONSTCD14
+inline
+year_month_weekday_last&
+year_month_weekday_last::operator+=(const years& y) NOEXCEPT
+{
+ *this = *this + y;
+ return *this;
+}
+
+CONSTCD14
+inline
+year_month_weekday_last&
+year_month_weekday_last::operator-=(const years& y) NOEXCEPT
+{
+ *this = *this - y;
+ return *this;
+}
+
+CONSTCD11 inline year year_month_weekday_last::year() const NOEXCEPT {return y_;}
+CONSTCD11 inline month year_month_weekday_last::month() const NOEXCEPT {return m_;}
+
+CONSTCD11
+inline
+weekday
+year_month_weekday_last::weekday() const NOEXCEPT
+{
+ return wdl_.weekday();
+}
+
+CONSTCD11
+inline
+weekday_last
+year_month_weekday_last::weekday_last() const NOEXCEPT
+{
+ return wdl_;
+}
+
+CONSTCD14
+inline
+year_month_weekday_last::operator sys_days() const NOEXCEPT
+{
+ return sys_days{to_days()};
+}
+
+CONSTCD14
+inline
+year_month_weekday_last::operator local_days() const NOEXCEPT
+{
+ return local_days{to_days()};
+}
+
+CONSTCD11
+inline
+bool
+year_month_weekday_last::ok() const NOEXCEPT
+{
+ return y_.ok() && m_.ok() && wdl_.ok();
+}
+
+CONSTCD14
+inline
+days
+year_month_weekday_last::to_days() const NOEXCEPT
+{
+ auto const d = sys_days(y_/m_/last);
+ return (d - (date::weekday{d} - wdl_.weekday())).time_since_epoch();
+}
+
+CONSTCD11
+inline
+bool
+operator==(const year_month_weekday_last& x, const year_month_weekday_last& y) NOEXCEPT
+{
+ return x.year() == y.year() && x.month() == y.month() &&
+ x.weekday_last() == y.weekday_last();
+}
+
+CONSTCD11
+inline
+bool
+operator!=(const year_month_weekday_last& x, const year_month_weekday_last& y) NOEXCEPT
+{
+ return !(x == y);
+}
+
+template<class CharT, class Traits>
+inline
+std::basic_ostream<CharT, Traits>&
+operator<<(std::basic_ostream<CharT, Traits>& os, const year_month_weekday_last& ymwdl)
+{
+ return os << ymwdl.year() << '/' << ymwdl.month() << '/' << ymwdl.weekday_last();
+}
+
+CONSTCD14
+inline
+year_month_weekday_last
+operator+(const year_month_weekday_last& ymwdl, const months& dm) NOEXCEPT
+{
+ return (ymwdl.year() / ymwdl.month() + dm) / ymwdl.weekday_last();
+}
+
+CONSTCD14
+inline
+year_month_weekday_last
+operator+(const months& dm, const year_month_weekday_last& ymwdl) NOEXCEPT
+{
+ return ymwdl + dm;
+}
+
+CONSTCD14
+inline
+year_month_weekday_last
+operator-(const year_month_weekday_last& ymwdl, const months& dm) NOEXCEPT
+{
+ return ymwdl + (-dm);
+}
+
+CONSTCD11
+inline
+year_month_weekday_last
+operator+(const year_month_weekday_last& ymwdl, const years& dy) NOEXCEPT
+{
+ return {ymwdl.year()+dy, ymwdl.month(), ymwdl.weekday_last()};
+}
+
+CONSTCD11
+inline
+year_month_weekday_last
+operator+(const years& dy, const year_month_weekday_last& ymwdl) NOEXCEPT
+{
+ return ymwdl + dy;
+}
+
+CONSTCD11
+inline
+year_month_weekday_last
+operator-(const year_month_weekday_last& ymwdl, const years& dy) NOEXCEPT
+{
+ return ymwdl + (-dy);
+}
+
+// year_month from operator/()
+
+CONSTCD11
+inline
+year_month
+operator/(const year& y, const month& m) NOEXCEPT
+{
+ return {y, m};
+}
+
+CONSTCD11
+inline
+year_month
+operator/(const year& y, int m) NOEXCEPT
+{
+ return y / month(static_cast<unsigned>(m));
+}
+
+// month_day from operator/()
+
+CONSTCD11
+inline
+month_day
+operator/(const month& m, const day& d) NOEXCEPT
+{
+ return {m, d};
+}
+
+CONSTCD11
+inline
+month_day
+operator/(const day& d, const month& m) NOEXCEPT
+{
+ return m / d;
+}
+
+CONSTCD11
+inline
+month_day
+operator/(const month& m, int d) NOEXCEPT
+{
+ return m / day(static_cast<unsigned>(d));
+}
+
+CONSTCD11
+inline
+month_day
+operator/(int m, const day& d) NOEXCEPT
+{
+ return month(static_cast<unsigned>(m)) / d;
+}
+
+CONSTCD11 inline month_day operator/(const day& d, int m) NOEXCEPT {return m / d;}
+
+// month_day_last from operator/()
+
+CONSTCD11
+inline
+month_day_last
+operator/(const month& m, last_spec) NOEXCEPT
+{
+ return month_day_last{m};
+}
+
+CONSTCD11
+inline
+month_day_last
+operator/(last_spec, const month& m) NOEXCEPT
+{
+ return m/last;
+}
+
+CONSTCD11
+inline
+month_day_last
+operator/(int m, last_spec) NOEXCEPT
+{
+ return month(static_cast<unsigned>(m))/last;
+}
+
+CONSTCD11
+inline
+month_day_last
+operator/(last_spec, int m) NOEXCEPT
+{
+ return m/last;
+}
+
+// month_weekday from operator/()
+
+CONSTCD11
+inline
+month_weekday
+operator/(const month& m, const weekday_indexed& wdi) NOEXCEPT
+{
+ return {m, wdi};
+}
+
+CONSTCD11
+inline
+month_weekday
+operator/(const weekday_indexed& wdi, const month& m) NOEXCEPT
+{
+ return m / wdi;
+}
+
+CONSTCD11
+inline
+month_weekday
+operator/(int m, const weekday_indexed& wdi) NOEXCEPT
+{
+ return month(static_cast<unsigned>(m)) / wdi;
+}
+
+CONSTCD11
+inline
+month_weekday
+operator/(const weekday_indexed& wdi, int m) NOEXCEPT
+{
+ return m / wdi;
+}
+
+// month_weekday_last from operator/()
+
+CONSTCD11
+inline
+month_weekday_last
+operator/(const month& m, const weekday_last& wdl) NOEXCEPT
+{
+ return {m, wdl};
+}
+
+CONSTCD11
+inline
+month_weekday_last
+operator/(const weekday_last& wdl, const month& m) NOEXCEPT
+{
+ return m / wdl;
+}
+
+CONSTCD11
+inline
+month_weekday_last
+operator/(int m, const weekday_last& wdl) NOEXCEPT
+{
+ return month(static_cast<unsigned>(m)) / wdl;
+}
+
+CONSTCD11
+inline
+month_weekday_last
+operator/(const weekday_last& wdl, int m) NOEXCEPT
+{
+ return m / wdl;
+}
+
+// year_month_day from operator/()
+
+CONSTCD11
+inline
+year_month_day
+operator/(const year_month& ym, const day& d) NOEXCEPT
+{
+ return {ym.year(), ym.month(), d};
+}
+
+CONSTCD11
+inline
+year_month_day
+operator/(const year_month& ym, int d) NOEXCEPT
+{
+ return ym / day(static_cast<unsigned>(d));
+}
+
+CONSTCD11
+inline
+year_month_day
+operator/(const year& y, const month_day& md) NOEXCEPT
+{
+ return y / md.month() / md.day();
+}
+
+CONSTCD11
+inline
+year_month_day
+operator/(int y, const month_day& md) NOEXCEPT
+{
+ return year(y) / md;
+}
+
+CONSTCD11
+inline
+year_month_day
+operator/(const month_day& md, const year& y) NOEXCEPT
+{
+ return y / md;
+}
+
+CONSTCD11
+inline
+year_month_day
+operator/(const month_day& md, int y) NOEXCEPT
+{
+ return year(y) / md;
+}
+
+// year_month_day_last from operator/()
+
+CONSTCD11
+inline
+year_month_day_last
+operator/(const year_month& ym, last_spec) NOEXCEPT
+{
+ return {ym.year(), month_day_last{ym.month()}};
+}
+
+CONSTCD11
+inline
+year_month_day_last
+operator/(const year& y, const month_day_last& mdl) NOEXCEPT
+{
+ return {y, mdl};
+}
+
+CONSTCD11
+inline
+year_month_day_last
+operator/(int y, const month_day_last& mdl) NOEXCEPT
+{
+ return year(y) / mdl;
+}
+
+CONSTCD11
+inline
+year_month_day_last
+operator/(const month_day_last& mdl, const year& y) NOEXCEPT
+{
+ return y / mdl;
+}
+
+CONSTCD11
+inline
+year_month_day_last
+operator/(const month_day_last& mdl, int y) NOEXCEPT
+{
+ return year(y) / mdl;
+}
+
+// year_month_weekday from operator/()
+
+CONSTCD11
+inline
+year_month_weekday
+operator/(const year_month& ym, const weekday_indexed& wdi) NOEXCEPT
+{
+ return {ym.year(), ym.month(), wdi};
+}
+
+CONSTCD11
+inline
+year_month_weekday
+operator/(const year& y, const month_weekday& mwd) NOEXCEPT
+{
+ return {y, mwd.month(), mwd.weekday_indexed()};
+}
+
+CONSTCD11
+inline
+year_month_weekday
+operator/(int y, const month_weekday& mwd) NOEXCEPT
+{
+ return year(y) / mwd;
+}
+
+CONSTCD11
+inline
+year_month_weekday
+operator/(const month_weekday& mwd, const year& y) NOEXCEPT
+{
+ return y / mwd;
+}
+
+CONSTCD11
+inline
+year_month_weekday
+operator/(const month_weekday& mwd, int y) NOEXCEPT
+{
+ return year(y) / mwd;
+}
+
+// year_month_weekday_last from operator/()
+
+CONSTCD11
+inline
+year_month_weekday_last
+operator/(const year_month& ym, const weekday_last& wdl) NOEXCEPT
+{
+ return {ym.year(), ym.month(), wdl};
+}
+
+CONSTCD11
+inline
+year_month_weekday_last
+operator/(const year& y, const month_weekday_last& mwdl) NOEXCEPT
+{
+ return {y, mwdl.month(), mwdl.weekday_last()};
+}
+
+CONSTCD11
+inline
+year_month_weekday_last
+operator/(int y, const month_weekday_last& mwdl) NOEXCEPT
+{
+ return year(y) / mwdl;
+}
+
+CONSTCD11
+inline
+year_month_weekday_last
+operator/(const month_weekday_last& mwdl, const year& y) NOEXCEPT
+{
+ return y / mwdl;
+}
+
+CONSTCD11
+inline
+year_month_weekday_last
+operator/(const month_weekday_last& mwdl, int y) NOEXCEPT
+{
+ return year(y) / mwdl;
+}
+
+template <class Duration>
+struct fields;
+
+template <class CharT, class Traits, class Duration>
+std::basic_ostream<CharT, Traits>&
+to_stream(std::basic_ostream<CharT, Traits>& os, const CharT* fmt,
+ const fields<Duration>& fds, const std::string* abbrev = nullptr,
+ const std::chrono::seconds* offset_sec = nullptr);
+
+template <class CharT, class Traits, class Duration, class Alloc>
+std::basic_istream<CharT, Traits>&
+from_stream(std::basic_istream<CharT, Traits>& is, const CharT* fmt,
+ fields<Duration>& fds, std::basic_string<CharT, Traits, Alloc>* abbrev = nullptr,
+ std::chrono::minutes* offset = nullptr);
+
+// time_of_day
+
+enum {am = 1, pm};
+
+namespace detail
+{
+
+// width<n>::value is the number of fractional decimal digits in 1/n
+// width<0>::value and width<1>::value are defined to be 0
+// If 1/n takes more than 18 fractional decimal digits,
+// the result is truncated to 19.
+// Example: width<2>::value == 1
+// Example: width<3>::value == 19
+// Example: width<4>::value == 2
+// Example: width<10>::value == 1
+// Example: width<1000>::value == 3
+template <std::uint64_t n, std::uint64_t d = 10, unsigned w = 0,
+ bool should_continue = !(n < 2) && d != 0 && (w < 19)>
+struct width
+{
+ static CONSTDATA unsigned value = 1 + width<n, d%n*10, w+1>::value;
+};
+
+template <std::uint64_t n, std::uint64_t d, unsigned w>
+struct width<n, d, w, false>
+{
+ static CONSTDATA unsigned value = 0;
+};
+
+template <unsigned exp>
+struct static_pow10
+{
+private:
+ static CONSTDATA std::uint64_t h = static_pow10<exp/2>::value;
+public:
+ static CONSTDATA std::uint64_t value = h * h * (exp % 2 ? 10 : 1);
+};
+
+template <>
+struct static_pow10<0>
+{
+ static CONSTDATA std::uint64_t value = 1;
+};
+
+template <class Rep, unsigned w, bool in_range = (w < 19)>
+struct make_precision
+{
+ using type = std::chrono::duration<Rep,
+ std::ratio<1, static_pow10<w>::value>>;
+ static
<TRUNCATED>