2016-03-23 55 views
2

從來就寫了下面的函數接收的時間點,並返回與毫秒的ISO字符串:localtime_s和strftime使用建築物ISO時間字符串

std::string TimePointToISOString(const std::chrono::time_point<std::chrono::system_clock>& time) 
    { 
     std::time_t rawTime = std::chrono::system_clock::to_time_t(time); 
     struct tm timeinfo; 
     localtime_s(&timeinfo, &rawTime); 

     std::chrono::milliseconds ms = std::chrono::duration_cast<std::chrono::milliseconds>(time.time_since_epoch()); 
     std::size_t frac_seconds = ms.count() % 1000; 

     char buffer[32]; 
     std::strftime(buffer, 32, "%FT%TZ", &timeinfo); 

     std::string bufferStr(buffer); 
     std::stringstream ss; 
     ss << bufferStr.substr(0, 19) << "." << std::setw(3) << std::setfill ('0') << frac_seconds << bufferStr.substr(20); 

     return ss.str(); 
    } 

從來就使用在Linux上運行,與localtime()功能完全沒有問題。現在我正在遷移到Windows/VS2012,編譯器建議更改localtime()以獲得更安全的localtime_s(),立即完成。

轉換的strftime調用不會在運行時崩潰,出現以下錯誤後:

Expression: ("Invalid format directive", 0) 

編譯運行正常。幫助感謝您瞭解這裏發生了什麼。我想簡單的是我不會注意到...

回答

4

在C99中添加了%F%T轉換,而VS 2012只支持C89。儘管它仍然不支持所有的C99,但我相信VS 2015增加了更多(特別是C99庫函數,它們也是C++ 11的一部分),這應該可以正常工作。

如果您需要繼續使用舊的編譯器/庫,%F和%T對於C89中已經支持的某些格式基本上都是「快捷方式」。如果我是正確的閱讀需求,下面應該是等價的:

std::strftime(buffer, 32, "%Y-%m-%dT%H:%M:%SZ", &timeinfo); 

順便說一句,如果你的編譯器支持C++ 11,它通常更容易和更清潔的使用std::put_time,而不是strftime

+0

傑裏,從來就試過'SS <<的std :: put_time(timeinfo, 「FT%TZ%」) ;'也沒有成功......同樣的錯誤......在VS2012中完全不支持'%FT'和'%TZ'。所以我改成了'「%Y-%m-%dT%H:%M:%SZ」並且正在使用'strftime'和std :: put_time。感謝您的幫助。 – Mendes

+0

@Mendes:是的,我想'put_time'只不過是'strftime'的一個包裝器(或者兩者都使用相同的引擎),所以對於任何給定的編譯器,這兩個可能支持相同的轉換 - 在它們之間切換純粹是一個方便的問題,不太可能影響您的原始問題。 –

2

這是一個很好的問題(upvoted)。 Jerry Coffin的回答是一個很好的答案(也是upvoted)。這個答案是關於添加更多關於VS-2013及以後版本,gcc和clang的開源解決方案的信息。這個替代方案將產生相同的輸出到TimePointToISOString。爲了區分它,我已經給它的另一個名字:to_local_string

std::string 
to_local_string(const std::chrono::system_clock::time_point& time) 
{ 
    using namespace date; 

    auto zone = current_zone(); 
    auto local = floor<std::chrono::milliseconds>(zone->to_local(time).first); 
    auto dp = floor<days>(local); 
    year_month_day ymd = dp; 
    std::stringstream ss; 
    ss << ymd << 'T' << make_time(local-dp); 
    return ss.str(); 
} 

它使用在這裏找到了時區數據庫解析器:

https://github.com/HowardHinnant/date

這裏記載:

http://howardhinnant.github.io/tz.html

這是IANA Timezone database的解析器,在這裏用於簡單找到本地時區的UTC偏移量。一旦找到本地時間點(存儲爲std::chrono::system_clock::time_point),它會使用this library將其分解爲年/月/日/小時/分鐘/秒/毫秒字段類型,其實現可在相同的github站點找到。

我只是跑兩個TimePointToISOStringto_local_string在同一time_point輸出功率爲:

2016-03-23T22:54:52.626 
2016-03-23T22:54:52.626