Strftime to useable variables

Hi knowledgeable ones,
I have been struggling to solve this for over a week now and searched hundreds of topics but yet to find a solution.
I have a datalogging program that works fine. I thought I would enhance it by appending a header at midnight, I have included NTP protocol and get time from it. But I cannot find a way of extracting Hour, minutes and seconds to put into an 'if' statement.
I have the section of code that reflects my problem, if I can get this working with your help I can incorporate it into my main program.
I have highlighted where I fail in the code below.
When trying to compile the error statement is "c++ forbids comparison between pointer and integer [-fpermissive]" So I need to extract or covert the data from the array at that point.

Thanks for your help
Dave



#include <Arduino.h>
#include <WiFi.h>
#include <AsyncTCP.h>
#include <ESPAsyncWebServer.h>
#include "FS.h"
#include "SD.h"
#include "SPI.h"
#include "time.h"


// Replace with your network credentials
const char* ssid = "ssid";
const char* ssid = "password";

const char* ntpServer = "pool.ntp.org";
const long  gmtOffset_sec = 0;
const int   daylightOffset_sec = 3600;

void setup() {
  Serial.begin(9600);
  Serial.println("Initiaiase WiFi");

  WiFi.mode(WIFI_STA);
  WiFi.begin(ssid, password);
  Serial.print("Connecting to WiFi ..");
  while (WiFi.status() != WL_CONNECTED) {
    Serial.print('.');
    delay(1000);
  }
  Serial.println(WiFi.localIP());
  long rssi = WiFi.RSSI();
  Serial.print("RSSI:");
  Serial.println(rssi);

  configTime(gmtOffset_sec, daylightOffset_sec, ntpServer);

  struct tm timeinfo;
  if (!getLocalTime(&timeinfo)) {
    Serial.println("Failed to obtain time");
    return;
  }
  Serial.println(&timeinfo, "%A, %B %d %Y %H:%M:%S");
  }

void loop() {
  struct tm timeinfo;
  if (!getLocalTime(&timeinfo)) {
    Serial.println("Failed to obtain time");
    return;
  }
  Serial.println(&timeinfo, "%A, %B %d %Y %H:%M:%S");
  char output_hours [3];
  strftime(output_hours, 3, "%H", &timeinfo);
  char output_minutes [3];
  strftime(output_minutes, 3, "%M", &timeinfo);
  char output_seconds [3];
  strftime(output_seconds, 3, "%S", &timeinfo);
  Serial.print("output_hours = ");
  Serial.println(output_hours);
  Serial.print("output_Minutes = ");
  Serial.println(output_minutes);
  Serial.print("output_Seconds = ");
  Serial.println(output_seconds);
  delay(1000);

  //////***********Everything works up to this point
  ///// What I want to do now is something like this
  if  (output_hours == 00) {
    do something like
      Serial.println("Success");
  }
  else {
    Serial.println("Failure");
  }
}

are you using an ESP32 ?

You do

  struct tm timeinfo;
  if (!getLocalTime(&timeinfo)) {
    Serial.println("Failed to obtain time");
    return;
  }

and a struct tm looks like this

    struct tm {
        int8_t          tm_sec; /**< seconds after the minute - [ 0 to 59 ] */
        int8_t          tm_min; /**< minutes after the hour - [ 0 to 59 ] */
        int8_t          tm_hour; /**< hours since midnight - [ 0 to 23 ] */
        int8_t          tm_mday; /**< day of the month - [ 1 to 31 ] */
        int8_t          tm_wday; /**< days since Sunday - [ 0 to 6 ] */
        int8_t          tm_mon; /**< months since January - [ 0 to 11 ] */
        int16_t         tm_year; /**< years since 1900 */
        int16_t         tm_yday; /**< days since January 1 - [ 0 to 365 ] */
        int16_t         tm_isdst; /**< Daylight Saving Time flag */
    };

so if your struct is correct, then it's quite easy to get the hour or minute etc

I note that your code as posted will not compile because of

const char* ssid = "ssid";
const char* ssid = "password";

I assume that you meant

const char* ssid = "ssid";
const char* password = "password";

Here is a demo-code that shows how it can be done
some home-WLAN-Routers can be used as a NTP-server too
At least WLAN-Routers from AVM called Fritz!Box

#include <WiFi.h>

