Вывод силы strftime в том же местном часовом поясе

Мой текущий компьютер показывает время с CET:

$ date
Mon Dec  1 21:31:41 CET 2014

Однако моя локаль en_US:

$ locale | grep -i time
LC_TIME="en_US.UTF-8"

Я хотел бы отформатировать строку эпохи с помощью C в мой текущий местный часовой пояс, но я не знаю, как указать strptime изменить локальный по умолчанию:

#define _XOPEN_SOURCE
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>

int
main(void)
{
   struct tm tm;
   char buf[255];

   memset(&tm, 0, sizeof(struct tm));
   strptime("1412200800", "%s", &tm);
   strftime(buf, sizeof(buf), "%c %Z", &tm);
   puts(buf);
   exit(EXIT_SUCCESS);
}

На странице руководства указано, что оно форматирует время в соответствии с локалью, но, похоже, игнорирует мои настройки:

 $ export LC_TIME=de_DE.UTF-8
 $ locale | grep -i time
LC_TIME=de_DE.UTF-8
 $ ./a.out 
Thu Oct  2 00:00:00 2014 CEST

Я ожидаю:

Wed Thu Oct  1 22:00:00 2014 CET

Обновить

Итак, я полностью удалил %s и попробовал следующий подход, но безуспешно:

#define _XOPEN_SOURCE
#include <string.h>
#include <time.h>
#include <stdio.h>
#include <stdlib.h>
#include <locale.h>

int
main(void)
{
   struct tm *tim;
   setlocale(LC_ALL, "");
   char buf[255];
   time_t c;

   c = strtoul("1412200800", NULL, 0);
   tim = localtime(&c);
   strftime(buf, sizeof(buf), "%c" , tim);
   puts(buf);
   printf("%s %s\n", tzname[0], tzname[1]);
   exit(EXIT_SUCCESS);
}

Вывод по-прежнему остается тем, что я ожидал:

gcc strptime_test.c && ./a.out 
Thu 02 Oct 2014 12:00:00 AM CEST
CET CEST

обновление 2, решение:

Вместо использования localtime(&c); теперь я использую:

tim = gmtime(&c);
strftime(buf, sizeof(buf), "%c" , tim);

Которые дают желаемое поведение:

Wed 01 Oct 2014 10:00:00 PM GMT

person oz123    schedule 01.12.2014    source источник
comment
Я думаю, вы на самом деле спрашиваете о strftime   -  person M.M    schedule 01.12.2014
comment
@MattMcNabb, да, ты прав. Прости за это.   -  person oz123    schedule 01.12.2014


Ответы (1)


В вашем коде используется нестандартное расширение glibc для strptime; %s - количество секунд с начала эпохи.

Согласно Epoch Converter, 1412200800 равно Wed, 01 Oct 2014 22:00:00 GMT, поэтому ваша программа работает правильно. Однако неясно, следует ли брать секунды эпохи в UTC или в вашем местном часовом поясе, поэтому, как отмечает loreb в комментариях, вам также может потребоваться вызвать функцию преобразования часового пояса.

Вам нужно будет принять решение о том, является ли время (т. е. содержимое объектов time_t и struct tm) в вашей программе временем в формате UTC или местным временем.

Я бы предложил следующее исправление: заменить strptime на

time_t c = 1412200800;
tm = *gmtime(&c);     

Другая функция, которую можно использовать здесь вместо gmtime, — это localtime.


Кстати, я думаю, вы смешиваете локали и часовые пояса: «локаль» означает способ форматирования времени; например, по умолчанию может быть:

Sun Oct  1 00:00:00 2014

но версия в формате локали будет:

Sun, Oct 01, 2014 12:00:00 AM

Часовые пояса и локали - разные вещи. (Один языковой стандарт может охватывать несколько часовых поясов, а один часовой пояс может содержать несколько языковых стандартов).

NB. в C локалью по умолчанию является локаль C, а не системная. Чтобы прочитать локаль из переменных среды, выполните:

#include <locale.h>

// in main()
setlocale(LC_ALL, "");
person M.M    schedule 01.12.2014
comment
На catb.org/esr/time-programming есть хороший обзор текущей ситуации. - грустный, грустный беспорядок. - person loreb; 02.12.2014
comment
@loreb да, это некрасиво - person M.M; 02.12.2014
comment
@MattMcNabb, ваше решение, к сожалению, не работает (я использую Linux, если это имеет значение) - person oz123; 02.12.2014
comment
Я понимаю, что программа работает так, как ожидалось, но вопрос в том, как мне напечатать строку с форматированием времени CET вместо CEST? - person oz123; 02.12.2014
comment
Не работает - как я и имел в виду, но благодаря 3-му и 4-му чтению вашего ответа я нашел решение. Так что я приму это. Спасибо за обсуждение. - person oz123; 02.12.2014
comment
Ваш часовой пояс CET ; внутри этого есть CEST и CEDT в зависимости от того, активно ли летнее время - person M.M; 02.12.2014
comment
Частично это было непонятно из-за моего первоначального намерения. Я хотел, чтобы мое форматирование даты совпадало с форматированием в MongoDB, которое представлено в GMT. Так что мое оригинальное название немного хм причудливое. - person oz123; 02.12.2014