How to make ESP8266 things happen on specific times?

I want to be able to set the time for triggering certain events in my ESP8266.
Currently I am using millis to set an interval as a number of minutes and then I am checking in loop() for millis()-lasttime > interval to execute some event function.
But I want the events to happen on even minutes in time, millis depend on when the ESP was reset...
So I have added the NTP library and I have successfully been able to read back the time from the ESP:

case '3': //Return current NTP time
	#ifdef USE_NTP_TIME
		TimeMsg = NTP.getTimeDateString ();
		strcpy(msg, "Current time= ");
		strcat(msg, TimeMsg.c_str());
	#else
		strcpy(msg, "NTP time undefined");
	#endif
	ReplyCmd(msg, strlen(msg));
	break;

The output on my console is:
Current time = 2018-12-08 13:44:08

How can I use this in loop to activate my event?
For example if I could get the current time in seconds from midnight I could use that...
But how?

The "Time.h" library has some methods that will be helpful. It will also allow you to sync internal (millis-based) time to NTP time so that you only have to go out to NTP periodically to true things up.

13:44:08 = ((((13*60)+44)60)+8)1000 ms this is your offset (in minus so we should deduct it from 24h
=(24
3600
1000) ms anyway you get my drift.

But how do I get the hour, minute, second values? So I can create the offset like that?
What I can do is:

time_t CurrTime = NTP.getTime();

This returns a time_t variable, how can I get the h, m, s values from this?
Presumably I should make a time offset from millis() every new day right after midnight....

Post your full code.

I don't have any code for this yet...
All I have is this NTP setup at the moment:

#ifdef USE_NTP_TIME
    /* The NTP time retrieval needs this: */
    #include <TimeLib.h>
    #include "NtpClientLib.h"
#endif
#ifdef USE_NTP_TIME
    /*************** NTP time retrieval. Uses library NtpClientLib ****************/
    int8_t timeZone = 1;
    int8_t minutesTimeZone = 0;
    bool wifiFirstConnected = false;

    boolean syncEventTriggered = false; // True if a time even has been triggered
    NTPSyncEvent_t ntpEvent; // Last triggered event

    void onSTAConnected (WiFiEventStationModeConnected ipInfo)
    {
        SerialDebug.printf ("Connected to %s\r\n", ipInfo.ssid.c_str ());
    }

    // Start NTP only after IP network is connected, controlled by flag wifiFirstConnected
    void onSTAGotIP (WiFiEventStationModeGotIP ipInfo)
    {
        SerialDebug.printf ("Got IP: %s\r\n", ipInfo.ip.toString ().c_str ());
        //SerialDebug.printf ("Connected: %s\r\n", WiFi.status () == WL_CONNECTED ? "yes" : "no");
        wifiFirstConnected = true;
    }

    void processSyncEvent (NTPSyncEvent_t ntpEvt)
    {
        SerialDebug.print ("Time Sync event");
        switch (ntpEvt)
        {
            case timeSyncd:
                SerialDebug.println (": Time retrieved successfully!");
                break;

            case noResponse:
                SerialDebug.println (" error: NTP server not reachable");
                break;

            case invalidAddress:
                SerialDebug.println (" error: Invalid NTP server address");
                break;
        }
    }

#endif

void HandleNtpClient()
{
    /***************** NTP code here *******************************/
    #ifdef USE_NTP_TIME
        if (wifiFirstConnected) {  //One time execution following WiFi connect
            wifiFirstConnected = false;
            NTP.begin ("pool.ntp.org", timeZone, true, minutesTimeZone);
            NTP.setInterval (60, 86400);    //Initial NTP call repeat 1 min, then 24h between calls
        }

        if (syncEventTriggered) {
            processSyncEvent (ntpEvent);
            syncEventTriggered = false;
        }
    #endif
}

void setup()    //The setup function is called once at startup of the sketch
{
#ifdef USE_NTP_TIME
    /********** NTP code *********************/
    static WiFiEventHandler e1, e2;
    NTP.onNTPSyncEvent ([](NTPSyncEvent_t event) {
        ntpEvent = event;
        syncEventTriggered = true;
    });
    e1 = WiFi.onStationModeGotIP (onSTAGotIP);// As soon WiFi is connected, start NTP Client
    e2 = WiFi.onStationModeConnected (onSTAConnected);
    /*****************************************/
#endif
  //Other setup stuff...
}

void loop()
{
   //Stuff...
    HandleNtpClient();
   //Other stuff...
}

Take a look at the 'TimeNTP_ESP8266WiFi' example in the time library.

Could not make much of it...
But I added a debug command e3 to my sketch like this:

	String TimeMsg = "";
.... 
               case '3': //Return current NTP time
                    #ifdef USE_NTP_TIME
                        time_t CurrTime;
                        CurrTime = NTP.getTime();  //Time
                        ltoa(CurrTime, msg, 10);
                        strcat(msg, " = ");
                        TimeMsg = NTP.getTimeDateString();
                        strcat(msg, TimeMsg.c_str());
                    #else
                        strcpy(msg, "NTP time undefined");
                    #endif
                    ReplyCmd(msg, strlen(msg));
                    break;

When I run the command e3 I get these responses:

1544354241 = 2018-12-09 11:17:20
1544354254 = 2018-12-09 11:17:34
1544354271 = 2018-12-09 11:17:51
1544354345 = 2018-12-09 11:19:05

So the NTP.getTime() seems to get a value that increments by the second...
So now I "just" have to figure out how to calculate the offset to midnight of the returned value...
Seems like rather tedious work to scan the date string for the hour, minute, second items.
Is there not a built-in function to truncate the day part of a time_t value retrieved as shown above?
Integer modulo CurrTime % 84600 maybe?

I actually found all your answers in the TimeSerial example: in the intro it says

/* Messages consist of the letter T followed by ten digit time (as seconds since Jan 1 1970)
 * you can send the text on the next line using Serial Monitor to set the clock to noon Jan 1 2013
 T1357041600 */

Plus other valuable info.

and i made some examples of getting the info you want after syncing to your source

#include <TimeLib.h>

void setup() {
  Serial.begin(9600);
  time_t currtime=1544354345;
  
  Serial.print("Seconds = ");
  Serial.println(second(currtime),DEC);  // extracting seconds from a time_t variable

  setTime(NTP.getTime()); // sync Arduino time to an external source
  currtime=now();         // storing current Arduino time in a variable
  Serial.print("Seconds = ");
  Serial.println(second(currtime),DEC);

  Serial.print("Seconds = ");
  Serial.println(second(),DEC);  // extracting the seconds from current Arduino time.
}

void loop() {
}

Thanks!
I cannot use any of the print functions or similar because I need to get the result into a char array...

But after looking at your examples I came up with this that can help in determining the trigger for the events.

case '3': //Return current NTP time
    #ifdef USE_NTP_TIME
        time_t CurrTime;
        char tmpstr[16];
        int TimSec;
        int TimMin;
        int TimHour;

        TimeMsg = NTP.getTimeDateString();
        CurrTime = now();  //NTP.getTime();  //Time
        TimSec = second(CurrTime);
        TimMin = minute(CurrTime);
        TimHour = hour(CurrTime);
        ltoa(CurrTime, msg, 10);
        strcat(msg, "  ");
        itoa(TimHour, tmpstr, 10);
        strcat(msg, tmpstr);
        strcat(msg, ":");
        itoa(TimMin, tmpstr, 10);
        strcat(msg, tmpstr);
        strcat(msg, ":");
        itoa(TimSec, tmpstr, 10);
        strcat(msg, tmpstr);
        strcat(msg, " = ");
        strcat(msg, TimeMsg.c_str());
    #else
        strcpy(msg, "NTP time undefined");
    #endif
    ReplyCmd(msg, strlen(msg));
    break;

It produced this result in my control application for two commands:

=> e3
<= 1544367069 = 14:51:9 = 2018-12-09 14:51:09
=> e3
<= 1544367076 = 14:51:16 = 2018-12-09 14:51:16

So I replaced the NTP.getTime() with just now() and using the functions second minute and hour I got the conversions to be as wanted. The remaining stuff is only for building the reply string.

I tried to be clever and use the same time_t value for all output but this failed:

        CurrTime = now();  //Time
        TimeMsg = NTP.getTimeDateString(CurrTime);

Using CurrTime as an argument to NTP.getTimeDateString() resulted in getting to 2036!

<= 2085982132  7:28:52 = 2036-02-07 07:28:52

So I restored the sequence as shown above and it works.

Now I will stuff this into loop in some clever way to control task event execution.
Thanks again.