1

I need to get a nicely formatted timestamp (slightly modified ISO 8601) with millisecond precision.

And example date would look like this: 2011-09-28 13:11:15.237-08:00
The formatting should be able to be overwridden as well.

I've been playing around with boost::posix_time::microsec_clock::local_time() and boost::posix_time::time_facet which works just fine except when it comes to timestamps.
Since posix time doesn't contain time zone information this is just not possible (I'm guessing)

So, is there anything else I could use that has millisecond precision that contains timezone information or can I make the time_facet work with timezones?

Maybe I should always use UTC?

Thanks

Nicklas A.
  • 6,501
  • 7
  • 40
  • 65

1 Answers1

4

Have a look at the boost::local_time::local_date_time class. You can specify a time zone and use the local microsecond clock to initialize it like

boost::local_time::local_date_time  my_ldt(boost::local_time::local_microsec_clock::local_time(new boost::local_time::posix_time_zone("EST-5EDT,M4.1.0,M10.5.0")));

You should then be able to use the facets to format to a string.

Edit: Full example:

#include <iostream>
#include <iomanip>
#include <string>
#include <sstream>

#include <boost/date_time/local_time/local_time.hpp>

int main(void)
{
    boost::posix_time::ptime  now = boost::posix_time::second_clock::local_time();
    boost::posix_time::ptime  utc = boost::posix_time::second_clock::universal_time();

    boost::posix_time::time_duration tz_offset = (now - utc);

    std::stringstream   ss;
    boost::local_time::local_time_facet* output_facet = new boost::local_time::local_time_facet();
    ss.imbue(std::locale(std::locale::classic(), output_facet));

    output_facet->format("%H:%M:%S");
    ss.str("");
    ss << tz_offset;

    boost::local_time::time_zone_ptr    zone(new boost::local_time::posix_time_zone(ss.str().c_str()));
    boost::local_time::local_date_time  ldt = boost::local_time::local_microsec_clock::local_time(zone);
    boost::local_time::local_time_facet* output_facet = new boost::local_time::local_time_facet();
    ss.imbue(std::locale(std::locale::classic(), output_facet));
    output_facet->format("%Y-%m-%d %H:%M:%S%f%Q");
    ss.str("");
    ss << ldt;
    std::cout << ss.str() << std::endl; // "2004-02-29 12:34:56.000789-05:00"

    std::cout << "Press return to exit" << std::endl;
    std::string wait_for_line;
    std::getline(std::cin, wait_for_line);

    return (0);
}
tinman
  • 6,348
  • 1
  • 30
  • 43
  • But I don't want to specify the timezone myself, I want it to be the system timezone – Nicklas A. Sep 28 '11 at 20:59
  • @Nicklas A: Sorry, missed that. Looking at this question (http://stackoverflow.com/questions/2136970/get-current-timezone-in-boost) you need to perform some OS specific calls to get the current timezone to then embed into a Boost custom timezone. – tinman Sep 28 '11 at 21:00
  • I wonder how effective getting both the universal and local time and comparing them would be. – Nicklas A. Sep 28 '11 at 21:37
  • @Nicklas A: I've updated my code to show that it is possible, although you only get the current offset rather than a full timezone specification. – tinman Sep 29 '11 at 06:59
  • Nice easy solution. I just improved your code with a loop to avoid the case where you have 1 second of difference between now and utc, giving a bias like UTC+01:59:59 – Caduchon Mar 07 '16 at 13:29