diff options
author | Andy Schwerin <schwerin@10gen.com> | 2013-07-23 18:44:16 -0400 |
---|---|---|
committer | Andy Schwerin <schwerin@10gen.com> | 2013-07-24 12:48:42 -0400 |
commit | 0c9209c6d59477eadf27697999f6af59d931251c (patch) | |
tree | 12ee765c318793b4ca63ce7fdf99b2280a476b13 /src/mongo | |
parent | b159c99796a977ca74f20451f9552fadab8d8cda (diff) | |
download | mongo-0c9209c6d59477eadf27697999f6af59d931251c.tar.gz |
SERVER-7965 Introduce time formatting functions for ISO 8601 and Ctime; eliminate curTimeString().
Diffstat (limited to 'src/mongo')
-rw-r--r-- | src/mongo/SConscript | 1 | ||||
-rw-r--r-- | src/mongo/db/db.cpp | 4 | ||||
-rw-r--r-- | src/mongo/logger/message_event_utf8_encoder.cpp | 4 | ||||
-rw-r--r-- | src/mongo/util/time_support.cpp | 67 | ||||
-rw-r--r-- | src/mongo/util/time_support.h | 37 | ||||
-rw-r--r-- | src/mongo/util/time_support_test.cpp | 80 |
6 files changed, 157 insertions, 36 deletions
diff --git a/src/mongo/SConscript b/src/mongo/SConscript index fba3bed588c..d7b0f8c402b 100644 --- a/src/mongo/SConscript +++ b/src/mongo/SConscript @@ -54,6 +54,7 @@ env.StaticLibrary('foundation', '$BUILD_DIR/third_party/shim_boost']) env.CppUnitTest('text_test', 'util/text_test.cpp', LIBDEPS=['foundation']) +env.CppUnitTest('util/time_support_test', 'util/time_support_test.cpp', LIBDEPS=['foundation']) env.StaticLibrary('stringutils', ['util/stringutils.cpp', 'util/base64.cpp', 'util/hex.cpp']) diff --git a/src/mongo/db/db.cpp b/src/mongo/db/db.cpp index b1ea2074ecc..1c00773fe2e 100644 --- a/src/mongo/db/db.cpp +++ b/src/mongo/db/db.cpp @@ -254,9 +254,7 @@ namespace mongo { toLog.append( "hostname", getHostNameCached() ); toLog.appendTimeT( "startTime", time(0) ); - char buf[64]; - curTimeString( buf ); - toLog.append( "startTimeLocal", buf ); + toLog.append( "startTimeLocal", dateToCtimeString(curTimeMillis64()) ); toLog.append( "cmdLine", CmdLine::getParsedOpts() ); toLog.append( "pid", ProcessId::getCurrent().asLongLong() ); diff --git a/src/mongo/logger/message_event_utf8_encoder.cpp b/src/mongo/logger/message_event_utf8_encoder.cpp index b53c000e1e2..ab8aa87ba92 100644 --- a/src/mongo/logger/message_event_utf8_encoder.cpp +++ b/src/mongo/logger/message_event_utf8_encoder.cpp @@ -30,9 +30,7 @@ namespace logger { static const size_t maxLogLine = 10 * 1024; - char dateString[64]; - curTimeString(dateString); - os << dateString << ' '; + os << dateToCtimeString(curTimeMillis64()) << ' '; StringData contextName = event.getContextName(); if (!contextName.empty()) { os << '[' << contextName << "] "; diff --git a/src/mongo/util/time_support.cpp b/src/mongo/util/time_support.cpp index 901cedbe6f8..e8537998631 100644 --- a/src/mongo/util/time_support.cpp +++ b/src/mongo/util/time_support.cpp @@ -54,26 +54,6 @@ namespace mongo { #endif } -#if defined(_WIN32) - void curTimeString(char* timeStr) { - boost::xtime xt; - boost::xtime_get(&xt, MONGO_BOOST_TIME_UTC); - time_t_to_String(xt.sec, timeStr); - - char* milliSecStr = timeStr + 19; - _snprintf(milliSecStr, 5, ".%03d", static_cast<int32_t>(xt.nsec / 1000000)); - } -#else - void curTimeString(char* timeStr) { - struct timeval tv; - gettimeofday(&tv, NULL); - time_t_to_String(tv.tv_sec, timeStr); - - char* milliSecStr = timeStr + 19; - snprintf(milliSecStr, 5, ".%03d", static_cast<int32_t>(tv.tv_usec / 1000)); - } -#endif - // uses ISO 8601 dates without trailing Z // colonsOk should be false when creating filenames string terseCurrentTime(bool colonsOk) { @@ -86,16 +66,61 @@ namespace mongo { return buf; } +#define MONGO_ISO_DATE_FMT_NO_TZ "%Y-%m-%dT%H:%M:%S" string timeToISOString(time_t time) { struct tm t; time_t_to_Struct( time, &t ); - const char* fmt = "%Y-%m-%dT%H:%M:%SZ"; + const char* fmt = MONGO_ISO_DATE_FMT_NO_TZ "Z"; char buf[32]; fassert(16227, strftime(buf, sizeof(buf), fmt, &t) == 20); return buf; } + static inline std::string _dateToISOString(Date_t date, bool local) { + const int bufSize = 32; + char buf[bufSize]; + struct tm t; + time_t_to_Struct(date.toTimeT(), &t, local); + int pos = strftime(buf, bufSize, MONGO_ISO_DATE_FMT_NO_TZ, &t); + fassert(16981, 0 < pos); + char* cur = buf + pos; + int bufRemaining = bufSize - pos; + pos = snprintf(cur, bufRemaining, ".%03d", static_cast<int32_t>(date.asInt64() % 1000)); + fassert(16982, bufRemaining > pos && pos > 0); + cur += pos; + bufRemaining -= pos; + if (local) { + fassert(16983, bufRemaining >= 6); + strftime(cur, bufRemaining, "%z", &t); + } + else { + fassert(16984, bufRemaining >= 2); + *cur = 'Z'; + ++cur; + *cur = '\0'; + } + return buf; + } + + std::string dateToISOStringUTC(Date_t date) { + return _dateToISOString(date, false); + } + + std::string dateToISOStringLocal(Date_t date) { + return _dateToISOString(date, true); + } + +#undef MONGO_ISO_DATE_FMT_NO_TZ + + std::string dateToCtimeString(Date_t date) { + char buf[64]; + time_t_to_String(date.toTimeT(), buf); + char* milliSecStr = buf + 19; + snprintf(milliSecStr, 5, ".%03d", static_cast<int32_t>(date.asInt64() % 1000)); + return buf; + } + boost::gregorian::date currentDate() { boost::posix_time::ptime now = boost::posix_time::second_clock::local_time(); return now.date(); diff --git a/src/mongo/util/time_support.h b/src/mongo/util/time_support.h index f448628f0f0..fe931ab2a1f 100644 --- a/src/mongo/util/time_support.h +++ b/src/mongo/util/time_support.h @@ -27,21 +27,40 @@ namespace mongo { void time_t_to_Struct(time_t t, struct tm * buf , bool local = false ); + // uses ISO 8601 dates without trailing Z + // colonsOk should be false when creating filenames + std::string terseCurrentTime(bool colonsOk=true); + /** - * Gets the current time string (in fixed width) in UTC. Sample format: + * Formats "time" according to the ISO 8601 extended form standard, including date, + * and time, in the UTC timezone. * - * Wed Oct 31 13:34:47.996 + * Sample format: "2013-07-23T18:42:14Z" + */ + std::string timeToISOString(time_t time); + + /** + * Formats "date" according to the ISO 8601 extended form standard, including date, + * and time with milliseconds decimal component, in the UTC timezone. * - * @param timeStr pointer to the buffer to set the string - empirically, 64 bytes is enough for - * the buffer, 26 is not. + * Sample format: "2013-07-23T18:42:14.072Z" */ - void curTimeString(char* timeStr); + std::string dateToISOStringUTC(Date_t date); - // uses ISO 8601 dates without trailing Z - // colonsOk should be false when creating filenames - std::string terseCurrentTime(bool colonsOk=true); + /** + * Formats "date" according to the ISO 8601 extended form standard, including date, + * and time with milliseconds decimal component, in the local timezone. + * + * Sample format: "2013-07-23T18:42:14.072-05:00" + */ + std::string dateToISOStringLocal(Date_t date); - std::string timeToISOString(time_t time); + /** + * Formats "date" in fixed width in the local time zone. + * + * Sample format: "Wed Oct 31 13:34:47.996" + */ + std::string dateToCtimeString(Date_t date); boost::gregorian::date currentDate(); diff --git a/src/mongo/util/time_support_test.cpp b/src/mongo/util/time_support_test.cpp new file mode 100644 index 00000000000..db7104bebab --- /dev/null +++ b/src/mongo/util/time_support_test.cpp @@ -0,0 +1,80 @@ +/* Copyright 2013 10gen Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include <cstdlib> +#include <ctime> +#include <string> + +#include "mongo/base/init.h" +#include "mongo/bson/util/misc.h" +#include "mongo/unittest/unittest.h" +#include "mongo/util/log.h" +#include "mongo/util/time_support.h" + +namespace mongo { +namespace { + + /** + * To make this test deterministic, we set the time zone to America/New_York. + */ + MONGO_INITIALIZER(SetTimeZoneToEasternForTest)(InitializerContext*) { + if (-1 == setenv("TZ", "America/New_York", 1)) { + return Status(ErrorCodes::BadValue, errnoWithDescription()); + } + tzset(); + return Status::OK(); + } + + TEST(TimeFormatting, TimeTAsISO8601Zulu) { + ASSERT_EQUALS(std::string("1970-01-01T00:00:00Z"), timeToISOString(0)); + ASSERT_EQUALS(std::string("1970-06-30T01:06:40Z"), timeToISOString(15556000)); + ASSERT_EQUALS(std::string("2058-02-20T18:29:11Z"), timeToISOString(2781455351)); + ASSERT_EQUALS(std::string("2013-02-20T18:29:11Z"), timeToISOString(1361384951)); + } + + TEST(TimeFormatting, DateAsISO8601UTC) { + ASSERT_EQUALS(std::string("1970-01-01T00:00:00.000Z"), + dateToISOStringUTC(Date_t(0))); + ASSERT_EQUALS(std::string("1970-06-30T01:06:40.981Z"), + dateToISOStringUTC(Date_t(15556000981ULL))); + ASSERT_EQUALS(std::string("2058-02-20T18:29:11.100Z"), + dateToISOStringUTC(Date_t(2781455351100ULL))); + ASSERT_EQUALS(std::string("2013-02-20T18:29:11.100Z"), + dateToISOStringUTC(Date_t(1361384951100ULL))); + } + + TEST(TimeFormatting, DateAsISO8601Local) { + ASSERT_EQUALS(std::string("1969-12-31T19:00:00.000-0500"), + dateToISOStringLocal(Date_t(0))); + ASSERT_EQUALS(std::string("1970-06-29T21:06:40.981-0400"), + dateToISOStringLocal(Date_t(15556000981ULL))); + ASSERT_EQUALS(std::string("2058-02-20T13:29:11.100-0500"), + dateToISOStringLocal(Date_t(2781455351100ULL))); + ASSERT_EQUALS(std::string("2013-02-20T13:29:11.100-0500"), + dateToISOStringLocal(Date_t(1361384951100ULL))); + } + + TEST(TimeFormatting, DateAsCtime) { + ASSERT_EQUALS(std::string("Wed Dec 31 19:00:00.000"), dateToCtimeString(Date_t(0))); + ASSERT_EQUALS(std::string("Mon Jun 29 21:06:40.981"), + dateToCtimeString(Date_t(15556000981ULL))); + ASSERT_EQUALS(std::string("Wed Feb 20 13:29:11.100"), + dateToCtimeString(Date_t(2781455351100ULL))); + ASSERT_EQUALS(std::string("Wed Feb 20 13:29:11.100"), + dateToCtimeString(Date_t(1361384951100ULL))); + } + +} // namespace +} // namespace mongo |