1
Sep
0

C++ – Time, Clock, Time manager cross platform (Windows & Posix)

In this post, I share several C++ classes related to Time and Clock.
Also, I propose a class to count time (as simple timer in other words).

If you are seeking for a sleep function working on windows and Posix please refer to my older post : Thread, Mutex, Sleep for Windows and Posix.

Licence and Warranty

This code is under LGPL.
Without any warranty, this code is given without support and as it.

Global Time

To be able to count time, we need a global reference. BClock does that. It give a time in milli second : time since the computer was turn on for windows and time since Epoch (00:00:00 UTC, January 1, 1970) in posix.

#ifndef BCLOCK_HPP
#define BCLOCK_HPP

#include "BTime.hpp"

#include "OS.h"

#include <time.h>

#ifdef WINDOWS
#include <windows.h>
#else
#include <sys/time.h>
#endif

/**
* @author Berenger
* @version 0.5
* @date 11 novembre 2009
* @file BClock.hpp
* @package Time
* @brief Global time
* @class BClock
*
* @Must You have to configure this class depending on your system
* @Must Unix-like and windows System have been already made
*
*
* Note : clock is based on time.h clock that returns the number
* of clock ticks elapsed since the program was launched (unix)
* or since the computer was turned on (win)
*/

class BClock{
public:
	/**
	* @brief Get the current system milli seconds time
	* @return system time
	*/
        static double GetTotalSeconds(){
        #ifdef WINDOWS
                return static_cast<double>(GetTickCount())/1000.0;
        #else
                timeval t;
                gettimeofday(&t, NULL);
                return (t.tv_sec) + (t.tv_usec/1000000.0);
        #endif
        }
	/**
	* @brief Get the current system time
	* @return system time in BTime format
	*/
        static BTime GetTime(){
                BTime bt(GetTotalSeconds());
                return bt;
        }
};

#endif

Time Counter

We generally use time to know the elapsed time since we started something. This class enable to do that very simply and also propose a global counter (with a controller dp).

#ifndef BTIC_HPP
#define BTIC_HPP

#include "BClock.hpp"

/**
* @author Berenger
* @version 0.5
* @date 11 novembre 2009
* @file BTic.hpp
* @package Time
* @brief Small time counter
*
*
* This class represent a simple way to count time
* Methods are all inlined
* @Warning tac method do not reset the counter
*
* @example //Initialisation with default stream
* @example BTic tc;
* @example ... //do work
* @example tc.tic(); // start to count
* @example ... //do work
* @example ... //and again
* @example tc.tac(); // save result
* @example double timeItook = tc.elapsed(); // get result
* @example ... //do work
* @example double timeItookFromBegin = tc.tacAndElapsed(); // get result from start point!
*
*
*
*/

class BTic {
protected:
    double startTime; 	/**< To save the starting time*/
    double endTime;     /**< To save the ending time*/

public:
    /**
      * @brief constructor
      * @param in_start to start now
      */
    BTic(){
        this->endTime = 0;
        tic();
    }

    /**
      * @brief Copy constructor
      * @param inTic original tic
      */
    BTic(const BTic & inTic){
        this->startTime = inTic.startTime;
        this->endTime = inTic.endTime;
    }
    /** @brief destructor */
    virtual ~BTic(){}

    /**
  * @brief set start time
  */
    void tic(){
        this->startTime = BClock::GetTotalSeconds();
    }

    /**
  * @brief set end time
  */
    void tac(){
        this->endTime = BClock::GetTotalSeconds();
    }

    /**
  * @brief set end time and return resut
  * @return result
  */
    double tacAndElapsed(){
        tac();
        return elapsed();
    }
    /**
  * @brief get time diff between begin and end
                * @return diff time or BadTime if this->endTime < this->startTime
  * You can test the resutl validity
  * @example myTic.result() == BTic::BadTime ?
  */
    double elapsed(){
        return this->endTime - this->startTime;
    }

    /**
  * @brief reset counter
  */
    void reset(){
        this->endTime = 0;
        this->startTime = 0;
    }

};

#endif

Time Data Manager

This class is for managing time data. With it, you can use plus, dec, etc… with time data. Or knowing hours, minutes, etc. from ms.

#ifndef BTIME_HPP
#define BTIME_HPP

/**
* @author Berenger
* @version 0.5
* @date 11 novembre 2009
* @file BTime.hpp
* @package Time
* @brief Time descriptor
*
* This class represent the time from hours to milli seconds
* Operators have been overloaded to enable operations like
* -, +, +=, etc.
*
* @example //Initialisation with default stream
* @example BTime bt1(BClock::GetTotalSeconds()); // From milli seconds
* @example BTime bt2(BClock::BTime()); // Fom a BTime
* @example ...
* @example if( bt1 == bt2 ) // etc...
*/

