2013-06-30 49 views
3

我目前的模式(UNIX)是調用gettimeofday,施放tv_sec場到time_t,傳遞,通過localtime,並將結果與​​tv_usec結合。這給了我一個完整的日期(年,月,日,時,分,秒,納秒)。完全分離的日期從的std ::計時毫秒:: SYSTEM_CLOCK

我正在嘗試將我的代碼更新到C++ 11以實現可移植性和一般良好實踐。我能夠做到以下幾點:

auto currentTime = std::chrono::system_clock::now(); 
const time_t time = std::chrono::system_clock::to_time_t(currentTime); 
const tm *values = localtime(&time); 
// read values->tm_year, etc. 

但我卡在毫秒/納秒。首先,to_time_t聲稱舍入是實現定義的(!),所以我不知道22.6秒的最終讀數是否應該實際爲21.6,而對於另一個我不知道如何獲得自上一次以來的毫秒數秒(是標準保證的秒數是否正常?也就是說,我可以得到自紀元以來的總毫秒數,只是模數嗎?即使這樣可以感覺到難看)。

我應該如何從毫秒級的std::chrono::system_clock得到當前日期?

+0

_IF的std :: time_t的具有精度降低,這是實現定義的值是否是** **圓潤或**截斷**。在任何情況下,22.6將永遠不會是21.6,所以不要擔心。 –

+1

@TomKnapen,但21.6 *可以*成爲22.6,如果它是舍入而不是截斷秒。也許我的措辭不是最好的,但這就是我所掌握的。 – Dave

+0

根據我的經驗,四捨五入21.6等於22,截斷21.6等於21.因此,無論如何,除非您自己添加「小數」部分,否則21.6無法成爲22.6。 –

回答

2

我意識到,我可以使用from_time_t獲得「舍入」值,並檢查發生了哪種類型的舍入。這也並不依賴於每一秒確切地說是1000毫秒,並與出的現成的C++ 11的工作原理:

const auto currentTime = std::chrono::system_clock::now(); 
time_t time = std::chrono::system_clock::to_time_t(currentTime); 
auto currentTimeRounded = std::chrono::system_clock::from_time_t(time); 
if(currentTimeRounded > currentTime) { 
    -- time; 
    currentTimeRounded -= std::chrono::seconds(1); 
} 
const tm *values = localtime(&time); 
int year = values->tm_year + 1900; 
// etc. 
int milliseconds = std::chrono::duration_cast<std::chrono::duration<int,std::milli> >(currentTime - currentTimeRounded).count(); 
0

予讀出的標準是這樣的:

它實現中定義的值是否是圓的或截短的,但是自然地,舍入或截斷只發生在所得的time_t的最詳細的部分。那就是:從time_t獲得的組合信息絕不會比其粒度的0.5更差。

如果系統上的time_t只支持秒,那麼您可能會有0.5秒的系統不確定性(除非您知道如何實現)。

tv_usec不是標準的C++,而是posix上的time_t的訪問器。總之,你不應該期望任何舍入效應大於你係統支持的最小時間差值的一半,所以肯定不會超過0.5微秒。

最直接的方法是使用增強ptime。它爲fractional_seconds() http://www.boost.org/doc/libs/1_53_0/doc/html/date_time/posix_time.html#date_time.posix_time.ptime_class

互操作與std::chrono這樣的方法,你可以將這裏描述:https://stackoverflow.com/a/4918873/1149664

或者,看看這個問題:How to convert std::chrono::time_point to calendar datetime string with fractional seconds?

+0

我實際上是在'gettimeofday'結構中直接''tv_usec'的值通過'time_t'之前,我認爲這是安全的。我以爲'time_t'只有秒,所以我期待0.5秒的差距而不是0.5微秒,雖然我沒有測試(不知道我可以,因爲它的實現定義)。至於助推答案;我將不得不花一點時間來了解它在做什麼,但我儘可能避免提振,並堅持只是成爲標準的東西。 – Dave

+0

好的,我看到它在做什麼;你把時間寫到一個流中,然後再讀回來以有效地「落地」,然​​後獲得差異。我可以看到邏輯,但似乎令人生畏;將數字轉換爲字符串或僅從字符串中進行比較是我總是避免的。必須有辦法做到這一點,而無需操縱字符串/流... – Dave

+0

不,這不是重點,而不是我的意思。這個流只是爲了展示結果,並且你回到你所投入的內容。你想要怎樣處理這個時代?無論哪種情況,提升時間庫都是需要查看的地方。 –

0

而不是使用to_time_t這輪關閉的,你可以做,而不是像這樣

auto tp = std::system_clock::now(); 
auto s = std::chrono::duration_cast<std::chrono::seconds>(tp.time_since_epoch()); 
auto t = (time_t)(s.count()); 

這樣你就可以得到沒有舍入的秒數。它比檢查to_time_tfrom_time_t之間的差異更有效。

1

使用此free, open-source library你可以得到本地時間精確到毫秒這樣的:

#include "tz.h" 
#include <iostream> 

int 
main() 
{ 
    using namespace date; 
    using namespace std::chrono; 
    std::cout << make_zoned(current_zone(), 
          floor<milliseconds>(system_clock::now())) << '\n'; 
} 

對我來說這只是輸出:

2016-09-06 12:35:09.102 EDT 

make_zoned是一個工廠函數創建一個zoned_time<milliseconds>。工廠函數爲您推導出所需的精度。 A zoned_timetime_zonelocal_time的配對。你可以得到本地超時用:

local_time<milliseconds> lt = zt.get_local_time(); 

local_timechrono::time_point。如果你想這樣你可以將其分爲日期和時間字段類型:

auto zt = make_zoned(current_zone(), floor<milliseconds>(system_clock::now())); 
auto lt = zt.get_local_time(); 
local_days ld = floor<days>(lt);   // local time truncated to days 
year_month_day ymd{ld};     // {year, month, day} 
time_of_day<milliseconds> time{lt - ld}; // {hours, minutes, seconds, milliseconds} 
// auto time = make_time(lt - ld);  // another way to create time_of_day 
auto y = ymd.year();   // 2016_y 
auto m = ymd.month();  // sep 
auto d = ymd.day();   // 6_d 
auto h = time.hours();  // 12h 
auto min = time.minutes(); // 35min 
auto s = time.seconds();  // 9s 
auto ms = time.subseconds(); // 102ms