24 #ifndef GOBY_TIME_CONVERT_H
25 #define GOBY_TIME_CONVERT_H
29 #include <type_traits>
31 #include <boost/date_time.hpp>
32 #include <boost/units/cmath.hpp>
47 template <
typename ToTimeType,
typename FromTimeType,
48 typename std::enable_if<std::is_same<ToTimeType, FromTimeType>{},
int>
::type = 0>
49 ToTimeType
convert(FromTimeType from_time)
60 template <
typename ToTimeType,
typename FromTimeType,
61 typename ToUnitType =
typename ToTimeType::unit_type,
62 typename ToValueType =
typename ToTimeType::value_type,
63 typename FromUnitType =
typename FromTimeType::unit_type,
64 typename FromValueType =
typename FromTimeType::value_type,
65 typename std::enable_if<
66 !std::is_same<ToTimeType, FromTimeType>{} &&
67 std::is_same<ToTimeType, boost::units::quantity<ToUnitType, ToValueType>>{} &&
68 std::is_same<FromTimeType, boost::units::quantity<FromUnitType, FromValueType>>{},
70 ToTimeType
convert(FromTimeType from_time)
72 return ToTimeType(from_time);
81 template <
typename ToTimeType,
typename FromTimeType,
82 typename ToUnitType =
typename ToTimeType::unit_type,
83 typename ToValueType =
typename ToTimeType::value_type,
84 typename std::enable_if<
85 std::is_same<ToTimeType, boost::units::quantity<ToUnitType, ToValueType>>{} &&
86 (std::is_same<FromTimeType, SystemClock::time_point>{} ||
87 std::is_same<FromTimeType, std::chrono::system_clock::time_point>{}),
89 ToTimeType
convert(FromTimeType from_time)
91 std::int64_t microsecs_since_epoch =
92 from_time.time_since_epoch() / std::chrono::microseconds(1);
94 return ToTimeType(microsecs_since_epoch * boost::units::si::micro *
95 boost::units::si::seconds);
105 template <
typename ToTimeType,
typename FromTimeType,
106 typename FromUnitType =
typename FromTimeType::unit_type,
107 typename FromValueType =
typename FromTimeType::value_type,
108 typename std::enable_if<
109 (std::is_same<ToTimeType, SystemClock::time_point>{} ||
110 std::is_same<ToTimeType, std::chrono::system_clock::time_point>{}) &&
111 std::is_same<FromTimeType, boost::units::quantity<FromUnitType, FromValueType>>{},
113 ToTimeType
convert(FromTimeType from_time)
115 std::int64_t microsecs_since_epoch =
MicroTime(from_time).value();
116 auto duration_since_epoch = std::chrono::microseconds(microsecs_since_epoch);
118 std::chrono::duration_cast<typename ToTimeType::duration>(duration_since_epoch));
127 template <
typename ToTimeType,
typename FromTimeType,
128 typename std::enable_if<!std::is_same<ToTimeType, FromTimeType>{} &&
129 std::is_same<ToTimeType, boost::posix_time::ptime>{},
131 ToTimeType
convert(FromTimeType from_time)
133 std::int64_t time_in_value = convert<MicroTime, FromTimeType>(from_time) /
MicroTimeUnit();
135 using namespace boost::posix_time;
136 using namespace boost::gregorian;
138 if (time_in_value == -1)
139 return boost::posix_time::ptime(not_a_date_time);
142 const int MICROSEC_IN_SEC = 1000000;
143 ptime time_t_epoch(
date(1970, 1, 1));
144 std::int64_t m = time_in_value / MICROSEC_IN_SEC / 60;
145 std::int64_t s = (time_in_value / MICROSEC_IN_SEC) - m * 60;
146 std::int64_t micro_s = (time_in_value - (s + m * 60) * MICROSEC_IN_SEC);
147 return time_t_epoch + minutes(m) + seconds(s) + microseconds(micro_s);
157 template <
typename ToTimeType,
typename FromTimeType,
158 typename std::enable_if<!std::is_same<ToTimeType, FromTimeType>{} &&
159 std::is_same<FromTimeType, boost::posix_time::ptime>{},
161 ToTimeType
convert(FromTimeType from_time)
163 using namespace boost::posix_time;
164 using namespace boost::gregorian;
166 if (from_time == not_a_date_time)
168 return convert<ToTimeType, MicroTime>(MicroTime::from_value(-1));
172 const int MICROSEC_IN_SEC = 1000000;
174 date_duration date_diff = from_time.date() -
date(1970, 1, 1);
175 time_duration time_diff = from_time.time_of_day();
177 return convert<ToTimeType, MicroTime>(MicroTime::from_value(
178 static_cast<std::int64_t
>(date_diff.days()) * 24 * 3600 * MICROSEC_IN_SEC +
179 static_cast<std::int64_t
>(time_diff.total_seconds()) * MICROSEC_IN_SEC +
180 static_cast<std::int64_t
>(time_diff.fractional_seconds()) /
181 (time_duration::ticks_per_second() / MICROSEC_IN_SEC)));
190 template <
typename TimeType = SystemClock::time_po
int>
191 inline std::string
str(TimeType value = SystemClock::now<TimeType>())
193 std::stringstream ss;
194 ss << convert<boost::posix_time::ptime>(value);
203 template <
typename TimeType = SystemClock::time_po
int>
204 inline std::string
file_str(TimeType value = SystemClock::now<TimeType>())
206 auto rounded_seconds = boost::units::round(convert<SITime, TimeType>(value));
207 return boost::posix_time::to_iso_string(convert<boost::posix_time::ptime>(rounded_seconds));
216 template <
typename ToDurationType,
typename FromDurationType,
217 typename std::enable_if<std::is_same<ToDurationType, FromDurationType>{},
int>
::type = 0>
220 return from_duration;
230 typename ToDurationType,
typename FromDurationType,
231 typename ToUnitType =
typename ToDurationType::unit_type,
232 typename ToValueType =
typename ToDurationType::value_type,
233 typename FromUnitType =
typename FromDurationType::unit_type,
234 typename FromValueType =
typename FromDurationType::value_type,
235 typename std::enable_if<
236 !std::is_same<ToDurationType, FromDurationType>{} &&
237 std::is_same<ToDurationType, boost::units::quantity<ToUnitType, ToValueType>>{} &&
238 std::is_same<FromDurationType, boost::units::quantity<FromUnitType, FromValueType>>{},
242 return ToDurationType(from_duration);
252 typename ToDurationType,
typename FromDurationType,
253 typename ToUnitType =
typename ToDurationType::unit_type,
254 typename ToValueType =
typename ToDurationType::value_type,
255 typename FromRepType =
typename FromDurationType::rep,
256 typename FromPeriodType =
typename FromDurationType::period,
257 typename std::enable_if<
258 !std::is_same<ToDurationType, FromDurationType>{} &&
259 std::is_same<ToDurationType, boost::units::quantity<ToUnitType, ToValueType>>{} &&
260 std::is_same<FromDurationType, std::chrono::duration<FromRepType, FromPeriodType>>{},
264 return ToDurationType(MicroTime::from_value(
265 std::chrono::duration_cast<std::chrono::microseconds>(from_duration).count()));
275 typename ToDurationType,
typename FromDurationType,
276 typename ToRepType =
typename ToDurationType::rep,
277 typename ToPeriodType =
typename ToDurationType::period,
278 typename FromUnitType =
typename FromDurationType::unit_type,
279 typename FromValueType =
typename FromDurationType::value_type,
280 typename std::enable_if<
281 !std::is_same<ToDurationType, FromDurationType>{} &&
282 std::is_same<ToDurationType, std::chrono::duration<ToRepType, ToPeriodType>>{} &&
283 std::is_same<FromDurationType, boost::units::quantity<FromUnitType, FromValueType>>{},
287 MicroTime microtime_duration(from_duration);
288 return std::chrono::duration_cast<ToDurationType>(
289 std::chrono::microseconds(microtime_duration.value()));
298 template <
typename ToTimeType>
303 using namespace boost::posix_time;
304 using namespace boost::gregorian;
306 std::string::size_type dot_pos = utc.find(
'.');
309 if (utc.length() < 6)
310 return convert<ToTimeType>(ptime(not_a_date_time));
313 std::string s_fs =
"0";
315 if (dot_pos != std::string::npos)
316 s_fs = utc.substr(dot_pos + 1);
318 dot_pos = utc.size();
320 std::string s_hour = utc.substr(dot_pos - 6, 2), s_min = utc.substr(dot_pos - 4, 2),
321 s_sec = utc.substr(dot_pos - 2, 2);
325 int hour = boost::lexical_cast<int>(s_hour);
326 int min = boost::lexical_cast<int>(s_min);
327 int sec = boost::lexical_cast<int>(s_sec);
328 int micro_sec = boost::lexical_cast<int>(s_fs) * pow(10, 6 - s_fs.size());
330 boost::posix_time::time_duration return_duration(
331 boost::posix_time::time_duration(hour, min, sec, 0) + microseconds(micro_sec));
332 boost::posix_time::ptime return_time(return_date, return_duration);
333 return convert<ToTimeType>(return_time);
335 catch (boost::bad_lexical_cast&)
337 return convert<ToTimeType>(ptime(not_a_date_time));
348 template <
typename ToTimeType>
351 using namespace boost::posix_time;
352 using namespace boost::gregorian;
353 if (
date.length() != 6)
354 return convert<ToTimeType>(ptime(not_a_date_time));
359 int day = boost::lexical_cast<int>(
date.substr(0, 2));
360 int month = boost::lexical_cast<int>(
date.substr(2, 2));
361 int year = boost::lexical_cast<int>(
date.substr(4, 2));
370 return convert_from_nmea<ToTimeType>(utc, d);
372 catch (boost::bad_lexical_cast&)
374 return convert<ToTimeType>(ptime(not_a_date_time));
384 return goby::time::convert<TimeType, goby::time::SystemClock::time_point>(now());
unit< time_dimension, si::system > time
std::string str(TimeType value=SystemClock::now< TimeType >())
Returns the provided time (or current time if omitted) as a human-readable string.
ToDurationType convert_duration(FromDurationType from_duration)
Convert between duration representations (this function works for tautological conversions)
ToTimeType convert_from_nmea(const std::string &utc, boost::gregorian::date return_date=boost::gregorian::day_clock::universal_day())
Convert from NMEA0183 time representations (i.e. "HHMMSS[.SSSS]") to any time format supported by the...
boost::units::quantity< MicroTimeUnit, std::int64_t > MicroTime
quantity of microseconds (using int64)
ToTimeType convert(FromTimeType from_time)
Convert between time representations (this function works for tautological conversions)
decltype(boost::units::si::micro *boost::units::si::seconds) MicroTimeUnit
microsecond unit
std::string file_str(TimeType value=SystemClock::now< TimeType >())
Returns the provided time (or current time if omitted) as an ISO string suitable for file names (no s...
The global namespace for the Goby project.
type
Generic JSON types used in JWTs.
std::chrono::system_clock::time_point date
static time_point now() noexcept
Returns the current system time unless SimulatorSettings::using_sim_time is set to true,...