` пора.h` против `TimeLib.h` на платах AVR

Почему я получаю неверный результат при использовании библиотеки time.h при использовании плат AVR, таких как Nano / Uno / Pro Micro (в то время как при использовании TimeLib.h).

РЕЗУЛЬТАТ (для данной эпохи):

Время: 2022-04-02 16:11:20

время.ч: 0152-03-01 16:11:20

КОД:

#define CASE 1

#if CASE == 1
#include <time.h>
#elif CASE == 2
#include <TimeLib.h>
#endif

time_t bootTime = 1648915880;

void setup()
{
  // put your setup code here, to run once:
  Serial.begin(115200);
  Serial.println("\nStart!");
  delay(1000);

  char clk2[40];

#if CASE == 1
  struct tm *tm = localtime(&bootTime);
  sprintf(clk2, "%04d-%02d-%02d %02d:%02d:%02d", tm->tm_year, tm->tm_mon, tm->tm_mday, tm->tm_hour, tm->tm_min, tm->tm_sec);
  
#elif CASE == 2
  sprintf(clk2, "%04d-%02d-%02d %02d:%02d:%02d", year(bootTime), month(bootTime), day(bootTime), hour(bootTime), minute(bootTime), second(bootTime));
#endif
  Serial.println(clk2);
}

void loop()
{
  // put your main code here, to run repeatedly:
}

, 👍0

Обсуждение

localtime() требует установки часового пояса. Понятия не имею, как вы это установили. Вместо этого используйте gmtime (), чтобы получить время UTC (GMT), которое не имеет часового пояса., @Majenko

ну, для этого, я предположил, что это займет TZ = 0 или любое значение по умолчанию, без-TZ ., @Guy . D

Никогда ни о чем не догадывайся. Проблема с этими функциями заключается в том, что они выросли в UNIX (или Linux), где ОС предоставляет такие вещи, как выбранный часовой пояс. Как avr-libc справляется с этими вещами, я понятия не имею., @Majenko

со временем.структура h tm год начинается с 1900 года, а количество мотыльков от 0 до 11., @Juraj

@Juraj, да, это я знаю, но 153-й год, когда мы находимся в 2022 году, кажется немного странным. Кроме того, вычитание нескольких секунд времени загрузки привело к нерациональному изменению результата., @Guy . D


1 ответ


2

Вы предполагаете, что "эпоха" avr-libc совпадает с "эпохой" UNIX. Это не так. Согласно инструкции:

Хотя это и не указано в стандарте, часто ожидается, что time_t - это целое число со знаком, представляющее смещение в секундах от полуночи 1 января 1970 года ... т.е. "время Unix". Эта реализация использует 32-битное целое смещение без знака от полуночи 1 января 2000 года. Использование этой "эпохи" помогает упростить функции преобразования, в то время как 32-битное значение позволяет правильно представить время до Вт 7 февраля 06:28:15 2136 UTC. Макросы UNIX_OFFSET и NTP_OFFSET определены для облегчения преобразования в и из временных меток Unix и NTP.

Поэтому вам нужно вычесть значение UNIX_OFFSET из вашего значения времени, прежде чем передавать его любым функциям avr-libc.

Также вы должны инициализировать систему времени с помощью set_zone() и аналогичных функций.

,