形式の歴史的な日付文字列を考えてみましょう:
Thu Jan 9 12:35:34 2014
そのような文字列を何らかのC++日付表現に解析し、それから経過した時間を計算したいと思います。
結果の期間から、秒、分、時間、日数にアクセスする必要があります。
これは、新しいC++ 11 std::chrono
名前空間?そうでない場合、今日これについてどうすればよいですか?
私はg ++-4.8.1を使用していますが、おそらく答えはC++ 11仕様のみを対象としているはずです。
std::tm tm = {};
std::stringstream ss("Jan 9 2014 12:35:34");
ss >> std::get_time(&tm, "%b %d %Y %H:%M:%S");
auto tp = std::chrono::system_clock::from_time_t(std::mktime(&tm));
バージョン5より前のGCCはstd::get_time
を実装していません。また、書くことができるはずです:
std::tm tm = {};
strptime("Thu Jan 9 2014 12:35:34", "%a %b %d %Y %H:%M:%S", &tm);
auto tp = std::chrono::system_clock::from_time_t(std::mktime(&tm));
古い質問に対する新しい回答。新しい答えの理由:当時のツールは、求められていたものを正確に処理できないため、質問は元の形式から編集されました。そして、結果として受け入れられた答えは、元の質問が要求したものとは微妙に異なる動作を与えます。
私は受け入れられた答えを書き下ろそうとはしていません。それは良い答えです。 C APIがsoであるというだけで、このような間違いが発生することは避けられません。
元の質問は、"Thu, 9 Jan 2014 12:35:34 +0000"
を解析することでした。したがって、意図はUTC時間を表すタイムスタンプを解析することでした。ただし、strptime
(標準CまたはC++ではないがPOSIX)は、これがUTCタイムスタンプであることを示す後続のUTCオフセットを解析しません(%z
でフォーマットしますが、解析はしません) )。
その後、質問は"Thu Jan 9 12:35:34 2014"
について尋ねるように編集されました。しかし、質問はnot編集され、これがUTCタイムスタンプか、コンピューターの現在のlocalタイムゾーンのタイムスタンプかを明確にしました。受け入れられた回答implicitlyは、std::mktime
を使用しているため、タイムスタンプがコンピューターの現在のローカルタイムゾーンを表していると想定しています。
std::mktime
は、フィールドタイプtm
をシリアルタイプtime_t
に変換するだけでなく、コンピューターのローカルタイムゾーンからUTCへのオフセット調整も実行します。
しかし、元の(未編集の)質問に応じてUTCタイムスタンプを解析したい場合はどうでしょうか?
これは、この新しい 無料のオープンソースライブラリ を使用して今日実行できます。
#include "date.h"
#include <iostream>
#include <sstream>
int
main()
{
using namespace std;
using namespace date;
istringstream in{"Thu, 9 Jan 2014 12:35:34 +0000"};
sys_seconds tp;
in >> parse("%a, %d %b %Y %T %z", tp);
}
このライブラリcanは%z
を解析します。 date::sys_seconds
は次の型定義にすぎません:
std::chrono::time_point<std::chrono::system_clock, std::chrono::seconds>
質問はまた尋ねます:
結果の期間から、秒、分、時間、日数にアクセスする必要があります。
その部分は未回答のままです。 このライブラリ を使用して行う方法は次のとおりです。このパートでは、2番目の header-only library "chrono_io.h"
を使用します。
#include "chrono_io.h"
#include "date.h"
#include <iostream>
#include <sstream>
int
main()
{
using namespace std;
using namespace date;
istringstream in{"Thu, 9 Jan 2014 12:35:34 +0000"};
sys_seconds tp;
in >> parse("%a, %d %b %Y %T %z", tp);
auto tp_days = floor<days>(tp);
auto hms = make_time(tp - tp_days);
std::cout << "Number of days = " << tp_days.time_since_Epoch() << '\n';
std::cout << "Number of hours = " << hms.hours() << '\n';
std::cout << "Number of minutes = " << hms.minutes() << '\n';
std::cout << "Number of seconds = " << hms.seconds() << '\n';
}
floor<days>
は、秒精度time_point
をdays-precisiontime_point
に切り捨てます。 tp
から日精度time_point
を引くと、深夜(UTC)からの時間を表すduration
が残ります。
ファクトリ関数make_time
はduration
(この場合は午前0時からの時間)を取り、各フィールドのゲッターを含む{hours, minutes, seconds}
フィールドタイプを作成します。期間の精度が秒よりも細かい場合、このフィールドタイプにはサブ秒のゲッターも含まれます。
最後に、 "chrono_io.h"
を使用すると、これらの期間をすべて出力できます。この例の出力:
Number of days = 16079[86400]s
Number of hours = 12h
Number of minutes = 35min
Number of seconds = 34s
[86400]s
は、日単位の精度を持つduration
の単位を表します。 2014-01-09は1970-01-01の16079日後です。
これはかなりCっぽく、Simpleの答えほどエレガントではありませんが、うまくいくと思います。 この答えはおそらく間違っていますが、誰かが修正を投稿できるように、私はそれを残しておきます。
#include <iostream>
#include <ctime>
int main ()
{
struct tm timeinfo;
std::string buffer = "Thu, 9 Jan 2014 12:35:00";
if (!strptime(buffer.c_str(), "%a, %d %b %Y %T", &timeinfo))
std::cout << "Error.";
time_t now;
struct tm timeinfo2;
time(&now);
timeinfo2 = *gmtime(&now);
time_t seconds = difftime(mktime(&timeinfo2), mktime(&timeinfo));
time(&seconds);
struct tm result;
result = *gmtime ( &seconds );
std::cout << result.tm_sec << " " << result.tm_min << " "
<< result.tm_hour << " " << result.tm_mday;
return 0;
}
カバーされているケース(コードは以下):
今までの贈与日から
long int min0 = getMinutesSince( "2005-02-19 12:35:00" );
エポックから今まで
long int min1 = getMinutesSince1970( );
2つの日付と時間の間(エポックは特定の日付まで)
long int min0 = getMinutesSince1970Until( "2019-01-18 14:23:00" );
long int min1 = getMinutesSince1970Until( "2019-01-18 14:27:00" );
cout << min1 - min0 << endl;
完全なコード:
#include <iostream>
#include <chrono>
#include <sstream>
#include <string>
#include <iomanip>
using namespace std;
// ------------------------------------------------
// ------------------------------------------------
long int getMinutesSince1970Until( string dateAndHour ) {
tm tm = {};
stringstream ss( dateAndHour );
ss >> get_time(&tm, "%Y-%m-%d %H:%M:%S");
chrono::system_clock::time_point tp = chrono::system_clock::from_time_t(mktime(&tm));
return
chrono::duration_cast<chrono::minutes>(
tp.time_since_Epoch()).count();
} // ()
// ------------------------------------------------
// ------------------------------------------------
long int getMinutesSince1970() {
chrono::system_clock::time_point now = chrono::system_clock::now();
return
chrono::duration_cast<chrono::minutes>( now.time_since_Epoch() ).count();
} // ()
// ------------------------------------------------
// ------------------------------------------------
long int getMinutesSince( string dateAndHour ) {
tm tm = {};
stringstream ss( dateAndHour );
ss >> get_time(&tm, "%Y-%m-%d %H:%M:%S");
chrono::system_clock::time_point then =
chrono::system_clock::from_time_t(mktime(&tm));
chrono::system_clock::time_point now = chrono::system_clock::now();
return
chrono::duration_cast<chrono::minutes>(
now.time_since_Epoch()-
then.time_since_Epoch()
).count();
} // ()
// ------------------------------------------------
// ------------------------------------------------
int main () {
long int min = getMinutesSince1970Until( "1970-01-01 01:01:00" );
cout << min << endl;
long int min0 = getMinutesSince1970Until( "2019-01-18 14:23:00" );
long int min1 = getMinutesSince1970Until( "2019-01-18 14:27:00" );
if ( (min1 - min0) != 4 ) {
cout << " something is wrong " << endl;
} else {
cout << " it appears to work !" << endl;
}
min0 = getMinutesSince( "1970-01-01 01:00:00" );
min1 = getMinutesSince1970( );
if ( (min1 - min0) != 0 ) {
cout << " something is wrong " << endl;
} else {
cout << " it appears to work !" << endl;
}
} // ()