Страница 1 из 3
Элементарная задачка для программиста
Добавлено: 06 ноя 2011, 17:21
tma
Всем привет.
Потратил несколько часов и не смог решить, хреновый из меня программист. ;(
Нужно Cisco vsa time format: "18:27:28.032 UTC Wed Dec 9 1998" преобразовать в unix time с учетом таймзоны на Си (под Unix).
Функция strptime не подходит -- она не понимает миллисекунды.
Вот еще образцы: "21:04:33.433 MSK Sat Nov 05 2011" и "21:04:33.433 +0300 Sat Nov 05 2011".
Кто может выручить?
Re: Элементарная задачка для программиста
Добавлено: 06 ноя 2011, 18:07
tma
Спасибо, нашел
вариантик по ссылке.
Хотя это я уже вчера все прошел. Не выходит именно таймзона. ;(
Получаю в MSK, выход в UTC, а время в результате тоже самое, что и в MSK.
Re: Элементарная задачка для программиста
Добавлено: 06 ноя 2011, 21:19
tma
Уточню свой вопрос - нужно по аббревиатуре таймзоны определить смещение в секундах от UTC используя tzdata. Как?
Перерыл уже все, что только возможно.
Re: Элементарная задачка для программиста
Добавлено: 06 ноя 2011, 21:30
tma
Если б это было так просто...
Представим, что у меня есть дата до перехода на зимнее время и через 1 час еще одна запись.
Время у них будет одинаковое, а таймзона разная. Мне нужно обе даты перевести в UTC.
Затем нужно иметь возможность даты в прошлом (о чем знает tzdata) перевести в UTC.
Если не учитывать tzdata, то точно такое же время по MSK в прошлом году уже будет на 1 час меньше времени.
Время же приходит в разных таймзонах, нужно по аббревиатуре перевести его в смещение в секундах...
Re: Элементарная задачка для программиста
Добавлено: 06 ноя 2011, 22:01
tma
ddkprog писал(а):
парсишь какое там от GMT смещение, переводишь это смещение в unixtime stamp и плюсуешь к тому времени что уже получил
Я получил MSK. Какое у MSK смещение? В прошлом году это было UTC+3, в этом году уже UTC+4.
Ну ладно MSK -- я про него знаю, а какая-нибудь Ангола? Я даже не знаю как называется их таймзона, не говоря уже о смещении
и переходе на летнее время.
ddkprog писал(а):
ты хочешь парсить время с учетом уже базы tz
ну глянь в man time man localtime
что там по tz_name
Это константа, зовется __tz_name для BSD - tz_zone, в структуре tm.
Проблема в том, что туда ничего не записать.
Есть tzset, которая устанавливает внутренние переменные tzname, timezone, daylight на основе переменной окружения TZ.
Но TZ имеет свой собственный формат, просто MSK туда не записать.
Хранить же где-то соответствие MSK смещению +0300 при наличии tzdata глупо, плюс нужно загружать туда все обновления и т.д.
tm_isdst совершенно не то -- это флаг, есть ли переход на летнее/зимнее время.
Re: Элементарная задачка для программиста
Добавлено: 06 ноя 2011, 22:33
tma
Cisco присылает как +0300 (самый простой вариант), так и MSK. Но чтобы понять, что означает MSK, нужно где-то хранить эту информацию...
Я думал использовать для этого tzdata -- зачем изобретать велосипед?
А вот еще возможные варианты:
Код: Выделить всё
18:27:28.032 UTC Wed Dec 9 1998
21:04:33.433 +0300 Sat Nov 05 2011
21:04:33.433 MSK Sat Nov 05 2011
21:04:33.433 EST5EDT Sat Nov 05 2011
Про EST2EDT не уверен -- это tzset элементарно обрабатывает.
С UTC/GMT тоже все просто, но с остальным...
Задача минимум -- преобразовать полученную дату в UnixTime. С миллисекундами разобраться легко.
На даты в прошлом можно забить, но не хотелось бы.
Re: Элементарная задачка для программиста
Добавлено: 06 ноя 2011, 22:45
tma
Вот примерный код:
Код: Выделить всё
#define _XOPEN_SOURCE
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <sys/time.h>
const char *abmon[] = {
"Jan", "Feb", "Mar", "Apr", "May", "Jun",
"Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
};
int main(void)
{
struct tm tm;
struct tm ut;
time_t curtime;
int i, len, hour, min, sec, usec, mday, year;
char wday[3], mon[3], tz[10];
char in[255]="21:04:33.433 MSK Sat Nov 05 2011";
sscanf( in, "%d:%d:%d.%d %s %s %s %d %d", &hour, &min, &sec, &usec, &tz, &wday, &mon, &mday, &year );
tm.tm_hour = hour;
tm.tm_min = min;
tm.tm_sec = sec;
tm.tm_mday = mday;
tm.tm_year = year - 1900;
for (i = 0; i < 12; i++) {
len = strlen(abmon[i]);
if (strncasecmp(abmon[i], mon, len) == 0)
break;
}
tm.tm_mon = i;
tm.tm_isdst = -1;
setenv("TZ",tz,1);
curtime = mktime( &tm );
//curtime = mktime( &tm ) + usec / 1000;
tzset();
printf("timezone = %d, daylight = %d, tzname[0]/tzname[1] = %s/%s\n", timezone, daylight, tzname[0], tzname[1] );
printf("UnixTime: %d\n", curtime);
printf( "in: %s / %s\n", in, asctime( &tm ) );
gmtime_r( &curtime, &ut );
strftime(buf, sizeof(buf), "%H:%M:%S %Z %a %b %d %Y", &ut);
printf("Output: %s\n", buf);
unsetenv("TZ");
exit(EXIT_SUCCESS);
}
Результат:
Код: Выделить всё
timezone = 0, daylight = 0, tzname[0]/tzname[1] = MSK/
UnixTime: 1320527073
in: 21:04:33.433 MSK Sat Nov 05 2011 / Sat Nov 5 21:04:33 2011
Output: 21:04:33 GMT Sat Nov 05 2011
Re: Элементарная задачка для программиста
Добавлено: 07 ноя 2011, 00:37
tma
Если подсунуть строчку:
То в TZ записывается Europe/Moscow и все отрабатывает корректно.
Может хранить где-нибудь таблицу соответствия MSK=Europe/Moscow?
Хотя тоже не выход -- это программа на Си, а не БД...
Re: Элементарная задачка для программиста
Добавлено: 07 ноя 2011, 01:05
tma
MSK есть, но хранится она в tzdata в файле Europe/Moscow.
В TZ можно указать как путь к файлу (как полный так и относительный), а можно в формате TZ.
Проблема в том, что я получаю от Cisco именно MSK (или +0300 к примеру) и дальше хоть волком вой.
Re: Элементарная задачка для программиста
Добавлено: 07 ноя 2011, 04:01
tma
Я не могу настраивать cisco всех возможных клиентов или требовать, чтобы все они работали в UTC.
Увы, единственный вариант это научиться понимать таймзону. Построить таблицу соответствия можно (по той же tzdata),
но ее либо придется в памяти держать (а таймзоны далеко не все нужны), либо каждый раз парсить файл, что не лучше.
tzfile грузит в память структуру zoneinfo, но только определенного, а какой подсунуть? Пока одни вопросы...