2016-09-09 102 views
11

我正在編寫一個需要訪問使用timeval作爲當前時間表示的舊C庫的C++代碼。將std :: chrono :: system_clock :: time_point轉換爲struct timeval並返回

在老包拿到我們用當前的日期/時間:

struct timeval dateTime; 
gettimeofday(&dateTime, NULL); 

function(dateTime); // The function will do its task 

現在我需要用C++時辰,東西爲:

system_clock::time_point now = system_clock::now(); 
    struct timeval dateTime; 

    dateTime.tv_sec = ???? // Help appreaciated here 
    dateTime.tv_usec = ???? // Help appreaciated here 

    function(dateTime); 

在後面的代碼,我需要的方式回來,從返回struct timeval建設time_point變量:

struct timeval dateTime; 
    function(&dateTime); 

    system_clock::time_point returnedDateTime = ?? // Help appreacited 

我中號使用C++ 11。

回答

6

[編輯使用time_val,而不是自由瓦爾]

假設你信任你的system_clock以毫秒的精度,可以是這樣的:

struct timeval dest; 
    auto now=std::chrono::system_clock::now(); 
    auto millisecs= 
    std::chrono::duration_cast<std::chrono::milliseconds>(
     now.time_since_epoch() 
    );; 
    dest.tv_sec=millisecs.count()/1000; 
    dest.tv_usec=(millisecs.count()%1000)*1000; 

    std::cout << "s:" << dest.tv_sec << " usec:" << dest.tv_usec << std::endl; 

使用std::chrono::microsecondsduration_cast和調整(DIV/mod)代碼,從而獲得更高的精度 - 請注意您相信您獲得的值的準確性。

轉換回爲:

timeval src; 

    // again, trusting the value with only milliseconds accuracy 
    using dest_timepoint_type=std::chrono::time_point< 
    std::chrono::system_clock, std::chrono::milliseconds 
    >; 
    dest_timepoint_type converted{ 
    std::chrono::milliseconds{ 
     src.tv_sec*1000+src.tv_usec/1000 
    } 
    }; 

    // this is to make sure the converted timepoint is indistinguishable by one 
    // issued by the system_clock 
    std::chrono::system_clock::time_point recovered = 
     std::chrono::time_point_cast<std::chrono::system_clock::duration>(converted) 
    ; 
+0

可能應該指定爲'dateTime.tv_sec'和'dateTime.tv_usec',因爲目標是結束一個有效的'timeval'結構。 –

+0

@KyleStrand編輯 –

+0

'millisecs.count()/ 1000l;''''和'dest.tv_usec = millisecs.count()%1000l'中的'l'當然不是必需的。一個小問題。 – chux

4

請參閱std::chrono::system_clock::to_time_t(),它將time_point轉換爲time_t,它將成爲您的tv_sec。你沒有得到tv_usec,你可以將它設置爲0;或者你可以撥弄其他一些東西,包括duration_cast,以便從time_point中提取一小部分秒。

from_time_t()則相反。

2

下面是如何做轉換既不使用手動轉換因子,或取決於的time_t未指定舍入模式:

timeval 
to_timeval(std::chrono::system_clock::time_point tp) 
{ 
    using namespace std::chrono; 
    auto s = time_point_cast<seconds>(tp); 
    if (s > tp) 
     s = s - seconds{1}; 
    auto us = duration_cast<microseconds>(tp - s); 
    timeval tv; 
    tv.tv_sec = s.time_since_epoch().count(); 
    tv.tv_usec = us.count(); 
    return tv; 
} 

std::chrono::system_clock::time_point 
to_time_point(timeval tv) 
{ 
    using namespace std::chrono; 
    return system_clock::time_point{seconds{tv.tv_sec} + microseconds{tv.tv_usec}}; 
} 

to_timeval照顧向下舍入tp(萬一它爲負值)。 POSIX規範在這方面有點模糊,但我假設timeval代表了在時代之前的時間點,其值爲負值tv_sec,然後爲正值tv_usec值。然後從上一次second開始找到microseconds是一個簡單的操作。

如果我對我的假設不正確(並且可以找到更精確的POSIX規範),<chrono>有權模擬它所做的任何事情。

假設上述慣例,逆向轉換是難以置信的可讀性。它不需要評論。

這都可以這樣進行測試:

timeval 
make_timeval(time_t s, long us) 
{ 
    timeval tv; 
    tv.tv_sec = s; 
    tv.tv_usec = us; 
    return tv; 
} 

bool 
operator==(timeval x, timeval y) 
{ 
    return x.tv_sec == y.tv_sec && x.tv_usec == y.tv_usec; 
} 

int 
main() 
{ 
    using namespace std::chrono; 
    assert(make_timeval(0, 0) == to_timeval(system_clock::time_point{})); 
    assert(make_timeval(1, 0) == to_timeval(system_clock::time_point{seconds{1}})); 
    assert(make_timeval(1, 400000) == to_timeval(system_clock::time_point{seconds{1} + microseconds{400000}})); 
    assert(make_timeval(-1, 400000) == to_timeval(system_clock::time_point{seconds{-1} + microseconds{400000}})); 

    assert(to_time_point(make_timeval(0, 0)) == system_clock::time_point{}); 
    assert(to_time_point(make_timeval(1, 0)) == system_clock::time_point{seconds{1}}); 
    assert(to_time_point(make_timeval(1, 400000)) == system_clock::time_point{seconds{1} + microseconds{400000}}); 
    assert(to_time_point(make_timeval(-1, 400000)) == system_clock::time_point{seconds{-1} + microseconds{400000}}); 
} 

這是所有基於這樣的假設,即對於timevalsystem_clock曆元是相同的。這沒有指定,但對於所有現有的實現都是如此。運氣好的話,我們可以在不久的將來將這種現有的做法標準化。

請注意POSIX中的timeval既用作time_point,也用於duration。如果timeval當前代表持續時間,那麼to_time_point可能會導致運行時錯誤。如果客戶端將結果解釋爲持續時間,則to_timeval可能導致運行時錯誤。

相關問題