blob: 25208bdde8c18d56584403df2591a2361aa09887 [file]
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 4a3af3f..27fdc95 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -184,3 +184,5 @@ install(FILES cmake/${PROJECT_NAME}-config.cmake
set(quiet_on_empty QUIET_ON_EMPTY)
feature_summary(WHAT ALL FATAL_ON_MISSING_REQUIRED_PACKAGES ${quiet_on_empty})
+
+SET(CMAKE_CXX_FLAGS "-fno-omit-frame-pointer -O3 -g -gdwarf-4 ${CMAKE_CXX_FLAGS}")
diff --git a/include/cctz/time_zone.h b/include/cctz/time_zone.h
index 2d4495c..ec1d61f 100644
--- a/include/cctz/time_zone.h
+++ b/include/cctz/time_zone.h
@@ -95,6 +95,14 @@ class time_zone {
return lookup(detail::split_seconds(tp).first);
}
+ // Lookup the UTC offset for a timepoint
+ // The returned the lookup result doesn't contain valid cs
+ absolute_lookup lookup_offset(const time_point<seconds> &tp) const;
+ template <typename D>
+ absolute_lookup lookup_offset(const time_point<D> &tp) const {
+ return lookup_offset(detail::split_seconds(tp).first);
+ }
+
// A civil_lookup represents the absolute time(s) (time_point) that
// correspond to the given civil time (cctz::civil_second) within this
// time_zone. Usually the given civil time represents a unique instant
diff --git a/src/time_zone_if.h b/src/time_zone_if.h
index 8c19e12..1f78ea8 100644
--- a/src/time_zone_if.h
+++ b/src/time_zone_if.h
@@ -37,6 +37,10 @@ class TimeZoneIf {
virtual time_zone::absolute_lookup BreakTime(
const time_point<seconds>& tp) const = 0;
+ virtual time_zone::absolute_lookup
+ LookupOffset(const time_point<seconds> &tp) const {
+ return BreakTime(tp);
+ }
virtual time_zone::civil_lookup MakeTime(
const civil_second& cs) const = 0;
diff --git a/src/time_zone_impl.h b/src/time_zone_impl.h
index 8902614..e9747e2 100644
--- a/src/time_zone_impl.h
+++ b/src/time_zone_impl.h
@@ -50,6 +50,10 @@ class time_zone::Impl {
return zone_->BreakTime(tp);
}
+ time_zone::absolute_lookup LookupOffset(const time_point<seconds> &tp) const {
+ return zone_->LookupOffset(tp);
+ }
+
// Converts the civil-time components in this time zone into a time_point.
// That is, the opposite of BreakTime(). The requested civil time may be
// ambiguous or illegal due to a change of UTC offset.
diff --git a/src/time_zone_info.cc b/src/time_zone_info.cc
index cc4b001..2307f89 100644
--- a/src/time_zone_info.cc
+++ b/src/time_zone_info.cc
@@ -861,6 +861,64 @@ time_zone::absolute_lookup TimeZoneInfo::LocalTime(
tt.utc_offset, tt.is_dst, &abbreviations_[tt.abbr_index]};
}
+time_zone::absolute_lookup
+TimeZoneInfo::Offset(std::int_fast64_t unix_time,
+ const TransitionType &tt) const {
+ return {{}, tt.utc_offset, tt.is_dst, &abbreviations_[tt.abbr_index]};
+}
+
+time_zone::absolute_lookup TimeZoneInfo::Offset(std::int_fast64_t unix_time,
+ const Transition &tr) const {
+ const TransitionType &tt = transition_types_[tr.type_index];
+ // std::int_fast64_t local_unix = unix_time + tt.utc_offset;
+ return {{}, tt.utc_offset, tt.is_dst, &abbreviations_[tt.abbr_index]};
+}
+
+time_zone::absolute_lookup
+TimeZoneInfo::LookupOffset(const time_point<seconds> &tp) const {
+ std::int_fast64_t unix_time = ToUnixSeconds(tp);
+ const std::size_t timecnt = transitions_.size();
+ assert(timecnt != 0); // We always add a transition.
+
+ const std::size_t hint = local_time_hint_.load(std::memory_order_relaxed);
+ // This branch is likely to be taken if the hint is valid and the unix_time
+ // falls within the hinted transition range.
+ if (0 < hint && hint < timecnt) [[likely]] {
+ if (transitions_[hint - 1].unix_time <= unix_time) [[likely]] {
+ if (unix_time < transitions_[hint].unix_time) [[likely]] {
+ return Offset(unix_time, transitions_[hint - 1]);
+ }
+ }
+ }
+
+ if ((unix_time < transitions_[0].unix_time)) {
+ return Offset(unix_time, transition_types_[default_transition_type_]);
+ }
+ if (unix_time >= transitions_.back().unix_time) {
+ // After the last transition. If we extended the transitions using
+ // future_spec_, shift back to a supported year using the 400-year
+ // cycle of calendaric equivalence and then compensate accordingly.
+ if (extended_) {
+ const std::int_fast64_t diff =
+ unix_time - transitions_[timecnt - 1].unix_time;
+ const year_t shift = diff / kSecsPer400Years + 1;
+ const auto d = seconds(shift * kSecsPer400Years);
+ time_zone::absolute_lookup al = BreakTime(tp - d);
+ al.cs = YearShift(al.cs, shift * 400);
+ return al;
+ }
+ return Offset(unix_time, transitions_[timecnt - 1]);
+ }
+
+ const Transition target = {unix_time, 0, civil_second(), civil_second()};
+ const Transition *begin = &transitions_[0];
+ const Transition *tr = std::upper_bound(begin, begin + timecnt, target,
+ Transition::ByUnixTime());
+ local_time_hint_.store(static_cast<std::size_t>(tr - begin),
+ std::memory_order_relaxed);
+ return Offset(unix_time, *--tr);
+}
+
// BreakTime() translation for a particular transition.
time_zone::absolute_lookup TimeZoneInfo::LocalTime(
std::int_fast64_t unix_time, const Transition& tr) const {
diff --git a/src/time_zone_info.h b/src/time_zone_info.h
index 6e00019..9ada2df 100644
--- a/src/time_zone_info.h
+++ b/src/time_zone_info.h
@@ -68,6 +68,8 @@ class TimeZoneInfo : public TimeZoneIf {
// TimeZoneIf implementations.
time_zone::absolute_lookup BreakTime(
const time_point<seconds>& tp) const override;
+ time_zone::absolute_lookup
+ LookupOffset(const time_point<seconds> &tp) const override;
time_zone::civil_lookup MakeTime(
const civil_second& cs) const override;
bool NextTransition(const time_point<seconds>& tp,
@@ -93,8 +95,13 @@ class TimeZoneInfo : public TimeZoneIf {
bool Load(ZoneInfoSource* zip);
// Helpers for BreakTime() and MakeTime().
+ time_zone::absolute_lookup Offset(std::int_fast64_t unix_time,
+ const Transition &tr) const;
+ time_zone::absolute_lookup Offset(std::int_fast64_t unix_time,
+ const TransitionType &tt) const;
+
time_zone::absolute_lookup LocalTime(std::int_fast64_t unix_time,
- const TransitionType& tt) const;
+ const TransitionType &tt) const;
time_zone::absolute_lookup LocalTime(std::int_fast64_t unix_time,
const Transition& tr) const;
time_zone::civil_lookup TimeLocal(const civil_second& cs,
diff --git a/src/time_zone_lookup.cc b/src/time_zone_lookup.cc
index 32ca398..5086bec 100644
--- a/src/time_zone_lookup.cc
+++ b/src/time_zone_lookup.cc
@@ -150,6 +150,11 @@ time_zone::absolute_lookup time_zone::lookup(
return effective_impl().BreakTime(tp);
}
+time_zone::absolute_lookup
+time_zone::lookup_offset(const time_point<seconds> &tp) const {
+ return effective_impl().LookupOffset(tp);
+}
+
time_zone::civil_lookup time_zone::lookup(const civil_second& cs) const {
return effective_impl().MakeTime(cs);
}