diff options
| author | Carl Hetherington <cth@carlh.net> | 2015-06-04 11:59:21 +0100 |
|---|---|---|
| committer | Carl Hetherington <cth@carlh.net> | 2015-06-04 11:59:21 +0100 |
| commit | 4d85135f66ce6fa11c14cd3ae62b2400f4322480 (patch) | |
| tree | 9398f37e96bb0d0072528f4161ec10f91377271b /src | |
| parent | 1e558b3f3a2435ead56426e892591e85d2da6887 (diff) | |
Support optional milliseconds in LocalTime.
Diffstat (limited to 'src')
| -rw-r--r-- | src/local_time.cc | 51 | ||||
| -rw-r--r-- | src/local_time.h | 11 |
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 |
