Maciek
Maciek

Reputation:

C++ :: Boost :: posix_time (elapsed seconds. elapsed fractional seconds)

I'm trying to come up with an answer to two questions that didn't seem hard at first. Q1 : How do I obtain the number of elapsed seconds between UTC.Now() and a given date? A1 : Just like in the code below! Q2 : How do I determine how many fractional seconds have elapsed since the last "full" second ? I'd like to print the "total_elapsed_seconds.fractional_seconds" -> "1234124.45". How do I do that? A2 : ???

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

using namespace std;
using namespace boost::gregorian;
using namespace boost::posix_time; 

void main()
{
    ptime Jan1st1970(date(1970, 1, 1));
    for(int i = 0; i < 10; i++)
    {
        ptime Now = second_clock::universal_time();
        time_duration diff = Now - Jan1st1970;
        cout << Now << " : " << diff.total_seconds() << "." << diff.fractional_seconds() << endl;
    }
}

Upvotes: 4

Views: 11840

Answers (4)

teeks99
teeks99

Reputation: 3642

You don't mention what operating system you use, but I know for a fact that window's clock won't give you resolution better than about 15 milliseconds (unless you really play some games).
However, windows has what's called a performance timer that can give you nanosecond level resolution. It is really just a counter of how many times the CPU cycles (you can divide by the CPU's frequency to get time), so to use it as a clock you have to add that time to a known time:

ptime Start = microsec_clock::universal_time();
initMyClockToZero();  // You have to write this to use the performance timer
.... do something ....
int64 microseconds = getMyClockMicrosec(); // this too
ptime Now = Start + posix_time::microseconds(microseconds);

I've also got a stopwatch style timer that I wrote myself using the windows calls.

#ifndef STOPWATCH_HPP
#define STOPWATCH_HPP

#include <iostream>
#include <windows.h>

//! \brief Stopwatch for timing performance values
//!
//! This stopwatch class is designed for timing performance of various
//! software operations.  If the values you get back a greater than a 
//! few seconds, you should be using a different tool.
//! On a Core 2 Duo E6850 @ 3.00GHz, the start/stop sequence takes 
//! approximately 230 nano seconds in the debug configuration and 180 
//! nano seconds in the release configuration.  If you are timing on the
//! sub-microsecond scale, please take this into account and test it on
//! your machine.
class Stopwatch{
public:
    //! \param start if set to true will initialize and then start the 
    //! timer.
    Stopwatch(bool start=false){
        _start.QuadPart = 0;
        _stop.QuadPart = 0;
        if(start)
            Start();
    }

    //! Starts the stopwatch running
    void Start(){
        QueryPerformanceCounter(&_start);
    }
    //! Run this when the event being timed is complete
    void Stop(){
        QueryPerformanceCounter(&_stop);
    }
   //! Stops the timer and returns the result
   double StopResult(){
      Stop();
      return ResultNanoseconds();
   }
    //! You can get the result of the stopwatch start-stop sequence at
    //! your leisure.  
    double ResultNanoseconds(){
        LARGE_INTEGER frequency;
        QueryPerformanceFrequency(&frequency);
        double cyclesPerNanosecond = static_cast<double>(frequency.QuadPart) / 1000000000.0;

        LARGE_INTEGER elapsed;
        elapsed.QuadPart = _stop.QuadPart - _start.QuadPart;
        return elapsed.QuadPart / cyclesPerNanosecond;
    }
    void PrintResultNanoseconds(){
        std::cout << ResultNanoseconds() << "nanosec" << std::endl;
    }
    void PrintResultMicroseconds(){
        std::cout << ResultNanoseconds()/100 << "microsec" << std::endl;
    }
    void PrintResultMilliseconds(){
        std::cout << ResultNanoseconds()/100000 << "millisec" << std::endl;
    }
    void PrintResultSeconds(){
        std::cout << ResultNanoseconds()/1000000000 << "sec" << std::endl;
    }
private:
    LARGE_INTEGER _start;
    LARGE_INTEGER _stop;
};

#endif STOPWATCH_HPP

Upvotes: 2

lothar
lothar

Reputation: 20257

Add this to your example to get the "current" fractional seconds:

cout << Now.time_of_day().fractional_seconds() << endl;

And change the clock from second_clock to microsec_clock to get non zero fractional seconds.

ptime Now = microsec_clock::universal_time();

Upvotes: 0

zdan
zdan

Reputation: 29470

You are using the second_clock to get the current time. As the name implies, it is accurate only to the nearest second. Since your reference time has no fractional seconds the duration fractional seconds always ends up being 0. Use the microsec_clock instead:

ptime Now = microsec_clock::universal_time();

Also, in such a tight loop, I wouldn't expect the clock to update on every iteration, so you may also want to add a sleep from boost::thread:

boost::this_thread::sleep(boost::posix_time::milliseconds(25));

Upvotes: 8

Maciek
Maciek

Reputation:

That does indeed sound reasonable, however the output gives me :

2009-May-28 20:14:32 : 1243541672.0
2009-May-28 20:14:32 : 1243541672.0
2009-May-28 20:14:32 : 1243541672.0
2009-May-28 20:14:32 : 1243541672.0
2009-May-28 20:14:32 : 1243541672.0
2009-May-28 20:14:32 : 1243541672.0
2009-May-28 20:14:32 : 1243541672.0
2009-May-28 20:14:32 : 1243541672.0
2009-May-28 20:14:32 : 1243541672.0
2009-May-28 20:14:32 : 1243541672.0
Press any key to continue . . .

in truth, I was expecting more digits - I'm hoping for a result in 10 ^ (-6) [sec] range.

Upvotes: 1

Related Questions