Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: time.h ARMCC
Форум разработчиков электроники ELECTRONIX.ru > Микроконтроллеры (MCs) > ARM
Pridnya
Здравствуйте!
Как учитывается временная зона в стандартной библиотеке времени time.h?
Все что нашел в файле time.h - упоминание в функции strftime()
Цитата
%Z is replaced by the timezone name or abbreviation, or by no characters if no time zone is determinable.

Попробовал все, что можно вывести, выводит все, кроме временной зоны:
Цитата
time_t rawtime = 1480685759; // Fri, 02 Dec 2016 13:35:59 GMT
struct tm * timeinfo;
timeinfo = (struct tm*)localtime(&rawtime); // Convert time_t to tm as UTC time
char buffer [80];

strftime (buffer,80,"%I:%M%p",timeinfo);
puts (buffer); // 01:35PM

strftime (buffer,80,"%H:%M:%S%p",timeinfo);
puts (buffer); // 13:35:59PM

strftime (buffer,80,"%H:%M:%S",timeinfo);
puts (buffer); // 13:35:59

strftime (buffer,80,"%d.%m.%y",timeinfo);
puts (buffer); // 02.12.16

strftime (buffer,80,"%a_%A",timeinfo);
puts (buffer); // Fri_Friday

strftime (buffer,80,"%b_%B",timeinfo);
puts (buffer); // Dec_December

strftime (buffer,80,"%c",timeinfo);
puts (buffer); // 02 Dec 2016 13:35:59

strftime (buffer,80,"%j",timeinfo);
puts (buffer); // 337 (day of the year as a decimal number (001-366))

strftime (buffer,80,"%W",timeinfo);
puts (buffer); // 48 (the week number of the year (Monday as the first day))

strftime (buffer,80,"%x",timeinfo);
puts (buffer); // 02 Dec 2016

strftime (buffer,80,"%X",timeinfo);
puts (buffer); // 13:35:59

strftime (buffer,80,"%y",timeinfo);
puts (buffer); // 16 (year without century).

strftime (buffer,80,"%Y",timeinfo);
puts (buffer); // 2016 (year with century)

strftime (buffer,80,"%Z",timeinfo);
puts (buffer); // ???

Не знаю, как её задавать. Ведь с систем синхронизации будет время UTC+0, а у меня локальное UTC+3. Т.е. где-то должна быть временная зона.

Посмотрел у других - для PIC24 (компилятор XC16) в файле time.h есть переменная time_zone:
Код
extern int    time_zone;    /* minutes WESTWARD of Greenwich */
                /* this value defaults to 0 since with
                   operating systems like MS-DOS there is
                   no time zone information available */
KnightIgor
Цитата(Pridnya @ Dec 5 2016, 08:49) *

Уже давненько(!), мне понадобилось то же самое (у меня тоже KEIL), и я обнаружил, что функции есть, а реализации - нет. Пришлось финтить: заводить свою константу настройки и добавлять 3600*n, где n[-a..+b], при выдаче UTC time_t "наружу" и, соответственнно, вычитать такую же константу при установке времени в системе из значения локального времени "снаружи". Поскольку код стар (даже суперстар wink.gif), я уже и не копал, что там в библиотеках в KEIL 5.x, но есть у меня нехорошее подозрение... Интересное начинается, когда еще и зимнее/летнее время надо учитывать. У вас в России хоть этого уже нет: этим можете еще похвастаться.
Pridnya
Цитата(KnightIgor @ Dec 5 2016, 11:58) *
Уже давненько(!), мне понадобилось то же самое (у меня тоже KEIL), и я обнаружил, что функции есть, а реализации - нет. Пришлось финтить: заводить свою константу настройки и добавлять 3600*n, где n[-a..+b], при выдаче UTC time_t "наружу" и, соответственнно, вычитать такую же константу при установке времени в системе из значения локального времени "снаружи". Поскольку код стар (даже суперстар wink.gif), я уже и не копал, что там в библиотеках в KEIL 5.x, но есть у меня нехорошее подозрение... Интересное начинается, когда еще и зимнее/летнее время надо учитывать. У вас в России хоть этого уже нет: этим можете еще похвастаться.


