24#ifndef GOBY_TIME_CONVERT_H
25#define GOBY_TIME_CONVERT_H
31#include <boost/date_time.hpp>
32#include <boost/units/cmath.hpp>
47template <
typename ToTimeType,
typename FromTimeType,
48 typename std::enable_if<std::is_same<ToTimeType, FromTimeType>{},
int>::type = 0>
60template <
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>>{},
72 return ToTimeType(from_time);
81template <
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>{}),
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);
105template <
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>>{},
113ToTimeType
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));
127template <
typename ToTimeType,
typename FromTimeType,
128 typename std::enable_if<!std::is_same<ToTimeType, FromTimeType>{} &&
129 std::is_same<ToTimeType, boost::posix_time::ptime>{},
131ToTimeType
convert(FromTimeType from_time)
133 std::int64_t time_in_value = convert<MicroTime, FromTimeType>(from_time) /
MicroTimeUnit();
135 if (time_in_value == -1)
136 return boost::posix_time::ptime(boost::posix_time::not_a_date_time);
139 const int MICROSEC_IN_SEC = 1000000;
140 boost::posix_time::ptime time_t_epoch(boost::gregorian::date(1970, 1, 1));
141 std::int64_t m = time_in_value / MICROSEC_IN_SEC / 60;
142 std::int64_t s = (time_in_value / MICROSEC_IN_SEC) - m * 60;
143 std::int64_t micro_s = (time_in_value - (s + m * 60) * MICROSEC_IN_SEC);
144 return time_t_epoch + boost::posix_time::minutes(m) + boost::posix_time::seconds(s) +
145 boost::posix_time::microseconds(micro_s);
155template <
typename ToTimeType,
typename FromTimeType,
156 typename std::enable_if<!std::is_same<ToTimeType, FromTimeType>{} &&
157 std::is_same<FromTimeType, boost::posix_time::ptime>{},
159ToTimeType
convert(FromTimeType from_time)
161 if (from_time == boost::posix_time::not_a_date_time)
163 return convert<ToTimeType, MicroTime>(MicroTime::from_value(-1));
167 const int MICROSEC_IN_SEC = 1000000;
169 boost::gregorian::date_duration date_diff =
170 from_time.date() - boost::gregorian::date(1970, 1, 1);
171 boost::posix_time::time_duration time_diff = from_time.time_of_day();
173 return convert<ToTimeType, MicroTime>(MicroTime::from_value(
174 static_cast<std::int64_t
>(date_diff.days()) * 24 * 3600 * MICROSEC_IN_SEC +
175 static_cast<std::int64_t
>(time_diff.total_seconds()) * MICROSEC_IN_SEC +
176 static_cast<std::int64_t
>(time_diff.fractional_seconds()) /
177 (boost::posix_time::time_duration::ticks_per_second() / MICROSEC_IN_SEC)));
186template <
typename TimeType = SystemClock::time_po
int>
187inline std::string
str(TimeType value = SystemClock::now<TimeType>())
189 std::stringstream ss;
190 ss << convert<boost::posix_time::ptime>(value);
199template <
typename TimeType = SystemClock::time_po
int>
200inline std::string
file_str(TimeType value = SystemClock::now<TimeType>())
202 auto rounded_seconds = boost::units::round(convert<SITime, TimeType>(value));
203 return boost::posix_time::to_iso_string(convert<boost::posix_time::ptime>(rounded_seconds));
212template <
typename ToDurationType,
typename FromDurationType,
213 typename std::enable_if<std::is_same<ToDurationType, FromDurationType>{},
int>::type = 0>
216 return from_duration;
226 typename ToDurationType,
typename FromDurationType,
227 typename ToUnitType =
typename ToDurationType::unit_type,
228 typename ToValueType =
typename ToDurationType::value_type,
229 typename FromUnitType =
typename FromDurationType::unit_type,
230 typename FromValueType =
typename FromDurationType::value_type,
231 typename std::enable_if<
232 !std::is_same<ToDurationType, FromDurationType>{} &&
233 std::is_same<ToDurationType, boost::units::quantity<ToUnitType, ToValueType>>{} &&
234 std::is_same<FromDurationType, boost::units::quantity<FromUnitType, FromValueType>>{},
238 return ToDurationType(from_duration);
248 typename ToDurationType,
typename FromDurationType,
249 typename ToUnitType =
typename ToDurationType::unit_type,
250 typename ToValueType =
typename ToDurationType::value_type,
251 typename FromRepType =
typename FromDurationType::rep,
252 typename FromPeriodType =
typename FromDurationType::period,
253 typename std::enable_if<
254 !std::is_same<ToDurationType, FromDurationType>{} &&
255 std::is_same<ToDurationType, boost::units::quantity<ToUnitType, ToValueType>>{} &&
256 std::is_same<FromDurationType, std::chrono::duration<FromRepType, FromPeriodType>>{},
260 return ToDurationType(MicroTime::from_value(
261 std::chrono::duration_cast<std::chrono::microseconds>(from_duration).count()));
271 typename ToDurationType,
typename FromDurationType,
272 typename ToRepType =
typename ToDurationType::rep,
273 typename ToPeriodType =
typename ToDurationType::period,
274 typename FromUnitType =
typename FromDurationType::unit_type,
275 typename FromValueType =
typename FromDurationType::value_type,
276 typename std::enable_if<
277 !std::is_same<ToDurationType, FromDurationType>{} &&
278 std::is_same<ToDurationType, std::chrono::duration<ToRepType, ToPeriodType>>{} &&
279 std::is_same<FromDurationType, boost::units::quantity<FromUnitType, FromValueType>>{},
283 MicroTime microtime_duration(from_duration);
284 return std::chrono::duration_cast<ToDurationType>(
285 std::chrono::microseconds(microtime_duration.value()));
294template <
typename ToTimeType>
297 boost::gregorian::date return_date = boost::gregorian::day_clock::universal_day())
299 using namespace boost::posix_time;
300 using namespace boost::gregorian;
302 std::string::size_type dot_pos = utc.find(
'.');
305 if (utc.length() < 6)
306 return convert<ToTimeType>(ptime(not_a_date_time));
309 std::string s_fs =
"0";
311 if (dot_pos != std::string::npos)
312 s_fs = utc.substr(dot_pos + 1);
314 dot_pos = utc.size();
316 std::string s_hour = utc.substr(dot_pos - 6, 2), s_min = utc.substr(dot_pos - 4, 2),
317 s_sec = utc.substr(dot_pos - 2, 2);
321 int hour = boost::lexical_cast<int>(s_hour);
322 int min = boost::lexical_cast<int>(s_min);
323 int sec = boost::lexical_cast<int>(s_sec);
324 int micro_sec = boost::lexical_cast<int>(s_fs) * pow(10, 6 - s_fs.size());
326 boost::posix_time::time_duration return_duration(
327 boost::posix_time::time_duration(hour, min, sec, 0) + microseconds(micro_sec));
328 boost::posix_time::ptime return_time(return_date, return_duration);
329 return convert<ToTimeType>(return_time);
331 catch (boost::bad_lexical_cast&)
333 return convert<ToTimeType>(ptime(not_a_date_time));
344template <
typename ToTimeType>
347 using namespace boost::posix_time;
348 using namespace boost::gregorian;
349 if (date.length() != 6)
350 return convert<ToTimeType>(ptime(not_a_date_time));
355 int day = boost::lexical_cast<int>(date.substr(0, 2));
356 int month = boost::lexical_cast<int>(date.substr(2, 2));
357 int year = boost::lexical_cast<int>(date.substr(4, 2));
365 boost::gregorian::date d(year, month, day);
366 return convert_from_nmea<ToTimeType>(utc, d);
368 catch (boost::bad_lexical_cast&)
370 return convert<ToTimeType>(ptime(not_a_date_time));
380 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.
static time_point now() noexcept
Returns the current system time unless SimulatorSettings::using_sim_time is set to true,...