In this guide, we’ll show you how to get date and time using the ESP32 or ESP8266 to run one or multiple tasks every day at an exact time. For this application, your ESP boards will get the time using Network Time Protocol (NTP), so they must be connected to the Internet. The ESP boards will be programmed using Arduino IDE.

Prerequisites
Before proceeding make sure you have the ESP32 or ESP8266 boards add-on installed in Arduino IDE:
- Installing ESP32 Board in Arduino IDE 2 (Windows, Mac OS X, Linux)
- Installing ESP8266 NodeMCU Board in Arduino IDE 2 (Windows, Mac OS X, Linux)
For this tutorial, you only need an ESP32 or an ESP8266 board:
NTP (Network Time Protocol)
To get track of time, we’ll be using NTP. NTP stands for Network Time Protocol and it is a networking protocol for clock synchronization between computer systems. In other words, it is used to synchronize computer clock times in a network.
There are NTP servers like pool.ntp.org that anyone can use to request time as a client. In this case, the ESP32/ESP8266 is an NTP Client that requests time from an NTP Server (pool.ntp.org).

If you want to learn more about NTP Client-Server interaction with the ESP boards, you can read the following guides:
- ESP32 NTP Client-Server: Get Date and Time (Arduino IDE)
- ESP8266 NodeMCU NTP Client-Server: Get Date and Time (Arduino IDE)
For this guide you’ll be using the default time.h library that comes with the Arduino framework so you don’t need to install additional libraries.
ESP32/ESP8266 Run Daily Task at Specific Time – Code
To get date and time with the ESP boards, you don’t need to install any libraries. You simply include the time.h library in your code.
The following code gets date and time from the NTP Server, prints the results on the Serial Monitor, and checks if the daily task has run or not.
/*
Rui Santos & Sara Santos - Random Nerd Tutorials
https://RandomNerdTutorials.com/esp32-esp8266-run-daily-task/
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files.
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
*/
#include <Arduino.h>
#if defined(ESP32)
#include <WiFi.h>
#elif defined(ESP8266)
#include <ESP8266WiFi.h>
#endif
#include <time.h>
// Replace with your network credentials
const char* ssid = "REPLACE_WITH_YOUR_SSID";
const char* password = "REPLACE_WITH_YOUR_PASSWORD";
// Timezone string for your region, example: https://github.com/nayarsystems/posix_tz_db/blob/master/zones.csv
const char* timezone = "WET0WEST,M3.5.0/1,M10.5.0"; // WET0WEST,M3.5.0/1,M10.5.0 = Europe/Lisbon
// Time that the daily task runs in 24 hour format
const int taskHour = 16; // Hour example in 24 hour format: 16 = 4 PM
const int taskMinute = 5; // 5 minutes
// Store the day when the task last ran to ensure it only runs once per day
int lastRunDay = -1;
unsigned long lastNTPUpdate = 0; // Timestamp for the last NTP sync
const unsigned long ntpSyncInterval = 30 * 60 * 1000; // Sync every 30 minutes (in ms)
void syncTime() {
Serial.print("Synchronizing time with NTP server...");
configTime(0, 0, "pool.ntp.org", "time.nist.gov"); // UTC offset set to 0
time_t now = time(nullptr);
while (now < 24 * 3600) { // Wait until time is valid
delay(100);
now = time(nullptr);
}
Serial.println(" Time synchronized!");
// Set timezone
setenv("TZ", timezone, 1);
tzset();
lastNTPUpdate = millis(); // Record the time of the last sync
}
void setup() {
Serial.begin(115200);
// Connect to Wi-Fi
Serial.print("Connecting to ");
Serial.println(ssid);
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}
Serial.println("");
Serial.println("WiFi connected.");
syncTime();
}
void loop() {
time_t now = time(nullptr);
struct tm timeinfo;
localtime_r(&now, &timeinfo);
// Current time and date
Serial.printf("Current time: %02d:%02d:%02d, Date: %04d-%02d-%02d\n",
timeinfo.tm_hour, timeinfo.tm_min, timeinfo.tm_sec,
timeinfo.tm_year + 1900, timeinfo.tm_mon + 1, timeinfo.tm_mday);
// Check if it's time to run the daily task
if (timeinfo.tm_hour == taskHour && timeinfo.tm_min == taskMinute && lastRunDay != timeinfo.tm_mday) {
dailyTask();
// Set the day to ensure it only runs once per day
lastRunDay = timeinfo.tm_mday;
}
// Resynchronize with NTP every 30 minutes
if (millis() - lastNTPUpdate > ntpSyncInterval) {
syncTime();
}
delay(1000); // Run loop every second
}
void dailyTask() {
Serial.println("#########\nDoing daily task...\n#########");
// ENTER YOUR TASK HERE
}
How the Code Works
Let’s take a quick look at the code to see how it works. First, include the libraries to connect to Wi-Fi and get time.
#include <Arduino.h>
#if defined(ESP32)
#include <WiFi.h>
#elif defined(ESP8266)
#include <ESP8266WiFi.h>
#endif
#include <time.h>
Setting SSID and Password
Type your network credentials in the following variables, so that the ESP32/ESP8266 is able to establish an Internet connection and get date and time from the NTP server.
// Replace with your network credentials
const char* ssid = "REPLACE_WITH_YOUR_SSID";
const char* password = "REPLACE_WITH_YOUR_PASSWORD";
Set timezone Variable
Then, you need to define the timezone variable to retrieve the correct time for your location.
const char* timezone = "WET0WEST,M3.5.0/1,M10.5.0";
For example, I live in Porto. The time zone is Europe/Lisbon. From the list of time zone string variables, I see that the time zone string variable for my location is WET0WEST,M3.5.0/1,M10.5.0. You can check a list of time zone string variables here.
Set the Hour and Minute the Task Runs
Set the hour and minute you want your daily task to run. The time for the daily task is set in 24-hour format, so the taskHour set to 16 refers to 4 PM.
const int taskHour = 16;
const int taskMinute = 5;
Other Variables
Store the day when the task last ran to ensure it only runs once a day:
int lastRunDay = -1;
Timestamp for the last NTP sync and how often you want to sync your time with the NTP server:
unsigned long lastNTPUpdate = 0;
const unsigned long ntpSyncInterval = 30 * 60 * 1000; // Sync every 30 minutes (in ms)
setup()
In the setup() you initialize the Serial communication at baud rate 115200 to print the results:
Serial.begin(115200);
These next lines connect the ESP board to your router to establish an Internet connection.
// Connect to Wi-Fi
Serial.print("Connecting to ");
Serial.println(ssid);
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}
Serial.println("");
Serial.println("WiFi connected.");
Finally, call the syncTime() function to synchronize your board with the NTP server.
syncTime();
syncTime()
The syncTime() function connects to the NTP server, retrieves the date and time, and updates the time with the correct time zone defined earlier.
void syncTime() {
Serial.print("Synchronizing time with NTP server...");
configTime(0, 0, "pool.ntp.org", "time.nist.gov"); // UTC offset set to 0
time_t now = time(nullptr);
while (now < 24 * 3600) { // Wait until time is valid
delay(100);
now = time(nullptr);
}
Serial.println(" Time synchronized!");
// Set timezone
setenv("TZ", timezone, 1);
tzset();
lastNTPUpdate = millis(); // Record the time of the last sync
}
loop()
In the loop() we prepare the time and date variables. We also print the variables in the Serial Monitor for debugging purposes:
time_t now = time(nullptr);
struct tm timeinfo;
localtime_r(&now, &timeinfo);
// Current time and date
Serial.printf("Current time: %02d:%02d:%02d, Date: %04d-%02d-%02d\n",
timeinfo.tm_hour, timeinfo.tm_min, timeinfo.tm_sec,
timeinfo.tm_year + 1900, timeinfo.tm_mon + 1, timeinfo.tm_mday);
This part of the code checks if it’s the exact time to run the daily task:
if (timeinfo.tm_hour == taskHour && timeinfo.tm_min == taskMinute && lastRunDay != timeinfo.tm_mday) {
dailyTask();
// Set the day to ensure it only runs once per day
lastRunDay = timeinfo.tm_mday;
}
Finally, check if 30 minutes have passed, if that’s true it’s required to sync the time. We also add a delay to run the loop every second.
// Resynchronize with NTP every 30 minutes
if (millis() - lastNTPUpdate > ntpSyncInterval) {
syncTime();
}
delay(1000); // Run loop every second
dailyTask()
You can modify the dailyTask() function to add the desired code for your project that executes at the specified time:
void dailyTask() {
Serial.println("#########\nDoing daily task...\n#########");
// ENTER YOUR TASK HERE
}
Note: You can apply the same logic using an external RTC module if you don’t have access to the internet or if you don’t want to rely on the ESP32/ESP8266 internal clock. You can use a DS3231 or DS1307 RTC module.
Demonstration
At the moment the code is only printing a message in the Arduino IDE Serial Monitor when the task runs. You should modify the code to perform any other useful task. Here’s an example of how it should look like:

