Commit d65595c8 by Gennadiy Rozental Committed by Copybara-Service

Import of CCTZ from GitHub.

PiperOrigin-RevId: 543896343
Change-Id: Ia91b3e082b764b750bbbe9a3ce63192263d51438
parent e6c09ae4
......@@ -23,6 +23,7 @@
#include <chrono>
#include <cstdint>
#include <limits>
#include <ratio> // NOLINT: We use std::ratio in this header
#include <string>
#include <utility>
......
......@@ -14,15 +14,13 @@
#if !defined(HAS_STRPTIME)
#if !defined(_MSC_VER) && !defined(__MINGW32__) && !defined(__VXWORKS__)
#define HAS_STRPTIME \
1 // assume everyone has strptime() except windows
// and VxWorks
#define HAS_STRPTIME 1 // Assume everyone else has strptime().
#endif
#endif
#if defined(HAS_STRPTIME) && HAS_STRPTIME
#if !defined(_XOPEN_SOURCE) && !defined(__OpenBSD__)
#define _XOPEN_SOURCE // Definedness suffices for strptime.
#define _XOPEN_SOURCE // Definedness suffices for strptime().
#endif
#endif
......
......@@ -23,19 +23,19 @@ ABSL_NAMESPACE_BEGIN
namespace time_internal {
namespace cctz {
std::unique_ptr<TimeZoneIf> TimeZoneIf::Load(const std::string& name) {
std::unique_ptr<TimeZoneIf> TimeZoneIf::UTC() { return TimeZoneInfo::UTC(); }
std::unique_ptr<TimeZoneIf> TimeZoneIf::Make(const std::string& name) {
// Support "libc:localtime" and "libc:*" to access the legacy
// localtime and UTC support respectively from the C library.
// NOTE: The "libc:*" zones are internal, test-only interfaces, and
// are subject to change/removal without notice. Do not use them.
if (name.compare(0, 5, "libc:") == 0) {
return std::unique_ptr<TimeZoneIf>(new TimeZoneLibC(name.substr(5)));
return TimeZoneLibC::Make(name.substr(5));
}
// Otherwise use the "zoneinfo" implementation by default.
std::unique_ptr<TimeZoneInfo> tz(new TimeZoneInfo);
if (!tz->Load(name)) tz.reset();
return std::unique_ptr<TimeZoneIf>(tz.release());
// Otherwise use the "zoneinfo" implementation.
return TimeZoneInfo::Make(name);
}
// Defined out-of-line to avoid emitting a weak vtable in all TUs.
......
......@@ -33,8 +33,9 @@ namespace cctz {
// Subclasses implement the functions for civil-time conversions in the zone.
class TimeZoneIf {
public:
// A factory function for TimeZoneIf implementations.
static std::unique_ptr<TimeZoneIf> Load(const std::string& name);
// Factory functions for TimeZoneIf implementations.
static std::unique_ptr<TimeZoneIf> UTC(); // never fails
static std::unique_ptr<TimeZoneIf> Make(const std::string& name);
virtual ~TimeZoneIf();
......@@ -51,7 +52,9 @@ class TimeZoneIf {
virtual std::string Description() const = 0;
protected:
TimeZoneIf() {}
TimeZoneIf() = default;
TimeZoneIf(const TimeZoneIf&) = delete;
TimeZoneIf& operator=(const TimeZoneIf&) = delete;
};
// Convert between time_point<seconds> and a count of seconds since the
......
......@@ -99,11 +99,13 @@ void time_zone::Impl::ClearTimeZoneMapTestOnly() {
}
}
time_zone::Impl::Impl() : name_("UTC"), zone_(TimeZoneIf::UTC()) {}
time_zone::Impl::Impl(const std::string& name)
: name_(name), zone_(TimeZoneIf::Load(name_)) {}
: name_(name), zone_(TimeZoneIf::Make(name_)) {}
const time_zone::Impl* time_zone::Impl::UTCImpl() {
static const Impl* utc_impl = new Impl("UTC"); // never fails
static const Impl* utc_impl = new Impl;
return utc_impl;
}
......
......@@ -78,7 +78,11 @@ class time_zone::Impl {
std::string Description() const { return zone_->Description(); }
private:
Impl();
explicit Impl(const std::string& name);
Impl(const Impl&) = delete;
Impl& operator=(const Impl&) = delete;
static const Impl* UTCImpl();
const std::string name_;
......
......@@ -18,6 +18,7 @@
#include <atomic>
#include <cstddef>
#include <cstdint>
#include <memory>
#include <string>
#include <vector>
......@@ -64,12 +65,9 @@ struct TransitionType {
// A time zone backed by the IANA Time Zone Database (zoneinfo).
class TimeZoneInfo : public TimeZoneIf {
public:
TimeZoneInfo() = default;
TimeZoneInfo(const TimeZoneInfo&) = delete;
TimeZoneInfo& operator=(const TimeZoneInfo&) = delete;
// Loads the zoneinfo for the given name, returning true if successful.
bool Load(const std::string& name);
// Factories.
static std::unique_ptr<TimeZoneInfo> UTC(); // never fails
static std::unique_ptr<TimeZoneInfo> Make(const std::string& name);
// TimeZoneIf implementations.
time_zone::absolute_lookup BreakTime(
......@@ -83,17 +81,9 @@ class TimeZoneInfo : public TimeZoneIf {
std::string Description() const override;
private:
struct Header { // counts of:
std::size_t timecnt; // transition times
std::size_t typecnt; // transition types
std::size_t charcnt; // zone abbreviation characters
std::size_t leapcnt; // leap seconds (we expect none)
std::size_t ttisstdcnt; // UTC/local indicators (unused)
std::size_t ttisutcnt; // standard/wall indicators (unused)
bool Build(const tzhead& tzh);
std::size_t DataLength(std::size_t time_len) const;
};
TimeZoneInfo() = default;
TimeZoneInfo(const TimeZoneInfo&) = delete;
TimeZoneInfo& operator=(const TimeZoneInfo&) = delete;
bool GetTransitionType(std::int_fast32_t utc_offset, bool is_dst,
const std::string& abbr, std::uint_least8_t* index);
......@@ -102,6 +92,7 @@ class TimeZoneInfo : public TimeZoneIf {
bool ExtendTransitions();
bool ResetToBuiltinUTC(const seconds& offset);
bool Load(const std::string& name);
bool Load(ZoneInfoSource* zip);
// Helpers for BreakTime() and MakeTime().
......
......@@ -62,7 +62,7 @@ auto tm_zone(const std::tm& tm) -> decltype(tzname[0]) {
}
#elif defined(__native_client__) || defined(__myriad2__) || \
defined(__EMSCRIPTEN__)
// Uses the globals: 'timezone' and 'tzname'.
// Uses the globals: '_timezone' and 'tzname'.
auto tm_gmtoff(const std::tm& tm) -> decltype(_timezone + 0) {
const bool is_dst = tm.tm_isdst > 0;
return _timezone + (is_dst ? 60 * 60 : 0);
......@@ -193,8 +193,9 @@ std::time_t find_trans(std::time_t lo, std::time_t hi, tm_gmtoff_t offset) {
} // namespace
TimeZoneLibC::TimeZoneLibC(const std::string& name)
: local_(name == "localtime") {}
std::unique_ptr<TimeZoneLibC> TimeZoneLibC::Make(const std::string& name) {
return std::unique_ptr<TimeZoneLibC>(new TimeZoneLibC(name));
}
time_zone::absolute_lookup TimeZoneLibC::BreakTime(
const time_point<seconds>& tp) const {
......@@ -323,6 +324,9 @@ std::string TimeZoneLibC::Description() const {
return local_ ? "localtime" : "UTC";
}
TimeZoneLibC::TimeZoneLibC(const std::string& name)
: local_(name == "localtime") {}
} // namespace cctz
} // namespace time_internal
ABSL_NAMESPACE_END
......
......@@ -27,10 +27,10 @@ namespace cctz {
// A time zone backed by gmtime_r(3), localtime_r(3), and mktime(3),
// and which therefore only supports UTC and the local time zone.
// TODO: Add support for fixed offsets from UTC.
class TimeZoneLibC : public TimeZoneIf {
public:
explicit TimeZoneLibC(const std::string& name);
// Factory.
static std::unique_ptr<TimeZoneLibC> Make(const std::string& name);
// TimeZoneIf implementations.
time_zone::absolute_lookup BreakTime(
......@@ -44,6 +44,10 @@ class TimeZoneLibC : public TimeZoneIf {
std::string Description() const override;
private:
explicit TimeZoneLibC(const std::string& name);
TimeZoneLibC(const TimeZoneLibC&) = delete;
TimeZoneLibC& operator=(const TimeZoneLibC&) = delete;
const bool local_; // localtime or UTC
};
......
......@@ -734,6 +734,10 @@ TEST(TimeZone, UTC) {
time_zone loaded_utc0;
EXPECT_TRUE(load_time_zone("UTC0", &loaded_utc0));
EXPECT_EQ(loaded_utc0, utc);
time_zone loaded_bad;
EXPECT_FALSE(load_time_zone("Invalid/TimeZone", &loaded_bad));
EXPECT_EQ(loaded_bad, utc);
}
TEST(TimeZone, NamedTimeZones) {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment