0
$\begingroup$

Rosanswers logo

I want to convert ros time stamps out of message headers to std::string in a form like YYYY MM DD HH MM SS.SSS or similar. Optionally not including the year or month or day would be nice.

An example showing converting the stamp to a generic unix time data structure then passing that into a function that can convert from that to a string using a format string would be very useful to have (ros time to time_t to strftime would be nice), also something showing modern C++ and std::chrono.

Ideally a minimum of dependencies (like boost) or blocks of conversion code to cut and paste would be required.

Conversion from ROS timestamp to ISO-8601 time format outputs UTC time using boost and doesn't show any other control over the output format so isn't sufficient.


Originally posted by lucasw on ROS Answers with karma: 8729 on 2019-12-26

Post score: 3


$\endgroup$

2 Answers 2

1
$\begingroup$

Rosanswers logo

Converting to local timezone, not using boost (and the seconds needs to be capital 'S' for strftime):

   std::string stampToString(const ros::Time& stamp, const std::string format="%Y-%m-%d %H:%M:%S")
   {
      const int output_size = 100;
      char output[output_size];
      std::time_t raw_time = static_cast<time_t>(stamp.sec);
      struct tm* timeinfo = localtime(&raw_time);
      std::strftime(output, output_size, format.c_str(), timeinfo);
      std::stringstream ss; 
      ss << std::setw(9) << std::setfill('0') << stamp.nsec;  
      const size_t fractional_second_digits = 4;
      return std::string(output) + "." + ss.str().substr(0, fractional_second_digits);
    }

Originally posted by lucasw with karma: 8729 on 2019-12-28

This answer was NOT ACCEPTED on the original site

Post score: 3


Original comments

Comment by rjosodtssp on 2020-11-18:
the best one

$\endgroup$
0
$\begingroup$

Rosanswers logo

The way you control the output format of a boost::posix_time object is by constructing a facet with the format flags that you want and apply the facet to a std::stringstream used to generate the string. It will be clearer with an example:

#include <iostream>
#include <locale>
#include <string>
#include <boost/date_time/posix_time/posix_time.hpp>
#include <boost/date_time/posix_time/posix_time_io.hpp>
#include <ros/ros.h>
...
auto current_time = ros::Time::now().toBoost(); //You asked for modern C++, so... there :P
std::stringstream ss;
boost::posix_time::time_facet facet("%Y %m %d %H %M %s");
ss.imbue(std::locale(std::locale::classic(), &facet));
ss << current_time;
ROS_INFO("Current time: %s", ss.str().c_str());

I hope you find this helpful. (Did this on-the-fly, so this code might not compile, but should put you on the right track)


Originally posted by Martin Peris with karma: 5625 on 2019-12-26

This answer was NOT ACCEPTED on the original site

Post score: 3


Original comments

Comment by lucasw on 2019-12-28:
It compiles but crashes when the locale destructor tries to free facet:

#3  0x00007ffff5cf390a in malloc_printerr (
    str=str@entry=0x7ffff5e1b7a8 "munmap_chunk(): invalid pointer") at malloc.c:5350  
#4  0x00007ffff5cfaecc in munmap_chunk (p=0x7fffffffb040) at malloc.c:2846
#5  __GI___libc_free (mem=0x7fffffffb050) at malloc.c:3117
#6  0x00007ffff6310834 in std::locale::_Impl::~_Impl() ()
   from /usr/lib/x86_64-linux-gnu/libstdc++.so.6
#7  0x00007ffff63109e4 in std::locale::~locale() () from /usr/lib/x86_64-linux-gnu/libstdc++.so.6

so this instead:

auto facet = new boost::posix_time::time_facet("%Y %m %d %H %M %s");
ss.imbue(std::locale(std::locale::classic(), facet));

(so it would be better to create facet once and reuse it). https://stackoverflow.com/questions/17779660/who-is-responsible-for-deleting-the-facet

Comment by lucasw on 2019-12-28:
std::locale::classic and std::cout.getloc() are giving me UTC time, if that could be made into local time I'd prefer this answer.

$\endgroup$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.