time.cc 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500
  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. inline absl::Time::Breakdown InfiniteFutureBreakdown() {
  59. absl::Time::Breakdown bd;
  60. bd.year = std::numeric_limits<int64_t>::max();
  61. bd.month = 12;
  62. bd.day = 31;
  63. bd.hour = 23;
  64. bd.minute = 59;
  65. bd.second = 59;
  66. bd.subsecond = absl::InfiniteDuration();
  67. bd.weekday = 4;
  68. bd.yearday = 365;
  69. bd.offset = 0;
  70. bd.is_dst = false;
  71. bd.zone_abbr = "-00";
  72. return bd;
  73. }
  74. inline absl::Time::Breakdown InfinitePastBreakdown() {
  75. Time::Breakdown bd;
  76. bd.year = std::numeric_limits<int64_t>::min();
  77. bd.month = 1;
  78. bd.day = 1;
  79. bd.hour = 0;
  80. bd.minute = 0;
  81. bd.second = 0;
  82. bd.subsecond = -absl::InfiniteDuration();
  83. bd.weekday = 7;
  84. bd.yearday = 1;
  85. bd.offset = 0;
  86. bd.is_dst = false;
  87. bd.zone_abbr = "-00";
  88. return bd;
  89. }
  90. inline absl::TimeZone::CivilInfo InfiniteFutureCivilInfo() {
  91. TimeZone::CivilInfo ci;
  92. ci.cs = CivilSecond::max();
  93. ci.subsecond = InfiniteDuration();
  94. ci.offset = 0;
  95. ci.is_dst = false;
  96. ci.zone_abbr = "-00";
  97. return ci;
  98. }
  99. inline absl::TimeZone::CivilInfo InfinitePastCivilInfo() {
  100. TimeZone::CivilInfo ci;
  101. ci.cs = CivilSecond::min();
  102. ci.subsecond = -InfiniteDuration();
  103. ci.offset = 0;
  104. ci.is_dst = false;
  105. ci.zone_abbr = "-00";
  106. return ci;
  107. }
  108. inline absl::TimeConversion InfiniteFutureTimeConversion() {
  109. absl::TimeConversion tc;
  110. tc.pre = tc.trans = tc.post = absl::InfiniteFuture();
  111. tc.kind = absl::TimeConversion::UNIQUE;
  112. tc.normalized = true;
  113. return tc;
  114. }
  115. inline TimeConversion InfinitePastTimeConversion() {
  116. absl::TimeConversion tc;
  117. tc.pre = tc.trans = tc.post = absl::InfinitePast();
  118. tc.kind = absl::TimeConversion::UNIQUE;
  119. tc.normalized = true;
  120. return tc;
  121. }
  122. // Makes a Time from sec, overflowing to InfiniteFuture/InfinitePast as
  123. // necessary. If sec is min/max, then consult cs+tz to check for overlow.
  124. Time MakeTimeWithOverflow(const cctz::time_point<cctz::seconds>& sec,
  125. const cctz::civil_second& cs,
  126. const cctz::time_zone& tz,
  127. bool* normalized = nullptr) {
  128. const auto max = cctz::time_point<cctz::seconds>::max();
  129. const auto min = cctz::time_point<cctz::seconds>::min();
  130. if (sec == max) {
  131. const auto al = tz.lookup(max);
  132. if (cs > al.cs) {
  133. if (normalized) *normalized = true;
  134. return absl::InfiniteFuture();
  135. }
  136. }
  137. if (sec == min) {
  138. const auto al = tz.lookup(min);
  139. if (cs < al.cs) {
  140. if (normalized) *normalized = true;
  141. return absl::InfinitePast();
  142. }
  143. }
  144. const auto hi = (sec - unix_epoch()).count();
  145. return time_internal::FromUnixDuration(time_internal::MakeDuration(hi));
  146. }
  147. // Returns Mon=1..Sun=7.
  148. inline int MapWeekday(const cctz::weekday& wd) {
  149. switch (wd) {
  150. case cctz::weekday::monday:
  151. return 1;
  152. case cctz::weekday::tuesday:
  153. return 2;
  154. case cctz::weekday::wednesday:
  155. return 3;
  156. case cctz::weekday::thursday:
  157. return 4;
  158. case cctz::weekday::friday:
  159. return 5;
  160. case cctz::weekday::saturday:
  161. return 6;
  162. case cctz::weekday::sunday:
  163. return 7;
  164. }
  165. return 1;
  166. }
  167. bool FindTransition(const cctz::time_zone& tz,
  168. bool (cctz::time_zone::*find_transition)(
  169. const cctz::time_point<cctz::seconds>& tp,
  170. cctz::time_zone::civil_transition* trans) const,
  171. Time t, TimeZone::CivilTransition* trans) {
  172. // Transitions are second-aligned, so we can discard any fractional part.
  173. const auto tp = unix_epoch() + cctz::seconds(ToUnixSeconds(t));
  174. cctz::time_zone::civil_transition tr;
  175. if (!(tz.*find_transition)(tp, &tr)) return false;
  176. trans->from = CivilSecond(tr.from);
  177. trans->to = CivilSecond(tr.to);
  178. return true;
  179. }
  180. } // namespace
  181. //
  182. // Time
  183. //
  184. absl::Time::Breakdown Time::In(absl::TimeZone tz) const {
  185. if (*this == absl::InfiniteFuture()) return InfiniteFutureBreakdown();
  186. if (*this == absl::InfinitePast()) return InfinitePastBreakdown();
  187. const auto tp = unix_epoch() + cctz::seconds(time_internal::GetRepHi(rep_));
  188. const auto al = cctz::time_zone(tz).lookup(tp);
  189. const auto cs = al.cs;
  190. const auto cd = cctz::civil_day(cs);
  191. absl::Time::Breakdown bd;
  192. bd.year = cs.year();
  193. bd.month = cs.month();
  194. bd.day = cs.day();
  195. bd.hour = cs.hour();
  196. bd.minute = cs.minute();
  197. bd.second = cs.second();
  198. bd.subsecond = time_internal::MakeDuration(0, time_internal::GetRepLo(rep_));
  199. bd.weekday = MapWeekday(cctz::get_weekday(cd));
  200. bd.yearday = cctz::get_yearday(cd);
  201. bd.offset = al.offset;
  202. bd.is_dst = al.is_dst;
  203. bd.zone_abbr = al.abbr;
  204. return bd;
  205. }
  206. //
  207. // Conversions from/to other time types.
  208. //
  209. absl::Time FromUDate(double udate) {
  210. return time_internal::FromUnixDuration(absl::Milliseconds(udate));
  211. }
  212. absl::Time FromUniversal(int64_t universal) {
  213. return absl::UniversalEpoch() + 100 * absl::Nanoseconds(universal);
  214. }
  215. int64_t ToUnixNanos(Time t) {
  216. if (time_internal::GetRepHi(time_internal::ToUnixDuration(t)) >= 0 &&
  217. time_internal::GetRepHi(time_internal::ToUnixDuration(t)) >> 33 == 0) {
  218. return (time_internal::GetRepHi(time_internal::ToUnixDuration(t)) *
  219. 1000 * 1000 * 1000) +
  220. (time_internal::GetRepLo(time_internal::ToUnixDuration(t)) / 4);
  221. }
  222. return FloorToUnit(time_internal::ToUnixDuration(t), absl::Nanoseconds(1));
  223. }
  224. int64_t ToUnixMicros(Time t) {
  225. if (time_internal::GetRepHi(time_internal::ToUnixDuration(t)) >= 0 &&
  226. time_internal::GetRepHi(time_internal::ToUnixDuration(t)) >> 43 == 0) {
  227. return (time_internal::GetRepHi(time_internal::ToUnixDuration(t)) *
  228. 1000 * 1000) +
  229. (time_internal::GetRepLo(time_internal::ToUnixDuration(t)) / 4000);
  230. }
  231. return FloorToUnit(time_internal::ToUnixDuration(t), absl::Microseconds(1));
  232. }
  233. int64_t ToUnixMillis(Time t) {
  234. if (time_internal::GetRepHi(time_internal::ToUnixDuration(t)) >= 0 &&
  235. time_internal::GetRepHi(time_internal::ToUnixDuration(t)) >> 53 == 0) {
  236. return (time_internal::GetRepHi(time_internal::ToUnixDuration(t)) * 1000) +
  237. (time_internal::GetRepLo(time_internal::ToUnixDuration(t)) /
  238. (4000 * 1000));
  239. }
  240. return FloorToUnit(time_internal::ToUnixDuration(t), absl::Milliseconds(1));
  241. }
  242. int64_t ToUnixSeconds(Time t) {
  243. return time_internal::GetRepHi(time_internal::ToUnixDuration(t));
  244. }
  245. time_t ToTimeT(Time t) { return absl::ToTimespec(t).tv_sec; }
  246. double ToUDate(Time t) {
  247. return absl::FDivDuration(time_internal::ToUnixDuration(t),
  248. absl::Milliseconds(1));
  249. }
  250. int64_t ToUniversal(absl::Time t) {
  251. return absl::FloorToUnit(t - absl::UniversalEpoch(), absl::Nanoseconds(100));
  252. }
  253. absl::Time TimeFromTimespec(timespec ts) {
  254. return time_internal::FromUnixDuration(absl::DurationFromTimespec(ts));
  255. }
  256. absl::Time TimeFromTimeval(timeval tv) {
  257. return time_internal::FromUnixDuration(absl::DurationFromTimeval(tv));
  258. }
  259. timespec ToTimespec(Time t) {
  260. timespec ts;
  261. absl::Duration d = time_internal::ToUnixDuration(t);
  262. if (!time_internal::IsInfiniteDuration(d)) {
  263. ts.tv_sec = time_internal::GetRepHi(d);
  264. if (ts.tv_sec == time_internal::GetRepHi(d)) { // no time_t narrowing
  265. ts.tv_nsec = time_internal::GetRepLo(d) / 4; // floor
  266. return ts;
  267. }
  268. }
  269. if (d >= absl::ZeroDuration()) {
  270. ts.tv_sec = std::numeric_limits<time_t>::max();
  271. ts.tv_nsec = 1000 * 1000 * 1000 - 1;
  272. } else {
  273. ts.tv_sec = std::numeric_limits<time_t>::min();
  274. ts.tv_nsec = 0;
  275. }
  276. return ts;
  277. }
  278. timeval ToTimeval(Time t) {
  279. timeval tv;
  280. timespec ts = absl::ToTimespec(t);
  281. tv.tv_sec = ts.tv_sec;
  282. if (tv.tv_sec != ts.tv_sec) { // narrowing
  283. if (ts.tv_sec < 0) {
  284. tv.tv_sec = std::numeric_limits<decltype(tv.tv_sec)>::min();
  285. tv.tv_usec = 0;
  286. } else {
  287. tv.tv_sec = std::numeric_limits<decltype(tv.tv_sec)>::max();
  288. tv.tv_usec = 1000 * 1000 - 1;
  289. }
  290. return tv;
  291. }
  292. tv.tv_usec = static_cast<int>(ts.tv_nsec / 1000); // suseconds_t
  293. return tv;
  294. }
  295. Time FromChrono(const std::chrono::system_clock::time_point& tp) {
  296. return time_internal::FromUnixDuration(time_internal::FromChrono(
  297. tp - std::chrono::system_clock::from_time_t(0)));
  298. }
  299. std::chrono::system_clock::time_point ToChronoTime(absl::Time t) {
  300. using D = std::chrono::system_clock::duration;
  301. auto d = time_internal::ToUnixDuration(t);
  302. if (d < ZeroDuration()) d = Floor(d, FromChrono(D{1}));
  303. return std::chrono::system_clock::from_time_t(0) +
  304. time_internal::ToChronoDuration<D>(d);
  305. }
  306. //
  307. // TimeZone
  308. //
  309. absl::TimeZone::CivilInfo TimeZone::At(Time t) const {
  310. if (t == absl::InfiniteFuture()) return InfiniteFutureCivilInfo();
  311. if (t == absl::InfinitePast()) return InfinitePastCivilInfo();
  312. const auto ud = time_internal::ToUnixDuration(t);
  313. const auto tp = unix_epoch() + cctz::seconds(time_internal::GetRepHi(ud));
  314. const auto al = cz_.lookup(tp);
  315. TimeZone::CivilInfo ci;
  316. ci.cs = CivilSecond(al.cs);
  317. ci.subsecond = time_internal::MakeDuration(0, time_internal::GetRepLo(ud));
  318. ci.offset = al.offset;
  319. ci.is_dst = al.is_dst;
  320. ci.zone_abbr = al.abbr;
  321. return ci;
  322. }
  323. absl::TimeZone::TimeInfo TimeZone::At(CivilSecond ct) const {
  324. const cctz::civil_second cs(ct);
  325. const auto cl = cz_.lookup(cs);
  326. TimeZone::TimeInfo ti;
  327. switch (cl.kind) {
  328. case cctz::time_zone::civil_lookup::UNIQUE:
  329. ti.kind = TimeZone::TimeInfo::UNIQUE;
  330. break;
  331. case cctz::time_zone::civil_lookup::SKIPPED:
  332. ti.kind = TimeZone::TimeInfo::SKIPPED;
  333. break;
  334. case cctz::time_zone::civil_lookup::REPEATED:
  335. ti.kind = TimeZone::TimeInfo::REPEATED;
  336. break;
  337. }
  338. ti.pre = MakeTimeWithOverflow(cl.pre, cs, cz_);
  339. ti.trans = MakeTimeWithOverflow(cl.trans, cs, cz_);
  340. ti.post = MakeTimeWithOverflow(cl.post, cs, cz_);
  341. return ti;
  342. }
  343. bool TimeZone::NextTransition(Time t, CivilTransition* trans) const {
  344. return FindTransition(cz_, &cctz::time_zone::next_transition, t, trans);
  345. }
  346. bool TimeZone::PrevTransition(Time t, CivilTransition* trans) const {
  347. return FindTransition(cz_, &cctz::time_zone::prev_transition, t, trans);
  348. }
  349. //
  350. // Conversions involving time zones.
  351. //
  352. absl::TimeConversion ConvertDateTime(int64_t year, int mon, int day, int hour,
  353. int min, int sec, TimeZone tz) {
  354. // Avoids years that are too extreme for CivilSecond to normalize.
  355. if (year > 300000000000) return InfiniteFutureTimeConversion();
  356. if (year < -300000000000) return InfinitePastTimeConversion();
  357. const CivilSecond cs(year, mon, day, hour, min, sec);
  358. const auto ti = tz.At(cs);
  359. TimeConversion tc;
  360. tc.pre = ti.pre;
  361. tc.trans = ti.trans;
  362. tc.post = ti.post;
  363. switch (ti.kind) {
  364. case TimeZone::TimeInfo::UNIQUE:
  365. tc.kind = TimeConversion::UNIQUE;
  366. break;
  367. case TimeZone::TimeInfo::SKIPPED:
  368. tc.kind = TimeConversion::SKIPPED;
  369. break;
  370. case TimeZone::TimeInfo::REPEATED:
  371. tc.kind = TimeConversion::REPEATED;
  372. break;
  373. }
  374. tc.normalized = false;
  375. if (year != cs.year() || mon != cs.month() || day != cs.day() ||
  376. hour != cs.hour() || min != cs.minute() || sec != cs.second()) {
  377. tc.normalized = true;
  378. }
  379. return tc;
  380. }
  381. absl::Time FromTM(const struct tm& tm, absl::TimeZone tz) {
  382. civil_year_t tm_year = tm.tm_year;
  383. // Avoids years that are too extreme for CivilSecond to normalize.
  384. if (tm_year > 300000000000ll) return InfiniteFuture();
  385. if (tm_year < -300000000000ll) return InfinitePast();
  386. int tm_mon = tm.tm_mon;
  387. if (tm_mon == std::numeric_limits<int>::max()) {
  388. tm_mon -= 12;
  389. tm_year += 1;
  390. }
  391. const auto ti = tz.At(CivilSecond(tm_year + 1900, tm_mon + 1, tm.tm_mday,
  392. tm.tm_hour, tm.tm_min, tm.tm_sec));
  393. return tm.tm_isdst == 0 ? ti.post : ti.pre;
  394. }
  395. struct tm ToTM(absl::Time t, absl::TimeZone tz) {
  396. struct tm tm = {};
  397. const auto ci = tz.At(t);
  398. const auto& cs = ci.cs;
  399. tm.tm_sec = cs.second();
  400. tm.tm_min = cs.minute();
  401. tm.tm_hour = cs.hour();
  402. tm.tm_mday = cs.day();
  403. tm.tm_mon = cs.month() - 1;
  404. // Saturates tm.tm_year in cases of over/underflow, accounting for the fact
  405. // that tm.tm_year is years since 1900.
  406. if (cs.year() < std::numeric_limits<int>::min() + 1900) {
  407. tm.tm_year = std::numeric_limits<int>::min();
  408. } else if (cs.year() > std::numeric_limits<int>::max()) {
  409. tm.tm_year = std::numeric_limits<int>::max() - 1900;
  410. } else {
  411. tm.tm_year = static_cast<int>(cs.year() - 1900);
  412. }
  413. switch (GetWeekday(cs)) {
  414. case Weekday::sunday:
  415. tm.tm_wday = 0;
  416. break;
  417. case Weekday::monday:
  418. tm.tm_wday = 1;
  419. break;
  420. case Weekday::tuesday:
  421. tm.tm_wday = 2;
  422. break;
  423. case Weekday::wednesday:
  424. tm.tm_wday = 3;
  425. break;
  426. case Weekday::thursday:
  427. tm.tm_wday = 4;
  428. break;
  429. case Weekday::friday:
  430. tm.tm_wday = 5;
  431. break;
  432. case Weekday::saturday:
  433. tm.tm_wday = 6;
  434. break;
  435. }
  436. tm.tm_yday = GetYearDay(cs) - 1;
  437. tm.tm_isdst = ci.is_dst ? 1 : 0;
  438. return tm;
  439. }
  440. ABSL_NAMESPACE_END
  441. } // namespace absl