簡體   English   中英

當時間字符串使用“PM”字段時,如何始終與 std::put_time std::get_time 往返?

[英]How to consitently roundtrip with std::put_time std::get_time when the time string uses a "PM" field?

編輯:將 tmb.tm_isdst 初始化為 0

我在解析帶有“AM”/“PM”字段的日期時遇到問題。 通常,無論我使用的轉換說明符組合如何,它似乎都會忽略此字段。 有時它似乎隨機解析時間。

我正在解析的示例日期是

08/22/2020 10:16:57 PM

我正在使用"en_US.utf-8"語言環境和以下轉換說明符字符串:

"%x %I:%M:%S %p" //ignores AM/PM
"%x %X" // hour gets a random number and minutes/seconds equal 0
"%x %r" // hour gets a random number and minutes/seconds equal 0

我試過 x86-64 GCC 5 到 10 和 x86-64 clang 3.4.1 到 10。

這是無法進行往返的示例代碼( 帶有 godbot 的實時代碼):

#include <sstream>
#include <locale>
#include <iomanip>
 
int main(){
    std::time_t t = 1598134617;
    std::tm tm = *std::localtime(&t);
    std::stringstream ss;
    ss.imbue(std::locale("en_US.utf-8"));
    ss << std::put_time(&tm, "%x %I:%M:%S %p");

    std::cout << ss.str() << std::endl;

    std::tm tmb;
    ss >> std::get_time(&tmb,"%x %I:%M:%S %p");
    tmb.tm_isdst = 0;
    std::cout << "years since 1900:\t" << tmb.tm_year << std::endl;
    std::cout << "month:\t\t\t" << tmb.tm_mon << std::endl;
    std::cout << "day:\t\t\t" << tmb.tm_mday << std::endl;
    std::cout << "hour:\t\t\t" << tmb.tm_hour << std::endl;
    std::cout << "mins:\t\t\t" << tmb.tm_min << std::endl;
    std::cout << "secs:\t\t\t" << tmb.tm_sec << std::endl;
    std::cout << "dst:\t\t\t" << tmb.tm_isdst << std::endl;
    std::cout << "timestamp:\t\t" << (mktime(&tmb));
}

此代碼輸出錯誤的時間戳,因此由於未解析“PM”字段而導致往返失敗。

時間戳應該是1598134617; 打印 1598091417:

08/22/2020 10:16:57 PM
years since 1900:   120
month:              7
day:                22
hour:               10
mins:               16
secs:               57
dst:                0
timestamp:          1598091417

關於如何在 c++ 中一致地解析“AM”/“PM”字段有什么想法嗎?

使用 clang 時,將其添加到命令行: -stdlib=libc++ 這使用std::get_timestd::put_time函數的 llvm 實現。

您已經犯下了未初始化std::tm tmbtm_isdst成員的主要(和流行!)錯誤。 我不知道它在你的例子中的價值是什么,但是當我測試你的代碼時,它給了我一些看似隨機的預期值偏移,即使時間是上午。 添加tmb.tm_isdst = -1; tmb聲明后解決了問題。 這是因為mktime()依賴於這個值,但std::get_time() (和strptime() )沒有設置它。

設置tm_isdst = -1表示“我希望系統在提供的時間決定 DST 是否生效。” 只要時間沒有歧義(例如,在“回退”夏令時轉換期間),這種自動模式就可以完美運行。

請求當地立法者放棄 DST,請求編譯器編寫者警告使用部分初始化的struct tm

暫無
暫無

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

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