summaryrefslogtreecommitdiff
path: root/src/mongo/util/time_support.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/mongo/util/time_support.cpp')
-rw-r--r--src/mongo/util/time_support.cpp102
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);