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