unsigned long MyTestTimer = 0;                   // variables MUST be of type unsigned long
const byte    OnBoard_LED = 2;

//const char *ssid     = ""; 
const   char *ssid     = "";

const char *password = "";

// a lot of home-wlan-routers can be used as a NTP-server too
const char* ntpServer = "fritz.box"; 
const long  gmtOffset_sec = 0;
const int   daylightOffset_sec = 7200;

#include <time.h>                   // time() ctime()
time_t now;                         // this is the epoch
tm myTimeInfo;                      // the structure tm holds time information in a more convient way

void showTime() {
  time(&now);                       // read the current time
  localtime_r(&now, &myTimeInfo);           // update the structure tm with the current time
  Serial.print("year:");
  Serial.print(myTimeInfo.tm_year + 1900);  // years since 1900
  Serial.print("\tmonth:");
  Serial.print(myTimeInfo.tm_mon + 1);      // January = 0 (!)
  Serial.print("\tday:");
  Serial.print(myTimeInfo.tm_mday);         // day of month
  Serial.print("\thour:");
  Serial.print(myTimeInfo.tm_hour);         // hours since midnight  0-23
  Serial.print("\tmin:");
  Serial.print(myTimeInfo.tm_min);          // minutes after the hour  0-59
  Serial.print("\tsec:");
  Serial.print(myTimeInfo.tm_sec);          // seconds after the minute  0-61*
  Serial.print("\twday");
  Serial.print(myTimeInfo.tm_wday);         // days since Sunday 0-6
  if (myTimeInfo.tm_isdst == 1)             // Daylight Saving Time flag
    Serial.print("\tDST");
  else
    Serial.print("\tstandard");
    
  Serial.println();
}

void connectToWifi() {
  Serial.print("Connecting to "); 
  Serial.println(ssid);

  WiFi.persistent(false);
  WiFi.mode(WIFI_STA);

  WiFi.begin(ssid, password);

  while (WiFi.status() != WL_CONNECTED) {
    BlinkHeartBeatLED(OnBoard_LED, 333);
    delay(332);
    Serial.print(".");
  }
  Serial.print("\n connected.");
  Serial.println(WiFi.localIP() );

}

void synchroniseWith_NTP_Time() {
  Serial.print("configTime uses ntpServer ");
  Serial.println(ntpServer);
  configTime(gmtOffset_sec, daylightOffset_sec, ntpServer);
  Serial.print("synchronising time");
  
  while (myTimeInfo.tm_year + 1900 < 2000 ) {
    time(&now);                       // read the current time
    localtime_r(&now, &myTimeInfo);
    BlinkHeartBeatLED(OnBoard_LED, 100);
    delay(100);
    Serial.print(".");
  }
  Serial.print("\n time synchronsized \n");
  showTime();    
}


void PrintFileNameDateTime() {
  Serial.println( F("Code running comes from file ") );
  Serial.println(__FILE__);
  Serial.print( F("  compiled ") );
  Serial.print(__DATE__);
  Serial.print( F(" ") );
  Serial.println(__TIME__);  
}

boolean TimePeriodIsOver (unsigned long &periodStartTime, unsigned long TimePeriod) {
  unsigned long currentMillis  = millis();  
  if ( currentMillis - periodStartTime >= TimePeriod )
  {
    periodStartTime = currentMillis; // set new expireTime
    return true;                // more time than TimePeriod) has elapsed since last time if-condition was true
  } 
  else return false;            // not expired
}


void BlinkHeartBeatLED(int IO_Pin, int BlinkPeriod) {
  static unsigned long MyBlinkTimer;
  pinMode(IO_Pin, OUTPUT);
  
  if ( TimePeriodIsOver(MyBlinkTimer,BlinkPeriod) ) {
    digitalWrite(IO_Pin,!digitalRead(IO_Pin) ); 
  }
}


void setup() {
  Serial.begin(115200);
  Serial.println("\n Setup-Start \n");
  PrintFileNameDateTime();
  
  connectToWifi();
  synchroniseWith_NTP_Time();
}

void loop() {
  BlinkHeartBeatLED(OnBoard_LED,100);

  if ( TimePeriodIsOver(MyTestTimer,1000) ) {
    showTime();    
  }  
}

best regards Stefan

sorry yes I'm using an ESP32

sorry UKHeliBob my typo when removing my credentials

just get the data from the struct

