C11工具類:時間處理


  C++11提供時間管理類,包括三種類型:時間間隔duration,時鍾clocks,時間點time point。

1、記錄時常的duration

1.1 原型

  duration表示一段時間間隔,用來記錄時間長度,可以表示時分秒等單位。其原型如下:

template<class Rep, class Period = std::ratio<1, 1>> class duration;

  Rep表示一個數值類型,表示時鍾數的類型,第二個參數表示始終周期。

  std::ratio原型如下:

template<std::intmax_t Num, std::intmax_t Denom = 1> class ratio;

  std::ratio表示時鍾周期的秒數,Num表示分子,Denom表示分母,分母默認為1,分數值表示秒數。

ratio<2>          //2秒
ratio<60>         //一分鍾
ratio<60*60>      //一小時 
ratio<60*60*24>        //一天    
ratio<1, 1000>         //一毫秒
ratio<1, 1000000>      //一微秒
ratio<1, 1000000000>   //一納秒

  標准庫還定義了一些常用的時間間隔:

typedef duration<Rep, ratio<3600, 1>> hours;
typedef duration<Rep, ratio<60, 1>> minutes;
typedef duration<Rep, ratio<1, 1>> seconds;
typedef duration<Rep, ratio<1, 1000>> milliseconds;
typedef duration<Rep, ratio<1, 1000000>> microseconds;
typedef duration<Rep, ratio<1, 1000000000>> nanoseconds;

  可以通過常用類型來使用到我們代碼中,如線程休眠:

std::this_thread::sleep_for(std::chrono::seconds(3));         //休眠3秒
std::this_thread::sleep_for(std::chrono::milliseconds(100));  //休眠100毫秒

1.2 運算

1.2.1 統計

  chrono提供獲取時間間隔的時鍾周期的方法count()。

#include <iostream>
#include <chrono>

using namespace std;

int main()
{
    //3毫秒
    std::chrono::milliseconds ms{3}; 
    std::cout << "3 ms duration has " << ms.count() << " ticks." << std::endl;
    
    //通過3毫秒初始化6000微秒
    std::chrono::microseconds us = 2*ms;
    std::cout << "6000 us duration has " << us.count() << " ticks." << std::endl;
    
    //自定義一個時鍾周期
    std::chrono::duration<double, std::ratio<1, 30>> hz30{3.5};
    std::cout << "3.5 hz duration has " << hz30.count() << " ticks." << std::endl;

    return 0;
}

//執行結果
3 ms duration has 3 ticks.
6000 us duration has 6000 ticks.
3.5 hz duration has 3.5 ticks.

1.2.2 間隔運算

  時間間隔可以做運算,計算兩段時間的差值。

std::chrono::minutes t1{10};        //10分鍾
std::chrono::seconds t2{60};        //60秒
std::chrono::seconds t3 = t1 - t2;

std::cout << t3.count() << " seconds." << std::endl;
//輸出
540 seconds.

  duration也有一套自己的運算規則,當兩個duration始終周期不同的時候,會統一成一種時鍾,然后再做運算。其規則如下:

  對於ratio<x1, y1> r1,ratio<x2, y2> r2;如果x1、x2最大公約數為x,y1、y2最大公約數為y,那么統一之后的ratio為ratio<x,y>。

#include <iostream>
#include <chrono>
#include <typeinfo>

using namespace std;

int main()
{
    std::chrono::duration<double, std::ratio<9, 7>> d1{3};
    std::chrono::duration<double, std::ratio<6, 5>> d2{1};
    auto d3 = d1 - d2;
    
    std::cout << "typeid:" << typeid(d3).name() << std::endl;
    std::cout << d3.count() << std::endl;

    return 0;
}
//執行結果
typeid:std::chrono::duration<double, std::ratio<3, 35>>
31

  根據規則,7/9和6/5,分子最大公約數為3,分母最小公倍數為35,所以統一之后的duration為std::chrono::duration<double, std::ratio<3, 35>>,所以始終周期為((7/9)/(3/35)*3) - ((6/5)/(3/35)*1) = 31。

1.2.3 轉換

  可以通過duration_cast<>()來將當前的時鍾周期轉換為其它的時鍾周期。

//將秒轉換為分鍾數
std::chrono::seconds ts{600};
std::cout << std::chrono::duration_cast<std::chrono::minutes>(ts).count() << " minutes." << std::endl;
//執行結果
10 minutes.

2、時間點的表示

  time_point表示一個時間點,用來獲取從它的clock的紀元開始所經過的duration(比如從1970.1.1開始計算)和當前的時間。time_point可以和ctime結合起來顯示時間,必須用clock來計時。time_point有一個函數time_from_eproch()用來獲得紀元到time_point時間經過的duration。

#include <iostream>
#include <chrono>

using namespace std;
using namespace std::chrono;

int main()
{
    typedef duration<int, ratio<60*60*24>> days_type;

    time_point<system_clock, days_type> today = time_point_cast<days_type>(system_clock::now());

    cout << today.time_since_epoch().count() << endl;

    return 0;
}
//執行結果
17460

  time_point還支持一些算術運算,比如兩個time_point的差值時鍾周期數,還可以和duration相加減,但是必須是相同的clock。