ESP32/ESP8266 Run Multiple Daily Tasks – Code
Based on the previous example, you can duplicate some sections of the code to run multiple daily tasks at a specific time of day. Basically, you add two target times and check whether each task has already run for the current day using two variables. Here’s the full example:
/*
Rui Santos & Sara Santos - Random Nerd Tutorials
https://RandomNerdTutorials.com/esp32-esp8266-run-daily-task/
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files.
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
*/
#include <Arduino.h>
#if defined(ESP32)
#include <WiFi.h>
#elif defined(ESP8266)
#include <ESP8266WiFi.h>
#endif
#include <time.h>
// Replace with your network credentials
const char* ssid = "REPLACE_WITH_YOUR_SSID";
const char* password = "REPLACE_WITH_YOUR_PASSWORD";
// Timezone string for your region, example: https://github.com/nayarsystems/posix_tz_db/blob/master/zones.csv
const char* timezone = "WET0WEST,M3.5.0/1,M10.5.0"; // WET0WEST,M3.5.0/1,M10.5.0 = Europe/Lisbon
// Time that the daily task runs in 24 hour format
const int task1Hour = 8; // Task 1 at 8:15 AM
const int task1Minute = 15;
const int task2Hour = 18; // Task 2 at 6:45 PM
const int task2Minute = 45;
// Store the day when the task last ran to ensure it only runs once per day
int lastRunDayTask1 = -1;
int lastRunDayTask2 = -1;
unsigned long lastNTPUpdate = 0; // Timestamp for the last NTP sync
const unsigned long ntpSyncInterval = 30 * 60 * 1000; // Sync every 30 minutes (in ms)
void syncTime() {
Serial.print("Synchronizing time with NTP server...");
configTime(0, 0, "pool.ntp.org", "time.nist.gov"); // UTC offset set to 0
time_t now = time(nullptr);
while (now < 24 * 3600) { // Wait until time is valid
delay(100);
now = time(nullptr);
}
Serial.println(" Time synchronized!");
// Set timezone
setenv("TZ", timezone, 1);
tzset();
lastNTPUpdate = millis(); // Record the time of the last sync
}
void setup() {
Serial.begin(115200);
// Connect to Wi-Fi
Serial.print("Connecting to ");
Serial.println(ssid);
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}
Serial.println("");
Serial.println("WiFi connected.");
syncTime();
}
void loop() {
time_t now = time(nullptr);
struct tm timeinfo;
localtime_r(&now, &timeinfo);
// Current time and date
Serial.printf("Current time: %02d:%02d:%02d, Date: %04d-%02d-%02d\n",
timeinfo.tm_hour, timeinfo.tm_min, timeinfo.tm_sec,
timeinfo.tm_year + 1900, timeinfo.tm_mon + 1, timeinfo.tm_mday);
// Check if it's time to run the daily task #1
if (timeinfo.tm_hour == task1Hour && timeinfo.tm_min == task1Minute && lastRunDayTask1 != timeinfo.tm_mday) {
dailyTask1();
// Set the day to ensure it only runs once per day
lastRunDayTask1 = timeinfo.tm_mday;
}
// Check if it's time to run the daily task #2
if (timeinfo.tm_hour == task2Hour && timeinfo.tm_min == task2Minute && lastRunDayTask2 != timeinfo.tm_mday) {
dailyTask2();
// Set the day to ensure it only runs once per day
lastRunDayTask2 = timeinfo.tm_mday;
}
// Resynchronize with NTP every 30 minutes
if (millis() - lastNTPUpdate > ntpSyncInterval) {
syncTime();
}
delay(1000); // Run loop every second
}
void dailyTask1() {
Serial.println("#########\nDoing daily task #1...\n#########");
// ENTER YOUR TASK HERE
}
void dailyTask2() {
Serial.println("#########\nDoing daily task #2...\n#########");
// ENTER YOUR TASK HERE
}
Don’t forget to insert your network credentials, time zone, desired tasks’ time and modify the dailyTask functions to run your daily task. By default, with this new code, you’ll have task #1 running at 8:15 AM and task #2 at 6:45 PM.
Wrapping Up
This quick guide taught you how to create a simple code that can run one or multiple tasks with your ESP boards at a desired time.
We hope you found this tutorial useful. We have other tutorials related to time that you may like:
- ESP32 NTP Client-Server: Get Date and Time (Arduino IDE)
- ESP8266 NodeMCU NTP Client-Server: Get Date and Time (Arduino IDE)
- ESP32 NTP Time – Setting Up Timezones and Daylight Saving Time
- ESP32 Data Logging Temperature to MicroSD Card (with NTP time)
- ESP32: Guide for DS1307 Real Time Clock (RTC) Module (Arduino IDE)
Learn more about the ESP32 with our resources:
- Build Web Servers with ESP32 and ESP8266 eBook
- Learn ESP32 with Arduino IDE (eBook)
- More ESP32 tutorials and projects…
Thank you for reading.
I wonder if you could create a similar tutorial that implements the ESP32 deep sleep capability with a 32.768kHz crystal on GPIO XTAL32 pins to keep the RTC from drifting. Then the ESP32 could wake up at precisely the right time and send a message. Of course, it would need to occasionally synchronize with the NTP server because even a crystal will drift (but not by very much).
Exactly what I thought. I didn’t even know an ESP32 had such a pin though
good IDEA
Hello
My internet router can also be addressed as an NTP server on my FritzBox. The query on its IP address works flawlessly. The router also retrieves the data from an NTP server and makes it available on the home network.