2009-04-17 2 views
27

Каков наилучший способ преобразования данных между локальным временем и UTC в C/C++?Преобразование между локальными временами и GMT/UTC в C/C++

Под «datetime», я имею в виду некоторое представление времени, которое содержит дату и время суток. Я буду доволен time_t, struct tm или любым другим представлением, которое позволяет.

Моя платформа - Linux.

Вот конкретная проблема, которую я пытаюсь решить: я получаю пару значений, содержащих юлианскую дату и количество секунд в день. Эти значения указаны в GMT. Мне нужно преобразовать это значение в локальный часовой пояс «YYYYMMDDHHMMSS». Я знаю, как преобразовать юлианскую дату в Y-M-D, и, очевидно, легко конвертировать секунды в HHMMSS. Однако сложной частью является преобразование часового пояса. Я уверен, что смогу найти решение, но я бы предпочел найти «стандартный» или «хорошо известный» способ, а не спотыкаться.


Возможное связан вопрос Get Daylight Saving Transition Dates For Time Zones in C

ответ

21

Вы должны использовать комбинации gmtime/localtime и timegm/mktime. Это должно дать вам ортогональные инструменты для совершения конверсий между struct tm и time_t.

Для UTC/GMT:

time_t t; 
struct tm tm; 
struct tm * tmp; 
... 
t = timegm(&tm); 
... 
tmp = gmtime(t); 

Для МестноеВремя:

t = mktime(&tm); 
... 
tmp = localtime(t); 

Все tzset() делает это установить внутреннюю переменную временную зону из переменных в TZ среды. Я не думаю, что это должно быть вызвано не один раз.

Если вы пытаетесь конвертировать между часовыми поясами, вы должны изменить struct tmtm_gmtoff.

+0

Спасибо! Я знал что-то вроде timegm(), должно было существовать, но не знал названия. –

+0

Рад помочь. Преобразование времени может быть довольно сложной областью. Обычно рекомендуется хранить все в UTC, когда это возможно. Преобразование между часовыми поясами еще сложнее! –

+1

Да, к сожалению, разработчики системы выбрали местное время как «стандартный» формат временной отметки для протокола обмена сообщениями. Я ненавижу, когда люди делают это. –

2

Если вам нужно беспокоиться о преобразовании даты/времени с правилами часового пояса, вы можете посмотреть в ICU.

17

Если на Windows, вы не имеете timegm() доступны для вас:

struct tm *tptr; 
time_t secs, local_secs, gmt_secs; 
time(&secs); // Current time in GMT 
// Remember that localtime/gmtime overwrite same location 
tptr = localtime(&secs); 
local_secs = mktime(tptr); 
tptr = gmtime(&secs); 
gmt_secs = mktime(tptr); 
long diff_secs = long(local_secs - gmt_secs); 

или что-то подобное ...

+0

Не должны быть' secs' и 'gmt_secs' идентичны? Я бы подумал, что вы можете упростить это довольно немного. – jowo

+1

Я пробовал это. Я попытался проверить его, проверив результат против инверсии. В некоторых случаях он работает, а для других он выключен на час. Я предполагаю, что это потому, что DST запускается и останавливается на разных датах в разных местах, где я пытаюсь (используя GMT, но конвертируя с локальным временем PST). Есть ли способ компенсировать это? –

+1

Эта версия, которая использует библиотеку времени Boost POSIX, кажется, работает, несмотря на разные даты DST через часовые пояса: http://stackoverflow.com/a/6849810/857029. –

Смежные вопросы