Merge branch 'gm_issue_19' of git://github.com/gmcode/date into gmcode-gm_issue_19

This commit is contained in:
Howard Hinnant 2015-10-27 11:53:29 -04:00
commit 333894fc9d
2 changed files with 50 additions and 27 deletions

16
date.h
View File

@ -2245,8 +2245,15 @@ year_month_day::operator day_point() const noexcept
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]
#ifdef _MSC_VER
#pragma warning(push)
#pragma warning(disable: 4146) // unary minus operator applied to unsigned type, result still unsigned
#endif
auto const doy = (153*(m + (m > 2 ? -3u : 9)) + 2)/5 + d-1; // [0, 365]
auto const doe = yoe * 365 + yoe/4 - yoe/100 + doy; // [0, 146096]
#ifdef _MSC_VER
#pragma warning(pop)
#endif
auto const doe = yoe * 365 + yoe/4 - yoe/100 + doy; // [0, 146096]
return day_point{days{era * 146097 + static_cast<int>(doe) - 719468}};
}
@ -2350,7 +2357,14 @@ year_month_day::from_day_point(const day_point& dp) noexcept
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]
#ifdef _MSC_VER
#pragma warning(push)
#pragma warning(disable: 4146) // unary minus operator applied to unsigned type, result still unsigned
#endif
auto const m = mp + (mp < 10 ? 3 : -9u); // [1, 12]
#ifdef _MSVC_VER
#pragma warning(pop)
#endif
return year_month_day{date::year{y + (m <= 2)}, date::month(m), date::day(d)};
}

61
tz.cpp
View File

@ -61,6 +61,14 @@
// gcc/mingw supports unistd.h on Win32 but MSVC does not.
#ifdef _WIN32
// Prevent windows defining min/max macros that will interfere with C++ versions.
#ifndef NOMINMAX
#define NOMINMAX
#endif
// We don't need everything Windows.h has to offer.
#ifndef WIN32_LEAN_AND_MEAN
#define WIN32_LEAN_AND_MEAN
#endif
#include <Windows.h>
#include <io.h>
#else
@ -318,7 +326,7 @@ static void get_windows_timezone_info(std::vector<timezone_info>& tz_list)
if (!zone_key.get_binary("TZI", &tz.tzi, sizeof(TZI)))
continue;
#endif
auto result = zone_key.close();
zone_key.close();
tz_list.push_back(std::move(tz));
}
@ -1157,24 +1165,24 @@ Rule::split_overlaps(std::vector<Rule>& rules)
return nm < x.name();
}) - rules.cbegin());
split_overlaps(rules, i, e);
auto first = rules.cbegin() + static_cast<difference_type>(i);
auto last = rules.cbegin() + static_cast<difference_type>(e);
auto t = std::lower_bound(first, last, min_year);
if (t > first+1)
auto first_rule = rules.cbegin() + static_cast<difference_type>(i);
auto last_rule = rules.cbegin() + static_cast<difference_type>(e);
auto t = std::lower_bound(first_rule, last_rule, min_year);
if (t > first_rule+1)
{
if (t == last || t->starting_year() >= min_year)
if (t == last_rule || t->starting_year() >= min_year)
--t;
auto d = static_cast<std::size_t>(t - first);
rules.erase(first, t);
auto d = static_cast<std::size_t>(t - first_rule);
rules.erase(first_rule, t);
e -= d;
}
first = rules.cbegin() + static_cast<difference_type>(i);
last = rules.cbegin() + static_cast<difference_type>(e);
t = std::upper_bound(first, last, max_year);
if (t != last)
first_rule = rules.cbegin() + static_cast<difference_type>(i);
last_rule = rules.cbegin() + 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 - t);
rules.erase(t, last);
auto d = static_cast<std::size_t>(last_rule - t);
rules.erase(t, last_rule);
e -= d;
}
i = e;
@ -1336,21 +1344,21 @@ find_previous_rule(const Rule* r, date::year y)
// [first, last) all have the same name
static
std::pair<const Rule*, date::year>
find_next_rule(const Rule* first, const Rule* last, const Rule* r, date::year y)
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-1)
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-1 || r->ending_year() < r[1].ending_year())
if (r == last_rule-1 || r->ending_year() < r[1].ending_year())
{
while (r > first && r->starting_year() == r[-1].starting_year())
while (r > first_rule && r->starting_year() == r[-1].starting_year())
--r;
return {r, ++y};
}
@ -1464,6 +1472,7 @@ find_rule_for_zone(const std::pair<const Rule*, const Rule*>& eqr,
found = tp_loc < r->mdt().to_time_point(ry);
break;
default:
found = false;
assert(false);
}
if (found)
@ -1478,16 +1487,16 @@ find_rule_for_zone(const std::pair<const Rule*, const Rule*>& eqr,
static
Info
find_rule(const std::pair<const Rule*, date::year>& first,
const std::pair<const Rule*, date::year>& last,
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.first;
auto ry = first.second;
auto r = first_rule.first;
auto ry = first_rule.second;
Info x{day_point(year::min()/boring_day), day_point(year::max()/boring_day),
seconds{0}, initial_save, initial_abbrev};
while (r != nullptr)
@ -1495,9 +1504,9 @@ find_rule(const std::pair<const Rule*, date::year>& first,
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.first && ry == last.second))
if (tx <= tr || (r == last_rule.first && ry == last_rule.second))
{
if (tx < tr && r == first.first && ry == first.second)
if (tx < tr && r == first_rule.first && ry == first_rule.second)
{
x.end = r->mdt().to_sys(ry, offset, x.save);
break;
@ -1509,12 +1518,12 @@ find_rule(const std::pair<const Rule*, date::year>& first,
}
// r != nullptr && tx >= tr (if tr were to be recomputed)
auto prev_save = initial_save;
if (!(r == first.first && ry == first.second))
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.first && ry == last.second))
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);