summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorCarl Hetherington <cth@carlh.net>2015-06-04 11:59:21 +0100
committerCarl Hetherington <cth@carlh.net>2015-06-04 11:59:21 +0100
commit4d85135f66ce6fa11c14cd3ae62b2400f4322480 (patch)
tree9398f37e96bb0d0072528f4161ec10f91377271b /src
parent1e558b3f3a2435ead56426e892591e85d2da6887 (diff)
Support optional milliseconds in LocalTime.
Diffstat (limited to 'src')
-rw-r--r--src/local_time.cc51
-rw-r--r--src/local_time.h11
2 files changed, 43 insertions, 19 deletions
diff --git a/src/local_time.cc b/src/local_time.cc
index f5d79938..32e8e093 100644
--- a/src/local_time.cc
+++ b/src/local_time.cc
@@ -23,6 +23,7 @@
#include "local_time.h"
#include "exceptions.h"
+#include "dcp_assert.h"
#include <boost/lexical_cast.hpp>
#include <boost/date_time/c_local_time_adjustor.hpp>
#include <cstdio>
@@ -43,6 +44,7 @@ LocalTime::LocalTime ()
_hour = tm->tm_hour;
_minute = tm->tm_min;
_second = tm->tm_sec;
+ _millisecond = 0;
set_local_time_zone ();
}
@@ -58,6 +60,8 @@ LocalTime::LocalTime (boost::posix_time::ptime t)
_hour = t.time_of_day().hours ();
_minute = t.time_of_day().minutes ();
_second = t.time_of_day().seconds ();
+ _millisecond = t.time_of_day().fractional_seconds () / 1000;
+ DCP_ASSERT (_millisecond < 1000);
set_local_time_zone ();
}
@@ -74,46 +78,59 @@ LocalTime::set_local_time_zone ()
_tz_minute = offset.minutes ();
}
-/** @param s A string of the form 2013-01-05T18:06:59+04:00 */
+/** @param s A string of the form 2013-01-05T18:06:59[.123]+04:00 */
LocalTime::LocalTime (string s)
{
- /* 2013-01-05T18:06:59+04:00 */
- /* 0123456789012345678901234 */
+ /* 2013-01-05T18:06:59+04:00 or 2013-01-05T18:06:59.123+04:00 */
+ /* 0123456789012345678901234 or 01234567890123456789012345678 */
if (s.length() < 25) {
throw TimeFormatError (s);
}
/* Check incidental characters */
- if (s[4] != '-' || s[7] != '-' || s[10] != 'T' || s[13] != ':' || s[16] != ':' || s[22] != ':') {
+ bool const common = s[4] == '-' && s[7] == '-' && s[10] == 'T' && s[13] == ':' && s[16] == ':';
+ bool const without_millisecond = common && s[22] == ':';
+ bool const with_millisecond = common && s[19] == '.' && s[26] == ':';
+
+ if (!with_millisecond && !without_millisecond) {
throw TimeFormatError (s);
}
-
+
_year = lexical_cast<int> (s.substr (0, 4));
_month = lexical_cast<int> (s.substr (5, 2));
_day = lexical_cast<int> (s.substr (8, 2));
_hour = lexical_cast<int> (s.substr (11, 2));
_minute = lexical_cast<int> (s.substr (14, 2));
_second = lexical_cast<int> (s.substr (17, 2));
- _tz_hour = lexical_cast<int> (s.substr (20, 2));
- _tz_minute = lexical_cast<int> (s.substr (23, 2));
+ if (without_millisecond) {
+ _millisecond = 0;
+ _tz_hour = lexical_cast<int> (s.substr (20, 2));
+ _tz_minute = lexical_cast<int> (s.substr (23, 2));
+ } else {
+ _millisecond = lexical_cast<int> (s.substr (20, 3));
+ _tz_hour = lexical_cast<int> (s.substr (24, 2));
+ _tz_minute = lexical_cast<int> (s.substr (27, 2));
+ }
+
+ int const plus_minus_position = with_millisecond ? 23 : 19;
- if (s[19] == '-') {
+ if (s[plus_minus_position] == '-') {
_tz_hour = -_tz_hour;
- } else if (s[19] != '+') {
+ } else if (s[plus_minus_position] != '+') {
throw TimeFormatError (s);
}
}
-/** @return A string of the form 2013-01-05T18:06:59+04:00 */
+/** @return A string of the form 2013-01-05T18:06:59+04:00 or 2013-01-05T18:06:59.123+04:00 */
string
-LocalTime::as_string () const
+LocalTime::as_string (bool with_millisecond) const
{
char buffer[32];
snprintf (
buffer, sizeof (buffer),
"%sT%s%s%02d:%02d",
- date().c_str(), time_of_day().c_str(), (_tz_hour >= 0 ? "+" : "-"), abs (_tz_hour), _tz_minute
+ date().c_str(), time_of_day(with_millisecond).c_str(), (_tz_hour >= 0 ? "+" : "-"), abs (_tz_hour), _tz_minute
);
return buffer;
}
@@ -127,11 +144,15 @@ LocalTime::date () const
return buffer;
}
-/** @return The time in the form HH:MM:SS */
+/** @return The time in the form HH:MM:SS or HH:MM:SS.mmm */
string
-LocalTime::time_of_day () const
+LocalTime::time_of_day (bool with_millisecond) const
{
char buffer[32];
- snprintf (buffer, sizeof (buffer), "%02d:%02d:%02d", _hour, _minute, _second);
+ if (with_millisecond) {
+ snprintf (buffer, sizeof (buffer), "%02d:%02d:%02d.%03d", _hour, _minute, _second, _millisecond);
+ } else {
+ snprintf (buffer, sizeof (buffer), "%02d:%02d:%02d", _hour, _minute, _second);
+ }
return buffer;
}
diff --git a/src/local_time.h b/src/local_time.h
index c67aaee8..b1751f8b 100644
--- a/src/local_time.h
+++ b/src/local_time.h
@@ -1,5 +1,5 @@
/*
- Copyright (C) 2014 Carl Hetherington <cth@carlh.net>
+ Copyright (C) 2014-2015 Carl Hetherington <cth@carlh.net>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -33,10 +33,12 @@ namespace dcp {
/** @class LocalTime
* @brief A representation of a local time (down to the second), including its offset
- * from GMT.
+ * from GMT (equivalent to xs:dateTime).
*
* I tried to use boost for this, really I did, but I could not get it
* to parse strings of the required format (those that include time zones).
+ *
+ * See http://www.w3.org/TR/xmlschema-2/#dateTime
*/
class LocalTime
{
@@ -45,9 +47,9 @@ public:
LocalTime (boost::posix_time::ptime);
LocalTime (std::string);
- std::string as_string () const;
+ std::string as_string (bool with_millisecond = false) const;
std::string date () const;
- std::string time_of_day () const;
+ std::string time_of_day (bool with_millisecond = false) const;
private:
friend class ::local_time_test;
@@ -61,6 +63,7 @@ private:
int _hour; ///< hour number of the day (0-23)
int _minute; ///< minute number of the hour (0-59)
int _second; ///< second number of the minute (0-59)
+ int _millisecond; ///< millisecond number of the second (0-999)
int _tz_hour; ///< hours by which this time is offset from UTC
int _tz_minute; ///< minutes by which this time is offset from UTC