2017-04-05 8 views
2

Visual Studio 2015でWindowsで次のコードを実行しています。基本的には、std::get_timeを使用して日付を解析しますが、日付が無効な場合31日を超えると、ストリームにフェイルビットを設定していないように見えます。Visual 2015のstd :: get_timeが不正な日付で失敗しない

私はこれをg ++ 5.4.0でUbuntuで試してみましたが、失敗ビットを設定して「解析が失敗しました!」と表示されます。これはWindows上のバグですか、何か間違っていますか?

ありがとうございます!

std::string date = "2019-2-37 23:00:00"; // day (37) is wrong. 
std::string format = "%Y-%m-%d %H:%M:%S"; 
std::tm tm_object{}; 
std::istringstream input(date);   
input.imbue(std::locale(std::setlocale(LC_ALL, nullptr))); 
input >> std::get_time(&tm_object, format.c_str()); 
if (input.fail()) 
{ 
    std::cout << "Parsing failed!"; 
} 
else 
{ 
    std::cout << "Parsing ok!\n"; 
    std::cout << "Day is : " << tm_object.tm_mday; 
} 

答えて

2

WindowsでHoward Hinnant's free, open-source header-only datetime libraryを使用して、目的の動作をさせることができます。構文はわずかに異なり、使用するのがずっと簡単で、<chrono>と互換性があります。また、C++標準の時間解析パーツよりも文書化され、指定されています。

#include "date.h" 
#include <iostream> 
#include <sstream> 
#include <string> 

int 
main() 
{ 
    std::string date = "2019-2-37 23:00:00"; // day (37) is wrong. 
    std::string format = "%Y-%m-%d %H:%M:%S"; 
    date::sys_seconds tm_object{}; 
    std::istringstream input(date);   
    input >> date::parse(format, tm_object); 
    if (input.fail()) 
    { 
     std::cout << "Parsing failed!"; 
    } 
    else 
    { 
     std::cout << "Parsing ok!\n"; 
     date::year_month_day ymd = date::floor<date::days>(tm_object); 
     std::cout << "Day is : " << ymd.day(); 
    } 
} 

出力:

Parsing failed! 

このライブラリはまた、G ++ 5.4.0と打ち鳴らすで動作します。

また、を"%F %T"に簡略化することもできます。また、必要に応じて秒未満の精度でも機能することができます。

+0

あなたの答えをありがとうHoward、あなたの図書館は私のために働く! とにかく、なぜWindows用のstrptime関数がないのか、なぜstd :: get_timeがVisual 2015で日付が正しいのかわからない理由がわかりません。 – rboc

+0

@rboc:うれしいことです! 'strptime'は標準のC++ではなく、POSIXで指定されています。 'std :: get_time'は' strptime'で指定します。 POSIXでは、 'strptime'について「エラーは定義されていません。 (http://pubs.opengroup.org/onlinepubs/009695399/functions/strptime.html) –

+0

はい、しかし、少なくともstrptimeは失敗した完了(2月37日)でnullポインタを返します。私はstd :: get_timeをVisual Studio 2015で同様のことをすることを期待しました。 – rboc

2

標準のグレーゾーンの世界へようこそ! std::get_time(さまざまなオーバーロード)は、第22章ローカリゼーションライブラリおよび標準の入出力ライブラリ27で指定されています。

私の知る限りでは、標準が必要です

  • 入力文字列が正しく有効な形式に有効な日付を記載している場合、std::tmオブジェクトは入力文字列が解析できない場合したがって
  • 移入され、ビットにフェイル入力文字列が

を設定するしかし、ここでは、入力文字列を解析することができ、そしていくつかの実装が行進32がちょうど4月1であると仮定することができ、それが実装制御するもので、標準で規定されていない別の言い方をするとされなければなりません入力値に対して行うものとする。非数値の日はエラーを返すが、これは実装に依存する。

+1

私は、2月37日に失敗ビットを設定するべきだと考えました。 :-) – rboc

関連する問題