1

Can anyone provide a sample code that would convert a human readable date like 2019-10-27 22:10:35 to a unix timestamp like 1572214235?

I found many topics about it, but they eider refer to out of date libraries, or they seem to address more complex time functions, I find it hard to extract this functionality from them.

0

2 Answers 2

2

If you have a fixed format you can use strtok() to slice the string into individual segments, then convert those segments to integers. They can then be used with TimeLib.h with the setTime() function. You can then query TimeLib for the unix timestamp with now().

Edit: using PaulStoffregen's TimeLib, this code sets current time and returns current unix timestamp.

#include <TimeLib.h>

void setup() {
  Serial.begin(9600);

  // hour, min, sec, day, month, year
  setTime(22, 30, 11, 29, 3, 2019);

  // 1553898611
  Serial.println(now());
}
void loop() {}

Edit 2: And to convert any given date to a unix timestamp (without setting current time):

#include "TimeLib.h"

tmElements_t my_time;  // time elements structure
time_t unix_timestamp; // a timestamp

void setup() {
  Serial.begin(9600);

  // convert a date and time into unix time, offset 1970
  my_time.Second = 0;
  my_time.Hour = 23;
  my_time.Minute = 0;
  my_time.Day = 25;
  my_time.Month = 3 - 1;      // months start from 0, so deduct 1
  my_time.Year = 2017 - 1970; // years since 1970, so deduct 1970

  unix_timestamp =  makeTime(my_time);
  Serial.println(unix_timestamp);
}

void loop() {}
4
  • I already have them into separate values like year, month, etc, I just have no clue on how the code should look when using the time library. I am new to Arduino.
    – adrianTNT
    Commented Oct 28, 2019 at 14:17
  • Pass the values to setTime() - I forget the order, but I think it's setTime(hours, minutes, seconds, year, month, day) - though check the documentation or source to be sure. Then you get the time since the unix epoch with now().
    – Majenko
    Commented Oct 28, 2019 at 14:19
  • Thanks, I was able to do that and added a full sample code in your answer, I still need a way to convert any given date (not just current time).
    – adrianTNT
    Commented Oct 28, 2019 at 15:11
  • I hope you don't mind, I altered a code once more so I am able to select your answer as the correct one :D
    – adrianTNT
    Commented Oct 28, 2019 at 20:53
2

After parsing the time into numbers, you can use the standard C time library time.h. More specifically, use the mktime function to convert a struct tm into a time_t, and use difftime to get the seconds since the start of the Unix expoch:

#include <time.h>

void loop() {
    struct tm ltm = {0};
    ltm.tm_year = 2019 - 1900;
    ltm.tm_mon  = 11 - 1;
    ltm.tm_mday = 5;

    int32_t epoch_seconds = difftime(mktime(&ltm), (time_t)0);
    Serial.print("Remember, remember, ");
    Serial.print(epoch_seconds);
}

Note that in struct tm, the year starts at 1900 and the month starts at 0.

EDIT: In avr-libc, difftime returns an int32_t, not a double.

9
  • So I replace 2019 with my year and I leave/append the ` -1900` part, same for month, then where do I specify the hour, minute and second ?
    – adrianTNT
    Commented Oct 27, 2019 at 16:40
  • @adrianTNT Yes, you can use tm_hour, tm_min and tm_sec to specify hours, minutes and seconds, respectively. The available fields of struct tm are linked in the reference. Cf. en.cppreference.com/w/c/chrono/tm
    – Heinrich
    Commented Oct 27, 2019 at 20:58
  • I tried the code, seems close but I get a timestamp like 626227200.00 which (without .00) is around 1989, I am lost.
    – adrianTNT
    Commented Oct 28, 2019 at 14:13
  • Serial.print might have some trouble printing double-precision floats. Does it work when you change it to Serial.print((float)epoch_seconds, 0);? This should also cut off the '.00' decimal places at the end.
    – Heinrich
    Commented Oct 28, 2019 at 14:32
  • 1
    Note that: 1. mktime() interprets the time as being in the local time zone, which on AVR is UTC until you change it with set_zone()/set_dst(). 2. avr-libc uses the epoch 2000-01-01. If you want a Unix timestamp, you should use mktime(&ltm) + UNIX_OFFSET. Commented Jan 8, 2023 at 10:34

Not the answer you're looking for? Browse other questions tagged or ask your own question.