// Matrix Construct // // Copyright (C) Matrix Construct Developers, Authors & Contributors // Copyright (C) 2016-2018 Jason Volk // // Permission to use, copy, modify, and/or distribute this software for any // purpose with or without fee is hereby granted, provided that the above // copyright notice and this permission notice is present in all copies. The // full license for this software is available in the LICENSE file. #pragma once #define HAVE_IRCD_DATE_H namespace ircd { using microtime_t = std::pair; using steady_point = time_point; using system_point = time_point; microtime_t microtime(); string_view microtime(const mutable_buffer &); std::ostream &operator<<(std::ostream &, const microtime_t &); template unit now(); template<> steady_point now(); template<> system_point now(); template time_t &time(time_t &ref); template time_t time(); template time_t time(time_t *const &ptr); const char *const rfc7231_fmt { "%a, %d %b %Y %T %z" }; IRCD_OVERLOAD(localtime) string_view timef(const mutable_buffer &out, const struct tm &tm, const char *const &fmt = rfc7231_fmt); string_view timef(const mutable_buffer &out, const time_t &epoch, const char *const &fmt = rfc7231_fmt); string_view timef(const mutable_buffer &out, const time_t &epoch, localtime_t, const char *const &fmt = rfc7231_fmt); string_view timef(const mutable_buffer &out, localtime_t, const char *const &fmt = rfc7231_fmt); string_view timef(const mutable_buffer &out, const char *const &fmt = rfc7231_fmt); template std::string timestr(args&&...); std::ostream &operator<<(std::ostream &, const steady_point &); std::ostream &operator<<(std::ostream &, const system_point &); } inline std::ostream & ircd::operator<<(std::ostream &s, const system_point &tp) { return (s << duration_cast(tp.time_since_epoch()).count()); } inline std::ostream & ircd::operator<<(std::ostream &s, const steady_point &tp) { return (s << duration_cast(tp.time_since_epoch()).count()); } template std::string ircd::timestr(args&&... a) { static const size_t max{128}; return string(max, [&](const mutable_buffer &buf) { return timef(buf, std::forward(a)...); }); } inline ircd::string_view ircd::timef(const mutable_buffer &out, const char *const &fmt) { const auto epoch{time()}; return timef(out, epoch, fmt); } inline ircd::string_view ircd::timef(const mutable_buffer &out, localtime_t, const char *const &fmt) { const auto epoch{time()}; return timef(out, epoch, localtime, fmt); } inline ircd::string_view ircd::timef(const mutable_buffer &out, const time_t &epoch, localtime_t, const char *const &fmt) { struct tm tm; localtime_r(&epoch, &tm); return timef(out, tm, fmt); } inline ircd::string_view ircd::timef(const mutable_buffer &out, const time_t &epoch, const char *const &fmt) { struct tm tm; gmtime_r(&epoch, &tm); return timef(out, tm, fmt); } inline ircd::string_view ircd::timef(const mutable_buffer &out, const struct tm &tm, const char *const &fmt) { const auto len { strftime(data(out), size(out), fmt, &tm) }; return { data(out), len }; } template time_t ircd::time(time_t *const &ptr) { time_t buf, &ret{ptr? *ptr : buf}; return time(ret); } template time_t ircd::time() { time_t ret; return time(ret); } template time_t & ircd::time(time_t &ref) { ref = duration_cast(system_clock::now().time_since_epoch()).count(); return ref; } template<> inline ircd::steady_point ircd::now() { return steady_clock::now(); } template<> inline ircd::system_point ircd::now() { return system_clock::now(); } template unit ircd::now() { const auto now { steady_clock::now() }; const auto tse { now.time_since_epoch() }; return std::chrono::duration_cast(tse); } inline std::ostream & ircd::operator<<(std::ostream &s, const microtime_t &t) { char buf[64]; s << microtime(buf); return s; } inline ircd::string_view ircd::microtime(const mutable_buffer &buf) { const auto mt{microtime()}; const auto length { snprintf(data(buf), size(buf), "%zd.%06d", mt.first, mt.second) }; return string_view { data(buf), size_t(length) }; } inline ircd::microtime_t ircd::microtime() { struct timeval tv; syscall(&::gettimeofday, &tv, nullptr); return { tv.tv_sec, tv.tv_usec }; }