Для учета летнего и зимнего времени в стандартной библиотеке есть поле Daylight Savings Time flag, но я пока не проверял как оно работает, т.к. перевода времени на летнее и зимнее у нас нет:
Код
struct tm {
    int tm_sec;   /* seconds after the minute, 0 to 60
                     (0 - 60 allows for the occasional leap second) */
    int tm_min;   /* minutes after the hour, 0 to 59 */
    int tm_hour;  /* hours since midnight, 0 to 23 */
    int tm_mday;  /* day of the month, 1 to 31 */
    int tm_mon;   /* months since January, 0 to 11 */
    int tm_year;  /* years since 1900 */
    int tm_wday;  /* days since Sunday, 0 to 6 */
    int tm_yday;  /* days since January 1, 0 to 365 */
    int tm_isdst; /* Daylight Savings Time flag */
    union {       /* ABI-required extra fields, in a variety of types */
        struct {
            int __extra_1, __extra_2;
        };
        struct {
            long __extra_1_long, __extra_2_long;
        };
        struct {
            char *__extra_1_cptr, *__extra_2_cptr;
        };
        struct {
            void *__extra_1_vptr, *__extra_2_vptr;
        };
    };
};

а вот для временной зоны его нет. Есть какие-то поля "ABI-required extra fields, in a variety of types" , но я не знаю зачем они и как их использовать.
esaulenka
Вбил в поиск по хелпу кейла слово "timezone" и получил неутешительный ответ:
Цитата
Timezone
Not supported by the ARM C library.



Так что пишите свои костыли, раз уж надо...
Pridnya
Цитата(esaulenka @ Dec 5 2016, 17:13) *
Вбил в поиск по хелпу кейла слово "timezone" и получил неутешительный ответ:

Так что пишите свои костыли, раз уж надо...

Спасибо! Посмотрел, в каком документе упоминается:
Цитата
ARM® Compiler toolchain
Version 5.02
Using ARM C and C++ Libraries and Floating-Point Support.


Затем посмотрел, а как в других библиотеках, у Microchip в time.h XC32 Compiler, есть
Код
extern int    time_zone;

и примечание:
Цитата
No standard mechanism exists for setting the current timezone, or the rules for when Daylight Saving Time (DST) is in effect.
In this implementation, as in others, you can specify both with an environment variable such as TZ or TIMEZONE.

Получается, что нужно самому корректировать, прибавлять к счетчику три часа для UTC+3.
Alechek
Цитата(Pridnya @ Dec 6 2016, 00:06) *
Получается, что нужно самому корректировать, прибавлять к счетчику три часа для UTC+3.

А Вы хотели, чтобы само прибавлялось? Да еще и с учетом постоянного перкероения часовых поясов?
Pridnya
Цитата(Alechek @ Dec 6 2016, 07:14) *
А Вы хотели, чтобы само прибавлялось? Да еще и с учетом постоянного перкероения часовых поясов?

Я предполагал, что в стандартной библиотеке есть некая константа timezone = 3, которая учитывается при работе библиотеки - к UnixTime UTC+0 (время с NTP-сервера) прибавляется timezone*SecPerHour и получаем местное время UTC+3. Мне казалось, что операция стандартная и должна быть в стандартной библиотеке. Оказалось, что исторически так сложилось, что коррекция не поддерживается в стандартной библиотеке.
SasaVitebsk
Я полностью написал свою библиотеку. Там мизер, по сути. У меня и летнее время подключается/ отключается.
Проверял в инете типа http://www.bl2.ru/programing/timestamp.html

Часовой пояс важен, так как некоторые SCADA не совсем корректно себя ведут. Я сталкивался. Часть SCADA напрямую часовой пояс выгребают с компа. Для одной ничего не смогли сделать. Просто выбрали на приборе Timezone = 0.
Pridnya
Цитата(SasaVitebsk @ Dec 6 2016, 12:04) *
Я полностью написал свою библиотеку. Там мизер, по сути. У меня и летнее время подключается/ отключается.
Проверял в инете типа http://www.bl2.ru/programing/timestamp.html

Часовой пояс важен, так как некоторые SCADA не совсем корректно себя ведут. Я сталкивался. Часть SCADA напрямую часовой пояс выгребают с компа. Для одной ничего не смогли сделать. Просто выбрали на приборе Timezone = 0.