#include <iostream>
#include <chrono>
#include <ctime>
#include <iomanip>

using namespace std;
using namespace std::chrono;

int main()
{
    typedef duration<int, ratio<60*60*24>> days_type;

    system_clock::time_point now = system_clock::now();
    time_t last = system_clock::to_time_t(now - hours(24));
    time_t next = system_clock::to_time_t(now - hours(24));

    cout << "last day: " << put_time(localtime(&last), "%c") << endl;
    cout << "next day: " << put_time(localtime(&next), "%c") << endl;

    return 0;
}
//執行結果
last day: 10/20/17 23:05:50
next day: 10/20/17 23:05:50

3、獲取系統時鍾的clocks

  • clocks表示當前的系統時鍾,內部有time_point、duration、Rep、Period等信息,主要用來獲取當前時間,以及事項time_t和time_point的相互轉換。clocks包括如下三種時鍾:
  • system_clock:表示真實世界的掛鍾時間,具體時間依賴於系統。
  • steady_clock:不能被“調整”的時鍾,並不一定代表真實世界的掛鍾時間,保證先后調用now()的得到的時間值是不會遞減的。
  • high_resolution_clock:高精度時鍾,實際上system_clock或者steady_clock的別名,可以通過nowlai 獲取當前的時間點。
#include <iostream>
#include <chrono>

using namespace std;
using namespace std::chrono;

int main()
{
    system_clock::time_point t1 = system_clock::now();
    cout << "hello world." << endl;
    system_clock::time_point t2 = system_clock::now();
    cout << (t2-t1).count() << " tick count."<< endl;

    return 0;
}
//執行結果:
hello world.
10001 tick count.

  通過時鍾獲取的兩個時間點之間差多少個時鍾周期,可以通過duration_cast來將其轉換為其他時鍾周期的duration:

cout << duration_cast<microseconds> (t2-t1).count() << " microseconds."<< endl;
//輸出結果:
hello world.
1000 microseconds.

  system_clock的to_time_t可以將一個time_point轉換為ctime,而from_time_t方法則可以將ctime轉換為time_point。

std::time_t now_c = std::chrono::system_clock::to_time_t(time_point);

  steady_clock可以獲取穩定可靠的時間間隔,后一次調用now的值和前一次的差值不會因為修改了系統時間而改變,從而保證了穩定的時間間隔。

  system_clock和std::put_time配合起來使用可以格式化日期的輸出。

#include <ctime>
#include <iomanip>
#include <iostream>
#include <chrono>

using namespace std;
using namespace std::chrono;

int main()
{
    auto t = system_clock::to_time_t(system_clock::now());

    cout << put_time(localtime(&t), "%Y-%m-%d %X") << endl;
    cout << put_time(localtime(&t), "%Y-%m-%d %H.%M.%S") << endl;

    return 0;
}
//執行結果:
2017-10-29 21:19:30
2017-10-29 21.19.30

4、計時器timer

  可以利用high_resolution_clock來實現一個類似於boost.timer的計時器,這樣的timer在測試性能的時候經常用到。在程序日常開發的時候可以作為測試函數耗時。

void func()
{
    //dosomething...
}

int main()
{
    Timer t; //開始計時
    func();
    cout << t.elapsed() << endl; //打印func函數耗時
}

  C++中可以通過chrono庫來事項一個計時器,從而移除對其他三方庫的依賴。

#include <ctime>
#include <iomanip>
#include <iostream>
#include <chrono>

using namespace std;
using namespace std::chrono;

class CTimer
{
public:
    CTimer() : m_begin(high_resolution_clock::now()) {}

    //重置
    void mvReset() { m_begin = high_resolution_clock::now();  }

    //默認輸出毫秒
    template<typename Duration = milliseconds>
    int64_t elapsed() const
    {
        return duration_cast<Duration>(high_resolution_clock::now() - m_begin).count();
    }

    //微秒
    int64_t elapsed_micro() const
    {
        return elapsed<microseconds>();
    }

    //納秒
    int64_t elapsed_nano() const
    {
        return elapsed<nanoseconds>();
    }

    //
    int64_t elapsed_sconds() const
    {
        return elapsed<seconds>();
    }

    //
    int64_t elapsed_minutes() const
    {
        return elapsed<minutes>();
    }

    //
    int64_t elapsed_hours() const
    {
        return elapsed<hours>();
    }

private:
    time_point<high_resolution_clock> m_begin;
};

//test func
void func()
{
    cout << "hello world." << endl;
}

int main()
{
    CTimer t;
    func();
    cout << t.elapsed() << endl;                       //打印func函數耗時毫秒
    cout << t.elapsed_micro() << endl;                 //打印func函數耗時微秒
    cout << t.elapsed_nano() << endl;                  //打印func函數耗時納秒
    cout << t.elapsed_sconds() << endl;                //打印func函數耗時秒
    cout << t.elapsed_minutes() << endl;               //打印func函數耗時分
    cout << t.elapsed_hours() << endl;                 //打印func函數耗時小時

    return 0;
}
//執行結果
hello world.
1
1000
1000000
0
0
0


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM