time.cc 15 KB

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