Посмотрел ваш онлайн-калькулятор: "Время на вашем компьютере" в онлайн калькуляторе и на моем компьютере отличается на час (онлайн калькулятор ошибается - пишет что у меня 12:46, а у меня 13:46, что совпадет с временем сервера в онлайн-калькуляторе). Время UTC+0 совпадает с временем, которое я читаю с публичного NTP-сервера. На разницу в секндах не обращайте внимание - это я переключался между программами.
PS: У меня тоже UTC+3, как в онлайн-калькуляторе.
SasaVitebsk
Я написал "типа этого". Специально проверял по разным. У меня всё работает. Уже 2 года выпускают изделие.
Вообще непонятно как там можно ошибиться.
Когда будете писать, контролируйте при GMT 0. А TimeZone это просто смещение. Ошибиться в операции сложения... ну я не знаю. ))
Pridnya
Цитата(SasaVitebsk @ Dec 6 2016, 14:24) *
Я написал "типа этого". Специально проверял по разным. У меня всё работает. Уже 2 года выпускают изделие.
Вообще непонятно как там можно ошибиться.
Когда будете писать, контролируйте при GMT 0. А TimeZone это просто смещение. Ошибиться в операции сложения... ну я не знаю. ))

Я скриншоты привел для того, чтобы вы в своем онлайн-калькуляторе поискали, почему он пишет, что у меня на компьютере время такое-то, а оно на час отличается. У вас, наверное, ошибка, ведь часовые пояса у меня и у вас совпадают +3. Время на моем компьютере совпадает с "временем сервера", а не с "временем на вашем компьютере". rolleyes.gif Или я чего-то не понял?

Как прибавить три часа (3*3600) к UnixTime я знаю.
Lagman
Цитата(Pridnya @ Dec 6 2016, 14:50) *
Я скриншоты привел для того, чтобы вы в своем онлайн-калькуляторе поискали, почему он пишет, что у меня на компьютере время такое-то, а оно на час отличается.

У вас написано, что часовой пояс у вашего компьютера - Калининградское время (зима), а это как раз -1 час т.е. ваш winxp уже давно не знает правильного часового пояса, поищите в инете как это поправить через реестр.
Pridnya
Цитата(Lagman @ Dec 6 2016, 15:42) *
У вас написано, что часовой пояс у вашего компьютера - Калининградское время (зима), а это как раз -1 час т.е. ваш winxp уже давно не знает правильного часового пояса, поищите в инете как это поправить через реестр.

Спасибо! Сделал все как здесь описано, теперь время с онлайн-калькулятором совпадает (только секунды не синхронизированы, но это уже другой вопрос).
Ruslan1
Извините, то есть стандартизированного и документированного для Кейла пути работы с летним-зимним временем нет? И каждый свое делает как Бог на душу положит?
Грустно как-то. Нужно добавить в сорцы работу с летним/зимним- думал что лыжи не едут, а оказывается лыж просто нет совсем.

Ну хорошо, врукопашную.
А кто как даты перевода задает?
я как-то думал, что можно еще и дефолт сделать(последняя суббота марта...), но, разброд и шатание не поддаются алгоритмизации, понял, что лучше всегда требовать точно задать дату и время перевода, потому как дефолт-понятие растяжимое и у каждого он свой.

И, получается, что лучше просто иметь в конфиге startDateTime и endDateTime.

Или есть более изящный путь, без обновления этого конфига раз в год, определить какое сейчас здесь время, летнее или нелетнее?
Например, указать сайт, показывающий локальное время для данного прибора, и от него уже отталкиваться при определении времени? Или что-то подобное?

А еще: я, конечно, в школе учил географию, но как-то не думал, что переход на летнее время может быть в конце календарного года, а на зимнее- в начале года. Интересно, многие ли разработчики программ про это думали и учитывали в сорцах sm.gif

PS вот что бывает когда десятки лет работаешь в UTC, и вдруг надо в что-то местное переводить... Столько нового узнаешь об окружающем мире....
jcxz
Цитата(Ruslan1 @ Jan 23 2017, 20:30) *
А еще: я, конечно, в школе учил географию, но как-то не думал, что переход на летнее время может быть в конце календарного года, а на зимнее- в начале года. Интересно, многие ли разработчики программ про это думали и учитывали в сорцах sm.gif

