日付調整ルーチンを書いているときに同じ問題が発生しました。任意の日時値に86400秒(= 1日)を追加すると、日時値が1日増加します。ただし、テストでは、出力値は常に期待される出力に正確に1時間追加されました。たとえば、「2019-03-20 00:00:00 」を86400秒インクリメントすると、「2019-03-2101 :00:00」になります。逆も発生しました:「2019-03-21 00:00:00」は、 -86400によってデクリメントされ、「2019-03-2001 :00:00」になりました。
解決策は(不可解に)、入力日時に適用する前に、最終間隔から3600秒(1時間)を引くことでした。
解決策(@ Lightness-Races-in-Orbitからの有益なコメントのおかげで)は、をtm_isdst
呼び出す前に-1に設定することmktime()
でした。これはmktime()
、入力日時値のDSTステータスが不明でありmktime()
、システムタイムゾーンデータベースを使用して、入力日時値の正しいタイムゾーンを決定する必要があることを示しています。
この関数(以下で修正)は、日数の整数調整を可能にし、一貫して正しい結果を生成するようになりました。
#include <stdio.h>
#include <string.h>
#include <time.h>
/*******************************************************************************
* \fn adjust_date()
*******************************************************************************/
int adjust_date(
char *original_date,
char *adjusted_date,
char *pattern_in,
char *pattern_out,
int adjustment,
size_t out_size)
{
/*
struct tm {
int tm_sec; // seconds 0-59
int tm_min; // minutes 0-59
int tm_hour; // hours 0-23
int tm_mday; // day of the month 1-31
int tm_mon; // month 0-11
int tm_year; // year minus 1900
int tm_wday; // day of the week 0-6
int tm_yday; // day in the year 0-365
int tm_isdst; // daylight saving time
};
*/
struct tm day;
time_t one_day = 86400;
// time_t interval = (one_day * adjustment) - 3600;
time_t interval = (one_day * adjustment);
strptime(original_date, pattern_in, &day);
day.tm_isdst = -1;
time_t t1 = mktime(&day);
if (t1 == -1) {
printf("The mktime() function failed");
return -1;
}
time_t t2 = t1 + interval;
struct tm *ptm = localtime(&t2);
if (ptm == NULL) {
printf("The localtime() function failed");
return -1;
}
strftime(adjusted_date, out_size, pattern_out, ptm);
return 0;
}
/*******************************************************************************
* \fn main()
*******************************************************************************/
int main()
{
char in_date[64] = "20190321000000" ,
out_date[64],
pattern_in[64] = "%Y%m%d%H%M%S",
pattern_out[64] = "%Y-%m-%d %H:%M:%S";
int day_diff = -1,
ret = 0;
size_t out_size = 64;
memset(out_date, 0, sizeof(out_date));
ret = adjust_date(in_date, out_date, pattern_in, pattern_out, day_diff, out_size);
if (ret == 0)
{
printf("Adjusted date: '%s'\n", out_date);
}
return ret;
}
うまくいけば、これは誰かの助けになるでしょう。建設的なコメントをいただければ幸いです。