mirror of
https://github.com/HowardHinnant/date.git
synced 2025-08-05 05:34:27 +02:00
Port ptz.h to C++20
This commit is contained in:
@@ -61,12 +61,30 @@
|
|||||||
// They are provided here as a non-trivial custom time zone example, and if you really
|
// 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.
|
// have to have Posix time zones, you're welcome to use this one.
|
||||||
|
|
||||||
#include "date/tz.h"
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
|
#include <cassert>
|
||||||
#include <cctype>
|
#include <cctype>
|
||||||
|
#include <chrono>
|
||||||
#include <ostream>
|
#include <ostream>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
|
#ifndef HAS_CHRONO_20
|
||||||
|
# if defined(_LIBCPP_VERSION) && _LIBCPP_VERSION <= 200100
|
||||||
|
# define HAS_CHRONO_20 0
|
||||||
|
# else
|
||||||
|
# define HAS_CHRONO_20 1
|
||||||
|
# endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if HAS_CHRONO_20
|
||||||
|
namespace chr = std::chrono;
|
||||||
|
# define HAS_STRING_VIEW 1
|
||||||
|
# include <format>
|
||||||
|
#else
|
||||||
|
# include "date/tz.h"
|
||||||
|
namespace chr = date;
|
||||||
|
#endif
|
||||||
|
|
||||||
namespace Posix
|
namespace Posix
|
||||||
{
|
{
|
||||||
|
|
||||||
@@ -97,8 +115,8 @@ class rule
|
|||||||
{
|
{
|
||||||
enum {off, J, M, N};
|
enum {off, J, M, N};
|
||||||
|
|
||||||
date::month m_;
|
chr::month m_;
|
||||||
date::weekday wd_;
|
chr::weekday wd_;
|
||||||
unsigned short n_ : 14;
|
unsigned short n_ : 14;
|
||||||
unsigned short mode_ : 2;
|
unsigned short mode_ : 2;
|
||||||
std::chrono::duration<std::int32_t> time_ = std::chrono::hours{2};
|
std::chrono::duration<std::int32_t> time_ = std::chrono::hours{2};
|
||||||
@@ -107,7 +125,7 @@ public:
|
|||||||
rule() : mode_(off) {}
|
rule() : mode_(off) {}
|
||||||
|
|
||||||
bool ok() const {return mode_ != off;}
|
bool ok() const {return mode_ != off;}
|
||||||
date::local_seconds operator()(date::year y) const;
|
chr::local_seconds operator()(chr::year y) const;
|
||||||
std::string to_string() const;
|
std::string to_string() const;
|
||||||
|
|
||||||
friend std::ostream& operator<<(std::ostream& os, const rule& r);
|
friend std::ostream& operator<<(std::ostream& os, const rule& r);
|
||||||
@@ -141,15 +159,15 @@ operator!=(const rule& x, const rule& y)
|
|||||||
}
|
}
|
||||||
|
|
||||||
inline
|
inline
|
||||||
date::local_seconds
|
chr::local_seconds
|
||||||
rule::operator()(date::year y) const
|
rule::operator()(chr::year y) const
|
||||||
{
|
{
|
||||||
using date::local_days;
|
using chr::local_days;
|
||||||
using date::January;
|
using chr::January;
|
||||||
using date::days;
|
using chr::days;
|
||||||
using date::last;
|
using chr::last;
|
||||||
using sec = std::chrono::seconds;
|
using sec = std::chrono::seconds;
|
||||||
date::local_seconds t;
|
chr::local_seconds t;
|
||||||
switch (mode_)
|
switch (mode_)
|
||||||
{
|
{
|
||||||
case J:
|
case J:
|
||||||
@@ -177,7 +195,7 @@ rule::to_string() const
|
|||||||
std::string nm;
|
std::string nm;
|
||||||
if (off != hours{2})
|
if (off != hours{2})
|
||||||
{
|
{
|
||||||
date::hh_mm_ss<seconds> offset{off};
|
chr::hh_mm_ss<seconds> offset{off};
|
||||||
nm = '/';
|
nm = '/';
|
||||||
nm += std::to_string(offset.hours().count());
|
nm += std::to_string(offset.hours().count());
|
||||||
if (offset.minutes() != minutes{0} || offset.seconds() != seconds{0})
|
if (offset.minutes() != minutes{0} || offset.seconds() != seconds{0})
|
||||||
@@ -230,17 +248,29 @@ operator<<(std::ostream& os, const rule& r)
|
|||||||
switch (r.mode_)
|
switch (r.mode_)
|
||||||
{
|
{
|
||||||
case rule::J:
|
case rule::J:
|
||||||
|
#if HAS_CHRONO_20
|
||||||
|
os << "J " << r.n_ << std::format("{:%T}", r.time_);
|
||||||
|
#else
|
||||||
os << 'J' << r.n_ << date::format(" %T", r.time_);
|
os << 'J' << r.n_ << date::format(" %T", r.time_);
|
||||||
|
#endif
|
||||||
break;
|
break;
|
||||||
case rule::M:
|
case rule::M:
|
||||||
if (r.n_ == 5)
|
if (r.n_ == 5)
|
||||||
os << r.m_/r.wd_[date::last];
|
os << r.m_/r.wd_[chr::last];
|
||||||
else
|
else
|
||||||
os << r.m_/r.wd_[r.n_];
|
os << r.m_/r.wd_[r.n_];
|
||||||
|
#if HAS_CHRONO_20
|
||||||
|
os << ' ' << std::format("{:%T}", r.time_);
|
||||||
|
#else
|
||||||
os << date::format(" %T", r.time_);
|
os << date::format(" %T", r.time_);
|
||||||
|
#endif
|
||||||
break;
|
break;
|
||||||
case rule::N:
|
case rule::N:
|
||||||
|
#if HAS_CHRONO_20
|
||||||
|
os << r.n_ << ' ' << std::format("{:%T}", r.time_);
|
||||||
|
#else
|
||||||
os << r.n_ << date::format(" %T", r.time_);
|
os << r.n_ << date::format(" %T", r.time_);
|
||||||
|
#endif
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
@@ -263,21 +293,21 @@ public:
|
|||||||
explicit time_zone(const detail::string_t& name);
|
explicit time_zone(const detail::string_t& name);
|
||||||
|
|
||||||
template <class Duration>
|
template <class Duration>
|
||||||
date::sys_info get_info(date::sys_time<Duration> st) const;
|
chr::sys_info get_info(chr::sys_time<Duration> st) const;
|
||||||
template <class Duration>
|
template <class Duration>
|
||||||
date::local_info get_info(date::local_time<Duration> tp) const;
|
chr::local_info get_info(chr::local_time<Duration> tp) const;
|
||||||
|
|
||||||
template <class Duration>
|
template <class Duration>
|
||||||
date::sys_time<typename std::common_type<Duration, std::chrono::seconds>::type>
|
chr::sys_time<typename std::common_type<Duration, std::chrono::seconds>::type>
|
||||||
to_sys(date::local_time<Duration> tp) const;
|
to_sys(chr::local_time<Duration> tp) const;
|
||||||
|
|
||||||
template <class Duration>
|
template <class Duration>
|
||||||
date::sys_time<typename std::common_type<Duration, std::chrono::seconds>::type>
|
chr::sys_time<typename std::common_type<Duration, std::chrono::seconds>::type>
|
||||||
to_sys(date::local_time<Duration> tp, date::choose z) const;
|
to_sys(chr::local_time<Duration> tp, chr::choose z) const;
|
||||||
|
|
||||||
template <class Duration>
|
template <class Duration>
|
||||||
date::local_time<typename std::common_type<Duration, std::chrono::seconds>::type>
|
chr::local_time<typename std::common_type<Duration, std::chrono::seconds>::type>
|
||||||
to_local(date::sys_time<Duration> tp) const;
|
to_local(chr::sys_time<Duration> tp) const;
|
||||||
|
|
||||||
friend std::ostream& operator<<(std::ostream& os, const time_zone& z);
|
friend std::ostream& operator<<(std::ostream& os, const time_zone& z);
|
||||||
|
|
||||||
@@ -288,68 +318,68 @@ public:
|
|||||||
friend bool operator==(const time_zone& x, const time_zone& y);
|
friend bool operator==(const time_zone& x, const time_zone& y);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
date::sys_seconds get_start(date::year y) const;
|
chr::sys_seconds get_start(chr::year y) const;
|
||||||
date::sys_seconds get_prev_start(date::year y) const;
|
chr::sys_seconds get_prev_start(chr::year y) const;
|
||||||
date::sys_seconds get_next_start(date::year y) const;
|
chr::sys_seconds get_next_start(chr::year y) const;
|
||||||
date::sys_seconds get_end(date::year y) const;
|
chr::sys_seconds get_end(chr::year y) const;
|
||||||
date::sys_seconds get_prev_end(date::year y) const;
|
chr::sys_seconds get_prev_end(chr::year y) const;
|
||||||
date::sys_seconds get_next_end(date::year y) const;
|
chr::sys_seconds get_next_end(chr::year y) const;
|
||||||
date::sys_info contant_offset() const;
|
chr::sys_info contant_offset() const;
|
||||||
};
|
};
|
||||||
|
|
||||||
inline
|
inline
|
||||||
date::sys_seconds
|
chr::sys_seconds
|
||||||
time_zone::get_start(date::year y) const
|
time_zone::get_start(chr::year y) const
|
||||||
{
|
{
|
||||||
return date::sys_seconds{(start_rule_(y) - offset_).time_since_epoch()};
|
return chr::sys_seconds{(start_rule_(y) - offset_).time_since_epoch()};
|
||||||
}
|
}
|
||||||
|
|
||||||
inline
|
inline
|
||||||
date::sys_seconds
|
chr::sys_seconds
|
||||||
time_zone::get_prev_start(date::year y) const
|
time_zone::get_prev_start(chr::year y) const
|
||||||
{
|
{
|
||||||
return date::sys_seconds{(start_rule_(--y) - offset_).time_since_epoch()};
|
return chr::sys_seconds{(start_rule_(--y) - offset_).time_since_epoch()};
|
||||||
}
|
}
|
||||||
|
|
||||||
inline
|
inline
|
||||||
date::sys_seconds
|
chr::sys_seconds
|
||||||
time_zone::get_next_start(date::year y) const
|
time_zone::get_next_start(chr::year y) const
|
||||||
{
|
{
|
||||||
return date::sys_seconds{(start_rule_(++y) - offset_).time_since_epoch()};
|
return chr::sys_seconds{(start_rule_(++y) - offset_).time_since_epoch()};
|
||||||
}
|
}
|
||||||
|
|
||||||
inline
|
inline
|
||||||
date::sys_seconds
|
chr::sys_seconds
|
||||||
time_zone::get_end(date::year y) const
|
time_zone::get_end(chr::year y) const
|
||||||
{
|
{
|
||||||
return date::sys_seconds{(end_rule_(y) - (offset_ + save_)).time_since_epoch()};
|
return chr::sys_seconds{(end_rule_(y) - (offset_ + save_)).time_since_epoch()};
|
||||||
}
|
}
|
||||||
|
|
||||||
inline
|
inline
|
||||||
date::sys_seconds
|
chr::sys_seconds
|
||||||
time_zone::get_prev_end(date::year y) const
|
time_zone::get_prev_end(chr::year y) const
|
||||||
{
|
{
|
||||||
return date::sys_seconds{(end_rule_(--y) - (offset_ + save_)).time_since_epoch()};
|
return chr::sys_seconds{(end_rule_(--y) - (offset_ + save_)).time_since_epoch()};
|
||||||
}
|
}
|
||||||
|
|
||||||
inline
|
inline
|
||||||
date::sys_seconds
|
chr::sys_seconds
|
||||||
time_zone::get_next_end(date::year y) const
|
time_zone::get_next_end(chr::year y) const
|
||||||
{
|
{
|
||||||
return date::sys_seconds{(end_rule_(++y) - (offset_ + save_)).time_since_epoch()};
|
return chr::sys_seconds{(end_rule_(++y) - (offset_ + save_)).time_since_epoch()};
|
||||||
}
|
}
|
||||||
|
|
||||||
inline
|
inline
|
||||||
date::sys_info
|
chr::sys_info
|
||||||
time_zone::contant_offset() const
|
time_zone::contant_offset() const
|
||||||
{
|
{
|
||||||
using date::year;
|
using chr::year;
|
||||||
using date::sys_info;
|
using chr::sys_info;
|
||||||
using date::sys_days;
|
using chr::sys_days;
|
||||||
using date::January;
|
using chr::January;
|
||||||
using date::December;
|
using chr::December;
|
||||||
using date::last;
|
using chr::last;
|
||||||
using date::days;
|
using chr::days;
|
||||||
using std::chrono::minutes;
|
using std::chrono::minutes;
|
||||||
sys_info r;
|
sys_info r;
|
||||||
r.begin = sys_days{year::min()/January/1};
|
r.begin = sys_days{year::min()/January/1};
|
||||||
@@ -364,7 +394,7 @@ time_zone::contant_offset() const
|
|||||||
{
|
{
|
||||||
r.abbrev = dst_abbrev_;
|
r.abbrev = dst_abbrev_;
|
||||||
r.offset = offset_ + save_;
|
r.offset = offset_ + save_;
|
||||||
r.save = date::ceil<minutes>(save_);
|
r.save = chr::ceil<minutes>(save_);
|
||||||
}
|
}
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
@@ -435,19 +465,19 @@ time_zone::time_zone(const detail::string_t& s)
|
|||||||
}
|
}
|
||||||
|
|
||||||
template <class Duration>
|
template <class Duration>
|
||||||
date::sys_info
|
chr::sys_info
|
||||||
time_zone::get_info(date::sys_time<Duration> st) const
|
time_zone::get_info(chr::sys_time<Duration> st) const
|
||||||
{
|
{
|
||||||
using date::sys_info;
|
using chr::sys_info;
|
||||||
using date::year_month_day;
|
using chr::year_month_day;
|
||||||
using date::sys_days;
|
using chr::sys_days;
|
||||||
using date::floor;
|
using chr::floor;
|
||||||
using date::ceil;
|
using chr::ceil;
|
||||||
using date::days;
|
using chr::days;
|
||||||
using date::year;
|
using chr::year;
|
||||||
using date::January;
|
using chr::January;
|
||||||
using date::December;
|
using chr::December;
|
||||||
using date::last;
|
using chr::last;
|
||||||
using std::chrono::minutes;
|
using std::chrono::minutes;
|
||||||
sys_info r{};
|
sys_info r{};
|
||||||
r.offset = offset_;
|
r.offset = offset_;
|
||||||
@@ -517,23 +547,23 @@ time_zone::get_info(date::sys_time<Duration> st) const
|
|||||||
}
|
}
|
||||||
|
|
||||||
template <class Duration>
|
template <class Duration>
|
||||||
date::local_info
|
chr::local_info
|
||||||
time_zone::get_info(date::local_time<Duration> tp) const
|
time_zone::get_info(chr::local_time<Duration> tp) const
|
||||||
{
|
{
|
||||||
using date::local_info;
|
using chr::local_info;
|
||||||
using date::year_month_day;
|
using chr::year_month_day;
|
||||||
using date::days;
|
using chr::days;
|
||||||
using date::sys_days;
|
using chr::sys_days;
|
||||||
using date::sys_seconds;
|
using chr::sys_seconds;
|
||||||
using date::year;
|
using chr::year;
|
||||||
using date::ceil;
|
using chr::ceil;
|
||||||
using date::January;
|
using chr::January;
|
||||||
using date::December;
|
using chr::December;
|
||||||
using date::last;
|
using chr::last;
|
||||||
using std::chrono::seconds;
|
using std::chrono::seconds;
|
||||||
using std::chrono::minutes;
|
using std::chrono::minutes;
|
||||||
local_info r{};
|
local_info r{};
|
||||||
using date::floor;
|
using chr::floor;
|
||||||
if (start_rule_.ok())
|
if (start_rule_.ok())
|
||||||
{
|
{
|
||||||
auto y = year_month_day{floor<days>(tp)}.year();
|
auto y = year_month_day{floor<days>(tp)}.year();
|
||||||
@@ -591,13 +621,13 @@ time_zone::get_info(date::local_time<Duration> tp) const
|
|||||||
}
|
}
|
||||||
|
|
||||||
template <class Duration>
|
template <class Duration>
|
||||||
date::sys_time<typename std::common_type<Duration, std::chrono::seconds>::type>
|
chr::sys_time<typename std::common_type<Duration, std::chrono::seconds>::type>
|
||||||
time_zone::to_sys(date::local_time<Duration> tp) const
|
time_zone::to_sys(chr::local_time<Duration> tp) const
|
||||||
{
|
{
|
||||||
using date::local_info;
|
using chr::local_info;
|
||||||
using date::sys_time;
|
using chr::sys_time;
|
||||||
using date::ambiguous_local_time;
|
using chr::ambiguous_local_time;
|
||||||
using date::nonexistent_local_time;
|
using chr::nonexistent_local_time;
|
||||||
auto i = get_info(tp);
|
auto i = get_info(tp);
|
||||||
if (i.result == local_info::nonexistent)
|
if (i.result == local_info::nonexistent)
|
||||||
throw nonexistent_local_time(tp, i);
|
throw nonexistent_local_time(tp, i);
|
||||||
@@ -607,12 +637,12 @@ time_zone::to_sys(date::local_time<Duration> tp) const
|
|||||||
}
|
}
|
||||||
|
|
||||||
template <class Duration>
|
template <class Duration>
|
||||||
date::sys_time<typename std::common_type<Duration, std::chrono::seconds>::type>
|
chr::sys_time<typename std::common_type<Duration, std::chrono::seconds>::type>
|
||||||
time_zone::to_sys(date::local_time<Duration> tp, date::choose z) const
|
time_zone::to_sys(chr::local_time<Duration> tp, chr::choose z) const
|
||||||
{
|
{
|
||||||
using date::local_info;
|
using chr::local_info;
|
||||||
using date::sys_time;
|
using chr::sys_time;
|
||||||
using date::choose;
|
using chr::choose;
|
||||||
auto i = get_info(tp);
|
auto i = get_info(tp);
|
||||||
if (i.result == local_info::nonexistent)
|
if (i.result == local_info::nonexistent)
|
||||||
{
|
{
|
||||||
@@ -627,10 +657,10 @@ time_zone::to_sys(date::local_time<Duration> tp, date::choose z) const
|
|||||||
}
|
}
|
||||||
|
|
||||||
template <class Duration>
|
template <class Duration>
|
||||||
date::local_time<typename std::common_type<Duration, std::chrono::seconds>::type>
|
chr::local_time<typename std::common_type<Duration, std::chrono::seconds>::type>
|
||||||
time_zone::to_local(date::sys_time<Duration> tp) const
|
time_zone::to_local(chr::sys_time<Duration> tp) const
|
||||||
{
|
{
|
||||||
using date::local_time;
|
using chr::local_time;
|
||||||
using std::chrono::seconds;
|
using std::chrono::seconds;
|
||||||
using LT = local_time<typename std::common_type<Duration, seconds>::type>;
|
using LT = local_time<typename std::common_type<Duration, seconds>::type>;
|
||||||
auto i = get_info(tp);
|
auto i = get_info(tp);
|
||||||
@@ -641,10 +671,15 @@ inline
|
|||||||
std::ostream&
|
std::ostream&
|
||||||
operator<<(std::ostream& os, const time_zone& z)
|
operator<<(std::ostream& os, const time_zone& z)
|
||||||
{
|
{
|
||||||
using date::operator<<;
|
using chr::operator<<;
|
||||||
os << '{';
|
os << '{';
|
||||||
|
#if HAS_CHRONO_20
|
||||||
|
os << z.std_abbrev_ << ", " << z.dst_abbrev_ << ", " << std::format("{:%T, }", z.offset_)
|
||||||
|
<< std::format("{:%T, [}", z.save_) << z.start_rule_ << ", " << z.end_rule_ << ")}";
|
||||||
|
#else
|
||||||
os << z.std_abbrev_ << ", " << z.dst_abbrev_ << date::format(", %T, ", z.offset_)
|
os << z.std_abbrev_ << ", " << z.dst_abbrev_ << date::format(", %T, ", z.offset_)
|
||||||
<< date::format("%T, [", z.save_) << z.start_rule_ << ", " << z.end_rule_ << ")}";
|
<< date::format("%T, [", z.save_) << z.start_rule_ << ", " << z.end_rule_ << ")}";
|
||||||
|
#endif
|
||||||
return os;
|
return os;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -652,7 +687,7 @@ inline
|
|||||||
std::string
|
std::string
|
||||||
time_zone::name() const
|
time_zone::name() const
|
||||||
{
|
{
|
||||||
using namespace date;
|
using namespace chr;
|
||||||
using namespace std::chrono;
|
using namespace std::chrono;
|
||||||
auto print_abbrev = [](std::string const& nm)
|
auto print_abbrev = [](std::string const& nm)
|
||||||
{
|
{
|
||||||
@@ -669,7 +704,7 @@ time_zone::name() const
|
|||||||
auto print_offset = [](seconds off)
|
auto print_offset = [](seconds off)
|
||||||
{
|
{
|
||||||
std::string nm;
|
std::string nm;
|
||||||
date::hh_mm_ss<seconds> offset{-off};
|
chr::hh_mm_ss<seconds> offset{-off};
|
||||||
if (offset.is_negative())
|
if (offset.is_negative())
|
||||||
nm += '-';
|
nm += '-';
|
||||||
nm += std::to_string(offset.hours().count());
|
nm += std::to_string(offset.hours().count());
|
||||||
@@ -746,8 +781,8 @@ inline
|
|||||||
unsigned
|
unsigned
|
||||||
read_date(const string_t& s, unsigned i, rule& r)
|
read_date(const string_t& s, unsigned i, rule& r)
|
||||||
{
|
{
|
||||||
using date::month;
|
using chr::month;
|
||||||
using date::weekday;
|
using chr::weekday;
|
||||||
if (i == s.size())
|
if (i == s.size())
|
||||||
throw_invalid(s, i, "Expected rule but found end of string");
|
throw_invalid(s, i, "Expected rule but found end of string");
|
||||||
if (s[i] == 'J')
|
if (s[i] == 'J')
|
||||||
@@ -911,7 +946,11 @@ read_unsigned(const string_t& s, unsigned i, unsigned limit, unsigned& u,
|
|||||||
|
|
||||||
} // namespace Posix
|
} // namespace Posix
|
||||||
|
|
||||||
|
#if HAS_CHRONO_20
|
||||||
|
namespace std::chrono
|
||||||
|
#else
|
||||||
namespace date
|
namespace date
|
||||||
|
#endif
|
||||||
{
|
{
|
||||||
|
|
||||||
template <>
|
template <>
|
||||||
@@ -947,6 +986,6 @@ struct zoned_traits<Posix::time_zone>
|
|||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace date
|
} // namespace chr
|
||||||
|
|
||||||
#endif // PTZ_H
|
#endif // PTZ_H
|
||||||
|
Reference in New Issue
Block a user