Делал в своё время.
По памяти: у нас были следующие варианты задания в конфиге диапазона летнего времени:
1.Фиксированное число/месяц.
2.Последняя суббота N-го месяца.
3.Первая суббота N-го месяца (хотя уже не помню - возможно можно было выбрать номер субботы определённого месяца).
Всё учитывали.
И перевод может быть на не целое число часов (полчаса например).
Да и не переводил вобщем-то реально ничего (RTC). Часы реального времени шли всегда в линейном времени.
А уже если нужно было сезонное время, я определял - попадает-ли данная дата в диапазон летнего времени и включен-ли перевод? Если да - прибавлял к линейному времени смещение.
А вообще - перевод часов в системе реального времени, когда многое завязано на часы - это ОЧЕНЬ нетривиальная задача. Очень много проблем было с этим связано.
Особенно - когда на эти переводы ещё накладываются корректировки времени по интерфейсам связи и корректировки хода часов с ФАПЧ.
Служба реального времени - была одной из наиболее сложных частей ПО.
Ruslan1
jcxz, спасибо!
тоже думаю про похожее, так как хороших вариантов не так уж много.

Интересный вопрос- конфигуратор, в какой форме-формате задавать величины
как задать так чтобы покрыть все хотелки, не тупик в развитии, и при этом чтоб простой парсинг был.
Разглядывал как переменная TZ сделана, это кажется самый универсальный путь. Там два варианта стандартизировано, через день года(абсолютная дата) и через недели (для тривиальных ситуаций). Вкусность в том что это уже документировано, а не новый велосипед.
Осталось выделить нужную часть для использования в конфигураторе, чтобы все не делать. Думаю для начала только кусок с "day d of week w of month m" реализовать, потом разовью если нужно будет.

То есть для примера ниже все уже задокументировано, и не велосипед. Может, и исходники tzset() пригодятся sm.gif
Цитата
Here are some example TZ values, including the appropriate Daylight Saving Time and its dates of applicability. In North American Eastern Standard Time (EST) and Eastern Daylight Time (EDT), the normal offset from UTC is 5 hours; since this is west of the prime meridian, the sign is positive. Summer time begins on March’s second Sunday at 2:00am, and ends on November’s first Sunday at 2:00am.

EST+5EDT,M3.2.0/2,M11.1.0/2

Here is an example for New Zealand, where the standard time (NZST) is hours ahead of UTC, and daylight saving time (NZDT), 13 hours ahead of UTC, runs from the first Sunday in October to the third in March, and the changeovers happen at the default time of 02:00:00:

TZ="NZST-12:00:00NZDT-13:00:00,M10.1.0,M3.3.0"


Про часы и время- у меня тоже время всегда в UTC, коррекция на таймзону только в команду чтения локального времени вставлена. Теперь буду там же еще и зиму-лето вставлять. Лично я хорошо понимаю насколько это проблематично, особенно если неразрывность данных нужна и возможна передача в другие системы. Но для локального использования может быть и неплохо иногда.
SasaVitebsk
Цитата(Ruslan1 @ Jan 23 2017, 20:30) *
Ну хорошо, врукопашную.
А кто как даты перевода задает?
я как-то думал, что можно еще и дефолт сделать(последняя суббота марта...), но, разброд и шатание не поддаются алгоритмизации, понял, что лучше всегда требовать точно задать дату и время перевода, потому как дефолт-понятие растяжимое и у каждого он свой.

Ну я так и задаю. У меня 407 проц. Я календарь веду. То есть я контролирую дни недели. И перехожу (если опция включена) на летнее/ зимнее время согласно принятому. времени перехода.
Осуществляется это в диагностической задаче у меня. Сам переход выполняет проц аппаратно, но там тоже надо танцы с бубном делать. То есть в нужный момент включить признак, а потом выключить.
Сам проц не переходит.
У меня это контролируется в ТУ, поэтому проверяется на приёмочных и периодических испытаниях.
В старом приборе записывались даты и время перехода таблично... ))
Прикололся. )) Всё равно календарь веду, так я его вывожу одним из меню
Нажмите для просмотра прикрепленного файла
aiwa
Цитата(jcxz @ Jan 23 2017, 20:00) *
По памяти: у нас были следующие варианты задания в конфиге диапазона летнего времени:
1.Фиксированное число/месяц.
2.Последняя суббота N-го месяца.
3.Первая суббота N-го месяца (хотя уже не помню - возможно можно было выбрать номер субботы определённого месяца).
Всё учитывали.
И перевод может быть на не целое число часов (полчаса например).