class BTime{
protected:
    double seconds;	/**< seconds */

public:
    /**
  * @brief constructor with time
  * @param inTotalSeconds a time expressed in seconds
  */
    BTime(const double inTotalSeconds = 0.0){
        this->seconds = inTotalSeconds;
    }
    /**
  * @brief constructor from time details
  * @param inHours hours
  * @param inMinutes minutes
  * @param inSeconds seconds
  * @param inMs milliseconds
  */
    BTime(const long inHours, const long inMinutes, const long inSeconds, const long inMs){
        this->seconds = (inMs/1000.0) + inSeconds + (60 * inMinutes + (60 * inHours));
    }
    /**
  * @brief Copy constructor
  */
    BTime(const BTime& inTime){
        this->seconds = inTime.seconds;
    }

    /**
  * @brief Destructor
  */
    virtual ~BTime(){}

    // ------------------------- GETTER -------------------------- //

    /**
      * @brief Get milli seconds
      * @return current milli
      * This is not the total mico seconds!
      */
    int milliFormat() const {
        return int(this->seconds*1000) - int(this->seconds)*1000;
    }
    /**
      * @brief Get seconds
      * @return milli
      * This is not the total seconds!
      */
    int secondsFormat() const {
        // Total seconds - minutes in seconds - hours in seconds
        return int(this->seconds - (minutesFormat()*60) - (hoursFormat()*3600));
    }
    /**
      * @brief Get minutes
      * @return minutes
      * This is not the total minutes!
      */
    int minutesFormat() const {
        // Total minutes - hours in minutes
        return int((this->seconds/60) - (hoursFormat()*60L));
    }
    /**
      * @brief Get hours
      * @return current hours
      * This is not the total hours!
      */
    int hoursFormat() const {
        // Milli div by 1000*60*60
        return int(this->seconds/(3600));
    }

    // ------------------------- Tota -------------------------- //

    /**
      * @brief Get milli seconds
      * @return current milli
      * This is not the total mico seconds!
      */
    double totalMs() const {
        return this->seconds*1000.0;
    }
    /**
      * @brief Get seconds
      * @return milli
      * This is not the total seconds!
      */
    double totalSeconds() const {
        return this->seconds;
    }
    /**
      * @brief Get minutes
      * @return minutes
      * This is not the total minutes!
      */
    double totalMinutes() const {
        return this->seconds/60;
    }
    /**
      * @brief Get hours
      * @return current hours
      * This is not the total hours!
      */
    double totalHours() const {
        return this->seconds/3600;
    }

    // ------------------------- SETTER -------------------------- //

    /**
    * @brief Set time from seconds
    * @param inMs milli seconds value
    */
    void setTimeFromMilli(const unsigned int inMs){
        this->seconds = inMs/1000.0;
    }
    /**
    * @brief Set time from seconds
    * @param inSeconds seconds value
    */
    void setTimeFromSeconds(const unsigned int inSeconds){
        this->seconds = inSeconds;
    }
    /**
    * @brief Set time from minutes
    * @param inMinutes minutes value
    */
    void setTimeFromMinutes(const unsigned int inMinutes){
        this->seconds = inMinutes * 60000.0;
    }
    /**
    * @brief Set time from hours
    * @param inHours hours value
    * inlining
    */
    void setTimeFromHours(unsigned int inHours){
        this->seconds = inHours * 3600000.0;
    }

    // ------------------------- OPERATORS -------------------------- //

    /**
    * @brief Copy operator
    * @param inTime input time
    * @return the changed time
    */
    BTime& operator=(const BTime& inTime){
        this->seconds = inTime.seconds;
        return *this;
    }

    /**
    * @brief Inc operator
    * @param inTime input time
    * @return the changed time
    */
    BTime& operator+=(const BTime& inTime){
        this->seconds += inTime.seconds;
        return *this;
    }
    /**
    * @brief Dec operator
    * @param inTime input time
    * @return the changed time
    * In case of doint t1 -= t2 with t1 < t2, then some parameters
    * of t1 will be set to zeros.
    */
    BTime& operator-=(const BTime& inTime){
        this->seconds -= inTime.seconds;
        return *this;
    }

    /**
    * @brief Add operator
    * @param inTime input time
    * @return a new time
    */
    BTime operator+(const BTime& inTime) const{
        BTime result;
        result.seconds = this->seconds + inTime.seconds;
        return result;
    }

    /**
    * @brief Minus operator
    * @param inTime input time
    * @return the new changed time
    */
    BTime operator-(const BTime& inTime) const{
        BTime result(*this);
        result.seconds = this->seconds - inTime.seconds;
        return result;
    }

