summaryrefslogtreecommitdiff
path: root/src/mongo
diff options
context:
space:
mode:
authorAndy Schwerin <schwerin@10gen.com>2013-07-23 18:44:16 -0400
committerAndy Schwerin <schwerin@10gen.com>2013-07-24 12:48:42 -0400
commit0c9209c6d59477eadf27697999f6af59d931251c (patch)
tree12ee765c318793b4ca63ce7fdf99b2280a476b13 /src/mongo
parentb159c99796a977ca74f20451f9552fadab8d8cda (diff)
downloadmongo-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/SConscript1
-rw-r--r--src/mongo/db/db.cpp4
-rw-r--r--src/mongo/logger/message_event_utf8_encoder.cpp4
-rw-r--r--src/mongo/util/time_support.cpp67
-rw-r--r--src/mongo/util/time_support.h37
-rw-r--r--src/mongo/util/time_support_test.cpp80
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