簡體   English   中英

如何將 std::chrono::time_point 轉換為 long 並返回?

[英]How do I convert a std::chrono::time_point to long and back?

我需要將std::chrono::time_pointlong類型(整數 64 位)相互轉換。 我開始使用std::chrono ...

這是我的代碼:

int main ()
{
     std::chrono::time_point<std::chrono::system_clock> now = std::chrono::system_clock::now();

    auto epoch = now.time_since_epoch();
    auto value = std::chrono::duration_cast<std::chrono::milliseconds>(epoch);
    long duration = value.count();


    std::chrono::duration<long> dur(duration);

    std::chrono::time_point<std::chrono::system_clock> dt(dur);

    if (dt != now)
        std::cout << "Failure." << std::endl;
    else
        std::cout << "Success." << std::endl;
}

此代碼編譯,但未顯示成功。

為什么dt最后與now不同?

該代碼缺少什么?

std::chrono::time_point<std::chrono::system_clock> now = std::chrono::system_clock::now();

這是auto的好地方:

auto now = std::chrono::system_clock::now();

由於您希望以millisecond精度進行流量,因此最好在time_point中繼續並隱蔽它:

auto now_ms = std::chrono::time_point_cast<std::chrono::milliseconds>(now);

now_ms是一個time_point ,基於system_clock ,但精度為milliseconds ,而不是system_clock的精度。

auto epoch = now_ms.time_since_epoch();

epoch現在有類型std::chrono::milliseconds 下一條語句本質上變成了無操作(僅進行復制而不進行轉換):

auto value = std::chrono::duration_cast<std::chrono::milliseconds>(epoch);

這里:

long duration = value.count();

在您和我的代碼中, duration包含自system_clock紀元以來的milliseconds數。

這個:

std::chrono::duration<long> dur(duration);

創建一個用long表示的duration ,精度為seconds 這有效地將milliseconds value reinterpret_castseconds 這是一個邏輯錯誤。 正確的代碼如下所示:

std::chrono::milliseconds dur(duration);

這一行:

std::chrono::time_point<std::chrono::system_clock> dt(dur);

基於system_clock創建一個time_point ,具有將精度保持為system_clock的本機精度(通常比毫秒更精細)的能力。 但是,運行時值將正確反映保持整數毫秒(假設我對dur的類型進行了更正)。

即使進行了更正,此測試也會(幾乎總是)失敗:

if (dt != now)

因為dt擁有一個整數milliseconds ,但now擁有整數個比millisecond更精細的刻度(例如microsecondsnanoseconds )。 因此,只有在system_clock::now()返回整數milliseconds的極少數情況下,測試才會通過。

但您可以改為:

if (dt != now_ms)

現在,您將可靠地獲得預期的結果。

把它們放在一起:

int main ()
{
    auto now = std::chrono::system_clock::now();
    auto now_ms = std::chrono::time_point_cast<std::chrono::milliseconds>(now);

    auto value = now_ms.time_since_epoch();
    long duration = value.count();

    std::chrono::milliseconds dur(duration);

    std::chrono::time_point<std::chrono::system_clock> dt(dur);

    if (dt != now_ms)
        std::cout << "Failure." << std::endl;
    else
        std::cout << "Success." << std::endl;
}

就我個人而言,我發現所有std::chrono都過於冗長,因此我將其編碼為:

int main ()
{
    using namespace std::chrono;
    auto now = system_clock::now();
    auto now_ms = time_point_cast<milliseconds>(now);

    auto value = now_ms.time_since_epoch();
    long duration = value.count();

    milliseconds dur(duration);

    time_point<system_clock> dt(dur);

    if (dt != now_ms)
        std::cout << "Failure." << std::endl;
    else
        std::cout << "Success." << std::endl;
}

這將可靠地輸出:

Success.

最后,我建議消除臨時變量以將time_point和整數類型之間的代碼轉換減少到最低限度。 這些轉換是危險的,因此您編寫的操作裸整數類型的代碼越少越好:

int main ()
{
    using namespace std::chrono;
    // Get current time with precision of milliseconds
    auto now = time_point_cast<milliseconds>(system_clock::now());
    // sys_milliseconds is type time_point<system_clock, milliseconds>
    using sys_milliseconds = decltype(now);
    // Convert time_point to signed integral type
    auto integral_duration = now.time_since_epoch().count();
    // Convert signed integral type to time_point
    sys_milliseconds dt{milliseconds{integral_duration}};
    // test
    if (dt != now)
        std::cout << "Failure." << std::endl;
    else
        std::cout << "Success." << std::endl;
}

上面的主要危險不是在返回time_point的路上將integral_duration解釋為milliseconds 減輕這種風險的一種可能方法是編寫:

    sys_milliseconds dt{sys_milliseconds::duration{integral_duration}};

這將風險降低到只需確保您在退出時使用sys_milliseconds ,並在返回途中的兩個地方使用。

再舉一個例子:假設您要轉換為表示system_clock支持的任何持續時間(微秒、10微秒或納秒)的積分。 然后您不必擔心如上所述指定毫秒。 代碼簡化為:

int main ()
{
    using namespace std::chrono;
    // Get current time with native precision
    auto now = system_clock::now();
    // Convert time_point to signed integral type
    auto integral_duration = now.time_since_epoch().count();
    // Convert signed integral type to time_point
    system_clock::time_point dt{system_clock::duration{integral_duration}};
    // test
    if (dt != now)
        std::cout << "Failure." << std::endl;
    else
        std::cout << "Success." << std::endl;
}

這可行,但是如果您在一個平台上運行一半轉換(從積分轉換為整數),而在另一個平台上運行另一半轉換(從積分轉換),您將面臨system_clock::duration對這兩個轉換具有不同精度的風險。

我還要注意有兩種方法可以獲取時間點的毫秒數。 我不確定哪個更好,我已經對它們進行了基准測試,它們都具有相同的性能,所以我想這是一個偏好問題。 也許霍華德可以插話:

auto now = system_clock::now();

//Cast the time point to ms, then get its duration, then get the duration's count.
auto ms = time_point_cast<milliseconds>(now).time_since_epoch().count();

//Get the time point's duration, then cast to ms, then get its count.
auto ms = duration_cast<milliseconds>(tpBid.time_since_epoch()).count();

第一個在我的腦海中從左到右讀得更清楚。

作為單行:

long value_ms = std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::time_point_cast<std::chrono::milliseconds>(std::chrono::high_resolution_clock::now()).time_since_epoch()).count();

time_point對象僅支持與其他time_pointduration對象的算術運算。

您需要將long轉換為指定單位的duration ,然后您的代碼應該可以正常工作。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM