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());