2013-03-27 5 views
2

Учитывая дату и время ввода (в строковом формате), я пытаюсь получить для нее время эпохи, используя функции time, приведенные в ctime, например mktime. Преобразование даты эпохи time_t обратно к дате и времени приводит к дате и времени на один час меньше, чем оригинал. Я провел несколько дискуссий, в которых говорится, что может быть корректировка одного часа в случае летнего времени. Вот код:Работа с летним временем - C++

//sample strptime program. 

#include <iostream> 
#include <ctime> 
#include <string> 
using namespace std; 

long parseTime(string time) { 

    cout << "Time entered = " << time << endl; 

    long timeSinceEpoch; 

    struct tm t; 

    if(time.find("/") != string::npos) { 
    //format of date is mm/dd/yyyy. followed by clock in hh:mm (24 hour clock). 
    if(strptime(time.c_str(), "%m/%e/%Y %H:%M", &t) == NULL) { 
     cout << "Error. Check string for formatting." << endl; 
    } 
    } else if(time.find("-") != string::npos) { 
    //format of date is yyyy-mm-dd hh:mm:ss (hh in 24 hour clock format). 
    cout << "I am here." << endl; 
    if(strptime(time.c_str(), "%Y-%m-%e %H:%M:%S", &t) == NULL) { 
     cout << "Error. Check string for formatting of new date." << endl; 
    } 
    } 

    cout << "Details of the time structure:" << endl; 
    cout << "Years since 1900 = " << t.tm_year << endl; 
    cout << "Months since January = " << t.tm_mon << endl; 
    cout << "Day of the month = " << t.tm_mday << endl; 
    cout << "Hour = " << t.tm_hour << " Minute = " << t.tm_min << " second = " << t.tm_sec << endl; 

    timeSinceEpoch = mktime(&t); 
    time_t temp = mktime(&t); 
    cout << "Time since epoch = " << timeSinceEpoch << endl; 

    cout << "Reconverting to the time structure:" << endl; 
    struct tm* t2 = localtime(&temp); 
    cout << "Details of the time structure:" << endl; 
    cout << "Years since 1900 = " << t2->tm_year << endl; 
    cout << "Months since January = " << t2->tm_mon << endl; 
    cout << "Day of the month = " << t2->tm_mday << endl; 
    cout << "Hour = " << t2->tm_hour << " Minute = " << t2->tm_min << " second = " << t2->tm_sec << endl; 

    return timeSinceEpoch; 
} 

int main(int argc, char *argv[]) { 

    string date, t; 
    cout << "Enter date: " << endl; 
    cin >> date; 
    cout << "Enter time: " << endl; 
    cin >> t; 

    struct tm time; 
    string overall = date + " " + t; 

    long result = parseTime(overall); 
    cout << "Time in date + time = " << overall << " and since epoch = " << result << endl; 

return 0; 
} 

Основная сложность вход: Дата: 2013-03-11 время: 04:41:53

Мои вопросы (ы):
1. Проверка tm_idst flag возвращает ненулевое значение, что указывает на то, что DST действует. Однако, как я узнаю, о чем говорится в часовом поясе?
2. Указанная выше метка времени может не быть записана в том же часовом поясе, в котором я находился. Есть ли способ указать часовой пояс, чтобы флаги tm_idst были правильно установлены?
3. Как мне работать с DST, когда я не знаю, в какой временной зоне была записана метка времени?

+0

Получение временной зоны зависит от вашей операционной системы и библиотеки C, нет стандартного или независимого от платформы способа ее получения. Например, в Linux с glibc имеется дополнительное поле-член в структуре 'tm', называемой' tm_zone', которая представляет собой строку C-стиля, содержащую аббревиатуру часового пояса. –

+0

@Joachim: Я попробовал опцию 'tm_zone', но, похоже, ее там нет. Так что в основном, я просто получаю время с эпохи, переконвертируюсь в 'struct tm', и если есть разница в часах, добавьте к ней 3600 секунд? Это единственный вариант, с которым я имею дело с DST? – Sriram

+0

комментарий - если вы принимаете «вид» ISO-дат, то правильный формат ввода - YYYY-MM-DD (т.е. 4 + 2 + 2 ** всегда ***) - так что синтаксический анализ для этого - '% Y-% m-% d', формат% e в теории принимает ведущее место для дат с одной цифрой, тогда как [ISO всегда ожидает две цифры за месяц и год] (http://en.wikipedia.org/wiki/ ISO_8601). – Petesh

ответ

2

Plain C++ довольно редкий с данными о часовом поясе и без спецификации часового пояса во время форматирования существует несколько периодов, когда вы получите непоследовательный результат - например, повторное время, следующего за часами, возвращающимися назад. Вот почему всегда рекомендуется записывать все временные метки в UTC - т.е. никогда не применяют часовой пояс к записанной отметке времени, записывают ее в GMT, а затем обратно и вперед с этим значением в качестве отображаемой переменной, контроль над.

У Linux/BSD есть дополнительные поля, которые можно использовать для определения часового пояса, и смещение от UTC - например, на linux это поле __tm_gmtoff, а в BSD (/ Mac OS X) оно называется tm_gmtoff.

Существует дополнительное поле, обозначающее часовой пояс, который является __tm_zone на linux и tm_zone в BSD (/ Mac OS X), но это поле заполняется только по местному времени.

я немного изменил свой пример, и получил следующий результат:

Time entered = 2013-04-05 15:00 
I am here. 
Error. Check string for formatting of new date. 
Details of the time structure: 
Years since 1900 = 113 
Months since January = 3 
Day of the month = 5 
Hour = 15 Minute = 0 second = 0 
gmtoff = 0 
Time since epoch = 1365174000 
Reconverting to the time structure: 
Details of the time structure: 
Years since 1900 = 113 
Months since January = 3 
Day of the month = 5 
Hour = 16 Minute = 0 second = 0 
gmtoff = 3600 
Zone = IST 
Time in date + time = 2013-04-05 15:00 and since epoch = 1365174000 

Если вы используете эту структуру в Windows, вы собираетесь придется использовать другой механизм, хотя, как это Безразлично» t имеют эти два дополнительных поля.

+0

Я на cygwin. У меня нет 'tm_gmtoff' или' tm_zone'. Какие у меня варианты? Повторно конвертировать из времени эпохи в дату и если есть разница в часе между первоначальным и повторно преобразованным временем, добавьте 3600 секунд к тому времени с эпохи? – Sriram

+0

Ваше предложение иметь дело только с UTC - это хорошо, но я не контролирую создание timestamp. Мне нужно работать с данными. Мне сказали, что отметки времени записаны в КНТ. – Sriram

+0

@Sriram Как я уже говорил в конце ответа Windows не поддерживает эти поля. Я полагаю, вы имеете в виду, что время в КНТ/CDT, а не строго CST. Реализация strptime в cygwin ограничена. Я бы рекомендовал использовать boost для этого - это позволит гораздо более разумную обработку даты и времени. – Petesh