私は 1 つの構造体tmを持っています。そして、 tm
構造体
に一定の間隔 (xx 年、xx か月、xx 日で指定) を追加する必要があります。
これを行うための標準機能はありますか?
私が使用するコンパイラは、Windows XP の MSVC 2005 です。
時刻形式を変換する関数が 2 つあります。
mktime()
struct tm
(現地時間を表す)に変換しtime_t
ます。localtime()
time_t
の現地時間に変換されstruct tm
ます。興味深いのは最初のもので、範囲外の構造体メンバー値を受け入れ、変換の副産物としてそれら (およびその他すべて) を適切に設定します。これは、算術演算後にフィールド データ値を修正するために使用できます。ただし、フィールドのタイプは int であるため、たとえば年に秒数を追加すると、(16 ビット システムで) オーバーフローが発生する可能性があります。
したがって、実際の日付が必要な場合は、このコードが役立ちます (@pmg からの回答の変更されたコピー):
struct tm addinterval(struct tm x, int y, int m, int d) {
x.tm_year += y;
x.tm_mon += m;
x.tm_mday += d;
mktime(&x);
return x;
}
tm_isdst
メンバーについても注意してください。この値により、夏時間切り替え日付を飛び越えると、時間が前後にずれることがあります。
標準の加算演算子が機能します。
struct tm x;
/* add 2 years and 3 days to x */
x.tm_year += 2;
x.tm_mday += 3;
編集:関数を簡単に作成できます
struct tm addinterval(struct tm x, int y, int m, int d) {
x.tm_year += y;
x.tm_mon += m;
x.tm_mday += d;
mktime(&x); /* normalize result */
return x;
}
編集:mktime
結果を正規化するために追加
最初に手元の日付を日数に変換することをお勧めします。間隔を追加するのは簡単です。その後、数値を日付に戻します。
たとえば、 http: //alcor.concordia.ca/~gpkatch/gdate-algorithm.html で、日付を日数に変換して戻すためのアルゴリズムを見つけることができます。
他の回答は、システムが struct tm を初期化する方法と、正午の時刻の値が適切に初期化されたかどうかによって、非常に不安定な結果につながります。
日付の変更だけに関心がある場合は、時刻は同じままで、に渡す前に , , をすべて 0 にtm_isdst
設定tm_hour
します。さらに良いことに、一貫性を保つために、以前に値を取得し、後でリセットします (以前に一貫性がなかった場合は、一貫してそのままになります)。他の回答からのコードの再利用:tm_sec
mktime
tm addinterval(tm t, int y, int m, int d)
{
auto hour = t.tm_hour;
auto min = t.tm_min;
auto sec = t.tm_sec;
// First we discover the DST Flag. By setting hour to 12
// we can assure the mktime does not shift the date
// because it will shift the hour!
t.tm_isdst = 0;
t.tm_hour = 12;
t.tm_min = 0;
t.tm_sec = 0;
mktime(&t);
// Now we can add the interval
t.tm_year += y;
t.tm_mon += m;
t.tm_mday += d;
mktime(&t);
// Now reset the mid-day time values
t.tm_hour = hour;
t.tm_min = min;
t.tm_sec = sec;
// Return struct tm while keeping mid-day time the same
// while the only values that changed are the date and perhaps isdst.
return t;
}
もっとシンプルにできればいいのですが、そうあるべきです。