diff options
Diffstat (limited to 'src/mongo/util/time_support.cpp')
-rw-r--r-- | src/mongo/util/time_support.cpp | 102 |
1 files changed, 83 insertions, 19 deletions
diff --git a/src/mongo/util/time_support.cpp b/src/mongo/util/time_support.cpp index 69369582058..f6e44c1e3a3 100644 --- a/src/mongo/util/time_support.cpp +++ b/src/mongo/util/time_support.cpp @@ -41,6 +41,7 @@ #include "mongo/bson/util/builder.h" #include "mongo/platform/cstdint.h" #include "mongo/util/assert_util.h" +#include "mongo/util/mongoutils/str.h" #ifdef _WIN32 #include <boost/date_time/filetime_functions.hpp> @@ -64,15 +65,80 @@ timegm(struct tm *const tmp); namespace mongo { +namespace { + template <typename Stream> Stream& streamPut(Stream& os, Microseconds us) { + return os << us.count() << "\xce\xbcs"; + } + + template <typename Stream> Stream& streamPut(Stream& os, Milliseconds ms) { + return os << ms.count() << "ms"; + } + + template <typename Stream> Stream& streamPut(Stream& os, Seconds s) { + return os << s.count() << 's'; + } +} // namespace + + std::ostream& operator<<(std::ostream& os, Microseconds us) { + return streamPut(os, us); + } + + std::ostream& operator<<(std::ostream& os, Milliseconds ms) { + return streamPut(os, ms); + } + std::ostream& operator<<(std::ostream& os, Seconds s) { + return streamPut(os, s); + } + + template <typename Allocator> + StringBuilderImpl<Allocator>& operator<<(StringBuilderImpl<Allocator>& os, Microseconds us) { + return streamPut(os, us); + } + + template <typename Allocator> + StringBuilderImpl<Allocator>& operator<<(StringBuilderImpl<Allocator>& os, Milliseconds ms) { + return streamPut(os, ms); + } + + template <typename Allocator> + StringBuilderImpl<Allocator>& operator<<(StringBuilderImpl<Allocator>& os, Seconds s) { + return streamPut(os, s); + } + + template StringBuilderImpl<StackAllocator>& operator<<(StringBuilderImpl<StackAllocator>&, + Microseconds); + template StringBuilderImpl<StackAllocator>& operator<<(StringBuilderImpl<StackAllocator>&, + Milliseconds); + template StringBuilderImpl<StackAllocator>& operator<<(StringBuilderImpl<StackAllocator>&, + Seconds); + template StringBuilderImpl<TrivialAllocator>& operator<<(StringBuilderImpl<TrivialAllocator>&, + Microseconds); + template StringBuilderImpl<TrivialAllocator>& operator<<(StringBuilderImpl<TrivialAllocator>&, + Milliseconds); + template StringBuilderImpl<TrivialAllocator>& operator<<(StringBuilderImpl<TrivialAllocator>&, + Seconds); + + Date_t Date_t::max() { + return fromMillisSinceEpoch(std::numeric_limits<long long>::max()); + } + + Date_t Date_t::now() { + return fromMillisSinceEpoch(curTimeMillis64()); + } + bool Date_t::isFormatable() const { + if (millis < 0) { + return false; + } if (sizeof(time_t) == sizeof(int32_t)) { - return millis < 2147483647000ULL; // "2038-01-19T03:14:07Z" + return millis < 2147483647000LL; // "2038-01-19T03:14:07Z" } else { - return millis < 32535215999000ULL; // "3000-12-31T23:59:59Z" + return millis < 32535215999000LL; // "3000-12-31T23:59:59Z" } } + // jsTime_virtual_skew is just for testing. a test command manipulates it. long long jsTime_virtual_skew = 0; boost::thread_specific_ptr<long long> jsTime_virtual_thread_skew; @@ -690,7 +756,11 @@ namespace { resultMillis += (tzAdjSecs * 1000); - return StatusWith<Date_t>(resultMillis); + if (resultMillis > static_cast<unsigned long long>(std::numeric_limits<long long>::max())) { + return {ErrorCodes::BadValue, + str::stream() << dateString << " is too far in the future"}; + } + return Date_t::fromMillisSinceEpoch(static_cast<long long>(resultMillis)); } #undef MONGO_ISO_DATE_FMT_NO_TZ @@ -709,9 +779,10 @@ namespace { } time_t Date_t::toTimeT() const { - verify((long long)millis >= 0); // TODO when millis is signed, delete - verify(((long long)millis/1000) < (std::numeric_limits<time_t>::max)()); - return millis / 1000; + const auto secs = millis / 1000; + verify(secs >= std::numeric_limits<time_t>::min()); + verify(secs <= std::numeric_limits<time_t>::max()); + return secs; } boost::gregorian::date currentDate() { @@ -848,7 +919,11 @@ namespace { } /** Date_t is milliseconds since epoch */ - Date_t jsTime(); + Date_t jsTime() { + return Date_t::now() + + Milliseconds(getJSTimeVirtualThreadSkew()) + + Milliseconds(getJSTimeVirtualSkew()); + } /** warning this will wrap */ unsigned curTimeMicros(); @@ -860,12 +935,6 @@ namespace { boost::xtime_get(&xt, MONGO_BOOST_TIME_UTC); return ((unsigned long long)xt.sec) * 1000 + xt.nsec / 1000000; } - Date_t jsTime() { - boost::xtime xt; - boost::xtime_get(&xt, MONGO_BOOST_TIME_UTC); - unsigned long long t = xt.nsec / 1000000; - return ((unsigned long long) xt.sec * 1000) + t + getJSTimeVirtualSkew() + getJSTimeVirtualThreadSkew(); - } static unsigned long long getFiletime() { FILETIME ft; @@ -975,12 +1044,7 @@ namespace { gettimeofday(&tv, NULL); return ((unsigned long long)tv.tv_sec) * 1000 + tv.tv_usec / 1000; } - Date_t jsTime() { - timeval tv; - gettimeofday(&tv, NULL); - unsigned long long t = tv.tv_usec / 1000; - return ((unsigned long long) tv.tv_sec * 1000) + t + getJSTimeVirtualSkew() + getJSTimeVirtualThreadSkew(); - } + unsigned long long curTimeMicros64() { timeval tv; gettimeofday(&tv, NULL); |