Вопрос по c, timezone – Преобразование часовых поясов в C

6

Мне нужно конвертировать время между часовыми поясами в C (в Linux, так что все, что специфическое тоже будет делать).

Я знаю свое текущее время, местное и UTC, у меня есть смещение целевого времени. Я пытаюсь использовать mktime, gmtime, localtime и аналогичный набор функций, но все еще не могу понять это.

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

Ваш Ответ

3   ответа
5

В качестве комментариев не разрешается публиковать код, публиковать как отдельный ответ. Если вы знаете & quot; локальный & quot; время и "UTC" время, вы можете рассчитать смещение «другой» время от вашего & quot; местного & quot; время. Затем вы конвертируете struct tm в календарное время, добавляете желаемое количество секунд (смещение целевого времени) и конвертируете его обратно в struct tm:

(отредактировано для учета другого сценария, чтобы использовать нормализацию mktime)

#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <sys/time.h>

int main(int argc, char *argv) {
  struct timeval tv_utc;
  struct tm *local_tm, *other_tm;

  /* 'synthetic' time_t to convert to struct tm for the other time */
  time_t other_t_synt;
  /* Other time is 1 hour ahead of local time */
  int other_local_delta = 1*3600; 


  /* the below two lines are just to set local_tm to something */
  gettimeofday(&tv_utc, NULL);
  local_tm = localtime(&tv_utc.tv_sec);

  printf("Local time: %s", asctime(local_tm));

  #ifdef DO_NOT_WRITE_TO_LOCAL_TM
  other_t_synt = mktime(local_tm) + other_local_delta;
  #else
  local_tm->tm_sec += other_local_delta;
  /* mktime will normalize the seconds to a correct calendar date */
  other_t_synt = mktime(local_tm);
  #endif

  other_tm = localtime(&other_t_synt);

  printf("Other time: %s", asctime(other_tm));

  exit(0);
}
Неплохо подмечено. verma
В любом случае, автонормализация - это хорошо, я также отредактировал пример с вашим использованием. Я думал, что «эпоха» время other_t в этом сценарии будет синтетическим, если вы добавите дельту между другим временем и вашим временем, поэтому я также переименовал его соответственно.
Это предполагает, что мы знаем дельту между текущим и другим. Или UCT и другие тоже будут работать. Но эта дельта не обязательно является постоянной величиной в течение года (DST начинается / заканчивается в разных странах или даже изменяется в правилах преобразования местного времени для конкретной зоны). Есть лиgeneral способ преобразования из зоны A в зону B для произвольного значения эпохи Unix?
Да, это должно сработать - я пытался быть вежливым и избегать записи в чужую память, поскольку память, указанная в этом примере local_tm, не принадлежит моему коду.
Кажется, это работает хорошо. Я собираюсь использовать local_tm-> gt; tm_sec + = 3600; other_t = mktime (local_tm); вместо этого, пусть mktime сделает все для меня. verma
2

Вы можете использовать gmtime () и структуру tm для непосредственной установки этого, если вы знаете смещения.

Если вы знаете свое местное время и UTC, вы знаете свое местное смещение. При условии, что вы также знаете целевое смещение, это просто вопрос установки соответствующего tm_hour (и, возможно, переворачивания дня, если вы пойдете в & lt; 0 или & gt; 23).

Для некоторого примера кода, посмотрите этоСправочная страница gmtime, Показывает смещение на основе смещения часового пояса.


Редактировать:

В ответ на комментарии - вы также можете позволить mktime обработать переход для вас, что позволяет упростить это, преобразовав обратно в time_t. Вы можете использовать что-то вроде:

time_t currentTime;
tm * ptm;
time ( &currentTime );
ptm = gmtime ( &rawtime );
ptm->tm_hour += hours_to_shift;
ptm->tm_minutes += minutes_to_shift; // Handle .5 hr timezones this way

time_t shiftedTime = mktime( ptm );
// If you want to go back to a tm structure:

tm * pShiftedTm = gmtime( &shiftedTime );
Хороший вопрос, я буду редактировать для обновления.
На самом деле, я думаю, что есть способ избежать излишней арифметики вручную ... поскольку комментарии не разрешают код, я опубликую его как другой ответ.
FWIW, не только tm_hour - например, Стандартное время Индии (IST) UTC + 5,5
хм .. Я прочитал справочные страницы на mktime, где говорится, что если я изменю структуру tm, я могу использовать mktime для нормализации времени. Так что позаботимся о нормализации дат, а все остальное может усложниться. Затем я могу захотеть преобразовать это время обратно в tm struct (я не знаю, стоит ли мне использовать localtime или gmtime), чтобы я мог использовать такие функции, как strftime и т. Д., Чтобы получить отформатированные значения времени. verma
Да, верно. Вы потенциально должны манипулировать практически любым полем, но концепция обоснована.
0

По всей вероятности, ваша операционная система обеспечивает некоторую поддержку для этого.

В операционных системах Unix вы можете посмотреть справочные страницы дляasctime, asctime_r, ctime, ctime_r, difftime, gmtime, gmtime_r, localtime, localtime_r, mktime, timegm.

API-интерфейсы Posix, о которых вы упомянули, действительно не предлагают очевидного способа сделать то, что задает вопрос. В вопросах уже упоминаются некоторые из этих функций по именам, поэтому упоминание их снова и указание на страницы руководства, по сути, вряд ли будет полезным ответом.

Похожие вопросы