forked from HowardHinnant/date
Initial commit
This commit is contained in:
550
tz.h
Normal file
550
tz.h
Normal file
@@ -0,0 +1,550 @@
|
||||
#ifndef TZ_H
|
||||
#define TZ_H
|
||||
|
||||
// Howard Hinnant
|
||||
// This work is licensed under a Creative Commons Attribution 4.0 International License.
|
||||
// http://creativecommons.org/licenses/by/4.0/
|
||||
|
||||
// Get more recent database at http://www.iana.org/time-zones
|
||||
|
||||
// Questions:
|
||||
// 1. Reload database.
|
||||
// 4. Is the utc to sys renaming complete? Was it done correctly?
|
||||
|
||||
#include "date.h"
|
||||
|
||||
#include <algorithm>
|
||||
#include <cassert>
|
||||
#include <chrono>
|
||||
#include <cstdint>
|
||||
#include <istream>
|
||||
#include <ostream>
|
||||
#include <ratio>
|
||||
#include <sstream>
|
||||
#include <stdexcept>
|
||||
#include <string>
|
||||
#include <type_traits>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
namespace date
|
||||
{
|
||||
|
||||
using seconds_point = std::chrono::time_point<std::chrono::system_clock,
|
||||
std::chrono::seconds>;
|
||||
|
||||
enum class tz {utc, local, standard};
|
||||
enum class choose {earliest, latest};
|
||||
|
||||
class nonexistent_local_time
|
||||
: public std::runtime_error
|
||||
{
|
||||
public:
|
||||
template <class Rep, class Period>
|
||||
nonexistent_local_time(std::chrono::time_point<std::chrono::system_clock,
|
||||
std::chrono::duration<Rep, Period>> tp,
|
||||
seconds_point first, const std::string& first_abrev,
|
||||
seconds_point last, const std::string& last_abrev,
|
||||
seconds_point time_sys);
|
||||
|
||||
private:
|
||||
template <class Rep, class Period>
|
||||
static
|
||||
std::string
|
||||
make_msg(std::chrono::time_point<std::chrono::system_clock,
|
||||
std::chrono::duration<Rep, Period>> tp,
|
||||
seconds_point first, const std::string& first_abrev,
|
||||
seconds_point last, const std::string& last_abrev,
|
||||
seconds_point time_sys);
|
||||
};
|
||||
|
||||
template <class Rep, class Period>
|
||||
inline
|
||||
nonexistent_local_time::nonexistent_local_time(
|
||||
std::chrono::time_point<std::chrono::system_clock,
|
||||
std::chrono::duration<Rep, Period>> tp,
|
||||
seconds_point first, const std::string& first_abrev,
|
||||
seconds_point last, const std::string& last_abrev,
|
||||
seconds_point time_sys)
|
||||
: std::runtime_error(make_msg(tp, first, first_abrev, last, last_abrev, time_sys))
|
||||
{}
|
||||
|
||||
template <class Rep, class Period>
|
||||
std::string
|
||||
nonexistent_local_time::make_msg(std::chrono::time_point<std::chrono::system_clock,
|
||||
std::chrono::duration<Rep, Period>> tp,
|
||||
seconds_point first, const std::string& first_abrev,
|
||||
seconds_point last, const std::string& last_abrev,
|
||||
seconds_point time_sys)
|
||||
{
|
||||
using namespace date;
|
||||
std::ostringstream os;
|
||||
os << tp << " is in a gap between\n"
|
||||
<< first << ' ' << first_abrev << " and\n"
|
||||
<< last << ' ' << last_abrev
|
||||
<< " which are both equivalent to\n"
|
||||
<< time_sys << " UTC";
|
||||
return os.str();
|
||||
}
|
||||
|
||||
class ambiguous_local_time
|
||||
: public std::runtime_error
|
||||
{
|
||||
public:
|
||||
template <class Rep, class Period>
|
||||
ambiguous_local_time(std::chrono::time_point<std::chrono::system_clock,
|
||||
std::chrono::duration<Rep, Period>> tp,
|
||||
std::chrono::seconds first_offset,
|
||||
const std::string& first_abrev,
|
||||
std::chrono::seconds second_offset,
|
||||
const std::string& second_abrev);
|
||||
|
||||
private:
|
||||
template <class Rep, class Period>
|
||||
static
|
||||
std::string
|
||||
make_msg(std::chrono::time_point<std::chrono::system_clock,
|
||||
std::chrono::duration<Rep, Period>> tp,
|
||||
std::chrono::seconds first_offset, const std::string& first_abrev,
|
||||
std::chrono::seconds second_offset, const std::string& second_abrev);
|
||||
};
|
||||
|
||||
template <class Rep, class Period>
|
||||
inline
|
||||
ambiguous_local_time::ambiguous_local_time(
|
||||
std::chrono::time_point<std::chrono::system_clock,
|
||||
std::chrono::duration<Rep, Period>> tp,
|
||||
std::chrono::seconds first_offset,
|
||||
const std::string& first_abrev,
|
||||
std::chrono::seconds second_offset,
|
||||
const std::string& second_abrev)
|
||||
: std::runtime_error(make_msg(tp, first_offset, first_abrev, second_offset,
|
||||
second_abrev))
|
||||
{}
|
||||
|
||||
template <class Rep, class Period>
|
||||
std::string
|
||||
ambiguous_local_time::make_msg(std::chrono::time_point<std::chrono::system_clock,
|
||||
std::chrono::duration<Rep, Period>> tp,
|
||||
std::chrono::seconds first_offset,
|
||||
const std::string& first_abrev,
|
||||
std::chrono::seconds second_offset,
|
||||
const std::string& second_abrev)
|
||||
{
|
||||
using namespace date;
|
||||
std::ostringstream os;
|
||||
os << tp << " is ambiguous. It could be\n"
|
||||
<< tp << ' ' << first_abrev << " == " << tp - first_offset << " UTC or\n"
|
||||
<< tp << ' ' << second_abrev << " == " << tp - second_offset << " UTC";
|
||||
return os.str();
|
||||
}
|
||||
|
||||
class Rule;
|
||||
|
||||
struct Info
|
||||
{
|
||||
seconds_point begin;
|
||||
seconds_point end;
|
||||
std::chrono::seconds offset;
|
||||
std::chrono::minutes save;
|
||||
std::string abbrev;
|
||||
};
|
||||
|
||||
std::ostream&
|
||||
operator<<(std::ostream& os, const Info& r);
|
||||
|
||||
class Zone
|
||||
{
|
||||
private:
|
||||
struct zonelet;
|
||||
|
||||
std::string name_;
|
||||
std::vector<zonelet> zonelets_;
|
||||
|
||||
public:
|
||||
explicit Zone(const std::string& s);
|
||||
|
||||
const std::string& name() const {return name_;}
|
||||
Info get_info(std::chrono::system_clock::time_point tp, tz timezone) const;
|
||||
|
||||
template <class Rep, class Period>
|
||||
Info
|
||||
get_info(std::chrono::time_point<std::chrono::system_clock,
|
||||
std::chrono::duration<Rep, Period>> tp,
|
||||
tz timezone) const
|
||||
{
|
||||
using namespace std::chrono;
|
||||
return get_info(floor<system_clock::duration>(tp), timezone);
|
||||
}
|
||||
|
||||
template <class Rep, class Period>
|
||||
std::chrono::time_point<std::chrono::system_clock,
|
||||
typename std::common_type<std::chrono::duration<Rep, Period>,
|
||||
std::chrono::seconds>::type>
|
||||
to_sys(std::chrono::time_point<std::chrono::system_clock,
|
||||
std::chrono::duration<Rep, Period>> tp) const;
|
||||
|
||||
template <class Rep, class Period>
|
||||
std::chrono::time_point<std::chrono::system_clock,
|
||||
typename std::common_type<std::chrono::duration<Rep, Period>,
|
||||
std::chrono::seconds>::type>
|
||||
to_sys(std::chrono::time_point<std::chrono::system_clock,
|
||||
std::chrono::duration<Rep, Period>> tp,
|
||||
choose z) const;
|
||||
|
||||
template <class Rep, class Period>
|
||||
std::pair
|
||||
<
|
||||
std::chrono::time_point<std::chrono::system_clock,
|
||||
typename std::common_type<std::chrono::duration<Rep, Period>,
|
||||
std::chrono::seconds>::type>,
|
||||
std::string
|
||||
>
|
||||
to_local(std::chrono::time_point<std::chrono::system_clock,
|
||||
std::chrono::duration<Rep, Period>> tp) const;
|
||||
|
||||
friend bool operator==(const Zone& x, const Zone& y);
|
||||
friend bool operator< (const Zone& x, const Zone& y);
|
||||
friend std::ostream& operator<<(std::ostream& os, const Zone& z);
|
||||
|
||||
void add(const std::string& s);
|
||||
void adjust_infos(const std::vector<Rule>& rules);
|
||||
|
||||
private:
|
||||
void parse_info(std::istream& in);
|
||||
|
||||
template <class Rep, class Period, bool b>
|
||||
std::chrono::time_point<std::chrono::system_clock,
|
||||
typename std::common_type<std::chrono::duration<Rep, Period>,
|
||||
std::chrono::seconds>::type>
|
||||
to_sys_impl(std::chrono::time_point<std::chrono::system_clock,
|
||||
std::chrono::duration<Rep, Period>> tp,
|
||||
choose z, std::integral_constant<bool, b> do_throw) const;
|
||||
};
|
||||
|
||||
template <class Rep, class Period>
|
||||
inline
|
||||
std::chrono::time_point<std::chrono::system_clock,
|
||||
typename std::common_type<std::chrono::duration<Rep, Period>,
|
||||
std::chrono::seconds>::type>
|
||||
Zone::to_sys(std::chrono::time_point<std::chrono::system_clock,
|
||||
std::chrono::duration<Rep, Period>> tp) const
|
||||
{
|
||||
return to_sys_impl(tp, choose{}, std::true_type{});
|
||||
}
|
||||
|
||||
template <class Rep, class Period>
|
||||
inline
|
||||
std::chrono::time_point<std::chrono::system_clock,
|
||||
typename std::common_type<std::chrono::duration<Rep, Period>,
|
||||
std::chrono::seconds>::type>
|
||||
Zone::to_sys(std::chrono::time_point<std::chrono::system_clock,
|
||||
std::chrono::duration<Rep, Period>> tp, choose z) const
|
||||
{
|
||||
return to_sys_impl(tp, z, std::false_type{});
|
||||
}
|
||||
|
||||
template <class Rep, class Period>
|
||||
inline
|
||||
std::pair
|
||||
<
|
||||
std::chrono::time_point<std::chrono::system_clock,
|
||||
typename std::common_type<std::chrono::duration<Rep, Period>,
|
||||
std::chrono::seconds>::type>,
|
||||
std::string
|
||||
>
|
||||
Zone::to_local(std::chrono::time_point<std::chrono::system_clock,
|
||||
std::chrono::duration<Rep, Period>> tp) const
|
||||
{
|
||||
auto const i = get_info(tp, tz::utc);
|
||||
return {tp + i.offset, i.abbrev};
|
||||
}
|
||||
|
||||
inline bool operator==(const Zone& x, const Zone& y) {return x.name_ == y.name_;}
|
||||
inline bool operator< (const Zone& x, const Zone& y) {return x.name_ < y.name_;}
|
||||
|
||||
inline bool operator!=(const Zone& x, const Zone& y) {return !(x == y);}
|
||||
inline bool operator> (const Zone& x, const Zone& y) {return y < x;}
|
||||
inline bool operator<=(const Zone& x, const Zone& y) {return !(y < x);}
|
||||
inline bool operator>=(const Zone& x, const Zone& y) {return !(x < y);}
|
||||
|
||||
template <class Rep, class Period, bool b>
|
||||
std::chrono::time_point<std::chrono::system_clock,
|
||||
typename std::common_type<std::chrono::duration<Rep, Period>,
|
||||
std::chrono::seconds>::type>
|
||||
Zone::to_sys_impl(std::chrono::time_point<std::chrono::system_clock,
|
||||
std::chrono::duration<Rep, Period>> tp,
|
||||
choose z, std::integral_constant<bool, b> do_throw) const
|
||||
{
|
||||
using namespace date;
|
||||
using namespace std::chrono;
|
||||
auto i = get_info(tp, tz::local);
|
||||
auto tp_sys = tp - i.offset;
|
||||
if (tp_sys - i.begin <= days{1})
|
||||
{
|
||||
if (tp < i.begin + i.offset)
|
||||
{
|
||||
if (do_throw)
|
||||
{
|
||||
auto prev = get_info(i.begin - seconds{1}, tz::utc);
|
||||
throw nonexistent_local_time(tp, i.begin + prev.offset, prev.abbrev,
|
||||
i.begin + i.offset, i.abbrev, i.begin);
|
||||
}
|
||||
return i.begin;
|
||||
}
|
||||
assert(tp >= i.begin + get_info(i.begin - seconds{1}, tz::utc).offset);
|
||||
}
|
||||
if (i.end - tp_sys <= days{1})
|
||||
{
|
||||
assert(tp < i.end + i.offset);
|
||||
auto next = get_info(i.end, tz::utc);
|
||||
if (tp >= i.end + next.offset)
|
||||
{
|
||||
if (do_throw)
|
||||
throw ambiguous_local_time(tp, i.offset, i.abbrev,
|
||||
next.offset, next.abbrev);
|
||||
if (z == choose::earliest)
|
||||
return tp_sys;
|
||||
return tp - next.offset;
|
||||
}
|
||||
}
|
||||
return tp_sys;
|
||||
}
|
||||
|
||||
class Link
|
||||
{
|
||||
private:
|
||||
std::string name_;
|
||||
std::string target_;
|
||||
public:
|
||||
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 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);}
|
||||
|
||||
class Leap
|
||||
{
|
||||
private:
|
||||
seconds_point date_;
|
||||
|
||||
public:
|
||||
explicit Leap(const std::string& s);
|
||||
|
||||
seconds_point 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 std::chrono::time_point<std::chrono::system_clock, Duration>& y)
|
||||
{
|
||||
return x.date_ == y;
|
||||
}
|
||||
|
||||
template <class Duration>
|
||||
friend
|
||||
bool
|
||||
operator< (const Leap& x,
|
||||
const std::chrono::time_point<std::chrono::system_clock, Duration>& y)
|
||||
{
|
||||
return x.date_ < y;
|
||||
}
|
||||
|
||||
template <class Duration>
|
||||
friend
|
||||
bool
|
||||
operator< (const std::chrono::time_point<std::chrono::system_clock, Duration>& x,
|
||||
const Leap& y)
|
||||
{
|
||||
return x < y.date_;
|
||||
}
|
||||
|
||||
friend 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 std::chrono::time_point<std::chrono::system_clock, Duration>& x,
|
||||
const Leap& y)
|
||||
{
|
||||
return y == x;
|
||||
}
|
||||
|
||||
template <class Duration>
|
||||
inline
|
||||
bool
|
||||
operator!=(const Leap& x,
|
||||
const std::chrono::time_point<std::chrono::system_clock, Duration>& y)
|
||||
{
|
||||
return !(x == y);
|
||||
}
|
||||
|
||||
template <class Duration>
|
||||
inline
|
||||
bool
|
||||
operator!=(const std::chrono::time_point<std::chrono::system_clock, Duration>& x,
|
||||
const Leap& y)
|
||||
{
|
||||
return !(x == y);
|
||||
}
|
||||
|
||||
template <class Duration>
|
||||
inline
|
||||
bool
|
||||
operator> (const Leap& x,
|
||||
const std::chrono::time_point<std::chrono::system_clock, Duration>& y)
|
||||
{
|
||||
return y < x;
|
||||
}
|
||||
|
||||
template <class Duration>
|
||||
inline
|
||||
bool
|
||||
operator> (const std::chrono::time_point<std::chrono::system_clock, Duration>& x,
|
||||
const Leap& y)
|
||||
{
|
||||
return y < x;
|
||||
}
|
||||
|
||||
template <class Duration>
|
||||
inline
|
||||
bool
|
||||
operator<=(const Leap& x,
|
||||
const std::chrono::time_point<std::chrono::system_clock, Duration>& y)
|
||||
{
|
||||
return !(y < x);
|
||||
}
|
||||
|
||||
template <class Duration>
|
||||
inline
|
||||
bool
|
||||
operator<=(const std::chrono::time_point<std::chrono::system_clock, Duration>& x,
|
||||
const Leap& y)
|
||||
{
|
||||
return !(y < x);
|
||||
}
|
||||
|
||||
template <class Duration>
|
||||
inline
|
||||
bool
|
||||
operator>=(const Leap& x,
|
||||
const std::chrono::time_point<std::chrono::system_clock, Duration>& y)
|
||||
{
|
||||
return !(x < y);
|
||||
}
|
||||
|
||||
template <class Duration>
|
||||
inline
|
||||
bool
|
||||
operator>=(const std::chrono::time_point<std::chrono::system_clock, Duration>& x,
|
||||
const Leap& y)
|
||||
{
|
||||
return !(x < y);
|
||||
}
|
||||
|
||||
struct TZ_DB
|
||||
{
|
||||
std::vector<Zone> zones;
|
||||
std::vector<Link> links;
|
||||
std::vector<Leap> leaps;
|
||||
std::vector<Rule> rules;
|
||||
|
||||
TZ_DB() = default;
|
||||
TZ_DB(TZ_DB&&) = default;
|
||||
TZ_DB& operator=(TZ_DB&&) = default;
|
||||
};
|
||||
|
||||
std::ostream& operator<<(std::ostream& os, const TZ_DB& db);
|
||||
|
||||
const TZ_DB& get_tzdb();
|
||||
const TZ_DB& reload_tzdb();
|
||||
const TZ_DB& reload_tzdb(const std::string& new_install);
|
||||
|
||||
const Zone* locate_zone(const std::string& tz_name);
|
||||
const Zone* current_timezone();
|
||||
|
||||
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 = true;
|
||||
|
||||
static time_point now() noexcept;
|
||||
|
||||
template <class Duration>
|
||||
static
|
||||
std::chrono::time_point<utc_clock,
|
||||
typename std::common_type<Duration, std::chrono::seconds>::type>
|
||||
sys_to_utc(std::chrono::time_point<std::chrono::system_clock, Duration> t);
|
||||
|
||||
template <class Duration>
|
||||
static
|
||||
std::chrono::time_point<std::chrono::system_clock,
|
||||
typename std::common_type<Duration, std::chrono::seconds>::type>
|
||||
utc_to_sys(std::chrono::time_point<utc_clock, Duration> t);
|
||||
};
|
||||
|
||||
inline
|
||||
utc_clock::time_point
|
||||
utc_clock::now() noexcept
|
||||
{
|
||||
using namespace std::chrono;
|
||||
return sys_to_utc(system_clock::now());
|
||||
}
|
||||
|
||||
template <class Duration>
|
||||
std::chrono::time_point<utc_clock,
|
||||
typename std::common_type<Duration, std::chrono::seconds>::type>
|
||||
utc_clock::sys_to_utc(std::chrono::time_point<std::chrono::system_clock, Duration> t)
|
||||
{
|
||||
using namespace std::chrono;
|
||||
using duration = typename std::common_type<Duration, seconds>::type;
|
||||
using time_point = std::chrono::time_point<utc_clock, duration>;
|
||||
auto const& leaps = get_tzdb().leaps;
|
||||
auto const lt = std::upper_bound(leaps.begin(), leaps.end(), t);
|
||||
return time_point{t.time_since_epoch() + seconds{lt-leaps.begin()}};
|
||||
}
|
||||
|
||||
template <class Duration>
|
||||
std::chrono::time_point<std::chrono::system_clock,
|
||||
typename std::common_type<Duration, std::chrono::seconds>::type>
|
||||
utc_clock::utc_to_sys(std::chrono::time_point<utc_clock, Duration> t)
|
||||
{
|
||||
using namespace std::chrono;
|
||||
using duration = typename std::common_type<Duration, seconds>::type;
|
||||
using time_point = std::chrono::time_point<system_clock, duration>;
|
||||
auto const& leaps = get_tzdb().leaps;
|
||||
auto tp = time_point{t.time_since_epoch()};
|
||||
auto const lt = std::upper_bound(leaps.begin(), leaps.end(), tp);
|
||||
tp -= seconds{lt-leaps.begin()};
|
||||
if (lt != leaps.begin() && tp + seconds{1} < lt[-1])
|
||||
tp += seconds{1};
|
||||
return tp;
|
||||
}
|
||||
|
||||
} // namespace date
|
||||
|
||||
#endif // TZ_H
|
179
tz_private.h
Normal file
179
tz_private.h
Normal file
@@ -0,0 +1,179 @@
|
||||
#ifndef TZ_PRIVATE_H
|
||||
#define TZ_PRIVATE_H
|
||||
|
||||
// Howard Hinnant
|
||||
// This work is licensed under a Creative Commons Attribution 4.0 International License.
|
||||
// http://creativecommons.org/licenses/by/4.0/
|
||||
|
||||
#include "tz.h"
|
||||
|
||||
namespace date
|
||||
{
|
||||
|
||||
class MonthDayTime
|
||||
{
|
||||
private:
|
||||
struct pair
|
||||
{
|
||||
date::month_day month_day_;
|
||||
date::weekday weekday_;
|
||||
};
|
||||
|
||||
enum Type {month_day, month_last_dow, lteq, gteq};
|
||||
|
||||
Type type_{month_day};
|
||||
union U
|
||||
{
|
||||
date::month_day month_day_;
|
||||
date::month_weekday_last month_weekday_last_;
|
||||
pair month_day_weekday_;
|
||||
|
||||
U() : month_day_{date::jan/1} {}
|
||||
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(seconds_point 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);
|
||||
|
||||
seconds_point
|
||||
to_sys(date::year y, std::chrono::seconds offset, std::chrono::seconds save) const;
|
||||
date::day_point to_day_point(date::year y) const;
|
||||
|
||||
seconds_point 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 ineffect 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.
|
||||
|
||||
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 Zone::zonelet
|
||||
{
|
||||
enum tag {has_rule, has_save, is_empty};
|
||||
|
||||
std::chrono::seconds gmtoff_;
|
||||
tag tag_ = has_rule;
|
||||
union U
|
||||
{
|
||||
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_;
|
||||
seconds_point until_utc_;
|
||||
seconds_point until_std_;
|
||||
seconds_point until_loc_;
|
||||
std::chrono::minutes initial_save_{};
|
||||
std::string initial_abrev_;
|
||||
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;
|
||||
};
|
||||
|
||||
} // namespace date
|
||||
|
||||
#endif // TZ_PRIVATE_H
|
Reference in New Issue
Block a user