Thats exactly what I am trying to do but I cannot get it to work, hence the question

If you don’t get an error message from

struct tm timeinfo;
  if (!getLocalTime(&timeinfo)) {
    Serial.println("Failed to obtain time");
    return;
  }

Then do a

Serial.print("hour="); Serial.println(timeinfo.tm_hour);
Serial.print("minute="); Serial.println(timeinfo.tm_min);

And you should see the time

thanks, I can print time as you have shown but I what I want to do is:

if (hour == 00 && minutes ==00) {
  do something
}

so I want to extract the hour etc from the structure and store it as a normal variable
any ideas

PLEASE use code tags when posting code (edit your post #10 and add code tags)

You need to read about structures.

you don't need an additional variable, the variable is timeinfo and it holds the data in its attributes timeinfo.tm_hour and timeinfo.tm_min...

you can do

if ((timeinfo.tm_hour == 0) && (timeinfo.tm_min == 0)) {
  ... // do something here
}

note that you'll be at midnight for a whole minute so if it's just like this in the loop(), you will do this many thousands times possibly as the condition will be true for 60,000,000µs

1 Like
if(hour == 00 && minutes ==00)

If you can print timeinfo.tm_hour then why not use it when you want to test the value of the hour ?

because I hadn't thought of it
Thanks I will try it

Thanks for the info, I hadn't thought of doing it that way, I intend to narrow the time down but just using hours and minutes as an example

If you want to assign it to a variable anyway you have to find out what the datatype of

.tm_hour
.tm_min

is.
This is done this way:

looking up what is the filename of the library where the "time-Data" is defined
in this case this is
#include <time.h>

So you search on your harddisk for the filename "time.h"
make a copy of that file to make sure that some accidently happened changes do not affect the original file
after making a copy of the file open the copy
time copy.h with the arduino-IDE or any other texteditor like Notepad++ or editor.exe

".tm_hour" means the "variable is part of a "struct" with name "tm"

and voila there are the datatypes

    struct tm {
        int8_t          tm_sec; /**< seconds after the minute - [ 0 to 59 ] */
        int8_t          tm_min; /**< minutes after the hour - [ 0 to 59 ] */
        int8_t          tm_hour; /**< hours since midnight - [ 0 to 23 ] */
        int8_t          tm_mday; /**< day of the month - [ 1 to 31 ] */
        int8_t          tm_wday; /**< days since Sunday - [ 0 to 6 ] */
        int8_t          tm_mon; /**< months since January - [ 0 to 11 ] */
        int16_t         tm_year; /**< years since 1900 */
        int16_t         tm_yday; /**< days since January 1 - [ 0 to 365 ] */
        int16_t         tm_isdst; /**< Daylight Saving Time flag */
    };

tm_hour, tm_min are all uint8_t which is basically the same as "byte"

so if you define variables like

byte myHour;
byte myMin;

or

int myHour;
int  myMin;

you can assign the values

myHour = timeinfo.tm_hour;
myMin = timeinfo.tm_min;

for compairing several timepoints of a day this becomes easier if you calculate
minutesOfDay or SecondsOfDay

int minutesOfDay = timeinfo.tm_hour * 60 + timeinfo.tm_min;
long SecondsOfDay = timeinfo.tm_hour * 3600 + timeinfo.tm_min * 60 + timeinfo.tm_sec;

SecondsOfDay requires a long because
233600 + 5960 + 59 = 86399 which is more than an int 16 bit = +-32676 can hold

This reduces the coparison to a single variable and later always means a simple "bigger as"
best regards Stefan

1 Like

if you want any more support from me, or just as respect for the forum principles please add code tags to your post #10...

if you don't know how, read How to get the best out of this forum and modify your post accordingly

Or in this case you could look in post #2 in this topic :grinning:

Hi J-M-L
Thanks very much for your info, really helpful as are the others who have posted.
I was looking to see how to add code tags to my earlier post when your reply arrived and hopefully I can amend it. Thanks

was not quite that so I did it for you for this time.

@StefanL38 has posted a very detailed explanation about code tags, you can read this

Thanks very much
I am very new to this coding and I am learning as I go along.
I am a retired Instrumentation guy, hardware has been my life and now I trying coding as a hobby.
I managed to post my original code as per the guidelines, just didn't think about it in my replies.
but you are never to old to learn
Thanks