Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Convert string from __DATE__ into a time_t

I'm trying to convert the string produced from the __DATE__ macro into a time_t. I don't need a full-blown date/time parser, something that only handles the format of the __DATE__ macro would be great.

A preprocessor method would be nifty, but a function would work just as well. If it's relevant, I'm using MSVC.

like image 238
tfinniga Avatar asked Nov 19 '09 17:11

tfinniga


People also ask

What is Time_t Arduino?

In Arduino, time_t is simply an unsigned long (32 bit) variable that stores the number of seconds since a particular date and time (called an epoch).


2 Answers

Edit: the corrected function should look something like this:

time_t cvt_TIME(char const *time) { 
    char s_month[5];
    int month, day, year;
    struct tm t = {0};
    static const char month_names[] = "JanFebMarAprMayJunJulAugSepOctNovDec";

    sscanf(time, "%s %d %d", s_month, &day, &year);

    month = (strstr(month_names, s_month)-month_names)/3;

    t.tm_mon = month;
    t.tm_mday = day;
    t.tm_year = year - 1900;
    t.tm_isdst = -1;

    return mktime(&t);
}
like image 100
Jerry Coffin Avatar answered Sep 28 '22 10:09

Jerry Coffin


I don't know if any other Arduino hackers will stumble upon this question, but I found @JerryCoffin's answer to be quite helpful in solving this problem for my project. Here is a complete example you can paste into Arduino. It uses the Time lib referenced here.

#include "Arduino.h"
#include <Time.h>
#include <stdio.h>

time_t cvt_date(char const *date) { 
    char s_month[5];
    int month, day, year;
    tmElements_t tmel;
    static const char month_names[] = "JanFebMarAprMayJunJulAugSepOctNovDec";

    sscanf(date, "%s %d %d", s_month, &day, &year);

    month = (strstr(month_names, s_month)-month_names)/3+1;

    tmel.Hour = tmel.Minute = tmel.Second = 0; // This was working perfectly until 3am then broke until I added this.
    tmel.Month = month;
    tmel.Day = day;
 // year can be given as full four digit year or two digts (2010 or 10 for 2010);
 //it is converted to years since 1970
  if( year > 99)
      tmel.Year = year - 1970;
  else
      tmel.Year = year + 30;

    return makeTime(tmel);
}

void printdate(char const *date)
{
  Serial.println((String)"cvt_date('" + date + "')");
  time_t t = cvt_date(date);

  Serial.println((String) month(t) + "-" + day(t) + "-" + year(t));
  setTime(t);
  Serial.println((String) month()  + "/" + day()  + "/" + year() + "\n");
}

void setup()
{
  Serial.begin(9600); while (!Serial);
  printdate(__DATE__);       // works with the compiler macro
  printdate("Jan  1    00"); // works with 2 digit years
  printdate("Feb  28   01");
  printdate("Mar  7 5");     // works with 1 digit years
  printdate("Apr  10 1970"); // works from 1970
  printdate("May  13 1980");
  printdate("Jun  16 1990");
  printdate("Jul  19 1997");
  printdate("Aug  22 2000");
  printdate("Sep  25 2010");
  printdate("Oct  31 2014");
  printdate("Nov  30 2020");
  printdate("Dec  31 2105"); // through 2105
  printdate("Dec  31 2106"); // fails at and after 2106
}

void loop(){
}

Here are the Serial Terminal results...

cvt_date('Oct  5 2014')
10-5-2014
10/5/2014

cvt_date('Jan  1    00')
1-1-2000
1/1/2000

cvt_date('Feb  28   01')
2-28-2001
2/28/2001

cvt_date('Mar  7 5')
3-7-2005
3/7/2005

cvt_date('Apr  10 1970')
4-10-1970
4/10/1970

cvt_date('May  13 1980')
5-13-1980
5/13/1980

cvt_date('Jun  16 1990')
6-16-1990
6/16/1990

cvt_date('Jul  19 1997')
7-19-1997
7/19/1997

cvt_date('Aug  22 2000')
8-22-2000
8/22/2000

cvt_date('Sep  25 2010')
9-25-2010
9/25/2010

cvt_date('Oct  31 2014')
10-31-2014
10/31/2014

cvt_date('Nov  30 2020')
11-30-2020
11/30/2020

cvt_date('Dec  31 2105')
12-31-2105
12/31/2105

cvt_date('Dec  31 2106')
11-23-1970
11/23/1970

If all you want is to use the __DATE__ and you don't need a time_t or tmElements_t object, the code can be much simpler.

void logname(char const *date, char *buff) { 
    int month, day, year;
    static const char month_names[] = "JanFebMarAprMayJunJulAugSepOctNovDec";
    sscanf(date, "%s %d %d", buff, &day, &year);
    month = (strstr(month_names, buff)-month_names)/3+1;
    sprintf(buff, "%d%02d%02d.txt", year, month, day);
}

void setup()
{
  Serial.begin(9600); while (!Serial);
  Serial.print("log file name: ");
  char filename[16];
  logname(__DATE__, filename);
  Serial.println(filename);
}

void loop(){
}

Here are the Serial Terminal results...

log file name: 20141009.txt
like image 35
Bruno Bronosky Avatar answered Sep 28 '22 11:09

Bruno Bronosky