xref: /aosp_15_r20/external/abseil-cpp/absl/time/time.cc (revision 9356374a3709195abf420251b3e825997ff56c0f)
1*9356374aSAndroid Build Coastguard Worker // Copyright 2017 The Abseil Authors.
2*9356374aSAndroid Build Coastguard Worker //
3*9356374aSAndroid Build Coastguard Worker // Licensed under the Apache License, Version 2.0 (the "License");
4*9356374aSAndroid Build Coastguard Worker // you may not use this file except in compliance with the License.
5*9356374aSAndroid Build Coastguard Worker // You may obtain a copy of the License at
6*9356374aSAndroid Build Coastguard Worker //
7*9356374aSAndroid Build Coastguard Worker //      https://www.apache.org/licenses/LICENSE-2.0
8*9356374aSAndroid Build Coastguard Worker //
9*9356374aSAndroid Build Coastguard Worker // Unless required by applicable law or agreed to in writing, software
10*9356374aSAndroid Build Coastguard Worker // distributed under the License is distributed on an "AS IS" BASIS,
11*9356374aSAndroid Build Coastguard Worker // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12*9356374aSAndroid Build Coastguard Worker // See the License for the specific language governing permissions and
13*9356374aSAndroid Build Coastguard Worker // limitations under the License.
14*9356374aSAndroid Build Coastguard Worker 
15*9356374aSAndroid Build Coastguard Worker // The implementation of the absl::Time class, which is declared in
16*9356374aSAndroid Build Coastguard Worker // //absl/time.h.
17*9356374aSAndroid Build Coastguard Worker //
18*9356374aSAndroid Build Coastguard Worker // The representation for an absl::Time is an absl::Duration offset from the
19*9356374aSAndroid Build Coastguard Worker // epoch.  We use the traditional Unix epoch (1970-01-01 00:00:00 +0000)
20*9356374aSAndroid Build Coastguard Worker // for convenience, but this is not exposed in the API and could be changed.
21*9356374aSAndroid Build Coastguard Worker //
22*9356374aSAndroid Build Coastguard Worker // NOTE: To keep type verbosity to a minimum, the following variable naming
23*9356374aSAndroid Build Coastguard Worker // conventions are used throughout this file.
24*9356374aSAndroid Build Coastguard Worker //
25*9356374aSAndroid Build Coastguard Worker // tz: An absl::TimeZone
26*9356374aSAndroid Build Coastguard Worker // ci: An absl::TimeZone::CivilInfo
27*9356374aSAndroid Build Coastguard Worker // ti: An absl::TimeZone::TimeInfo
28*9356374aSAndroid Build Coastguard Worker // cd: An absl::CivilDay or a cctz::civil_day
29*9356374aSAndroid Build Coastguard Worker // cs: An absl::CivilSecond or a cctz::civil_second
30*9356374aSAndroid Build Coastguard Worker // bd: An absl::Time::Breakdown
31*9356374aSAndroid Build Coastguard Worker // cl: A cctz::time_zone::civil_lookup
32*9356374aSAndroid Build Coastguard Worker // al: A cctz::time_zone::absolute_lookup
33*9356374aSAndroid Build Coastguard Worker 
34*9356374aSAndroid Build Coastguard Worker #include "absl/time/time.h"
35*9356374aSAndroid Build Coastguard Worker 
36*9356374aSAndroid Build Coastguard Worker #if defined(_MSC_VER)
37*9356374aSAndroid Build Coastguard Worker #include <winsock2.h>  // for timeval
38*9356374aSAndroid Build Coastguard Worker #endif
39*9356374aSAndroid Build Coastguard Worker 
40*9356374aSAndroid Build Coastguard Worker #include <cstring>
41*9356374aSAndroid Build Coastguard Worker #include <ctime>
42*9356374aSAndroid Build Coastguard Worker #include <limits>
43*9356374aSAndroid Build Coastguard Worker 
44*9356374aSAndroid Build Coastguard Worker #include "absl/time/internal/cctz/include/cctz/civil_time.h"
45*9356374aSAndroid Build Coastguard Worker #include "absl/time/internal/cctz/include/cctz/time_zone.h"
46*9356374aSAndroid Build Coastguard Worker 
47*9356374aSAndroid Build Coastguard Worker namespace cctz = absl::time_internal::cctz;
48*9356374aSAndroid Build Coastguard Worker 
49*9356374aSAndroid Build Coastguard Worker namespace absl {
50*9356374aSAndroid Build Coastguard Worker ABSL_NAMESPACE_BEGIN
51*9356374aSAndroid Build Coastguard Worker 
52*9356374aSAndroid Build Coastguard Worker namespace {
53*9356374aSAndroid Build Coastguard Worker 
unix_epoch()54*9356374aSAndroid Build Coastguard Worker inline cctz::time_point<cctz::seconds> unix_epoch() {
55*9356374aSAndroid Build Coastguard Worker   return std::chrono::time_point_cast<cctz::seconds>(
56*9356374aSAndroid Build Coastguard Worker       std::chrono::system_clock::from_time_t(0));
57*9356374aSAndroid Build Coastguard Worker }
58*9356374aSAndroid Build Coastguard Worker 
59*9356374aSAndroid Build Coastguard Worker // Floors d to the next unit boundary closer to negative infinity.
FloorToUnit(absl::Duration d,absl::Duration unit)60*9356374aSAndroid Build Coastguard Worker inline int64_t FloorToUnit(absl::Duration d, absl::Duration unit) {
61*9356374aSAndroid Build Coastguard Worker   absl::Duration rem;
62*9356374aSAndroid Build Coastguard Worker   int64_t q = absl::IDivDuration(d, unit, &rem);
63*9356374aSAndroid Build Coastguard Worker   return (q > 0 || rem >= ZeroDuration() ||
64*9356374aSAndroid Build Coastguard Worker           q == std::numeric_limits<int64_t>::min())
65*9356374aSAndroid Build Coastguard Worker              ? q
66*9356374aSAndroid Build Coastguard Worker              : q - 1;
67*9356374aSAndroid Build Coastguard Worker }
68*9356374aSAndroid Build Coastguard Worker 
69*9356374aSAndroid Build Coastguard Worker ABSL_INTERNAL_DISABLE_DEPRECATED_DECLARATION_WARNING
InfiniteFutureBreakdown()70*9356374aSAndroid Build Coastguard Worker inline absl::Time::Breakdown InfiniteFutureBreakdown() {
71*9356374aSAndroid Build Coastguard Worker   absl::Time::Breakdown bd;
72*9356374aSAndroid Build Coastguard Worker   bd.year = std::numeric_limits<int64_t>::max();
73*9356374aSAndroid Build Coastguard Worker   bd.month = 12;
74*9356374aSAndroid Build Coastguard Worker   bd.day = 31;
75*9356374aSAndroid Build Coastguard Worker   bd.hour = 23;
76*9356374aSAndroid Build Coastguard Worker   bd.minute = 59;
77*9356374aSAndroid Build Coastguard Worker   bd.second = 59;
78*9356374aSAndroid Build Coastguard Worker   bd.subsecond = absl::InfiniteDuration();
79*9356374aSAndroid Build Coastguard Worker   bd.weekday = 4;
80*9356374aSAndroid Build Coastguard Worker   bd.yearday = 365;
81*9356374aSAndroid Build Coastguard Worker   bd.offset = 0;
82*9356374aSAndroid Build Coastguard Worker   bd.is_dst = false;
83*9356374aSAndroid Build Coastguard Worker   bd.zone_abbr = "-00";
84*9356374aSAndroid Build Coastguard Worker   return bd;
85*9356374aSAndroid Build Coastguard Worker }
86*9356374aSAndroid Build Coastguard Worker 
InfinitePastBreakdown()87*9356374aSAndroid Build Coastguard Worker inline absl::Time::Breakdown InfinitePastBreakdown() {
88*9356374aSAndroid Build Coastguard Worker   Time::Breakdown bd;
89*9356374aSAndroid Build Coastguard Worker   bd.year = std::numeric_limits<int64_t>::min();
90*9356374aSAndroid Build Coastguard Worker   bd.month = 1;
91*9356374aSAndroid Build Coastguard Worker   bd.day = 1;
92*9356374aSAndroid Build Coastguard Worker   bd.hour = 0;
93*9356374aSAndroid Build Coastguard Worker   bd.minute = 0;
94*9356374aSAndroid Build Coastguard Worker   bd.second = 0;
95*9356374aSAndroid Build Coastguard Worker   bd.subsecond = -absl::InfiniteDuration();
96*9356374aSAndroid Build Coastguard Worker   bd.weekday = 7;
97*9356374aSAndroid Build Coastguard Worker   bd.yearday = 1;
98*9356374aSAndroid Build Coastguard Worker   bd.offset = 0;
99*9356374aSAndroid Build Coastguard Worker   bd.is_dst = false;
100*9356374aSAndroid Build Coastguard Worker   bd.zone_abbr = "-00";
101*9356374aSAndroid Build Coastguard Worker   return bd;
102*9356374aSAndroid Build Coastguard Worker }
103*9356374aSAndroid Build Coastguard Worker ABSL_INTERNAL_RESTORE_DEPRECATED_DECLARATION_WARNING
104*9356374aSAndroid Build Coastguard Worker 
InfiniteFutureCivilInfo()105*9356374aSAndroid Build Coastguard Worker inline absl::TimeZone::CivilInfo InfiniteFutureCivilInfo() {
106*9356374aSAndroid Build Coastguard Worker   TimeZone::CivilInfo ci;
107*9356374aSAndroid Build Coastguard Worker   ci.cs = CivilSecond::max();
108*9356374aSAndroid Build Coastguard Worker   ci.subsecond = InfiniteDuration();
109*9356374aSAndroid Build Coastguard Worker   ci.offset = 0;
110*9356374aSAndroid Build Coastguard Worker   ci.is_dst = false;
111*9356374aSAndroid Build Coastguard Worker   ci.zone_abbr = "-00";
112*9356374aSAndroid Build Coastguard Worker   return ci;
113*9356374aSAndroid Build Coastguard Worker }
114*9356374aSAndroid Build Coastguard Worker 
InfinitePastCivilInfo()115*9356374aSAndroid Build Coastguard Worker inline absl::TimeZone::CivilInfo InfinitePastCivilInfo() {
116*9356374aSAndroid Build Coastguard Worker   TimeZone::CivilInfo ci;
117*9356374aSAndroid Build Coastguard Worker   ci.cs = CivilSecond::min();
118*9356374aSAndroid Build Coastguard Worker   ci.subsecond = -InfiniteDuration();
119*9356374aSAndroid Build Coastguard Worker   ci.offset = 0;
120*9356374aSAndroid Build Coastguard Worker   ci.is_dst = false;
121*9356374aSAndroid Build Coastguard Worker   ci.zone_abbr = "-00";
122*9356374aSAndroid Build Coastguard Worker   return ci;
123*9356374aSAndroid Build Coastguard Worker }
124*9356374aSAndroid Build Coastguard Worker 
125*9356374aSAndroid Build Coastguard Worker ABSL_INTERNAL_DISABLE_DEPRECATED_DECLARATION_WARNING
InfiniteFutureTimeConversion()126*9356374aSAndroid Build Coastguard Worker inline absl::TimeConversion InfiniteFutureTimeConversion() {
127*9356374aSAndroid Build Coastguard Worker   absl::TimeConversion tc;
128*9356374aSAndroid Build Coastguard Worker   tc.pre = tc.trans = tc.post = absl::InfiniteFuture();
129*9356374aSAndroid Build Coastguard Worker   tc.kind = absl::TimeConversion::UNIQUE;
130*9356374aSAndroid Build Coastguard Worker   tc.normalized = true;
131*9356374aSAndroid Build Coastguard Worker   return tc;
132*9356374aSAndroid Build Coastguard Worker }
133*9356374aSAndroid Build Coastguard Worker 
InfinitePastTimeConversion()134*9356374aSAndroid Build Coastguard Worker inline TimeConversion InfinitePastTimeConversion() {
135*9356374aSAndroid Build Coastguard Worker   absl::TimeConversion tc;
136*9356374aSAndroid Build Coastguard Worker   tc.pre = tc.trans = tc.post = absl::InfinitePast();
137*9356374aSAndroid Build Coastguard Worker   tc.kind = absl::TimeConversion::UNIQUE;
138*9356374aSAndroid Build Coastguard Worker   tc.normalized = true;
139*9356374aSAndroid Build Coastguard Worker   return tc;
140*9356374aSAndroid Build Coastguard Worker }
141*9356374aSAndroid Build Coastguard Worker ABSL_INTERNAL_RESTORE_DEPRECATED_DECLARATION_WARNING
142*9356374aSAndroid Build Coastguard Worker 
143*9356374aSAndroid Build Coastguard Worker // Makes a Time from sec, overflowing to InfiniteFuture/InfinitePast as
144*9356374aSAndroid Build Coastguard Worker // necessary. If sec is min/max, then consult cs+tz to check for overflow.
MakeTimeWithOverflow(const cctz::time_point<cctz::seconds> & sec,const cctz::civil_second & cs,const cctz::time_zone & tz,bool * normalized=nullptr)145*9356374aSAndroid Build Coastguard Worker Time MakeTimeWithOverflow(const cctz::time_point<cctz::seconds>& sec,
146*9356374aSAndroid Build Coastguard Worker                           const cctz::civil_second& cs,
147*9356374aSAndroid Build Coastguard Worker                           const cctz::time_zone& tz,
148*9356374aSAndroid Build Coastguard Worker                           bool* normalized = nullptr) {
149*9356374aSAndroid Build Coastguard Worker   const auto max = cctz::time_point<cctz::seconds>::max();
150*9356374aSAndroid Build Coastguard Worker   const auto min = cctz::time_point<cctz::seconds>::min();
151*9356374aSAndroid Build Coastguard Worker   if (sec == max) {
152*9356374aSAndroid Build Coastguard Worker     const auto al = tz.lookup(max);
153*9356374aSAndroid Build Coastguard Worker     if (cs > al.cs) {
154*9356374aSAndroid Build Coastguard Worker       if (normalized) *normalized = true;
155*9356374aSAndroid Build Coastguard Worker       return absl::InfiniteFuture();
156*9356374aSAndroid Build Coastguard Worker     }
157*9356374aSAndroid Build Coastguard Worker   }
158*9356374aSAndroid Build Coastguard Worker   if (sec == min) {
159*9356374aSAndroid Build Coastguard Worker     const auto al = tz.lookup(min);
160*9356374aSAndroid Build Coastguard Worker     if (cs < al.cs) {
161*9356374aSAndroid Build Coastguard Worker       if (normalized) *normalized = true;
162*9356374aSAndroid Build Coastguard Worker       return absl::InfinitePast();
163*9356374aSAndroid Build Coastguard Worker     }
164*9356374aSAndroid Build Coastguard Worker   }
165*9356374aSAndroid Build Coastguard Worker   const auto hi = (sec - unix_epoch()).count();
166*9356374aSAndroid Build Coastguard Worker   return time_internal::FromUnixDuration(time_internal::MakeDuration(hi));
167*9356374aSAndroid Build Coastguard Worker }
168*9356374aSAndroid Build Coastguard Worker 
169*9356374aSAndroid Build Coastguard Worker // Returns Mon=1..Sun=7.
MapWeekday(const cctz::weekday & wd)170*9356374aSAndroid Build Coastguard Worker inline int MapWeekday(const cctz::weekday& wd) {
171*9356374aSAndroid Build Coastguard Worker   switch (wd) {
172*9356374aSAndroid Build Coastguard Worker     case cctz::weekday::monday:
173*9356374aSAndroid Build Coastguard Worker       return 1;
174*9356374aSAndroid Build Coastguard Worker     case cctz::weekday::tuesday:
175*9356374aSAndroid Build Coastguard Worker       return 2;
176*9356374aSAndroid Build Coastguard Worker     case cctz::weekday::wednesday:
177*9356374aSAndroid Build Coastguard Worker       return 3;
178*9356374aSAndroid Build Coastguard Worker     case cctz::weekday::thursday:
179*9356374aSAndroid Build Coastguard Worker       return 4;
180*9356374aSAndroid Build Coastguard Worker     case cctz::weekday::friday:
181*9356374aSAndroid Build Coastguard Worker       return 5;
182*9356374aSAndroid Build Coastguard Worker     case cctz::weekday::saturday:
183*9356374aSAndroid Build Coastguard Worker       return 6;
184*9356374aSAndroid Build Coastguard Worker     case cctz::weekday::sunday:
185*9356374aSAndroid Build Coastguard Worker       return 7;
186*9356374aSAndroid Build Coastguard Worker   }
187*9356374aSAndroid Build Coastguard Worker   return 1;
188*9356374aSAndroid Build Coastguard Worker }
189*9356374aSAndroid Build Coastguard Worker 
FindTransition(const cctz::time_zone & tz,bool (cctz::time_zone::* find_transition)(const cctz::time_point<cctz::seconds> & tp,cctz::time_zone::civil_transition * trans)const,Time t,TimeZone::CivilTransition * trans)190*9356374aSAndroid Build Coastguard Worker bool FindTransition(const cctz::time_zone& tz,
191*9356374aSAndroid Build Coastguard Worker                     bool (cctz::time_zone::*find_transition)(
192*9356374aSAndroid Build Coastguard Worker                         const cctz::time_point<cctz::seconds>& tp,
193*9356374aSAndroid Build Coastguard Worker                         cctz::time_zone::civil_transition* trans) const,
194*9356374aSAndroid Build Coastguard Worker                     Time t, TimeZone::CivilTransition* trans) {
195*9356374aSAndroid Build Coastguard Worker   // Transitions are second-aligned, so we can discard any fractional part.
196*9356374aSAndroid Build Coastguard Worker   const auto tp = unix_epoch() + cctz::seconds(ToUnixSeconds(t));
197*9356374aSAndroid Build Coastguard Worker   cctz::time_zone::civil_transition tr;
198*9356374aSAndroid Build Coastguard Worker   if (!(tz.*find_transition)(tp, &tr)) return false;
199*9356374aSAndroid Build Coastguard Worker   trans->from = CivilSecond(tr.from);
200*9356374aSAndroid Build Coastguard Worker   trans->to = CivilSecond(tr.to);
201*9356374aSAndroid Build Coastguard Worker   return true;
202*9356374aSAndroid Build Coastguard Worker }
203*9356374aSAndroid Build Coastguard Worker 
204*9356374aSAndroid Build Coastguard Worker }  // namespace
205*9356374aSAndroid Build Coastguard Worker 
206*9356374aSAndroid Build Coastguard Worker //
207*9356374aSAndroid Build Coastguard Worker // Time
208*9356374aSAndroid Build Coastguard Worker //
209*9356374aSAndroid Build Coastguard Worker 
210*9356374aSAndroid Build Coastguard Worker ABSL_INTERNAL_DISABLE_DEPRECATED_DECLARATION_WARNING
In(absl::TimeZone tz) const211*9356374aSAndroid Build Coastguard Worker absl::Time::Breakdown Time::In(absl::TimeZone tz) const {
212*9356374aSAndroid Build Coastguard Worker   if (*this == absl::InfiniteFuture()) return InfiniteFutureBreakdown();
213*9356374aSAndroid Build Coastguard Worker   if (*this == absl::InfinitePast()) return InfinitePastBreakdown();
214*9356374aSAndroid Build Coastguard Worker 
215*9356374aSAndroid Build Coastguard Worker   const auto tp = unix_epoch() + cctz::seconds(time_internal::GetRepHi(rep_));
216*9356374aSAndroid Build Coastguard Worker   const auto al = cctz::time_zone(tz).lookup(tp);
217*9356374aSAndroid Build Coastguard Worker   const auto cs = al.cs;
218*9356374aSAndroid Build Coastguard Worker   const auto cd = cctz::civil_day(cs);
219*9356374aSAndroid Build Coastguard Worker 
220*9356374aSAndroid Build Coastguard Worker   absl::Time::Breakdown bd;
221*9356374aSAndroid Build Coastguard Worker   bd.year = cs.year();
222*9356374aSAndroid Build Coastguard Worker   bd.month = cs.month();
223*9356374aSAndroid Build Coastguard Worker   bd.day = cs.day();
224*9356374aSAndroid Build Coastguard Worker   bd.hour = cs.hour();
225*9356374aSAndroid Build Coastguard Worker   bd.minute = cs.minute();
226*9356374aSAndroid Build Coastguard Worker   bd.second = cs.second();
227*9356374aSAndroid Build Coastguard Worker   bd.subsecond = time_internal::MakeDuration(0, time_internal::GetRepLo(rep_));
228*9356374aSAndroid Build Coastguard Worker   bd.weekday = MapWeekday(cctz::get_weekday(cd));
229*9356374aSAndroid Build Coastguard Worker   bd.yearday = cctz::get_yearday(cd);
230*9356374aSAndroid Build Coastguard Worker   bd.offset = al.offset;
231*9356374aSAndroid Build Coastguard Worker   bd.is_dst = al.is_dst;
232*9356374aSAndroid Build Coastguard Worker   bd.zone_abbr = al.abbr;
233*9356374aSAndroid Build Coastguard Worker   return bd;
234*9356374aSAndroid Build Coastguard Worker }
235*9356374aSAndroid Build Coastguard Worker ABSL_INTERNAL_RESTORE_DEPRECATED_DECLARATION_WARNING
236*9356374aSAndroid Build Coastguard Worker 
237*9356374aSAndroid Build Coastguard Worker //
238*9356374aSAndroid Build Coastguard Worker // Conversions from/to other time types.
239*9356374aSAndroid Build Coastguard Worker //
240*9356374aSAndroid Build Coastguard Worker 
FromUDate(double udate)241*9356374aSAndroid Build Coastguard Worker absl::Time FromUDate(double udate) {
242*9356374aSAndroid Build Coastguard Worker   return time_internal::FromUnixDuration(absl::Milliseconds(udate));
243*9356374aSAndroid Build Coastguard Worker }
244*9356374aSAndroid Build Coastguard Worker 
FromUniversal(int64_t universal)245*9356374aSAndroid Build Coastguard Worker absl::Time FromUniversal(int64_t universal) {
246*9356374aSAndroid Build Coastguard Worker   return absl::UniversalEpoch() + 100 * absl::Nanoseconds(universal);
247*9356374aSAndroid Build Coastguard Worker }
248*9356374aSAndroid Build Coastguard Worker 
ToUnixNanos(Time t)249*9356374aSAndroid Build Coastguard Worker int64_t ToUnixNanos(Time t) {
250*9356374aSAndroid Build Coastguard Worker   if (time_internal::GetRepHi(time_internal::ToUnixDuration(t)) >= 0 &&
251*9356374aSAndroid Build Coastguard Worker       time_internal::GetRepHi(time_internal::ToUnixDuration(t)) >> 33 == 0) {
252*9356374aSAndroid Build Coastguard Worker     return (time_internal::GetRepHi(time_internal::ToUnixDuration(t)) *
253*9356374aSAndroid Build Coastguard Worker             1000 * 1000 * 1000) +
254*9356374aSAndroid Build Coastguard Worker            (time_internal::GetRepLo(time_internal::ToUnixDuration(t)) / 4);
255*9356374aSAndroid Build Coastguard Worker   }
256*9356374aSAndroid Build Coastguard Worker   return FloorToUnit(time_internal::ToUnixDuration(t), absl::Nanoseconds(1));
257*9356374aSAndroid Build Coastguard Worker }
258*9356374aSAndroid Build Coastguard Worker 
ToUnixMicros(Time t)259*9356374aSAndroid Build Coastguard Worker int64_t ToUnixMicros(Time t) {
260*9356374aSAndroid Build Coastguard Worker   if (time_internal::GetRepHi(time_internal::ToUnixDuration(t)) >= 0 &&
261*9356374aSAndroid Build Coastguard Worker       time_internal::GetRepHi(time_internal::ToUnixDuration(t)) >> 43 == 0) {
262*9356374aSAndroid Build Coastguard Worker     return (time_internal::GetRepHi(time_internal::ToUnixDuration(t)) *
263*9356374aSAndroid Build Coastguard Worker             1000 * 1000) +
264*9356374aSAndroid Build Coastguard Worker            (time_internal::GetRepLo(time_internal::ToUnixDuration(t)) / 4000);
265*9356374aSAndroid Build Coastguard Worker   }
266*9356374aSAndroid Build Coastguard Worker   return FloorToUnit(time_internal::ToUnixDuration(t), absl::Microseconds(1));
267*9356374aSAndroid Build Coastguard Worker }
268*9356374aSAndroid Build Coastguard Worker 
ToUnixMillis(Time t)269*9356374aSAndroid Build Coastguard Worker int64_t ToUnixMillis(Time t) {
270*9356374aSAndroid Build Coastguard Worker   if (time_internal::GetRepHi(time_internal::ToUnixDuration(t)) >= 0 &&
271*9356374aSAndroid Build Coastguard Worker       time_internal::GetRepHi(time_internal::ToUnixDuration(t)) >> 53 == 0) {
272*9356374aSAndroid Build Coastguard Worker     return (time_internal::GetRepHi(time_internal::ToUnixDuration(t)) * 1000) +
273*9356374aSAndroid Build Coastguard Worker            (time_internal::GetRepLo(time_internal::ToUnixDuration(t)) /
274*9356374aSAndroid Build Coastguard Worker             (4000 * 1000));
275*9356374aSAndroid Build Coastguard Worker   }
276*9356374aSAndroid Build Coastguard Worker   return FloorToUnit(time_internal::ToUnixDuration(t), absl::Milliseconds(1));
277*9356374aSAndroid Build Coastguard Worker }
278*9356374aSAndroid Build Coastguard Worker 
ToUnixSeconds(Time t)279*9356374aSAndroid Build Coastguard Worker int64_t ToUnixSeconds(Time t) {
280*9356374aSAndroid Build Coastguard Worker   return time_internal::GetRepHi(time_internal::ToUnixDuration(t));
281*9356374aSAndroid Build Coastguard Worker }
282*9356374aSAndroid Build Coastguard Worker 
ToTimeT(Time t)283*9356374aSAndroid Build Coastguard Worker time_t ToTimeT(Time t) { return absl::ToTimespec(t).tv_sec; }
284*9356374aSAndroid Build Coastguard Worker 
ToUDate(Time t)285*9356374aSAndroid Build Coastguard Worker double ToUDate(Time t) {
286*9356374aSAndroid Build Coastguard Worker   return absl::FDivDuration(time_internal::ToUnixDuration(t),
287*9356374aSAndroid Build Coastguard Worker                             absl::Milliseconds(1));
288*9356374aSAndroid Build Coastguard Worker }
289*9356374aSAndroid Build Coastguard Worker 
ToUniversal(absl::Time t)290*9356374aSAndroid Build Coastguard Worker int64_t ToUniversal(absl::Time t) {
291*9356374aSAndroid Build Coastguard Worker   return absl::FloorToUnit(t - absl::UniversalEpoch(), absl::Nanoseconds(100));
292*9356374aSAndroid Build Coastguard Worker }
293*9356374aSAndroid Build Coastguard Worker 
TimeFromTimespec(timespec ts)294*9356374aSAndroid Build Coastguard Worker absl::Time TimeFromTimespec(timespec ts) {
295*9356374aSAndroid Build Coastguard Worker   return time_internal::FromUnixDuration(absl::DurationFromTimespec(ts));
296*9356374aSAndroid Build Coastguard Worker }
297*9356374aSAndroid Build Coastguard Worker 
TimeFromTimeval(timeval tv)298*9356374aSAndroid Build Coastguard Worker absl::Time TimeFromTimeval(timeval tv) {
299*9356374aSAndroid Build Coastguard Worker   return time_internal::FromUnixDuration(absl::DurationFromTimeval(tv));
300*9356374aSAndroid Build Coastguard Worker }
301*9356374aSAndroid Build Coastguard Worker 
ToTimespec(Time t)302*9356374aSAndroid Build Coastguard Worker timespec ToTimespec(Time t) {
303*9356374aSAndroid Build Coastguard Worker   timespec ts;
304*9356374aSAndroid Build Coastguard Worker   absl::Duration d = time_internal::ToUnixDuration(t);
305*9356374aSAndroid Build Coastguard Worker   if (!time_internal::IsInfiniteDuration(d)) {
306*9356374aSAndroid Build Coastguard Worker     ts.tv_sec = static_cast<decltype(ts.tv_sec)>(time_internal::GetRepHi(d));
307*9356374aSAndroid Build Coastguard Worker     if (ts.tv_sec == time_internal::GetRepHi(d)) {  // no time_t narrowing
308*9356374aSAndroid Build Coastguard Worker       ts.tv_nsec = time_internal::GetRepLo(d) / 4;  // floor
309*9356374aSAndroid Build Coastguard Worker       return ts;
310*9356374aSAndroid Build Coastguard Worker     }
311*9356374aSAndroid Build Coastguard Worker   }
312*9356374aSAndroid Build Coastguard Worker   if (d >= absl::ZeroDuration()) {
313*9356374aSAndroid Build Coastguard Worker     ts.tv_sec = std::numeric_limits<time_t>::max();
314*9356374aSAndroid Build Coastguard Worker     ts.tv_nsec = 1000 * 1000 * 1000 - 1;
315*9356374aSAndroid Build Coastguard Worker   } else {
316*9356374aSAndroid Build Coastguard Worker     ts.tv_sec = std::numeric_limits<time_t>::min();
317*9356374aSAndroid Build Coastguard Worker     ts.tv_nsec = 0;
318*9356374aSAndroid Build Coastguard Worker   }
319*9356374aSAndroid Build Coastguard Worker   return ts;
320*9356374aSAndroid Build Coastguard Worker }
321*9356374aSAndroid Build Coastguard Worker 
ToTimeval(Time t)322*9356374aSAndroid Build Coastguard Worker timeval ToTimeval(Time t) {
323*9356374aSAndroid Build Coastguard Worker   timeval tv;
324*9356374aSAndroid Build Coastguard Worker   timespec ts = absl::ToTimespec(t);
325*9356374aSAndroid Build Coastguard Worker   tv.tv_sec = static_cast<decltype(tv.tv_sec)>(ts.tv_sec);
326*9356374aSAndroid Build Coastguard Worker   if (tv.tv_sec != ts.tv_sec) {  // narrowing
327*9356374aSAndroid Build Coastguard Worker     if (ts.tv_sec < 0) {
328*9356374aSAndroid Build Coastguard Worker       tv.tv_sec = std::numeric_limits<decltype(tv.tv_sec)>::min();
329*9356374aSAndroid Build Coastguard Worker       tv.tv_usec = 0;
330*9356374aSAndroid Build Coastguard Worker     } else {
331*9356374aSAndroid Build Coastguard Worker       tv.tv_sec = std::numeric_limits<decltype(tv.tv_sec)>::max();
332*9356374aSAndroid Build Coastguard Worker       tv.tv_usec = 1000 * 1000 - 1;
333*9356374aSAndroid Build Coastguard Worker     }
334*9356374aSAndroid Build Coastguard Worker     return tv;
335*9356374aSAndroid Build Coastguard Worker   }
336*9356374aSAndroid Build Coastguard Worker   tv.tv_usec = static_cast<int>(ts.tv_nsec / 1000);  // suseconds_t
337*9356374aSAndroid Build Coastguard Worker   return tv;
338*9356374aSAndroid Build Coastguard Worker }
339*9356374aSAndroid Build Coastguard Worker 
FromChrono(const std::chrono::system_clock::time_point & tp)340*9356374aSAndroid Build Coastguard Worker Time FromChrono(const std::chrono::system_clock::time_point& tp) {
341*9356374aSAndroid Build Coastguard Worker   return time_internal::FromUnixDuration(time_internal::FromChrono(
342*9356374aSAndroid Build Coastguard Worker       tp - std::chrono::system_clock::from_time_t(0)));
343*9356374aSAndroid Build Coastguard Worker }
344*9356374aSAndroid Build Coastguard Worker 
ToChronoTime(absl::Time t)345*9356374aSAndroid Build Coastguard Worker std::chrono::system_clock::time_point ToChronoTime(absl::Time t) {
346*9356374aSAndroid Build Coastguard Worker   using D = std::chrono::system_clock::duration;
347*9356374aSAndroid Build Coastguard Worker   auto d = time_internal::ToUnixDuration(t);
348*9356374aSAndroid Build Coastguard Worker   if (d < ZeroDuration()) d = Floor(d, FromChrono(D{1}));
349*9356374aSAndroid Build Coastguard Worker   return std::chrono::system_clock::from_time_t(0) +
350*9356374aSAndroid Build Coastguard Worker          time_internal::ToChronoDuration<D>(d);
351*9356374aSAndroid Build Coastguard Worker }
352*9356374aSAndroid Build Coastguard Worker 
353*9356374aSAndroid Build Coastguard Worker //
354*9356374aSAndroid Build Coastguard Worker // TimeZone
355*9356374aSAndroid Build Coastguard Worker //
356*9356374aSAndroid Build Coastguard Worker 
At(Time t) const357*9356374aSAndroid Build Coastguard Worker absl::TimeZone::CivilInfo TimeZone::At(Time t) const {
358*9356374aSAndroid Build Coastguard Worker   if (t == absl::InfiniteFuture()) return InfiniteFutureCivilInfo();
359*9356374aSAndroid Build Coastguard Worker   if (t == absl::InfinitePast()) return InfinitePastCivilInfo();
360*9356374aSAndroid Build Coastguard Worker 
361*9356374aSAndroid Build Coastguard Worker   const auto ud = time_internal::ToUnixDuration(t);
362*9356374aSAndroid Build Coastguard Worker   const auto tp = unix_epoch() + cctz::seconds(time_internal::GetRepHi(ud));
363*9356374aSAndroid Build Coastguard Worker   const auto al = cz_.lookup(tp);
364*9356374aSAndroid Build Coastguard Worker 
365*9356374aSAndroid Build Coastguard Worker   TimeZone::CivilInfo ci;
366*9356374aSAndroid Build Coastguard Worker   ci.cs = CivilSecond(al.cs);
367*9356374aSAndroid Build Coastguard Worker   ci.subsecond = time_internal::MakeDuration(0, time_internal::GetRepLo(ud));
368*9356374aSAndroid Build Coastguard Worker   ci.offset = al.offset;
369*9356374aSAndroid Build Coastguard Worker   ci.is_dst = al.is_dst;
370*9356374aSAndroid Build Coastguard Worker   ci.zone_abbr = al.abbr;
371*9356374aSAndroid Build Coastguard Worker   return ci;
372*9356374aSAndroid Build Coastguard Worker }
373*9356374aSAndroid Build Coastguard Worker 
At(CivilSecond ct) const374*9356374aSAndroid Build Coastguard Worker absl::TimeZone::TimeInfo TimeZone::At(CivilSecond ct) const {
375*9356374aSAndroid Build Coastguard Worker   const cctz::civil_second cs(ct);
376*9356374aSAndroid Build Coastguard Worker   const auto cl = cz_.lookup(cs);
377*9356374aSAndroid Build Coastguard Worker 
378*9356374aSAndroid Build Coastguard Worker   TimeZone::TimeInfo ti;
379*9356374aSAndroid Build Coastguard Worker   switch (cl.kind) {
380*9356374aSAndroid Build Coastguard Worker     case cctz::time_zone::civil_lookup::UNIQUE:
381*9356374aSAndroid Build Coastguard Worker       ti.kind = TimeZone::TimeInfo::UNIQUE;
382*9356374aSAndroid Build Coastguard Worker       break;
383*9356374aSAndroid Build Coastguard Worker     case cctz::time_zone::civil_lookup::SKIPPED:
384*9356374aSAndroid Build Coastguard Worker       ti.kind = TimeZone::TimeInfo::SKIPPED;
385*9356374aSAndroid Build Coastguard Worker       break;
386*9356374aSAndroid Build Coastguard Worker     case cctz::time_zone::civil_lookup::REPEATED:
387*9356374aSAndroid Build Coastguard Worker       ti.kind = TimeZone::TimeInfo::REPEATED;
388*9356374aSAndroid Build Coastguard Worker       break;
389*9356374aSAndroid Build Coastguard Worker   }
390*9356374aSAndroid Build Coastguard Worker   ti.pre = MakeTimeWithOverflow(cl.pre, cs, cz_);
391*9356374aSAndroid Build Coastguard Worker   ti.trans = MakeTimeWithOverflow(cl.trans, cs, cz_);
392*9356374aSAndroid Build Coastguard Worker   ti.post = MakeTimeWithOverflow(cl.post, cs, cz_);
393*9356374aSAndroid Build Coastguard Worker   return ti;
394*9356374aSAndroid Build Coastguard Worker }
395*9356374aSAndroid Build Coastguard Worker 
NextTransition(Time t,CivilTransition * trans) const396*9356374aSAndroid Build Coastguard Worker bool TimeZone::NextTransition(Time t, CivilTransition* trans) const {
397*9356374aSAndroid Build Coastguard Worker   return FindTransition(cz_, &cctz::time_zone::next_transition, t, trans);
398*9356374aSAndroid Build Coastguard Worker }
399*9356374aSAndroid Build Coastguard Worker 
PrevTransition(Time t,CivilTransition * trans) const400*9356374aSAndroid Build Coastguard Worker bool TimeZone::PrevTransition(Time t, CivilTransition* trans) const {
401*9356374aSAndroid Build Coastguard Worker   return FindTransition(cz_, &cctz::time_zone::prev_transition, t, trans);
402*9356374aSAndroid Build Coastguard Worker }
403*9356374aSAndroid Build Coastguard Worker 
404*9356374aSAndroid Build Coastguard Worker //
405*9356374aSAndroid Build Coastguard Worker // Conversions involving time zones.
406*9356374aSAndroid Build Coastguard Worker //
407*9356374aSAndroid Build Coastguard Worker ABSL_INTERNAL_DISABLE_DEPRECATED_DECLARATION_WARNING
ConvertDateTime(int64_t year,int mon,int day,int hour,int min,int sec,TimeZone tz)408*9356374aSAndroid Build Coastguard Worker absl::TimeConversion ConvertDateTime(int64_t year, int mon, int day, int hour,
409*9356374aSAndroid Build Coastguard Worker                                      int min, int sec, TimeZone tz) {
410*9356374aSAndroid Build Coastguard Worker   // Avoids years that are too extreme for CivilSecond to normalize.
411*9356374aSAndroid Build Coastguard Worker   if (year > 300000000000) return InfiniteFutureTimeConversion();
412*9356374aSAndroid Build Coastguard Worker   if (year < -300000000000) return InfinitePastTimeConversion();
413*9356374aSAndroid Build Coastguard Worker 
414*9356374aSAndroid Build Coastguard Worker   const CivilSecond cs(year, mon, day, hour, min, sec);
415*9356374aSAndroid Build Coastguard Worker   const auto ti = tz.At(cs);
416*9356374aSAndroid Build Coastguard Worker 
417*9356374aSAndroid Build Coastguard Worker   TimeConversion tc;
418*9356374aSAndroid Build Coastguard Worker   tc.pre = ti.pre;
419*9356374aSAndroid Build Coastguard Worker   tc.trans = ti.trans;
420*9356374aSAndroid Build Coastguard Worker   tc.post = ti.post;
421*9356374aSAndroid Build Coastguard Worker   switch (ti.kind) {
422*9356374aSAndroid Build Coastguard Worker     case TimeZone::TimeInfo::UNIQUE:
423*9356374aSAndroid Build Coastguard Worker       tc.kind = TimeConversion::UNIQUE;
424*9356374aSAndroid Build Coastguard Worker       break;
425*9356374aSAndroid Build Coastguard Worker     case TimeZone::TimeInfo::SKIPPED:
426*9356374aSAndroid Build Coastguard Worker       tc.kind = TimeConversion::SKIPPED;
427*9356374aSAndroid Build Coastguard Worker       break;
428*9356374aSAndroid Build Coastguard Worker     case TimeZone::TimeInfo::REPEATED:
429*9356374aSAndroid Build Coastguard Worker       tc.kind = TimeConversion::REPEATED;
430*9356374aSAndroid Build Coastguard Worker       break;
431*9356374aSAndroid Build Coastguard Worker   }
432*9356374aSAndroid Build Coastguard Worker   tc.normalized = false;
433*9356374aSAndroid Build Coastguard Worker   if (year != cs.year() || mon != cs.month() || day != cs.day() ||
434*9356374aSAndroid Build Coastguard Worker       hour != cs.hour() || min != cs.minute() || sec != cs.second()) {
435*9356374aSAndroid Build Coastguard Worker     tc.normalized = true;
436*9356374aSAndroid Build Coastguard Worker   }
437*9356374aSAndroid Build Coastguard Worker   return tc;
438*9356374aSAndroid Build Coastguard Worker }
439*9356374aSAndroid Build Coastguard Worker ABSL_INTERNAL_RESTORE_DEPRECATED_DECLARATION_WARNING
440*9356374aSAndroid Build Coastguard Worker 
FromTM(const struct tm & tm,absl::TimeZone tz)441*9356374aSAndroid Build Coastguard Worker absl::Time FromTM(const struct tm& tm, absl::TimeZone tz) {
442*9356374aSAndroid Build Coastguard Worker   civil_year_t tm_year = tm.tm_year;
443*9356374aSAndroid Build Coastguard Worker   // Avoids years that are too extreme for CivilSecond to normalize.
444*9356374aSAndroid Build Coastguard Worker   if (tm_year > 300000000000ll) return InfiniteFuture();
445*9356374aSAndroid Build Coastguard Worker   if (tm_year < -300000000000ll) return InfinitePast();
446*9356374aSAndroid Build Coastguard Worker   int tm_mon = tm.tm_mon;
447*9356374aSAndroid Build Coastguard Worker   if (tm_mon == std::numeric_limits<int>::max()) {
448*9356374aSAndroid Build Coastguard Worker     tm_mon -= 12;
449*9356374aSAndroid Build Coastguard Worker     tm_year += 1;
450*9356374aSAndroid Build Coastguard Worker   }
451*9356374aSAndroid Build Coastguard Worker   const auto ti = tz.At(CivilSecond(tm_year + 1900, tm_mon + 1, tm.tm_mday,
452*9356374aSAndroid Build Coastguard Worker                                     tm.tm_hour, tm.tm_min, tm.tm_sec));
453*9356374aSAndroid Build Coastguard Worker   return tm.tm_isdst == 0 ? ti.post : ti.pre;
454*9356374aSAndroid Build Coastguard Worker }
455*9356374aSAndroid Build Coastguard Worker 
ToTM(absl::Time t,absl::TimeZone tz)456*9356374aSAndroid Build Coastguard Worker struct tm ToTM(absl::Time t, absl::TimeZone tz) {
457*9356374aSAndroid Build Coastguard Worker   struct tm tm = {};
458*9356374aSAndroid Build Coastguard Worker 
459*9356374aSAndroid Build Coastguard Worker   const auto ci = tz.At(t);
460*9356374aSAndroid Build Coastguard Worker   const auto& cs = ci.cs;
461*9356374aSAndroid Build Coastguard Worker   tm.tm_sec = cs.second();
462*9356374aSAndroid Build Coastguard Worker   tm.tm_min = cs.minute();
463*9356374aSAndroid Build Coastguard Worker   tm.tm_hour = cs.hour();
464*9356374aSAndroid Build Coastguard Worker   tm.tm_mday = cs.day();
465*9356374aSAndroid Build Coastguard Worker   tm.tm_mon = cs.month() - 1;
466*9356374aSAndroid Build Coastguard Worker 
467*9356374aSAndroid Build Coastguard Worker   // Saturates tm.tm_year in cases of over/underflow, accounting for the fact
468*9356374aSAndroid Build Coastguard Worker   // that tm.tm_year is years since 1900.
469*9356374aSAndroid Build Coastguard Worker   if (cs.year() < std::numeric_limits<int>::min() + 1900) {
470*9356374aSAndroid Build Coastguard Worker     tm.tm_year = std::numeric_limits<int>::min();
471*9356374aSAndroid Build Coastguard Worker   } else if (cs.year() > std::numeric_limits<int>::max()) {
472*9356374aSAndroid Build Coastguard Worker     tm.tm_year = std::numeric_limits<int>::max() - 1900;
473*9356374aSAndroid Build Coastguard Worker   } else {
474*9356374aSAndroid Build Coastguard Worker     tm.tm_year = static_cast<int>(cs.year() - 1900);
475*9356374aSAndroid Build Coastguard Worker   }
476*9356374aSAndroid Build Coastguard Worker 
477*9356374aSAndroid Build Coastguard Worker   switch (GetWeekday(cs)) {
478*9356374aSAndroid Build Coastguard Worker     case Weekday::sunday:
479*9356374aSAndroid Build Coastguard Worker       tm.tm_wday = 0;
480*9356374aSAndroid Build Coastguard Worker       break;
481*9356374aSAndroid Build Coastguard Worker     case Weekday::monday:
482*9356374aSAndroid Build Coastguard Worker       tm.tm_wday = 1;
483*9356374aSAndroid Build Coastguard Worker       break;
484*9356374aSAndroid Build Coastguard Worker     case Weekday::tuesday:
485*9356374aSAndroid Build Coastguard Worker       tm.tm_wday = 2;
486*9356374aSAndroid Build Coastguard Worker       break;
487*9356374aSAndroid Build Coastguard Worker     case Weekday::wednesday:
488*9356374aSAndroid Build Coastguard Worker       tm.tm_wday = 3;
489*9356374aSAndroid Build Coastguard Worker       break;
490*9356374aSAndroid Build Coastguard Worker     case Weekday::thursday:
491*9356374aSAndroid Build Coastguard Worker       tm.tm_wday = 4;
492*9356374aSAndroid Build Coastguard Worker       break;
493*9356374aSAndroid Build Coastguard Worker     case Weekday::friday:
494*9356374aSAndroid Build Coastguard Worker       tm.tm_wday = 5;
495*9356374aSAndroid Build Coastguard Worker       break;
496*9356374aSAndroid Build Coastguard Worker     case Weekday::saturday:
497*9356374aSAndroid Build Coastguard Worker       tm.tm_wday = 6;
498*9356374aSAndroid Build Coastguard Worker       break;
499*9356374aSAndroid Build Coastguard Worker   }
500*9356374aSAndroid Build Coastguard Worker   tm.tm_yday = GetYearDay(cs) - 1;
501*9356374aSAndroid Build Coastguard Worker   tm.tm_isdst = ci.is_dst ? 1 : 0;
502*9356374aSAndroid Build Coastguard Worker 
503*9356374aSAndroid Build Coastguard Worker   return tm;
504*9356374aSAndroid Build Coastguard Worker }
505*9356374aSAndroid Build Coastguard Worker 
506*9356374aSAndroid Build Coastguard Worker ABSL_NAMESPACE_END
507*9356374aSAndroid Build Coastguard Worker }  // namespace absl
508