Добавлю, тоже по памяти, там еще был флажок полушария: северное или южное.

Цитата(Ruslan1 @ Jan 23 2017, 21:52) *
Интересный вопрос- конфигуратор, в какой форме-формате задавать величины
как задать так чтобы покрыть все хотелки, не тупик в развитии, и при этом чтоб простой парсинг был.

Я конфигуратор вставлял в стандартном формате, только миллисекунды перевел в секунды.
Ну и пренебрег случаем, когда все переводы вставляются для каждого года индивидуально ради экономии.
А парсинг там совершенно простой для любого случая - просто взял соответствующий копи-паст из линукса.
Ruslan1
Цитата(aiwa @ Jan 24 2017, 14:03) *
Добавлю, тоже по памяти, там еще был флажок полушария: северное или южное.

мне кажется, что это лишняя сущность.
И что указать в экваториальных странах, которые и в том и в этом? (Свят-свят! не хотел бы я там что-нить ставитьsm.gif)
Для вычисления достаточно просто честно проверять даты начала и конца указанной зоны при условии что событие не чаще раза в год, а не смотреть на начало-конец года.

в-общем, проникся я как tzset() работает, красиво. В будущем- нужно просто переменную TZ честно поддерживать, к чему и буду стремиться. Не нужно в этой области велосипедов, все уже придумано до для нас. Но сейчас сделаю еще более простую реализацию, чтоб не менять уже давно написанное в данном проекте.
aiwa
Цитата(Ruslan1 @ Jan 24 2017, 14:20) *
мне кажется, что это лишняя сущность.

Для вычисления достаточно просто честно проверять даты начала и конца указанной зоны при условии что событие не чаще раза в год, а не смотреть на начало-конец года.


Как раз этот флажок и нужен для проверки начала и конца указанной зоны, а точнее, его участие заключается в том что он для южного полушария всего лишь меняет местами начало и конец DLT-зоны. Может и не нужен, но используется в виде оператора if лишь один раз в год при построении границ зимнего времени.
jcxz
Цитата(aiwa @ Jan 24 2017, 15:13) *
Добавлю, тоже по памяти, там еще был флажок полушария: северное или южное.

Не помню флажка.
А Вы разве в нашем проекте участвовали???
И Вас в нашем проекте тоже не помню biggrin.gif
aiwa
Цитата(jcxz @ Jan 24 2017, 15:04) *
Не помню флажка.
А Вы разве в нашем проекте участвовали???
И Вас в нашем проекте тоже не помню biggrin.gif

Наверное в качестве флажка.
KnightIgor
Цитата(Ruslan1 @ Jan 24 2017, 14:20) *
Для вычисления достаточно просто честно проверять даты начала и конца указанной зоны при условии что событие не чаще раза в год, а не смотреть на начало-конец года.

Хотите, обломаю на взлете? В некоторых мусульманских странах (например, Марокко) на время Рамадана всегда действует зимнее время! Если Рамадан, который еще и "плывет" с годами в обратную сторону, как-то цепляет летнее время, начинаются очень интересные вещи! Алла, я в бар!
Сергей Борщ
QUOTE (KnightIgor @ Jan 25 2017, 19:44) *
Хотите, обломаю на взлете? В некоторых мусульманских странах
В некоторых странах летнее время вообще отменяют/восстанавливают по прихоти президента wink.gif
Ruslan1
Цитата(Сергей Борщ @ Jan 25 2017, 19:55) *
В некоторых странах летнее время вообще отменяют/восстанавливают по прихоти президента wink.gif

Ну, для таких случаев есть три варианта, как и с Рамоданом:
1. просто не разрешать эту опцию и работать в "зимнем" времени или вообще в UTC.
2. взять подписку с менеджера системы, что он уведомлен о необходимости переконфигурирования до наступления каждого нового периода летнего(зимнего) времени и прошел тренинг "как это делать".
3. Эксклюзивная прошивка с любыми хотелками, хоть семь с половиной переводов ежемесячно. Больше капризов- больше денег. Можем делать новую прошивку каждый год.

На самом деле, (2) это самый рабочий вариант, если вообще нужен этот перевод зимнее/летнее. Запросто пишется центральный скрипт, который с центральной машины обновляет конфиг файлы по всей подключенной системе.

P.S. еще раз Спасибо всем откликнувшимся!
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2025 Invision Power Services, Inc.