12

If I do date +%H-%M-%S on the commandline (Debian/Lenny), I get a user-friendly (not UTC, not DST-less, the time a normal person has on their wristwatch) time printed.

What's the simplest way to obtain the same thing with boost::date_time ?

If I do this:

std::ostringstream msg;

boost::local_time::local_date_time t = 
  boost::local_time::local_sec_clock::local_time(
    boost::local_time::time_zone_ptr()
  );

boost::local_time::local_time_facet* lf(
  new boost::local_time::local_time_facet("%H-%M-%S")
);

msg.imbue(std::locale(msg.getloc(),lf));
msg << t;

Then msg.str() is an hour earlier than the time I want to see. I'm not sure whether this is because it's showing UTC or local timezone time without a DST correction (I'm in the UK).

What's the simplest way to modify the above to yield the DST corrected local timezone time ? I have an idea it involves boost::date_time:: c_local_adjustor but can't figure it out from the examples.

timday
  • 24,582
  • 12
  • 83
  • 135
  • 2
    I believe this is a duplicate of http://stackoverflow.com/questions/2492775/get-local-time-with-boost/2493977. Short version: Use `boost::posix_time` to construct a time object from the system clock. This works great for the local time (the `C` locale). Whether you can construct times for other time zones depends on what locales you have available. – Nate Apr 12 '10 at 17:21
  • Thanks for the pointer; fundamental problem is I hadn't really appreciated the difference between local_time/posix_time. – timday Apr 12 '10 at 20:36

3 Answers3

17

This does what I want:

  namespace pt = boost::posix_time;
  std::ostringstream msg;
  const pt::ptime now = pt::second_clock::local_time();
  pt::time_facet*const f = new pt::time_facet("%H-%M-%S");
  msg.imbue(std::locale(msg.getloc(),f));
  msg << now;
Steve Lorimer
  • 27,059
  • 17
  • 118
  • 213
timday
  • 24,582
  • 12
  • 83
  • 135
  • 18
    He said a simple way. There is no simple way with Boost date/time. They abstracted and generalized *too much.* – std''OrgnlDave Apr 13 '12 at 18:44
  • 4
    I think that's a little harsh (although not completely unjustified). The above is simple enough (although verbose with all the namespacing). The problem is often more the documentation is telling you how to get to Alpha Centauri when you just wanted to walk around the block. On the other hand, I wanted to do the same thing in Python a while ago, and that didn't need a post on StackOverflow to work out. – timday Apr 13 '12 at 20:30
  • 1
    don't get me started on my first experience with boost's 'posix time' and how easy I thought it would be to get a POSIX time stamp out of it and how wrong I was! with that said we'd all be lost without Boost – std''OrgnlDave Apr 14 '12 at 01:41
  • 2
    What you have done will also be very inefficient if you are going to printing a lot of times. And it's a very common error I see. Create the facet and locale once, store it as a static and then start from the imbue() when you have something to print with it. – CashCow Feb 08 '13 at 13:53
4

While this is not using boost::date_time it's relatively easy with boost::locale, which is quite more adapted for this task. As your need is simply getting a formatted time from the current locale.

IMHO boost::date_time should be used when you deal with softwares like gantt/planning computations, were you have alot of date_time arithmetic. But simply for using time and doing some arithmetic on it, you will faster success with boost::locale.

#include <iostream>
#include <boost/locale.hpp>

using namespace boost;

int main(int argc, char **argv) {
   locale::generator gen;
   std::locale::global(gen(""));

   locale::date_time now;
   std::cout.imbue(std::locale());       
   std::cout << locale::as::ftime("%H-%M-%S") << now << std::endl;

   return 0;
}

Right now it should output : 15-45-48. :)

daminetreg
  • 9,724
  • 1
  • 23
  • 15
0

I haven't found other answers to be convenient enough, so here is an example that showcases how to get a local or universal time with full control of units:

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

#include <iostream>

int main()
{
    auto const now = boost::posix_time::microsec_clock::local_time(); // or universal_time() for GMT+0
    if (now.is_special()) {
        // some error happened
        return 1;
    }

    // example timestamp (eg for logging)
    auto const t = now.time_of_day();
    boost::format formater("[%02d:%02d:%02d.%06d]");
    formater % t.hours() % t.minutes() % t.seconds() % (t.total_microseconds() % 1000000);
    std::cout << formater.str();
}

Note: the time_of_day struct has no .microseconds() or .nanoseconds() functions, there is only .fractional_seconds() which returns an integer that is a multiple of configuration-dependent unit. .num_fractional_digits() can be used to obtain precision information where 10 ^ frac_digits is the number of fractional_seconds that is equal to 1 second.

To obtain configuration-independent sub-second units one can perform modulo with the total_ milli/micro/nano _seconds() functions as a workaround.

Xeverous
  • 973
  • 1
  • 12
  • 25