проблема с mktime при преобразовании несуществующей структуры tm (из-за смены дневного времени)

У меня проблема с mktime, если час не существует из-за перехода на летнее время, тогда mktime в Windows, использующих MSVS 2010, вернет time_t в прошлом, в моем случае на 23:00, когда он должен вернуть 1:00 утра следующего дня ( в Linux он возвращает 1:00, как и должно быть). Моя проблема возникает в часовом поясе Бразилии (GMT -3), когда должна произойти автоматическая настройка летнего времени. В их случае это произойдет 21 октября 2012 года в 0:00 (будет 01:00).

Это часть кода:

/* test_date1.cpp : Defines the entry point for the console application.
*
*/
#include "StdAfx.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>

int _tmain(int argc, _TCHAR* argv[])
{

time_t mytime=1350784881;
struct tm *timeinfo;
char *tz;

/*time ( &mytime ); */
timeinfo = localtime ( &mytime );

printf("%.2d/%.2d/%.4d, %.2d:%.2d isdst?=%d\n", 
timeinfo->tm_mday, timeinfo->tm_mon, timeinfo->tm_year,  timeinfo->tm_hour, timeinfo-> tm_min, timeinfo -> tm_isdst);

timeinfo->tm_mday=21;
timeinfo->tm_mon=9;
timeinfo->tm_year=112;
timeinfo->tm_hour=0;
timeinfo->tm_min=0;
timeinfo->tm_isdst=-1;

printf("The shit: %.2d/%.2d/%.4d, %.2d:%.2d isdst?=%d\n", 
    timeinfo->tm_mday, timeinfo->tm_mon, timeinfo->tm_year,  timeinfo->tm_hour, timeinfo-> tm_min, timeinfo -> tm_isdst);

mytime= mktime(timeinfo);
printf("mytime is=%d\n", mytime);

timeinfo = localtime ( &mytime );

printf("%.2d/%.2d/%.4d, %.2d:%.2d isdst?=%d\n", 
    timeinfo->tm_mday, timeinfo->tm_mon, timeinfo->tm_year,  timeinfo->tm_hour, timeinfo-> tm_min, timeinfo -> tm_isdst);

return 0;
}

Результаты в Windows:

20/09/0112, 23:01 isdst?=0
21/09/0112, 00:00 isdst?=-1
mytime is=1350784800
20/09/0112, 23:00 isdst?=0

А в линуксе есть:

20/09/0112, 23:01 isdst?=0
21/09/0112, 00:00 isdst?=-1
mytime is=1350788400
21/09/0112, 01:00 isdst?=1

Как видите, mytime diff составляет 3600 секунд между тем, что time_t возвращает C из Unix, и тем, что возвращает C из Microsoft Visual Studio 2010.

Эта программа должна работать на разных платформах (UNIX/WINDOWS/и т. д.) и в любом часовом поясе, поэтому я не должен жестко указывать часовой пояс.

Как вы видели, проблема в Windows, где время возвращается неправильно. В данный момент я не знаю, как решить эту проблему. У кого-то была эта конкретная проблема? Как вы это решили? Мне особенно нужно начало Местного Дня.

Большое спасибо,

Джокеруш


person JokeruSh    schedule 03.09.2012    source источник
comment
Всегда документируйте версию ОС, когда задаете подобный вопрос. Посмотрите, что дает вам переменная среды TZ.   -  person Hans Passant    schedule 03.09.2012


Ответы (1)


Я не знаю, определено ли поведение mktime, когда вы передаете ему недопустимое время, так что на самом деле это может быть не ошибка.

В любом случае, если не считать повторной реализации mktime самостоятельно, вам придется обойти эту проблему. Предлагаю следующий алгоритм:

  • Создайте struct tm на 9 утра рассматриваемого дня.
  • Преобразовать в time_t.
  • Вычтите 24 часа из time_t.

Если нет перехода на летнее время, то в этот момент вы смотрите на 9 утра предыдущего дня. Если началось летнее время, вы смотрите на 8 утра; если он закончился, вы смотрите на 10 утра.

  • Преобразовать обратно в структуру tm.
  • Сравните дату в структуре tm с исходной датой.
  • Если еще не подходящий день, добавьте час к time_t и повторите попытку.

Поскольку вы добавляете только час за раз, как только вы получите нужную дату, вы можете быть уверены, что у вас есть самое раннее время на эту дату.

Я делаю несколько предположений, которые считаю в настоящее время безопасными: что летнее время никогда не начинается и не заканчивается в течение часа, что оно никогда не начинается и не заканчивается между 8:00 и 10:00 и никогда не изменяется более чем на час.

Я намеренно не предполагаю, что летнее время никогда не начинается и не заканчивается вечером (например, 23:00 становится полночью или наоборот) или ранним утром (например, 2:00 становится 3:00 или наоборот, что, как это происходит, именно то, что происходит здесь).

person Harry Johnston    schedule 03.09.2012