Why do you use
MMDDYYYY hhmmss format?
ISO 8601 defined
YYYY-MM-DD hh:mm:ss (although 8601-1:2019 made the T prefix for time mandatory for some reason, making it
YYYY-MM-DDT
hh:mm:ss which I do not recommed).
The reason the
YYYY-MM-DD hh:mm:ss is superior is that not only is it unambiguous, it is internationally known; but most importantly, it sorts correctly without any extra work. (A plain ASCII/ISO Latin/Windows 457/1252/Unicode/UTF-8 sort will sort them correctly.)
Furthermore, if your date and time fields may have extra flag bits, use the
& (binary and) operator to pick only the useful bits, and emit them as unsigned integers:
// minimum size for dtbuf is 4+1+2+1+2+1+2+1+2+1+2 +1 = 20 chars
snprintf(dtbuf, sizeof dtbuf, "%04u-%02u-%02u %02u:%02u:%02u",
(boot_time.tm_year & 4095) + 1900,
(boot_time.tm_mon & 15) + 1,
(boot_time.tm_mday & 31),
(boot_time.tm_hour & 31),
(boot_time.tm_min & 63),
(boot_time.tm_sec & 63));
(I don't recall the exact details, but I believe there may have been some RTC chips where one of the fields' most significant bit acted as a user-DST flag or something. I do not think that is the case here, though.)
As pointed out above by nctnico, snprintf() always terminates the buffer with a nul char (
\0 - that's what the final +1 is in the dtbuf size calculation). If the string does not fit the given buffer, it will simply terminate it early, and return the actual number of chars it would have stored if there had been room (but excluding the final nul char, so you actually need room for one more).
The above code, assuming a sane snprintf() implementation, will never cause a buffer overrun; not even if you accidentally or on purpose change the size of the
dtbuf array. In your own version, there is a risk, if you reduce the size of the array to below 16, but forget to update the size in the snprintf() correspondingly.