24

Currently I use this code

string now() {
    time_t t = time(0);
    char buffer[9] = {0};

    strftime(buffer, 9, "%H:%M:%S", localtime(&t));
    return string(buffer);
}

to format time. I need to add milliseconds, so the output has the format: 16:56:12.321

Prospolon
  • 361
  • 1
  • 4
  • 12
  • 12
    The `std` c time functionality doesn't include milliseconds. If you have `c++11` facilities available, you might look at [`std::chrono`](http://en.cppreference.com/w/cpp/chrono) – BoBTFish Apr 18 '13 at 07:52
  • yes I can use c++11 ! I use VC11 – Prospolon Apr 18 '13 at 07:56
  • @Prospolon: Of course you can use C++11. But I suspect `11` in VC11 is relevant to C++11. – masoud Apr 18 '13 at 08:26
  • VC11 is the version of compiler in VS2012, thats what i meant; and vs2012 has full new std support I believe – Prospolon Apr 18 '13 at 09:36
  • @Prospolon A lot of things (such as uniform initialization, defaulted or deleted function, etc.) are not implemented in VC11. Most of the standard library which does not concern these core language features has been implemented. Except, for example, that `std::chrono::high_resolution_clock` in VC11 is a typedef for `std::chrono::system_clock` which the VC++ team call "a bug". Oh, and there's no uniform initialization, – Agentlien Apr 18 '13 at 09:45
  • 1
    I am aware of this, but I dont need uniform initialization here. This is irrelevant. – Prospolon Apr 18 '13 at 09:46
  • @Prospolon No, that I know, but since we're talking about time, the "bugs" in `std::chrono` are relevant. I'm just saying, you should be aware that VC11 is surprisingly far from feature-complete when it comes to C++11. – Agentlien Apr 18 '13 at 09:48
  • 2
    still this is the *lowest common denominator* of C++11 support across compilers, so I aim to compile using VC11 – Prospolon Apr 18 '13 at 09:50
  • 1
    @Prospolon If you are intending to write an open source application and want to target as large an audience as possible, that's a good call. Otherwise, lack of features seems like an odd reason to choose a specific compiler. I see it as one of the fee drawbacks of an otherwise excellent product from Microsoft. Oh, and, you may be happy to know that the Intel compiler, which can be easily integrated into visual studio offers an amazing profiler and is even further from feature complete than VC11! – Agentlien Apr 19 '13 at 06:49

6 Answers6

26

Don't waste your time with Boost (I know many will be offended by this statement and consider it heresy).

This discussion contains two very workable solutions that don't require you to enslave yourself to non-standard, 3rd party libraries.

C++ obtaining milliseconds time on Linux -- clock() doesn't seem to work properly

http://linux.die.net/man/3/clock_gettime

References to gettimeofday can be found here at opengroup.org

Community
  • 1
  • 1
Martin Goff
  • 330
  • 3
  • 5
  • 10
    If you had just posted this as an alternative to boost (as opposed to getting on your soap box and raging against the tyranny of third party libraries), I would give this an up-vote. – crashmstr Apr 18 '13 at 12:13
  • 3
    If Chrono has been added to C++11, then use the implementation of it in a C++11 compliant compiler. Built-in functions should take precedence over 3rd party libraries. I have nothing against Boost. But adding an entire library when built-in functions will solve the problem adds needless complexity/overhead to the project/code. – Martin Goff Apr 18 '13 at 13:23
22

Here is a solution I found without using boost

std::string getCurrentTimestamp()
{
using std::chrono::system_clock;
auto currentTime = std::chrono::system_clock::now();
char buffer[80];

auto transformed = currentTime.time_since_epoch().count() / 1000000;

auto millis = transformed % 1000;

std::time_t tt;
tt = system_clock::to_time_t ( currentTime );
auto timeinfo = localtime (&tt);
strftime (buffer,80,"%F %H:%M:%S",timeinfo);
sprintf(buffer, "%s:%03d",buffer,(int)millis);

return std::string(buffer);
}
Enrico Pintus
  • 259
  • 2
  • 7
19

You can use Boost's Posix Time.

You can use boost::posix_time::microsec_clock::local_time() to get current time from microseconds-resolution clock:

boost::posix_time::ptime now = boost::posix_time::microsec_clock::local_time();

