0

Why do I get wrong result when using time.h library when using AVR boards, such Nano/Uno/Pro Micro (while when using TimeLib.h).

OUTPUT (for given Epoch ):

TimeLib: 2022-04-02 16:11:20

time.h: 0152-03-01 16:11:20

CODE:

#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: }

guyd
  • 1,033
  • 2
  • 16
  • 51
  • 1
    localtime() requires a timezone to be set. No idea how you set that. Use gmtime() instead to get the UTC (GMT) time which has no timezone. – Majenko Apr 03 '22 at 11:33
  • well for that, I guessed it'll take TZ=0, or any default, no-TZ value. – guyd Apr 03 '22 at 12:01
  • Never guess anything. The problem with these functions is they grew up on UNIX (or Linux) where the OS provides things like the selected timezone. How avr-libc handles these things I have no clue. – Majenko Apr 03 '22 at 12:05
  • 1
    in time.h tm struct the year starts in 1900 and the moths are 0 to 11. – Juraj Apr 03 '22 at 12:14
  • @Juraj, yes- that I know, but year 153 while we are 2022, strikes a bit odd. Also subtracting few seconds bootTime, yielded a non rational change in result. – guyd Apr 03 '22 at 12:22

1 Answers1

2

You are assuming the avr-libc "epoch" is the same as the UNIX "epoch". It isn't. According to the manual:

Though not specified in the standard, it is often expected that time_t is a signed integer representing an offset in seconds from Midnight Jan 1 1970... i.e. 'Unix time'. This implementation uses an unsigned 32 bit integer offset from Midnight Jan 1 2000. The use of this 'epoch' helps to simplify the conversion functions, while the 32 bit value allows time to be properly represented until Tue Feb 7 06:28:15 2136 UTC. The macros UNIX_OFFSET and NTP_OFFSET are defined to assist in converting to and from Unix and NTP time stamps.

So you need to subtract the UNIX_OFFSET from your time value before passing it to any avr-libc functions.

Also you should initialize the time system with set_zone() and similar functions.

Majenko
  • 105,095
  • 5
  • 79
  • 137