Merge branch 'gmcode-gm_issue_19'

This commit is contained in:
Howard Hinnant
2015-10-27 12:14:54 -04:00
3 changed files with 49 additions and 29 deletions

14
date.h
View File

@@ -2245,7 +2245,14 @@ year_month_day::operator day_point() const noexcept
auto const d = static_cast<unsigned>(d_); auto const d = static_cast<unsigned>(d_);
auto const era = (y >= 0 ? y : y-399) / 400; auto const era = (y >= 0 ? y : y-399) / 400;
auto const yoe = static_cast<unsigned>(y - era * 400); // [0, 399] 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 doy = (153*(m + (m > 2 ? -3u : 9)) + 2)/5 + d-1; // [0, 365]
#ifdef _MSC_VER
#pragma warning(pop)
#endif
auto const doe = yoe * 365 + yoe/4 - yoe/100 + doy; // [0, 146096] auto const doe = yoe * 365 + yoe/4 - yoe/100 + doy; // [0, 146096]
return day_point{days{era * 146097 + static_cast<int>(doe) - 719468}}; 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 doy = doe - (365*yoe + yoe/4 - yoe/100); // [0, 365]
auto const mp = (5*doy + 2)/153; // [0, 11] auto const mp = (5*doy + 2)/153; // [0, 11]
auto const d = doy - (153*mp+2)/5 + 1; // [1, 31] 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] 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)}; return year_month_day{date::year{y + (m <= 2)}, date::month(m), date::day(d)};
} }

View File

@@ -30,7 +30,7 @@ if [ -z "$CXX_LANG" ]
then then
CXX_LANG=c++14 CXX_LANG=c++14
fi fi
OPTIONS="-std=${CXX_LANG} $OPTIONS -I$ROOT" OPTIONS="-std=${CXX_LANG} $OPTIONS -I$ROOT -Wall"
case $TRIPLE in case $TRIPLE in
*-*-mingw* | *-*-cygwin* | *-*-win*) *-*-mingw* | *-*-cygwin* | *-*-win*)

62
tz.cpp
View File