    /**
    * @brief Equality operator
    * @param inTime input time
    * @return true if times are equals
    */
    bool operator==(const BTime& inTime) const{
        return 	static_cast<long>(this->seconds*100000) == static_cast<long>(inTime.seconds*100000);
    }
    /**
    * @brief Equality operator
    * @param inTime input time
    * @return true if inTime is bigger
    */
    bool operator<(const BTime& inTime) const{
        return 	this->seconds < inTime.seconds;
    }
    /**
    * @brief Equality operator
    * @param inTime input time
    * @return true if inTime is smaller
    */
    bool operator>(const BTime& inTime) const{
        return 	this->seconds > inTime.seconds;
    }

    /**
  * @brief Equality operator
  * @param inTime input time
  * @return true if times are equals
  */
    bool operator!=(const BTime& inTime) const{
        return ! ((*this) == inTime);
    }
    /**
  * @brief Equality operator
  * @param inTime input time
  * @return true if inTime is bigger
  */
    bool operator<=(const BTime& inTime) const{
        return (*this) < inTime || (*this) == inTime;
    }
    /**
  * @brief Equality operator
  * @param inTime input time
  * @return true if inTime is smaller
  */
    bool operator>=(const BTime& inTime) const{
        return (*this) > inTime || (*this) == inTime;
    }
};

#endif

Test

The fallowing code shows how to use the previous classes.
First, it uses the global clock, you have to press a letter + enter to know the time spent.
Then, it uses the timer counter. And finally, it uses the time manager data.

#include "Time/BClock.hpp"
#include "Time/BTic.hpp"
#include "Time/BTime.hpp"

#include <iostream>

//////////////////////////////////////
// This file shows how to use time lib
//////////////////////////////////////

void work(){
    // Fack work
    std::cout << "Work ";
    for(double k = 0.0 ; k < 5 ; ++k){
        for(double j = 0.0 ; j < 500.0 ; ++j){
            for(double i = 0.0 ; i < 30000.0 ; ++i) {i++;i--;i++;i--;}
            for(double i = 0.0 ; i < 30000.0 ; ++i) {i++;i--;i++;i--;}
            for(double i = 0.0 ; i < 30000.0 ; ++i) {i++;i--;i++;i--;}
            for(double i = 0.0 ; i < 30000.0 ; ++i) {i++;i--;i++;i--;}
        }
        std::cout << '.';
    }
    std::cout << '\n';
}

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

int main(){
    // ------------------------------------------------
    // Clock Example
    // ------------------------------------------------
    double t1,t2;
    char c;

    std::cout << "t1 = " << (t1 = BClock::GetTotalSeconds()) << std::endl;
    std::cout << "Press a key + enter to stop" << std::endl;
    std::cin >> c;
    std::cout << "t2 = " << (t2 = BClock::GetTotalSeconds()) << std::endl;
    std::cout << "elapsed = " << (t2 - t1) << " ms" << std::endl;

    std::cout << "\n";

    // ------------------------------------------------
    // Tic Example
    // ------------------------------------------------
    std::cout << "Doing work...\n";

    BTic tic;
    tic.tic();

    work();

    tic.tac();

    std::cout << "elapsed after working = " << tic.elapsed() << " ms" << std::endl;
    std::cout << "\n";

    // ------------------------------------------------
    // Time Example
    // ------------------------------------------------
    BTime bt1(BClock::GetTotalSeconds());
    std::cout << "Global Clock = "<< bt1.hoursFormat() << ":" << bt1.minutesFormat() << ":" << bt1.secondsFormat() << std::endl;

    work();

    BTime bt2(BClock::GetTotalSeconds());

    if(bt1 == bt2) std::cout << "bt1 == bt2\n";
    else if(bt1 < bt2) std::cout << "bt1 < bt2\n";
    else if(bt1 > bt2) std::cout << "bt1 > bt2\n";
    else  std::cout << "cannot happen!\n";

    BTime diff = bt2 - bt1;
    std::cout << "total diff = "<< diff.totalSeconds() << " ms" << std::endl;
    std::cout << "details = "<< diff.hoursFormat() << ":" << diff.minutesFormat() << ":" << diff.secondsFormat() << ":" << diff.milliFormat()  << std::endl;

    return 0;
}

Result

$ ./Time-Berenger
t1 = 1.30755e+09
Press a key + enter to stop
z
t2 = 1.30755e+09
elapsed = 1.98094 ms

Doing work...
Work .....
elapsed after working = 1.40575 ms

Global Clock = 363207:29:16
Work .....
bt1 == bt2
total diff = 1.39905 ms
details = 0:0:1:399

OS define

The global clock needs to know if we are on linux or windows.
We use the fallowing file to know that.

#ifndef OS_H
#define OS_H

#if defined(_WIN32) || defined(ming)
    #define WINDOWS
#else
    #define POSIX
    #warning POSIX will be used
#endif

#endif

Source Code

Time Download C++ Source Code

Enjoyed reading this post?
Subscribe to the RSS feed and have all new posts delivered straight to you.

Comments are closed.

Celadon theme by the Themes Boutique