forked from HowardHinnant/date
Create local and system time types for timezone functions.
* Add sys_time. * Add sys_days. * Add sys_seconds. * Add local_time. * Add local_days. * Add local_seconds. * Rename day_point to sys_days. * Rename Zone to time_zone.
This commit is contained in:
@@ -20,6 +20,10 @@
|
||||
// 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 woud involve another several millennia of evolution).
|
||||
// We did not mean to shout.
|
||||
|
||||
#include "tz_private.h"
|
||||
|
||||
@@ -118,6 +122,8 @@ CONSTDATA auto max_year = date::year::max();
|
||||
// Arbitrary day of the year that will be away from any limits.
|
||||
// Used with year::min() and year::max().
|
||||
CONSTDATA auto boring_day = date::aug/18;
|
||||
CONSTDATA auto min_day = date::jan/1;
|
||||
CONSTDATA auto max_day = date::dec/31;
|
||||
|
||||
// +-------------------+
|
||||
// | End Configuration |
|
||||
@@ -549,7 +555,7 @@ parse_signed_time(std::istream& in)
|
||||
|
||||
// MonthDayTime
|
||||
|
||||
MonthDayTime::MonthDayTime(second_point tp, tz timezone)
|
||||
MonthDayTime::MonthDayTime(local_seconds tp, tz timezone)
|
||||
: zone_(timezone)
|
||||
{
|
||||
using namespace date;
|
||||
@@ -606,8 +612,8 @@ MonthDayTime::compare(date::year y, const MonthDayTime& x, date::year yx,
|
||||
{
|
||||
if (zone_ != x.zone_)
|
||||
{
|
||||
auto dp0 = to_day_point(y);
|
||||
auto dp1 = x.to_day_point(yx);
|
||||
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)
|
||||
@@ -642,7 +648,7 @@ MonthDayTime::compare(date::year y, const MonthDayTime& x, date::year yx,
|
||||
return t0 < t1 ? -1 : t0 == t1 ? 0 : 1;
|
||||
}
|
||||
|
||||
second_point
|
||||
sys_seconds
|
||||
MonthDayTime::to_sys(date::year y, std::chrono::seconds offset,
|
||||
std::chrono::seconds save) const
|
||||
{
|
||||
@@ -677,23 +683,23 @@ MonthDayTime::U::operator=(const pair& x)
|
||||
return *this;
|
||||
}
|
||||
|
||||
date::day_point
|
||||
MonthDayTime::to_day_point(date::year y) const
|
||||
date::sys_days
|
||||
MonthDayTime::to_sys_days(date::year y) const
|
||||
{
|
||||
using namespace std::chrono;
|
||||
using namespace date;
|
||||
switch (type_)
|
||||
{
|
||||
case month_day:
|
||||
return day_point(y/u.month_day_);
|
||||
return sys_days(y/u.month_day_);
|
||||
case month_last_dow:
|
||||
return day_point(y/u.month_weekday_last_);
|
||||
return sys_days(y/u.month_weekday_last_);
|
||||
case lteq:
|
||||
{
|
||||
auto const x = y/u.month_day_weekday_.month_day_;
|
||||
auto const wd1 = weekday(x);
|
||||
auto const wd0 = u.month_day_weekday_.weekday_;
|
||||
return day_point(x) - (wd1-wd0);
|
||||
return sys_days(x) - (wd1-wd0);
|
||||
}
|
||||
case gteq:
|
||||
break;
|
||||
@@ -701,13 +707,13 @@ MonthDayTime::to_day_point(date::year y) const
|
||||
auto const x = y/u.month_day_weekday_.month_day_;
|
||||
auto const wd1 = u.month_day_weekday_.weekday_;
|
||||
auto const wd0 = weekday(x);
|
||||
return day_point(x) + (wd1-wd0);
|
||||
return sys_days(x) + (wd1-wd0);
|
||||
}
|
||||
|
||||
second_point
|
||||
sys_seconds
|
||||
MonthDayTime::to_time_point(date::year y) const
|
||||
{
|
||||
return to_day_point(y) + h_ + m_ + s_;
|
||||
return to_sys_days(y) + h_ + m_ + s_;
|
||||
}
|
||||
|
||||
void
|
||||
@@ -721,7 +727,7 @@ MonthDayTime::canonicalize(date::year y)
|
||||
return;
|
||||
case month_last_dow:
|
||||
{
|
||||
auto const ymd = year_month_day(y/u.month_weekday_last_);
|
||||
auto const ymd = year_month_day(sys_days{y/u.month_weekday_last_});
|
||||
u.month_day_ = ymd.month()/ymd.day();
|
||||
type_ = month_day;
|
||||
return;
|
||||
@@ -731,7 +737,7 @@ MonthDayTime::canonicalize(date::year y)
|
||||
auto const x = y/u.month_day_weekday_.month_day_;
|
||||
auto const wd1 = weekday(x);
|
||||
auto const wd0 = u.month_day_weekday_.weekday_;
|
||||
auto const ymd = year_month_day(day_point(x) - (wd1-wd0));
|
||||
auto const ymd = year_month_day(sys_days(x) - (wd1-wd0));
|
||||
u.month_day_ = ymd.month()/ymd.day();
|
||||
type_ = month_day;
|
||||
return;
|
||||
@@ -741,7 +747,7 @@ MonthDayTime::canonicalize(date::year y)
|
||||
auto const x = y/u.month_day_weekday_.month_day_;
|
||||
auto const wd1 = u.month_day_weekday_.weekday_;
|
||||
auto const wd0 = weekday(x);
|
||||
auto const ymd = year_month_day(day_point(x) + (wd1-wd0));
|
||||
auto const ymd = year_month_day(sys_days(x) + (wd1-wd0));
|
||||
u.month_day_ = ymd.month()/ymd.day();
|
||||
type_ = month_day;
|
||||
return;
|
||||
@@ -1218,9 +1224,9 @@ Rule::split_overlaps(std::vector<Rule>& rules)
|
||||
rules.shrink_to_fit();
|
||||
}
|
||||
|
||||
// Zone
|
||||
// time_zone
|
||||
|
||||
Zone::zonelet::~zonelet()
|
||||
time_zone::zonelet::~zonelet()
|
||||
{
|
||||
#if !defined(_MSC_VER) || (_MSC_VER >= 1900)
|
||||
using minutes = std::chrono::minutes;
|
||||
@@ -1232,14 +1238,14 @@ Zone::zonelet::~zonelet()
|
||||
#endif
|
||||
}
|
||||
|
||||
Zone::zonelet::zonelet()
|
||||
time_zone::zonelet::zonelet()
|
||||
{
|
||||
#if !defined(_MSC_VER) || (_MSC_VER >= 1900)
|
||||
::new(&u.rule_) std::string();
|
||||
#endif
|
||||
}
|
||||
|
||||
Zone::zonelet::zonelet(const zonelet& i)
|
||||
time_zone::zonelet::zonelet(const zonelet& i)
|
||||
: gmtoff_(i.gmtoff_)
|
||||
, tag_(i.tag_)
|
||||
, format_(i.format_)
|
||||
@@ -1266,7 +1272,7 @@ Zone::zonelet::zonelet(const zonelet& i)
|
||||
#endif
|
||||
}
|
||||
|
||||
Zone::Zone(const std::string& s)
|
||||
time_zone::time_zone(const std::string& s)
|
||||
#if LAZY_INIT
|
||||
: adjusted_(new std::once_flag{})
|
||||
#endif
|
||||
@@ -1290,7 +1296,7 @@ Zone::Zone(const std::string& s)
|
||||
}
|
||||
|
||||
void
|
||||
Zone::add(const std::string& s)
|
||||
time_zone::add(const std::string& s)
|
||||
{
|
||||
try
|
||||
{
|
||||
@@ -1310,7 +1316,7 @@ Zone::add(const std::string& s)
|
||||
}
|
||||
|
||||
void
|
||||
Zone::parse_info(std::istream& in)
|
||||
time_zone::parse_info(std::istream& in)
|
||||
{
|
||||
using namespace date;
|
||||
using namespace std::chrono;
|
||||
@@ -1326,7 +1332,7 @@ Zone::parse_info(std::istream& in)
|
||||
if (in.eof() || in.peek() == '#')
|
||||
{
|
||||
zonelet.until_year_ = year::max();
|
||||
zonelet.until_date_ = MonthDayTime(boring_day, tz::utc);
|
||||
zonelet.until_date_ = MonthDayTime(max_day, tz::utc);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -1489,8 +1495,9 @@ find_rule_for_zone(const std::pair<const Rule*, const Rule*>& eqr,
|
||||
static
|
||||
std::pair<const Rule*, date::year>
|
||||
find_rule_for_zone(const std::pair<const Rule*, const Rule*>& eqr,
|
||||
const second_point& tp_utc, const second_point& tp_std,
|
||||
const second_point& tp_loc)
|
||||
const sys_seconds& tp_utc,
|
||||
const local_seconds& tp_std,
|
||||
const local_seconds& tp_loc)
|
||||
{
|
||||
using namespace std::chrono;
|
||||
using namespace date;
|
||||
@@ -1508,10 +1515,10 @@ find_rule_for_zone(const std::pair<const Rule*, const Rule*>& eqr,
|
||||
found = tp_utc < r->mdt().to_time_point(ry);
|
||||
break;
|
||||
case tz::standard:
|
||||
found = tp_std < r->mdt().to_time_point(ry);
|
||||
found = sys_seconds{tp_std.time_since_epoch()} < r->mdt().to_time_point(ry);
|
||||
break;
|
||||
case tz::local:
|
||||
found = tp_loc < r->mdt().to_time_point(ry);
|
||||
found = sys_seconds{tp_loc.time_since_epoch()} < r->mdt().to_time_point(ry);
|
||||
break;
|
||||
}
|
||||
if (found)
|
||||
@@ -1536,7 +1543,7 @@ find_rule(const std::pair<const Rule*, date::year>& first_rule,
|
||||
using namespace date;
|
||||
auto r = first_rule.first;
|
||||
auto ry = first_rule.second;
|
||||
Info x{day_point(year::min()/boring_day), day_point(year::max()/boring_day),
|
||||
Info x{sys_days(year::min()/min_day), sys_days(year::max()/max_day),
|
||||
seconds{0}, initial_save, initial_abbrev};
|
||||
while (r != nullptr)
|
||||
{
|
||||
@@ -1569,7 +1576,7 @@ find_rule(const std::pair<const Rule*, date::year>& first_rule,
|
||||
x.end = r->mdt().to_sys(ry, offset, x.save);
|
||||
}
|
||||
else
|
||||
x.end = day_point(year::max()/boring_day);
|
||||
x.end = sys_days(year::max()/max_day);
|
||||
break;
|
||||
}
|
||||
x.save = r->save();
|
||||
@@ -1580,7 +1587,7 @@ find_rule(const std::pair<const Rule*, date::year>& first_rule,
|
||||
}
|
||||
|
||||
void
|
||||
Zone::adjust_infos(const std::vector<Rule>& rules)
|
||||
time_zone::adjust_infos(const std::vector<Rule>& rules)
|
||||
{
|
||||
using namespace std::chrono;
|
||||
using namespace date;
|
||||
@@ -1640,7 +1647,7 @@ Zone::adjust_infos(const std::vector<Rule>& rules)
|
||||
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_ = z.until_utc_ + z.gmtoff_;
|
||||
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)
|
||||
@@ -1751,7 +1758,7 @@ format_abbrev(std::string format, const std::string& variable, std::chrono::seco
|
||||
}
|
||||
|
||||
Info
|
||||
Zone::get_info(std::chrono::system_clock::time_point tp, tz timezone) const
|
||||
time_zone::get_info_impl(sys_seconds tp, tz timezone) const
|
||||
{
|
||||
using namespace std::chrono;
|
||||
using namespace date;
|
||||
@@ -1761,17 +1768,18 @@ Zone::get_info(std::chrono::system_clock::time_point tp, tz timezone) const
|
||||
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)) + "]");
|
||||
auto tps = floor<seconds>(tp);
|
||||
#if LAZY_INIT
|
||||
std::call_once(*adjusted_, [this]()
|
||||
{
|
||||
const_cast<Zone*>(this)->adjust_infos(get_tzdb().rules);
|
||||
});
|
||||
std::call_once(*adjusted_,
|
||||
[this]()
|
||||
{
|
||||
const_cast<time_zone*>(this)->adjust_infos(get_tzdb().rules);
|
||||
});
|
||||
#endif
|
||||
auto i = std::upper_bound(zonelets_.begin(), zonelets_.end(), tps,
|
||||
[timezone](second_point t, const zonelet& zl)
|
||||
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 < zl.until_loc_;
|
||||
return timezone == tz::utc ? t < zl.until_utc_ :
|
||||
t < sys_seconds{zl.until_loc_.time_since_epoch()};
|
||||
});
|
||||
|
||||
Info r{};
|
||||
@@ -1782,7 +1790,7 @@ Zone::get_info(std::chrono::system_clock::time_point tp, tz timezone) const
|
||||
if (i != zonelets_.begin())
|
||||
r.begin = i[-1].until_utc_;
|
||||
else
|
||||
r.begin = day_point(year::min()/boring_day);
|
||||
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_;
|
||||
@@ -1792,15 +1800,15 @@ Zone::get_info(std::chrono::system_clock::time_point tp, tz timezone) const
|
||||
if (i != zonelets_.begin())
|
||||
r.begin = i[-1].until_utc_;
|
||||
else
|
||||
r.begin = day_point(year::min()/boring_day);
|
||||
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(tps, timezone), i->initial_save_,
|
||||
i->initial_abbrev_);
|
||||
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_;
|
||||
@@ -1814,7 +1822,7 @@ Zone::get_info(std::chrono::system_clock::time_point tp, tz timezone) const
|
||||
}
|
||||
|
||||
std::ostream&
|
||||
operator<<(std::ostream& os, const Zone& z)
|
||||
operator<<(std::ostream& os, const time_zone& z)
|
||||
{
|
||||
using namespace date;
|
||||
using namespace std::chrono;
|
||||
@@ -1822,10 +1830,11 @@ operator<<(std::ostream& os, const Zone& z)
|
||||
os.fill(' ');
|
||||
os.flags(std::ios::dec | std::ios::left);
|
||||
#if LAZY_INIT
|
||||
std::call_once(*z.adjusted_, [&z]()
|
||||
{
|
||||
const_cast<Zone&>(z).adjust_infos(get_tzdb().rules);
|
||||
});
|
||||
std::call_once(*z.adjusted_,
|
||||
[&z]()
|
||||
{
|
||||
const_cast<time_zone&>(z).adjust_infos(get_tzdb().rules);
|
||||
});
|
||||
#endif
|
||||
os.width(35);
|
||||
os << z.name_;
|
||||
@@ -1837,7 +1846,7 @@ operator<<(std::ostream& os, const Zone& z)
|
||||
os << ' ';
|
||||
os << make_time(s.gmtoff_) << " ";
|
||||
os.width(15);
|
||||
if (s.tag_ != Zone::zonelet::has_save)
|
||||
if (s.tag_ != time_zone::zonelet::has_save)
|
||||
os << s.u.rule_;
|
||||
else
|
||||
{
|
||||
@@ -2120,7 +2129,7 @@ init_tzdb()
|
||||
}
|
||||
else if (word == "Zone")
|
||||
{
|
||||
db.zones.push_back(Zone(line));
|
||||
db.zones.push_back(time_zone(line));
|
||||
continue_zone = true;
|
||||
}
|
||||
else if (line[0] == '\t' && continue_zone)
|
||||
@@ -2182,12 +2191,12 @@ get_tzdb()
|
||||
return ref;
|
||||
}
|
||||
|
||||
const Zone*
|
||||
const time_zone*
|
||||
locate_zone(const std::string& tz_name)
|
||||
{
|
||||
const auto& db = get_tzdb();
|
||||
auto zi = std::lower_bound(db.zones.begin(), db.zones.end(), tz_name,
|
||||
[](const Zone& z, const std::string& nm)
|
||||
[](const time_zone& z, const std::string& nm)
|
||||
{
|
||||
return z.name() < nm;
|
||||
});
|
||||
@@ -2201,7 +2210,7 @@ locate_zone(const std::string& tz_name)
|
||||
if (li != db.links.end() && li->name() == tz_name)
|
||||
{
|
||||
zi = std::lower_bound(db.zones.begin(), db.zones.end(), li->target(),
|
||||
[](const Zone& z, const std::string& nm)
|
||||
[](const time_zone& z, const std::string& nm)
|
||||
{
|
||||
return z.name() < nm;
|
||||
});
|
||||
@@ -2215,7 +2224,7 @@ locate_zone(const std::string& tz_name)
|
||||
|
||||
#ifdef TZ_TEST
|
||||
#ifdef _WIN32
|
||||
const Zone*
|
||||
const time_zone*
|
||||
locate_native_zone(const std::string& native_tz_name)
|
||||
{
|
||||
std::string standard_tz_name;
|
||||
@@ -2305,7 +2314,7 @@ operator<<(std::ostream& os, const Info& r)
|
||||
|
||||
#ifdef _WIN32
|
||||
|
||||
const Zone*
|
||||
const time_zone*
|
||||
current_zone()
|
||||
{
|
||||
#if TIMEZONE_MAPPING
|
||||
@@ -2346,7 +2355,7 @@ current_zone()
|
||||
|
||||
#else // ! WIN32
|
||||
|
||||
const Zone*
|
||||
const time_zone*
|
||||
current_zone()
|
||||
{
|
||||
// On some versions of some linux distro's (e.g. Ubuntu),
|
||||
|
||||
Reference in New Issue
Block a user