Then you can compute time offset in current day (since your duration output is in the form <hours>:<minutes>:<seconds>.<milliseconds>, I'm assuming they are calculated as current day offset; if they are not, feel free to use another starting point for duration/time interval):

boost::posix_time::time_duration td = now.time_of_day();

Then you can use .hours(), .minutes(), .seconds() accessors to get the corresponding values.
Unfortunately, there doesn't seem to be a .milliseconds() accessor, but there is a .total_milliseconds() one; so you can do a little subtraction math to get the remaining milliseconds to be formatted in the string.

Then you can use sprintf() (or sprintf()_s if you are interested in non-portable VC++-only code) to format those fields into a raw char buffer, and safely wrap this raw C string buffer into a robust convenient std::string instance.

See the commented code below for further details.

Output in console is something like:

11:43:52.276


Sample code:

///////////////////////////////////////////////////////////////////////////////

#include <stdio.h>      // for sprintf()

#include <iostream>     // for console output
#include <string>       // for std::string

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


//-----------------------------------------------------------------------------
// Format current time (calculated as an offset in current day) in this form:
//
//     "hh:mm:ss.SSS" (where "SSS" are milliseconds)
//-----------------------------------------------------------------------------
std::string now_str()
{
    // Get current time from the clock, using microseconds resolution
    const boost::posix_time::ptime now = 
        boost::posix_time::microsec_clock::local_time();

    // Get the time offset in current day
    const boost::posix_time::time_duration td = now.time_of_day();

    //
    // Extract hours, minutes, seconds and milliseconds.
    //
    // Since there is no direct accessor ".milliseconds()",
    // milliseconds are computed _by difference_ between total milliseconds
    // (for which there is an accessor), and the hours/minutes/seconds
    // values previously fetched.
    //
    const long hours        = td.hours();
    const long minutes      = td.minutes();
    const long seconds      = td.seconds();
    const long milliseconds = td.total_milliseconds() -
                              ((hours * 3600 + minutes * 60 + seconds) * 1000);

    //
    // Format like this:
    //
    //      hh:mm:ss.SSS
    //
    // e.g. 02:15:40:321
    //
    //      ^          ^
    //      |          |
    //      123456789*12
    //      ---------10-     --> 12 chars + \0 --> 13 chars should suffice
    //  
    // 
    char buf[40];
    sprintf(buf, "%02ld:%02ld:%02ld.%03ld", 
        hours, minutes, seconds, milliseconds);

    return buf;
}

int main()
{
    std::cout << now_str() << '\n';    
}

///////////////////////////////////////////////////////////////////////////////
ildjarn
  • 62,044
  • 9
  • 127
  • 211
Mr.C64
  • 41,637
  • 14
  • 86
  • 162
8

This is a really old question but for anyone else visiting, this is a solution I came up with using modern C++...

#include <chrono>
#include <ctime>
#include <sstream>
#include <iomanip>

std::string timestamp()
{
    using namespace std::chrono;
    using clock = system_clock;
    
    const auto current_time_point {clock::now()};
    const auto current_time {clock::to_time_t (current_time_point)};
    const auto current_localtime {*std::localtime (&current_time)};
    const auto current_time_since_epoch {current_time_point.time_since_epoch()};
    const auto current_milliseconds {duration_cast<milliseconds> (current_time_since_epoch).count() % 1000};
    
    std::ostringstream stream;
    stream << std::put_time (&current_localtime, "%T") << "." << std::setw (3) << std::setfill ('0') << current_milliseconds;
    return stream.str();
}
6

You can use boost::posix_time. See this SO question. Ex:

boost::posix_time::time_duration diff = tick - now;
diff.total_milliseconds();

To get the current time:

boost::posix_time::ptime t1 = boost::posix_time::microsec_clock::local_time();
// ('tick' and 'now' are of the type of 't1')

You can also use the C++11 chrono, if you can use C++11. Ex:

int elapsed_milliseconds = std::chrono::duration_cast<std::chrono::milliseconds>(end-start).count();

To get the current time (you have several different clocks available, see the doc):

std::chrono::time_point<std::chrono::system_clock> t2;
t2 = std::chrono::system_clock::now();
// ('start' and 'end' are of the type of 't2')

For the time in milliseconds, you can get the duration between midnight and the current time. Example with std::chrono:

unsigned int millis_since_midnight()
{
    // current time
    std::chrono::time_point<std::chrono::system_clock> now = std::chrono::system_clock::now();

    // get midnight
    time_t tnow = std::chrono::system_clock::to_time_t(now);
    tm *date = std::localtime(&tnow);
    date->tm_hour = 0;
    date->tm_min = 0;
    date->tm_sec = 0;
    auto midnight = std::chrono::system_clock::from_time_t(std::mktime(date));

    // number of milliseconds between midnight and now, ie current time in millis
    // The same technique can be used for time since epoch
    return std::chrono::duration_cast<std::chrono::milliseconds>(now - midnight).count();
}
Community
  • 1
  • 1
Synxis
  • 9,236
  • 2
  • 42
  • 64
  • 1
    what is `end` & `start` ? I need current time, not millis only – Prospolon Apr 18 '13 at 09:35
  • start and end are two times. You can get the current time in milliseconds via a duration_cast between midnight and now. See my edit. – Synxis Apr 18 '13 at 09:50
3

I'd recommend to use Boost.Chrono instead of Boost.Datetime library because Chrono became a part of C++11. Examples here

Andriy Tylychko
  • 15,967
  • 6
  • 64
  • 112