C ++ time_t проблема - PullRequest
       3

C ++ time_t проблема

8 голосов
/ 07 сентября 2010

У меня проблемы с управлением датами в C ++ (VS 2008).

Согласно спецификациям MSDN , time_t обозначает:

Количество секунд с 1 января 1970 года, 0:00 UTC

поэтому я написал этот фрагмент кода:

#include <stdio.h>
#include <time.h>

time_t GetDate(int year, int month, int day, int hour, int min, int sec)
{
    time_t rawtime;
    struct tm * timeinfo;

    time ( &rawtime );
    timeinfo = gmtime ( &rawtime );
    timeinfo->tm_year = year - 1900;
    timeinfo->tm_mon = month - 1;
    timeinfo->tm_mday = day;
    timeinfo->tm_hour = hour;
    timeinfo->tm_min = min;
    timeinfo->tm_sec = sec;
    timeinfo->tm_isdst = 0; // disable daylight saving time

    time_t ret = mktime ( timeinfo );

    return ret;
}

int main ()
{
    time_t time_0 = GetDate(1970,1,1,0,0,0);
    // time_0 == -1 !!!
    time_t time_1 = GetDate(1970,1,1,1,0,0);
    // time_1 == 0 !!!
    return 0;
}

Кажется, он сдвинут на 1 час (т. Е. Нулевое время - 1 января 1970 г., 1:00 UTC).

Изначально я думал, что проблема может исходить от флага DayLightSaving, но он не меняется при его изменении.

Я что-то не так делаю?

Заранее спасибо


P.S. Теоретически, я мог бы не обращать внимания на нулевое значение времени, потому что это только контрольное время.

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


EDIT:

вот решение, благодаря Джош Келли Ответ

time_t mktimeUTC(struct tm* timeinfo)
{
    // *** enter in UTC mode
    char* oldTZ = getenv("TZ");
    putenv("TZ=UTC");
    _tzset();
    // ***

    time_t ret = mktime ( timeinfo );

    // *** Restore previous TZ
    if(oldTZ == NULL)
    {
        putenv("TZ=");
    }
    else
    {
        char buff[255];
        sprintf(buff,"TZ=%s",oldTZ);
        putenv(buff);
    }
    _tzset();
    // ***

    return ret;
}

Ответы [ 2 ]

8 голосов
/ 07 сентября 2010

mktime принимает struct tm, давая местное время и возвращает количество секунд с 1 января 1970 года, 0:00 UTC .Следовательно, ваш GetDate(1970,1,1,0,0,0); вызов вернет 0, если ваш местный часовой пояс UTC, но может вернуть другие значения для других часовых поясов.

Редактировать: Для версии UTC mktime иливаш GetDate, попробуйте следующее (не проверено):

  1. Вызовите getenv, чтобы сохранить текущее значение переменной среды TZ (если есть).
  2. Позвоните putenv, чтобы изменить переменную среды TZ на "UTC".
  3. Позвоните _tzset, чтобы сделать ваши изменения активными.
  4. Позвоните mktime.
  5. Восстановите старое значение TZ, затем снова наберите _tzset.
1 голос
/ 07 сентября 2010

Просто WAG, но попробуйте следующее:

timeinfo->tm_year = year - (unsigned long)1900;
timeinfo->tm_mon = month - (unsigned long)1;
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...