C++でHH :: MM :: SS方式で時間を節約する方法を探しています。私はここでそれらが多くの解決策であることを知り、少し調べた後、time
とlocaltime
を選びました。ただし、localtime
関数は少し注意が必要なようです。 says :
Localtimeとgmtimeへのすべての呼び出しは同じ静的構造を使用するため、各呼び出しは前の呼び出しの結果を上書きします。
これが引き起こす問題は、次のコードスニペットに示されています。
#include <ctime>
#include <iostream>
using namespace std;
int main() {
time_t t1 = time(0); // get time now
struct tm * now = localtime( & t1 );
std::cout << t1 << std::endl;
sleep(2);
time_t t2 = time(0); // get time now
struct tm * now2 = localtime( & t2 );
std::cout << t2 << std::endl;
cout << (now->tm_year + 1900) << '-'
<< (now->tm_mon + 1) << '-'
<< now->tm_mday << ", "
<< now->tm_hour << ":" << now->tm_min << ":" << now->tm_sec
<< endl;
cout << (now2->tm_year + 1900) << '-'
<< (now2->tm_mon + 1) << '-'
<< now2->tm_mday << ", "
<< now2->tm_hour << ":" << now2->tm_min << ":" << now2->tm_sec
<< endl;
}
このための一般的な出力は次のとおりです。
1320655946
1320655948
2011-11-7, 9:52:28
2011-11-7, 9:52:28
ご覧のとおり、time_t
タイムスタンプは正しいですが、現地時間はすべてを台無しにします。
私の質問は、タイプtime_t
のタイムスタンプを人間が読める時間に変換するにはどうすればよいですか?
localtime
とgmtime
の再入可能性が心配な場合は、複数の呼び出しを処理できるlocaltime_r
とgmtime_r
があります。
時間を好みに合わせてフォーマットする場合は、関数strftime
を確認してください。
localtime()呼び出しは、結果を内部バッファーに保管します。
それを呼び出すたびに、バッファを上書きします。
別の解決策は、バッファーのコピーを作成することです。
time_t t1 = time(0); // get time now
struct tm* now = localtime( & t1 ); // convert to local time
struct tm copy = *now; // make a local copy.
// ^^^ notice no star.
ただし、注意:現地時間に変換する必要があるのは、値を表示するときだけです。それ以外の場合は、時刻をUTCとして保持する必要があります(保存と操作のため)。表示変換用にオブジェクトを変換するだけなので、すぐに印刷すれば問題は発生しません。
localtime
には、レガシーインターフェイスと最もよく考えられるものがあります。たとえば、マルチスレッドコードでは使用できません。マルチスレッド環境では、Posixではlocaltime_r
を使用でき、Windowsではlocaltime_s
を使用できます。それ以外の場合は、結果を保存するだけです。
tm then = *localtime( &t1 );
// ...
tm now = *localtime( &t2 );
ただし、localtime
のみを呼び出す方が慣用的です。
出力をフォーマットする直前。例:
std::string
timestampToString( time_t timeAndDate )
{
char results[100];
if ( strftime( results, sizeof( results ), "%Y-%m-%d, %H:%M:%S",
localtime( &timeAndDate) ) == 0 ) {
assert( 0 );
}
return results;
}
そして書く:
std::cout << formatTime( t1 ) << std::endl;
(フォーマットを引数として使用する、より一般的なフォーマット関数を作成することもできます。)