diff --git a/date.h b/date.h index 587b7b9..a9a54ff 100644 --- a/date.h +++ b/date.h @@ -6593,7 +6593,7 @@ parse(std::basic_istream& is, detail::parse(is, format.c_str(), tp, &abbrev, &offset); } -#endif +#endif // use in >> parse(format, x); instead // const CharT* formats @@ -6801,7 +6801,188 @@ parse(std::basic_istream& is, const CharT* format, detail::parse(is, format, tp, &abbrev, &offset); } -#endif +#endif // use in >> parse(format, x); instead + +template +void +to_stream(std::basic_ostream& os, const CharT* fmt, + const year_month_day& ymd) +{ + using CT = std::chrono::seconds; + detail::fields fds{ymd, time_of_day{}}; + detail::to_stream(os, fmt, fds); +} + +template +std::basic_string +format(const std::locale& loc, const CharT* fmt, const year_month_day& ymd) +{ + std::basic_ostringstream os; + os.imbue(loc); + to_stream(os, fmt, ymd); + return os.str(); +} + +template +std::basic_string +format(const CharT* fmt, const year_month_day& ymd) +{ + std::basic_ostringstream os; + to_stream(os, fmt, ymd); + return os.str(); +} + +template +std::basic_string +format(const std::locale& loc, const std::basic_string& fmt, + const year_month_day& ymd) +{ + std::basic_ostringstream os; + os.imbue(loc); + to_stream(os, fmt.c_str(), ymd); + return os.str(); +} + +template +std::basic_string +format(const std::basic_string& fmt, const year_month_day& ymd) +{ + std::basic_ostringstream os; + to_stream(os, fmt.c_str(), ymd); + return os.str(); +} + +namespace detail +{ + +template > +struct parse_ymd_manip +{ + const std::basic_string format_; + year_month_day& ymd_; + std::basic_string* abbrev_; + std::chrono::minutes* offset_; + +public: + parse_ymd_manip(std::basic_string format, + year_month_day& ymd, std::basic_string* abbrev = nullptr, + std::chrono::minutes* offset = nullptr) + : format_(std::move(format)) + , ymd_(ymd) + , abbrev_(abbrev) + , offset_(offset) + {} + +}; + +template +inline +std::basic_istream& +operator>>(std::basic_istream& is, + const parse_ymd_manip& x) +{ + using namespace std; + using namespace std::chrono; + using CT = seconds; + fields fds{}; + parse(is, x.format_.c_str(), fds, x.abbrev_, x.offset_); + if (!fds.ymd.ok()) + is.setstate(ios::failbit); + if (!is.fail()) + x.ymd_ = fds.ymd; + return is; +} + +} // namespace detail + +template +inline +detail::parse_ymd_manip +parse(const std::basic_string& format, year_month_day& ymd) +{ + return {format, ymd}; +} + +template +inline +detail::parse_ymd_manip +parse(const std::basic_string& format, year_month_day& ymd, + std::basic_string& abbrev) +{ + return {format, ymd, &abbrev}; +} + +template +inline +detail::parse_ymd_manip +parse(const std::basic_string& format, year_month_day& ymd, + std::chrono::minutes& offset) +{ + return {format, ymd, nullptr, &offset}; +} + +template +inline +detail::parse_ymd_manip +parse(const std::basic_string& format, year_month_day& ymd, + std::basic_string& abbrev, std::chrono::minutes& offset) +{ + return {format, ymd, &abbrev, &offset}; +} + +template +inline +detail::parse_ymd_manip +parse(const std::basic_string& format, year_month_day& ymd, + std::chrono::minutes& offset, std::basic_string& abbrev) +{ + return {format, ymd, &abbrev, &offset}; +} + +// const CharT* formats + +template +inline +detail::parse_ymd_manip +parse(const CharT* format, year_month_day& ymd) +{ + return {format, ymd}; +} + +template +inline +detail::parse_ymd_manip +parse(const CharT* format, year_month_day& ymd, + std::basic_string& abbrev) +{ + return {format, ymd, &abbrev}; +} + +template +inline +detail::parse_ymd_manip +parse(const CharT* format, year_month_day& ymd, std::chrono::minutes& offset) +{ + return {format, ymd, nullptr, &offset}; +} + +template +inline +detail::parse_ymd_manip +parse(const CharT* format, year_month_day& ymd, + std::basic_string& abbrev, std::chrono::minutes& offset) +{ + return {format, ymd, &abbrev, &offset}; +} + +template +inline +detail::parse_ymd_manip +parse(const CharT* format, year_month_day& ymd, + std::chrono::minutes& offset, std::basic_string& abbrev) +{ + return {format, ymd, &abbrev, &offset}; +} } // namespace date diff --git a/tz.h b/tz.h index c4ac1c7..74adf50 100644 --- a/tz.h +++ b/tz.h @@ -1387,15 +1387,205 @@ tai_clock::now() NOEXCEPT return to_tai_time(system_clock::now()); } +template +void +to_stream(std::basic_ostream& os, const CharT* fmt, + const tai_time& t) +{ + using namespace std; + using namespace std::chrono; + using CT = typename common_type::type; + const string abbrev("TAI"); + CONSTDATA seconds offset{0}; + auto tp = sys_time{t.time_since_epoch()} - + (sys_days(year{1970}/jan/1) - sys_days(year{1958}/jan/1)); + auto const sd = floor(tp); + year_month_day ymd = sd; + auto time = make_time(tp - sd); + detail::fields fds{ymd, time}; + detail::to_stream(os, fmt, fds, &abbrev, &offset); +} + template std::basic_ostream& operator<<(std::basic_ostream& os, const tai_time& t) { + to_stream(os, "%F %T", t); + return os; +} + +template +std::basic_string +format(const std::locale& loc, const CharT* fmt, const tai_time& tp) +{ + std::basic_ostringstream os; + os.imbue(loc); + to_stream(os, fmt, tp); + return os.str(); +} + +template +std::basic_string +format(const CharT* fmt, const tai_time& tp) +{ + std::basic_ostringstream os; + to_stream(os, fmt, tp); + return os.str(); +} + +template +std::basic_string +format(const std::locale& loc, const std::basic_string& fmt, + const tai_time& tp) +{ + std::basic_ostringstream os; + os.imbue(loc); + to_stream(os, fmt.c_str(), tp); + return os.str(); +} + +template +std::basic_string +format(const std::basic_string& fmt, const tai_time& tp) +{ + std::basic_ostringstream os; + to_stream(os, fmt.c_str(), tp); + return os.str(); +} + +namespace detail +{ + +template > +struct parse_tai_manip +{ + const std::basic_string format_; + tai_time& tp_; + std::basic_string* abbrev_; + std::chrono::minutes* offset_; + +public: + parse_tai_manip(std::basic_string format, + tai_time& tp, std::basic_string* abbrev = nullptr, + std::chrono::minutes* offset = nullptr) + : format_(std::move(format)) + , tp_(tp) + , abbrev_(abbrev) + , offset_(offset) + {} + +}; + +template +std::basic_istream& +operator>>(std::basic_istream& is, + const parse_tai_manip& x) +{ + using namespace std; using namespace std::chrono; - using duration = typename std::common_type::type; - auto tp = sys_time{t.time_since_epoch()} - - (sys_days(year{1970}/jan/1) - sys_days(year{1958}/jan/1)); - return os << tp; + using CT = typename common_type::type; + minutes offset{}; + auto offptr = x.offset_ ? x.offset_ : &offset; + fields fds{}; + parse(is, x.format_.c_str(), fds, x.abbrev_, offptr); + if (!fds.ymd.ok()) + is.setstate(ios::failbit); + if (!is.fail()) + x.tp_ = tai_time{duration_cast( + (sys_days(fds.ymd) + fds.tod.to_duration() + (sys_days(year{1970}/jan/1) - + sys_days(year{1958}/jan/1)) - *offptr).time_since_epoch())}; + return is; +} + +} // namespace detail + +template +inline +detail::parse_tai_manip +parse(const std::basic_string& format, tai_time& tp) +{ + return {format, tp}; +} + +template +inline +detail::parse_tai_manip +parse(const std::basic_string& format, tai_time& tp, + std::basic_string& abbrev) +{ + return {format, tp, &abbrev}; +} + +template +inline +detail::parse_tai_manip +parse(const std::basic_string& format, tai_time& tp, + std::chrono::minutes& offset) +{ + return {format, tp, nullptr, &offset}; +} + +template +inline +detail::parse_tai_manip +parse(const std::basic_string& format, tai_time& tp, + std::basic_string& abbrev, std::chrono::minutes& offset) +{ + return {format, tp, &abbrev, &offset}; +} + +template +inline +detail::parse_tai_manip +parse(const std::basic_string& format, tai_time& tp, + std::chrono::minutes& offset, std::basic_string& abbrev) +{ + return {format, tp, &abbrev, &offset}; +} + +// const CharT* formats + +template +inline +detail::parse_tai_manip +parse(const CharT* format, tai_time& tp) +{ + return {format, tp}; +} + +template +inline +detail::parse_tai_manip +parse(const CharT* format, tai_time& tp, + std::basic_string& abbrev) +{ + return {format, tp, &abbrev}; +} + +template +inline +detail::parse_tai_manip +parse(const CharT* format, tai_time& tp, std::chrono::minutes& offset) +{ + return {format, tp, nullptr, &offset}; +} + +template +inline +detail::parse_tai_manip +parse(const CharT* format, tai_time& tp, + std::basic_string& abbrev, std::chrono::minutes& offset) +{ + return {format, tp, &abbrev, &offset}; +} + +template +inline +detail::parse_tai_manip +parse(const CharT* format, tai_time& tp, + std::chrono::minutes& offset, std::basic_string& abbrev) +{ + return {format, tp, &abbrev, &offset}; } // gps_clock @@ -1455,15 +1645,206 @@ gps_clock::now() NOEXCEPT return to_gps_time(system_clock::now()); } +template +void +to_stream(std::basic_ostream& os, const CharT* fmt, + const gps_time& t) +{ + using namespace std; + using namespace std::chrono; + using CT = typename common_type::type; + const string abbrev("GPS"); + CONSTDATA seconds offset{0}; + auto tp = sys_time{t.time_since_epoch()} + + (sys_days(year{1980}/jan/sun[1]) - sys_days(year{1970}/jan/1)); + auto const sd = floor(tp); + year_month_day ymd = sd; + auto time = make_time(tp - sd); + detail::fields fds{ymd, time}; + detail::to_stream(os, fmt, fds, &abbrev, &offset); +} + template std::basic_ostream& operator<<(std::basic_ostream& os, const gps_time& t) { + to_stream(os, "%F %T", t); + return os; +} + +template +std::basic_string +format(const std::locale& loc, const CharT* fmt, const gps_time& tp) +{ + std::basic_ostringstream os; + os.imbue(loc); + to_stream(os, fmt, tp); + return os.str(); +} + +template +std::basic_string +format(const CharT* fmt, const gps_time& tp) +{ + std::basic_ostringstream os; + to_stream(os, fmt, tp); + return os.str(); +} + +template +std::basic_string +format(const std::locale& loc, const std::basic_string& fmt, + const gps_time& tp) +{ + std::basic_ostringstream os; + os.imbue(loc); + to_stream(os, fmt.c_str(), tp); + return os.str(); +} + +template +std::basic_string +format(const std::basic_string& fmt, const gps_time& tp) +{ + std::basic_ostringstream os; + to_stream(os, fmt.c_str(), tp); + return os.str(); +} + +namespace detail +{ + +template > +struct parse_gps_manip +{ + const std::basic_string format_; + gps_time& tp_; + std::basic_string* abbrev_; + std::chrono::minutes* offset_; + +public: + parse_gps_manip(std::basic_string format, + gps_time& tp, std::basic_string* abbrev = nullptr, + std::chrono::minutes* offset = nullptr) + : format_(std::move(format)) + , tp_(tp) + , abbrev_(abbrev) + , offset_(offset) + {} + +}; + +template +std::basic_istream& +operator>>(std::basic_istream& is, + const parse_gps_manip& x) +{ + using namespace std; using namespace std::chrono; - using duration = typename std::common_type::type; - auto tp = sys_time{t.time_since_epoch()} + - (sys_days(year{1980}/jan/sun[1]) - sys_days(year{1970}/jan/1)); - return os << tp; + using CT = typename common_type::type; + minutes offset{}; + auto offptr = x.offset_ ? x.offset_ : &offset; + fields fds{}; + parse(is, x.format_.c_str(), fds, x.abbrev_, offptr); + if (!fds.ymd.ok()) + is.setstate(ios::failbit); + if (!is.fail()) + x.tp_ = gps_time{duration_cast( + (sys_days(fds.ymd) + fds.tod.to_duration() - + (sys_days(year{1980}/jan/sun[1]) - + sys_days(year{1970}/jan/1)) - *offptr).time_since_epoch())}; + return is; +} + +} // namespace detail + +template +inline +detail::parse_gps_manip +parse(const std::basic_string& format, gps_time& tp) +{ + return {format, tp}; +} + +template +inline +detail::parse_gps_manip +parse(const std::basic_string& format, gps_time& tp, + std::basic_string& abbrev) +{ + return {format, tp, &abbrev}; +} + +template +inline +detail::parse_gps_manip +parse(const std::basic_string& format, gps_time& tp, + std::chrono::minutes& offset) +{ + return {format, tp, nullptr, &offset}; +} + +template +inline +detail::parse_gps_manip +parse(const std::basic_string& format, gps_time& tp, + std::basic_string& abbrev, std::chrono::minutes& offset) +{ + return {format, tp, &abbrev, &offset}; +} + +template +inline +detail::parse_gps_manip +parse(const std::basic_string& format, gps_time& tp, + std::chrono::minutes& offset, std::basic_string& abbrev) +{ + return {format, tp, &abbrev, &offset}; +} + +// const CharT* formats + +template +inline +detail::parse_gps_manip +parse(const CharT* format, gps_time& tp) +{ + return {format, tp}; +} + +template +inline +detail::parse_gps_manip +parse(const CharT* format, gps_time& tp, + std::basic_string& abbrev) +{ + return {format, tp, &abbrev}; +} + +template +inline +detail::parse_gps_manip +parse(const CharT* format, gps_time& tp, std::chrono::minutes& offset) +{ + return {format, tp, nullptr, &offset}; +} + +template +inline +detail::parse_gps_manip +parse(const CharT* format, gps_time& tp, + std::basic_string& abbrev, std::chrono::minutes& offset) +{ + return {format, tp, &abbrev, &offset}; +} + +template +inline +detail::parse_gps_manip +parse(const CharT* format, gps_time& tp, + std::chrono::minutes& offset, std::basic_string& abbrev) +{ + return {format, tp, &abbrev, &offset}; } template