00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034 #include "absl/time/time.h"
00035
00036 #include <cstring>
00037 #include <ctime>
00038 #include <limits>
00039
00040 #include "absl/time/internal/cctz/include/cctz/civil_time.h"
00041 #include "absl/time/internal/cctz/include/cctz/time_zone.h"
00042
00043 namespace cctz = absl::time_internal::cctz;
00044
00045 namespace absl {
00046
00047 namespace {
00048
00049 inline cctz::time_point<cctz::seconds> unix_epoch() {
00050 return std::chrono::time_point_cast<cctz::seconds>(
00051 std::chrono::system_clock::from_time_t(0));
00052 }
00053
00054
00055 inline int64_t FloorToUnit(absl::Duration d, absl::Duration unit) {
00056 absl::Duration rem;
00057 int64_t q = absl::IDivDuration(d, unit, &rem);
00058 return (q > 0 ||
00059 rem >= ZeroDuration() ||
00060 q == std::numeric_limits<int64_t>::min()) ? q : q - 1;
00061 }
00062
00063 inline absl::Time::Breakdown InfiniteFutureBreakdown() {
00064 absl::Time::Breakdown bd;
00065 bd.year = std::numeric_limits<int64_t>::max();
00066 bd.month = 12;
00067 bd.day = 31;
00068 bd.hour = 23;
00069 bd.minute = 59;
00070 bd.second = 59;
00071 bd.subsecond = absl::InfiniteDuration();
00072 bd.weekday = 4;
00073 bd.yearday = 365;
00074 bd.offset = 0;
00075 bd.is_dst = false;
00076 bd.zone_abbr = "-00";
00077 return bd;
00078 }
00079
00080 inline absl::Time::Breakdown InfinitePastBreakdown() {
00081 Time::Breakdown bd;
00082 bd.year = std::numeric_limits<int64_t>::min();
00083 bd.month = 1;
00084 bd.day = 1;
00085 bd.hour = 0;
00086 bd.minute = 0;
00087 bd.second = 0;
00088 bd.subsecond = -absl::InfiniteDuration();
00089 bd.weekday = 7;
00090 bd.yearday = 1;
00091 bd.offset = 0;
00092 bd.is_dst = false;
00093 bd.zone_abbr = "-00";
00094 return bd;
00095 }
00096
00097 inline absl::TimeZone::CivilInfo InfiniteFutureCivilInfo() {
00098 TimeZone::CivilInfo ci;
00099 ci.cs = CivilSecond::max();
00100 ci.subsecond = InfiniteDuration();
00101 ci.offset = 0;
00102 ci.is_dst = false;
00103 ci.zone_abbr = "-00";
00104 return ci;
00105 }
00106
00107 inline absl::TimeZone::CivilInfo InfinitePastCivilInfo() {
00108 TimeZone::CivilInfo ci;
00109 ci.cs = CivilSecond::min();
00110 ci.subsecond = -InfiniteDuration();
00111 ci.offset = 0;
00112 ci.is_dst = false;
00113 ci.zone_abbr = "-00";
00114 return ci;
00115 }
00116
00117 inline absl::TimeConversion InfiniteFutureTimeConversion() {
00118 absl::TimeConversion tc;
00119 tc.pre = tc.trans = tc.post = absl::InfiniteFuture();
00120 tc.kind = absl::TimeConversion::UNIQUE;
00121 tc.normalized = true;
00122 return tc;
00123 }
00124
00125 inline TimeConversion InfinitePastTimeConversion() {
00126 absl::TimeConversion tc;
00127 tc.pre = tc.trans = tc.post = absl::InfinitePast();
00128 tc.kind = absl::TimeConversion::UNIQUE;
00129 tc.normalized = true;
00130 return tc;
00131 }
00132
00133
00134
00135 Time MakeTimeWithOverflow(const cctz::time_point<cctz::seconds>& sec,
00136 const cctz::civil_second& cs,
00137 const cctz::time_zone& tz,
00138 bool* normalized = nullptr) {
00139 const auto max = cctz::time_point<cctz::seconds>::max();
00140 const auto min = cctz::time_point<cctz::seconds>::min();
00141 if (sec == max) {
00142 const auto al = tz.lookup(max);
00143 if (cs > al.cs) {
00144 if (normalized) *normalized = true;
00145 return absl::InfiniteFuture();
00146 }
00147 }
00148 if (sec == min) {
00149 const auto al = tz.lookup(min);
00150 if (cs < al.cs) {
00151 if (normalized) *normalized = true;
00152 return absl::InfinitePast();
00153 }
00154 }
00155 const auto hi = (sec - unix_epoch()).count();
00156 return time_internal::FromUnixDuration(time_internal::MakeDuration(hi));
00157 }
00158
00159
00160 inline int MapWeekday(const cctz::weekday& wd) {
00161 switch (wd) {
00162 case cctz::weekday::monday:
00163 return 1;
00164 case cctz::weekday::tuesday:
00165 return 2;
00166 case cctz::weekday::wednesday:
00167 return 3;
00168 case cctz::weekday::thursday:
00169 return 4;
00170 case cctz::weekday::friday:
00171 return 5;
00172 case cctz::weekday::saturday:
00173 return 6;
00174 case cctz::weekday::sunday:
00175 return 7;
00176 }
00177 return 1;
00178 }
00179
00180 bool FindTransition(const cctz::time_zone& tz,
00181 bool (cctz::time_zone::*find_transition)(
00182 const cctz::time_point<cctz::seconds>& tp,
00183 cctz::time_zone::civil_transition* trans) const,
00184 Time t, TimeZone::CivilTransition* trans) {
00185
00186 const auto tp = unix_epoch() + cctz::seconds(ToUnixSeconds(t));
00187 cctz::time_zone::civil_transition tr;
00188 if (!(tz.*find_transition)(tp, &tr)) return false;
00189 trans->from = CivilSecond(tr.from);
00190 trans->to = CivilSecond(tr.to);
00191 return true;
00192 }
00193
00194 }
00195
00196
00197
00198
00199
00200 absl::Time::Breakdown Time::In(absl::TimeZone tz) const {
00201 if (*this == absl::InfiniteFuture()) return InfiniteFutureBreakdown();
00202 if (*this == absl::InfinitePast()) return InfinitePastBreakdown();
00203
00204 const auto tp = unix_epoch() + cctz::seconds(time_internal::GetRepHi(rep_));
00205 const auto al = cctz::time_zone(tz).lookup(tp);
00206 const auto cs = al.cs;
00207 const auto cd = cctz::civil_day(cs);
00208
00209 absl::Time::Breakdown bd;
00210 bd.year = cs.year();
00211 bd.month = cs.month();
00212 bd.day = cs.day();
00213 bd.hour = cs.hour();
00214 bd.minute = cs.minute();
00215 bd.second = cs.second();
00216 bd.subsecond = time_internal::MakeDuration(0, time_internal::GetRepLo(rep_));
00217 bd.weekday = MapWeekday(cctz::get_weekday(cd));
00218 bd.yearday = cctz::get_yearday(cd);
00219 bd.offset = al.offset;
00220 bd.is_dst = al.is_dst;
00221 bd.zone_abbr = al.abbr;
00222 return bd;
00223 }
00224
00225
00226
00227
00228
00229 absl::Time FromUDate(double udate) {
00230 return time_internal::FromUnixDuration(absl::Milliseconds(udate));
00231 }
00232
00233 absl::Time FromUniversal(int64_t universal) {
00234 return absl::UniversalEpoch() + 100 * absl::Nanoseconds(universal);
00235 }
00236
00237 int64_t ToUnixNanos(Time t) {
00238 if (time_internal::GetRepHi(time_internal::ToUnixDuration(t)) >= 0 &&
00239 time_internal::GetRepHi(time_internal::ToUnixDuration(t)) >> 33 == 0) {
00240 return (time_internal::GetRepHi(time_internal::ToUnixDuration(t)) *
00241 1000 * 1000 * 1000) +
00242 (time_internal::GetRepLo(time_internal::ToUnixDuration(t)) / 4);
00243 }
00244 return FloorToUnit(time_internal::ToUnixDuration(t), absl::Nanoseconds(1));
00245 }
00246
00247 int64_t ToUnixMicros(Time t) {
00248 if (time_internal::GetRepHi(time_internal::ToUnixDuration(t)) >= 0 &&
00249 time_internal::GetRepHi(time_internal::ToUnixDuration(t)) >> 43 == 0) {
00250 return (time_internal::GetRepHi(time_internal::ToUnixDuration(t)) *
00251 1000 * 1000) +
00252 (time_internal::GetRepLo(time_internal::ToUnixDuration(t)) / 4000);
00253 }
00254 return FloorToUnit(time_internal::ToUnixDuration(t), absl::Microseconds(1));
00255 }
00256
00257 int64_t ToUnixMillis(Time t) {
00258 if (time_internal::GetRepHi(time_internal::ToUnixDuration(t)) >= 0 &&
00259 time_internal::GetRepHi(time_internal::ToUnixDuration(t)) >> 53 == 0) {
00260 return (time_internal::GetRepHi(time_internal::ToUnixDuration(t)) * 1000) +
00261 (time_internal::GetRepLo(time_internal::ToUnixDuration(t)) /
00262 (4000 * 1000));
00263 }
00264 return FloorToUnit(time_internal::ToUnixDuration(t), absl::Milliseconds(1));
00265 }
00266
00267 int64_t ToUnixSeconds(Time t) {
00268 return time_internal::GetRepHi(time_internal::ToUnixDuration(t));
00269 }
00270
00271 time_t ToTimeT(Time t) { return absl::ToTimespec(t).tv_sec; }
00272
00273 double ToUDate(Time t) {
00274 return absl::FDivDuration(time_internal::ToUnixDuration(t),
00275 absl::Milliseconds(1));
00276 }
00277
00278 int64_t ToUniversal(absl::Time t) {
00279 return absl::FloorToUnit(t - absl::UniversalEpoch(), absl::Nanoseconds(100));
00280 }
00281
00282 absl::Time TimeFromTimespec(timespec ts) {
00283 return time_internal::FromUnixDuration(absl::DurationFromTimespec(ts));
00284 }
00285
00286 absl::Time TimeFromTimeval(timeval tv) {
00287 return time_internal::FromUnixDuration(absl::DurationFromTimeval(tv));
00288 }
00289
00290 timespec ToTimespec(Time t) {
00291 timespec ts;
00292 absl::Duration d = time_internal::ToUnixDuration(t);
00293 if (!time_internal::IsInfiniteDuration(d)) {
00294 ts.tv_sec = time_internal::GetRepHi(d);
00295 if (ts.tv_sec == time_internal::GetRepHi(d)) {
00296 ts.tv_nsec = time_internal::GetRepLo(d) / 4;
00297 return ts;
00298 }
00299 }
00300 if (d >= absl::ZeroDuration()) {
00301 ts.tv_sec = std::numeric_limits<time_t>::max();
00302 ts.tv_nsec = 1000 * 1000 * 1000 - 1;
00303 } else {
00304 ts.tv_sec = std::numeric_limits<time_t>::min();
00305 ts.tv_nsec = 0;
00306 }
00307 return ts;
00308 }
00309
00310 timeval ToTimeval(Time t) {
00311 timeval tv;
00312 timespec ts = absl::ToTimespec(t);
00313 tv.tv_sec = ts.tv_sec;
00314 if (tv.tv_sec != ts.tv_sec) {
00315 if (ts.tv_sec < 0) {
00316 tv.tv_sec = std::numeric_limits<decltype(tv.tv_sec)>::min();
00317 tv.tv_usec = 0;
00318 } else {
00319 tv.tv_sec = std::numeric_limits<decltype(tv.tv_sec)>::max();
00320 tv.tv_usec = 1000 * 1000 - 1;
00321 }
00322 return tv;
00323 }
00324 tv.tv_usec = static_cast<int>(ts.tv_nsec / 1000);
00325 return tv;
00326 }
00327
00328 Time FromChrono(const std::chrono::system_clock::time_point& tp) {
00329 return time_internal::FromUnixDuration(time_internal::FromChrono(
00330 tp - std::chrono::system_clock::from_time_t(0)));
00331 }
00332
00333 std::chrono::system_clock::time_point ToChronoTime(absl::Time t) {
00334 using D = std::chrono::system_clock::duration;
00335 auto d = time_internal::ToUnixDuration(t);
00336 if (d < ZeroDuration()) d = Floor(d, FromChrono(D{1}));
00337 return std::chrono::system_clock::from_time_t(0) +
00338 time_internal::ToChronoDuration<D>(d);
00339 }
00340
00341
00342
00343
00344
00345 absl::TimeZone::CivilInfo TimeZone::At(Time t) const {
00346 if (t == absl::InfiniteFuture()) return InfiniteFutureCivilInfo();
00347 if (t == absl::InfinitePast()) return InfinitePastCivilInfo();
00348
00349 const auto ud = time_internal::ToUnixDuration(t);
00350 const auto tp = unix_epoch() + cctz::seconds(time_internal::GetRepHi(ud));
00351 const auto al = cz_.lookup(tp);
00352
00353 TimeZone::CivilInfo ci;
00354 ci.cs = CivilSecond(al.cs);
00355 ci.subsecond = time_internal::MakeDuration(0, time_internal::GetRepLo(ud));
00356 ci.offset = al.offset;
00357 ci.is_dst = al.is_dst;
00358 ci.zone_abbr = al.abbr;
00359 return ci;
00360 }
00361
00362 absl::TimeZone::TimeInfo TimeZone::At(CivilSecond ct) const {
00363 const cctz::civil_second cs(ct);
00364 const auto cl = cz_.lookup(cs);
00365
00366 TimeZone::TimeInfo ti;
00367 switch (cl.kind) {
00368 case cctz::time_zone::civil_lookup::UNIQUE:
00369 ti.kind = TimeZone::TimeInfo::UNIQUE;
00370 break;
00371 case cctz::time_zone::civil_lookup::SKIPPED:
00372 ti.kind = TimeZone::TimeInfo::SKIPPED;
00373 break;
00374 case cctz::time_zone::civil_lookup::REPEATED:
00375 ti.kind = TimeZone::TimeInfo::REPEATED;
00376 break;
00377 }
00378 ti.pre = MakeTimeWithOverflow(cl.pre, cs, cz_);
00379 ti.trans = MakeTimeWithOverflow(cl.trans, cs, cz_);
00380 ti.post = MakeTimeWithOverflow(cl.post, cs, cz_);
00381 return ti;
00382 }
00383
00384 bool TimeZone::NextTransition(Time t, CivilTransition* trans) const {
00385 return FindTransition(cz_, &cctz::time_zone::next_transition, t, trans);
00386 }
00387
00388 bool TimeZone::PrevTransition(Time t, CivilTransition* trans) const {
00389 return FindTransition(cz_, &cctz::time_zone::prev_transition, t, trans);
00390 }
00391
00392
00393
00394
00395
00396 absl::TimeConversion ConvertDateTime(int64_t year, int mon, int day, int hour,
00397 int min, int sec, TimeZone tz) {
00398
00399 if (year > 300000000000) return InfiniteFutureTimeConversion();
00400 if (year < -300000000000) return InfinitePastTimeConversion();
00401
00402 const CivilSecond cs(year, mon, day, hour, min, sec);
00403 const auto ti = tz.At(cs);
00404
00405 TimeConversion tc;
00406 tc.pre = ti.pre;
00407 tc.trans = ti.trans;
00408 tc.post = ti.post;
00409 switch (ti.kind) {
00410 case TimeZone::TimeInfo::UNIQUE:
00411 tc.kind = TimeConversion::UNIQUE;
00412 break;
00413 case TimeZone::TimeInfo::SKIPPED:
00414 tc.kind = TimeConversion::SKIPPED;
00415 break;
00416 case TimeZone::TimeInfo::REPEATED:
00417 tc.kind = TimeConversion::REPEATED;
00418 break;
00419 }
00420 tc.normalized = false;
00421 if (year != cs.year() || mon != cs.month() || day != cs.day() ||
00422 hour != cs.hour() || min != cs.minute() || sec != cs.second()) {
00423 tc.normalized = true;
00424 }
00425 return tc;
00426 }
00427
00428 absl::Time FromTM(const struct tm& tm, absl::TimeZone tz) {
00429 const CivilSecond cs(tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday,
00430 tm.tm_hour, tm.tm_min, tm.tm_sec);
00431 const auto ti = tz.At(cs);
00432 return tm.tm_isdst == 0 ? ti.post : ti.pre;
00433 }
00434
00435 struct tm ToTM(absl::Time t, absl::TimeZone tz) {
00436 struct tm tm = {};
00437
00438 const auto ci = tz.At(t);
00439 const auto& cs = ci.cs;
00440 tm.tm_sec = cs.second();
00441 tm.tm_min = cs.minute();
00442 tm.tm_hour = cs.hour();
00443 tm.tm_mday = cs.day();
00444 tm.tm_mon = cs.month() - 1;
00445
00446
00447
00448 if (cs.year() < std::numeric_limits<int>::min() + 1900) {
00449 tm.tm_year = std::numeric_limits<int>::min();
00450 } else if (cs.year() > std::numeric_limits<int>::max()) {
00451 tm.tm_year = std::numeric_limits<int>::max() - 1900;
00452 } else {
00453 tm.tm_year = static_cast<int>(cs.year() - 1900);
00454 }
00455
00456 const CivilDay cd(cs);
00457 switch (GetWeekday(cd)) {
00458 case Weekday::sunday:
00459 tm.tm_wday = 0;
00460 break;
00461 case Weekday::monday:
00462 tm.tm_wday = 1;
00463 break;
00464 case Weekday::tuesday:
00465 tm.tm_wday = 2;
00466 break;
00467 case Weekday::wednesday:
00468 tm.tm_wday = 3;
00469 break;
00470 case Weekday::thursday:
00471 tm.tm_wday = 4;
00472 break;
00473 case Weekday::friday:
00474 tm.tm_wday = 5;
00475 break;
00476 case Weekday::saturday:
00477 tm.tm_wday = 6;
00478 break;
00479 }
00480 tm.tm_yday = GetYearDay(cd) - 1;
00481 tm.tm_isdst = ci.is_dst ? 1 : 0;
00482
00483 return tm;
00484 }
00485
00486 }