@@ -61,6 +61,14 @@
// gcc/mingw supports unistd.h on Win32 but MSVC does not. // gcc/mingw supports unistd.h on Win32 but MSVC does not.
#ifdef _WIN32 #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 <Windows.h>
#include <io.h> #include <io.h>
#else #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))) if (!zone_key.get_binary("TZI", &tz.tzi, sizeof(TZI)))
continue; continue;
#endif #endif
auto result = zone_key.close(); zone_key.close();
tz_list.push_back(std::move(tz)); tz_list.push_back(std::move(tz));
} }
@@ -1157,24 +1165,24 @@ Rule::split_overlaps(std::vector<Rule>& rules)
return nm < x.name(); return nm < x.name();
}) - rules.cbegin()); }) - rules.cbegin());
split_overlaps(rules, i, e); split_overlaps(rules, i, e);
auto first = rules.cbegin() + static_cast<difference_type>(i); auto first_rule = rules.cbegin() + static_cast<difference_type>(i);
auto last = rules.cbegin() + static_cast<difference_type>(e); auto last_rule = rules.cbegin() + static_cast<difference_type>(e);
auto t = std::lower_bound(first, last, min_year); auto t = std::lower_bound(first_rule, last_rule, min_year);
if (t > first+1) if (t > first_rule+1)
{ {
if (t == last || t->starting_year() >= min_year) if (t == last_rule || t->starting_year() >= min_year)
--t; --t;
auto d = static_cast<std::size_t>(t - first); auto d = static_cast<std::size_t>(t - first_rule);
rules.erase(first, t); rules.erase(first_rule, t);
e -= d; e -= d;
} }
first = rules.cbegin() + static_cast<difference_type>(i); first_rule = rules.cbegin() + static_cast<difference_type>(i);
last = rules.cbegin() + static_cast<difference_type>(e); last_rule = rules.cbegin() + static_cast<difference_type>(e);
t = std::upper_bound(first, last, max_year); t = std::upper_bound(first_rule, last_rule, max_year);
if (t != last) if (t != last_rule)
{ {
auto d = static_cast<std::size_t>(last - t); auto d = static_cast<std::size_t>(last_rule - t);
rules.erase(t, last); rules.erase(t, last_rule);
e -= d; e -= d;
} }
i = e; i = e;
@@ -1336,21 +1344,21 @@ find_previous_rule(const Rule* r, date::year y)
// [first, last) all have the same name // [first, last) all have the same name
static static
std::pair<const Rule*, date::year> 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; using namespace date;
if (y == r->ending_year()) if (y == r->ending_year())
{ {
if (r == last-1) if (r == last_rule-1)
return {nullptr, year::max()}; return {nullptr, year::max()};
++r; ++r;
if (y == r->ending_year()) if (y == r->ending_year())
return {r, y}; return {r, y};
return {r, r->starting_year()}; 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; --r;
return {r, ++y}; return {r, ++y};
} }
@@ -1463,8 +1471,6 @@ find_rule_for_zone(const std::pair<const Rule*, const Rule*>& eqr,
case tz::local: case tz::local:
found = tp_loc < r->mdt().to_time_point(ry); found = tp_loc < r->mdt().to_time_point(ry);
break; break;
default:
assert(false);
} }
if (found) if (found)
break; break;
@@ -1478,16 +1484,16 @@ find_rule_for_zone(const std::pair<const Rule*, const Rule*>& eqr,
static static
Info Info
find_rule(const std::pair<const Rule*, date::year>& first, find_rule(const std::pair<const Rule*, date::year>& first_rule,
const std::pair<const Rule*, date::year>& last, const std::pair<const Rule*, date::year>& last_rule,
const date::year& y, const std::chrono::seconds& offset, const date::year& y, const std::chrono::seconds& offset,
const MonthDayTime& mdt, const std::chrono::minutes& initial_save, const MonthDayTime& mdt, const std::chrono::minutes& initial_save,
const std::string& initial_abbrev) const std::string& initial_abbrev)
{ {
using namespace std::chrono; using namespace std::chrono;
using namespace date; using namespace date;
auto r = first.first; auto r = first_rule.first;
auto ry = first.second; auto ry = first_rule.second;
Info x{day_point(year::min()/boring_day), day_point(year::max()/boring_day), Info x{day_point(year::min()/boring_day), day_point(year::max()/boring_day),
seconds{0}, initial_save, initial_abbrev}; seconds{0}, initial_save, initial_abbrev};
while (r != nullptr) while (r != nullptr)
@@ -1495,9 +1501,9 @@ find_rule(const std::pair<const Rule*, date::year>& first,
auto tr = r->mdt().to_sys(ry, offset, x.save); auto tr = r->mdt().to_sys(ry, offset, x.save);
auto tx = mdt.to_sys(y, offset, x.save); auto tx = mdt.to_sys(y, offset, x.save);
// Find last rule where tx >= tr // 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); x.end = r->mdt().to_sys(ry, offset, x.save);
break; break;
@@ -1509,12 +1515,12 @@ find_rule(const std::pair<const Rule*, date::year>& first,
} }
// r != nullptr && tx >= tr (if tr were to be recomputed) // r != nullptr && tx >= tr (if tr were to be recomputed)
auto prev_save = initial_save; 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(); prev_save = find_previous_rule(r, ry).first->save();
x.begin = r->mdt().to_sys(ry, offset, prev_save); x.begin = r->mdt().to_sys(ry, offset, prev_save);
x.save = r->save(); x.save = r->save();
x.abbrev = r->abbrev(); 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 std::tie(r, ry) = find_next_rule(r, ry); // can't return nullptr for r
assert(r != nullptr); assert(r != nullptr);