ESP32 NTP Client-Server: Get Date and Time (Arduino IDE)

Learn how to request date and time from an NTP Server using the ESP32 with Arduino IDE. Getting date and time is useful in data logging projects to timestamp readings. To get time from an NTP Server, the ESP32 needs to have an Internet connection and you don’t need additional hardware (like an RTC clock).

ESP32 NTP Client-Server Get Date and Time Arduino IDE

Before proceeding with this tutorial you need to have the ESP32 add-on installed in your Arduino IDE:

Recommended: Get Date and Time with ESP8266 NodeMCU NTP Client-Server

NTP (Network Time Protocol)

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 is an NTP Client that requests time from an NTP Server (pool.ntp.org).

NTP Network Time Protocol ESP32 Request time and date

Getting Date and Time from NTP Server

To get date and time with the ESP32, you don’t need to install any libraries. You simply need to include the time.h library in your code.

The following code gets date and time from the NTP Server and prints the results on the Serial Monitor. It was based on the example provided by the time.h library.

/*
  Rui Santos
  Complete project details at https://RandomNerdTutorials.com/esp32-date-time-ntp-client-server-arduino/
  
  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 <WiFi.h>
#include "time.h"

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

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

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.");
  
  // Init and get the time
  configTime(gmtOffset_sec, daylightOffset_sec, ntpServer);
  printLocalTime();

  //disconnect WiFi as it's no longer needed
  WiFi.disconnect(true);
  WiFi.mode(WIFI_OFF);
}

void loop(){
  delay(1000);
  printLocalTime();
}

void printLocalTime(){
  struct tm timeinfo;
  if(!getLocalTime(&timeinfo)){
    Serial.println("Failed to obtain time");
    return;
  }
  Serial.println(&timeinfo, "%A, %B %d %Y %H:%M:%S");
  Serial.print("Day of week: ");
  Serial.println(&timeinfo, "%A");
  Serial.print("Month: ");
  Serial.println(&timeinfo, "%B");
  Serial.print("Day of Month: ");
  Serial.println(&timeinfo, "%d");
  Serial.print("Year: ");
  Serial.println(&timeinfo, "%Y");
  Serial.print("Hour: ");
  Serial.println(&timeinfo, "%H");
  Serial.print("Hour (12 hour format): ");
  Serial.println(&timeinfo, "%I");
  Serial.print("Minute: ");
  Serial.println(&timeinfo, "%M");
  Serial.print("Second: ");
  Serial.println(&timeinfo, "%S");

  Serial.println("Time variables");
  char timeHour[3];
  strftime(timeHour,3, "%H", &timeinfo);
  Serial.println(timeHour);
  char timeWeekDay[10];
  strftime(timeWeekDay,10, "%A", &timeinfo);
  Serial.println(timeWeekDay);
  Serial.println();
}

View raw code

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 <WiFi.h>
#include "time.h"

Setting SSID and Password

Type your network credentials in the following variables, so that the ESP32 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";

NTP Server and Time Settings

Then, you need to define the following variables to configure and get time from an NTP server: ntpServer, gmtOffset_sec and daylightOffset_sec.

NTP Server

We’ll request the time from pool.ntp.org, which is a cluster of timeservers that anyone can use to request the time.

const char* ntpServer = "pool.ntp.org";

GMT Offset

The gmtOffset_sec variable defines the offset in seconds between your time zone and GMT. We live in Portugal, so the time offset is 0. Change the time gmtOffset_sec variable to match your time zone.

const long gmtOffset_sec = 0;

Daylight Offset

The daylightOffset_sec variable defines the offset in seconds for daylight saving time. It is generally one hour, that corresponds to 3600 seconds

const int daylightOffset_sec = 3600;

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 ESP32 to your router.

// 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.");

Configure the time with the settings you’ve defined earlier:

configTime(gmtOffset_sec, daylightOffset_sec, ntpServer);

printLocalTime()

After configuring the time, call the printLocalTime() function to print the time in the Serial Monitor.

In that function, create a time structure (struct tm) called timeinfo that contains all the details about the time (min, sec, hour, etc…).

struct tm timeinfo;

The tm structure contains a calendar date and time broken down into its components:

  • tm_sec: seconds after the minute;
  • tm_min: minutes after the hour;
  • tm_hour: hours since midnight;
  • tm_mday: day of the month;
  • tm_year: years since 1900;
  • tm_wday: days since Sunday;
  • tm_yday: days since January 1;
  • tm_isdst: Daylight Saving Time flag;
  • tm structure documentation.

Get all the details about date and time and save them on the timeinfo structure.

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

Then, print all details about the time in the Serial Monitor.

Serial.println(&timeinfo, "%A, %B %d %Y %H:%M:%S");
Serial.print("Day of week: ");
Serial.println(&timeinfo, "%A");
Serial.print("Month: ");
Serial.println(&timeinfo, "%B");
Serial.print("Day of Month: ");
Serial.println(&timeinfo, "%d");
Serial.print("Year: ");
Serial.println(&timeinfo, "%Y");
Serial.print("Hour: ");
Serial.println(&timeinfo, "%H");
Serial.print("Hour (12 hour format): ");
Serial.println(&timeinfo, "%I");
Serial.print("Minute: ");
Serial.println(&timeinfo, "%M");
Serial.print("Second: ");
Serial.println(&timeinfo, "%S");

To access the members of the date and time structure you can use the following specifiers:

%AFull weekday name
%BFull month name
%dDay of the month
%YYear
%HHour in 24h format
%IHour in 12h format
%MMinute
%SSecond

There are other specifiers you can use to get information in other format, for example: abbreviated month name (%b), abbreviated weekday name (%a), week number with the first Sunday as the first day of week one (%U), and others (read more).

We also show you an example, if you want to save information about time in variables. For example, if you want to save the hour into a variable called timeHour, create a char variable with a length of 3 characters (it must save the hour characters plus the terminating character). Then, copy the information about the hour that is on the timeinfo structure into the timeHour variable using the strftime() function.

Serial.println("Time variables");
char timeHour[3];
strftime(timeHour,3, "%H", &timeinfo);
Serial.println(timeHour);

To get other variables, use a similar process. For example, for the week day, we need to create a char variable with a length of 10 characters because the longest day of the week contains 9 characters (saturday).

char timeWeekDay[10];
strftime(timeWeekDay,10, "%A", &timeinfo);
Serial.println(timeWeekDay);
Serial.println();

Demonstration

After inserting your network credentials and modifying the variables to change your timezone and daylight saving time, you can test the example.

Upload the code your ESP32 board. Make sure you have the right board and COM port selected. After uploading the code, press the ESP32 “Enable” button, and you should get the date and time every second as shown in the following figure.

ESP32 Get Date and Time NTP Client-Server Arduino IDE Serial Monitor demonstration

Wrapping Up

In this tutorial you’ve learned how to get date and time from an NTP server using the ESP32 programmed with Arduino IDE. Now, you can use what you’ve learned here to timestamp the sensor readings in your own projects.

This method only works if the ESP32 is connected to the Internet. If your project doesn’t have access to the internet, you need to use other method. You can use an RTC module like the DS1307.

If you want to learn more about the ESP32, check our resources:

Thanks for reading.



Learn how to build a home automation system and we’ll cover the following main subjects: Node-RED, Node-RED Dashboard, Raspberry Pi, ESP32, ESP8266, MQTT, and InfluxDB database DOWNLOAD »
Learn how to build a home automation system and we’ll cover the following main subjects: Node-RED, Node-RED Dashboard, Raspberry Pi, ESP32, ESP8266, MQTT, and InfluxDB database DOWNLOAD »

Enjoyed this project? Stay updated by subscribing our newsletter!

133 thoughts on “ESP32 NTP Client-Server: Get Date and Time (Arduino IDE)”

      • I’ve been using the ESP32 with the NTP code in a project linked to a Blynk program for controlling 3 heating circuits.
        As a means of checking the ESP32 is still running I send the local time from the ESP32 to Blynk every minute.
        The project has been running successfully for weeks until this morning I noticed the time was one hour head of local time. I’m in the UK. It seems as the NTP has brought Summer Time early!
        To check I’ve run your example program and I get the same result.
        I have these settings
        const char* ntpServer = “pool.ntp.org”;
        const long gmtOffset_sec = 0;
        const int daylightOffset_sec = 3600;
        Any ideas please?

        Reply
        • Just come across this myself, my keepalive email arrived an hour before the midnight change over when I expected it, Checked clock (NTP) and its one hour ahead, because US NTP – so will be correct again on the 28th March I think

          According to this
          https://www.meinbergglobal.com/english/faq/faq_33.htm
          Looks like you(we) have to handle it locally

          Change over dates are ..
          US changes on Second Sunday March at 02:00 local standard time
          UK changes on Last Sunday March at 01:00 UTC
          Then there is the change back in winter to consider

          Based on those dates – need to adjust this code item
          “const int daylightOffset_sec = 3600;”
          Or wait for them to come into sysnc again on the 28th

          Reply
          • Just reading thru the Q/A in these comments
            Seems a common issue – not seen a definitive answer yet

            Although just seen a comment further below by
            Jos
            March 19, 2020 at 7:13 pm

            Looks promising , will be experimenting with that solution tomorrow

          • Set your timezone correctly.

            const char* TZ_INFO = “GMT+0BST-1,M3.5.0/01:00:00,M10.5.0/02:00:00”;

            const char* ntpServer = “uk.pool.ntp.org”;

            configTime(0, 0, ntpServer);

            setenv(“TZ”, TZ_INFO, 1);
            tzset();

      • Hey i need help. i use NTP for my ESP32 project
        the project should be like this
        1. There are 2 ESP32 (A and B)
        2. A will send data to B (and printed time stamp as shown in google drive picture)
        3. B will receive that data and send it back to A (and printed timed stamp)
        4 A will receive data from B
        my problem is the NTP time stamp wasn’t synchronized.
        when A sending data the timestamp is ( ….:1.945333)
        when B receiving data the timestamp is (….:1.3798)
        when B sending back the data (…..:1.7583)
        when A receiving the data (….:1.949366)
        I tried using timeClient.update, timeClient.forceUpdate but still can’t
        the code are in gdrive if you want to see.
        thankyou so much for your reply.
        https://drive.google.com/drive/folders/1XEf3wtC2dMaWqqLWlyOblD8ptyb6DwTf?usp=sharing

        Reply
      • Hi dear Sara Santos
        How can I set alarm? for example I want set alarm at
        Sunday, April 23 2023 10:15:00
        Could you help me ?
        Best regards
        Hassan Nikkhoo

        Reply
    • I believe this code DOES NOT work with 8266. The reason is that time.h does not work with 8266 and there is no internal RTC with the 8266.
      As you can see, this sketch calls the NTP server only once to set the internal RTC of the ESP32 then it disconnects itself from the Internet.

      Reply
      • A Lee,

        Where is the time actually gotten from the NTP server?
        * I’m thinking that configTime(…) only sets up the communication but does not actually contact the NTP server
        * It looks like getLocalTime(&timeinfo)) contacts the NTP server(?) – but if that’s the case wouldn’t this report an error once WiFi is turned off?

        Most of us probably want to sync the RTC to the NTP server only periodically. Frequent retrievals of timestamps would be from the ESP32’s internal RTC. Thus we need to isolate the command that does the actual NTP contact. For the whole time our WiFi would be running, never disconnected.

        I think I’m misconstruing something, but I’m not sure what it is.

        Reply
    • Hi Joseph, I do like this approach to build a clock because it accesses the NTP server only once. The problem that I have encountered is that the ESP32 “WiFi Manager” is not reliable compare with 8266. This is another article all together!

      Reply
  1. I love the ESP32 and your clear explanations that are always well tested before publication. I do not understand how we can disconnect from WiFi and also turn off WiFi and still get accurate time data.

    Reply
      • I was puzzled by this point too. If you are updating the article at all, it woudl be good to mention that ESP32 has a built in RTC and that therefore it is only necessary to get a time snapshot from NTP once (or perhaps once per day if the internal clock drifts). For me it was not clear from the article that the snapshop was all that was needed.

        Many thanks for a great tutorial on this.

        Reply
        • ESP32 internal clock is quite bad, drifts some 10-15 min for every 8 hours or so when in deep sleep. I am using ESP32 for some time sensitive application, had to resort to external GPS module with pps. everytime esp32 wakes up, get the time sync from gps.

          Reply
          • Thanks for sharing this experience. Fortunately for me, my application only needs accuracy to a few minutes a day and the ESP is not deep sleeping much, so if I “sniff” the NTP server every 3-4 hours i should be all sorted.

  2. Hi
    I changed your code
    $sql = “INSERT INTO Sensor (value1, value2, value3)
    VALUES (‘” . $value1 . “‘, ‘” . $value2 . “‘, ‘” . $value3 . “‘)”;

    with this:
    $sql = “INSERT INTO `Sensor` ( `value1`, `value2`, `value3`, `reading_time`) VALUES ( ‘” . $value1 . “‘, ‘” . $value2 . “‘, ‘” . $value3 . “‘, UTC_TIMESTAMP())”;

    This way I always put a utc timestamp in the database
    The problem was that I sometimes had to add 7 hours and other times 8 hours

    Esben

    Reply
    • Hi.
      With this code, you can adjust the daylightOffset_sec (to adjust summer time) and the gmtOffset_sec to adjust the time for your timezone.
      Regards,
      Sara

      Reply
  3. the code wont compile for me at configTime(gmtOffset_sec, daylightOffset_sec, ntpServer);

    Said configTime ‘was not declared’

    Reply
  4. Hello there!
    How can I store the entire “Serial.println(&timeinfo, “%A, %B %d %Y %H:%M:%S”);” into a single variable?

    Reply
  5. hey Rui.
    I use this to sync time once in a while.
    // server.on (“/ ntpsync”, HTTP_GET, [] (AsyncWebServerRequest * request) {
    // configTime (gmtOffset_sec, daylightOffset_sec, ntpServer);
    // request-> redirect (“/ rtc”);
    //});
    Is there a way to test whether the synchronization is successful.

    i can not use this “if(!getLocalTime(&timeinfo)){}”
    Cause it only gives me the time of esp32 internal clock.

    Reply
    • I solved it by using the NTPClient library.
      // #include <NTPClient.h>
      //#include <WiFiUdp.h>

      // server.on(“/ntpsync”, HTTP_GET, [](AsyncWebServerRequest *request){
      // unsigned long nowLong;
      //timeval tv;

      // timeClient.update();
      // int timeout = millis() / 1000;
      // timeClient.begin();
      // timeClient.setTimeOffset(7200);
      //while(!timeClient.update()) {
      //timeClient.forceUpdate();
      // if((millis() / 1000) > timeout + 5){
      // break;
      // }
      // }
      // if (timeClient.update()){
      // nowLong = timeClient.getEpochTime();

      // tv.tv_sec=nowLong;
      // tv.tv_usec = 0;
      // settimeofday(&tv, 0);
      // request->redirect(“/rtc”);
      // }
      // else{
      // request->send (200, “text/html”, “Failed sync to NTP server”);
      // }
      // });

      Reply
  6. Hi Ron:

    I think “configTime” configs the internal RTC on the ESP 32 (esp 8266 has no internal RTC) with data from NTP server. See below message from Sarah on April 3rd:

    That’s because the ESP32 has an internal RTC that can keep track of time.

    getLocalTime(&timeinfo) — get the time and date info from the internal RTC. That’s why once the internal RTC is configurated with NTP data. The ESP 32 can be disconnected from WiFi. I hope this helps.

    Reply
    • Hi A Lee,

      So, once per day when I want to re-sync the RTC with the NTP server, I just execute the configTime(gmtOffset_sec, daylightOffset_sec, ntpServer); statement again? My WiFi stays on all the time due to the needs of other parts of the application, so I don’t have to turn it on/off for each re-sync.

      Reply
      • I have not done this process because I am using the ESP 32 as a clock. Yes, just run this configTime(gmtOffset_sec, daylightOffset_sec, ntpServer) everytime you want to sync the time.

        Reply
  7. Hi,

    I just spent several hours searching the internet for how to do automatic daylight saving time changes on the ESP32 using the Arduino IDE. I’m posting this here because it may save someone else having to search so much info.

    This code seems to work:
    // Comment out original code with manual setting of offsets
    // configTime(gmtOffset_sec, daylightOffset_sec, ntpServer);
    // Can use 0,0 for offsets now because using TZ below
    configTime(0, 0, ntpServer);
    // Set offsets and daylight saving change rules for UK
    setenv(“TZ”,”GMTGMT-1,M3.4.0/01,M10.4.0/02″,1);
    // Set offsets etc for Paris – I checked time is UK time +1 hour with this
    // setenv(“TZ”,”CET-1CEST,M3.5.0,M10.5.0/3″,1);
    tzset();

    There are plenty of examples for TZ strings for different time zones on the internet (I searched so many places I can’t remember exactly where I got the strings from for the above code). It currently sets the correct time offset (UTC + 1 hour for daylight saving). I haven’t tested it for change from daylight saving on to off. I guess I’ll find out later this month if it works. I couldn’t think of an easy way to test it now.

    Finally thank you so much for the nice ESP32 tutorials. I have made a web server for my loft to control the LED strip lighting in different areas. It also monitors the door on a humane rodent trap and sends me an e-mail if the door closes. I used your NTP, SMTP and web server tutorials to help me get started

    Best regards
    Dave

    Reply
    • and does it work now we are in winter time again?
      i have issues with dst now.. esp32 still gives an extra hour today.
      i live in gmt plus 1 and with dst. but this code still ads 1 extra hour today(28/10/2020)
      regards Thomas

      Reply
    • No unfortunately I’m still on +1 DST too. I haven’t looked at why it doesn’t work. Rebooting it made no difference.

      Reply
      • Now in November it seems to work right again. I just installed a newer time library (1.6) but i wont know if it works correct until the next dst change…

        Reply
        • Mine is still stuck in DST+1. When I saw your message I hoped reboot would fix it, but unfortunately not. Perhaps I’ll try updating my libraries. I’m not actively working on this project any longer. It’s installed in my loft and works fine. The time is only used for time stamps on log entries and emails. I’m the only person that looks at this info and it’s of no significance if the time is +1 hour. It would be more satisfying if it worked properly though. It probably wouldn’t be hard to write a test NTP server, or perhaps there is something available for download. I’m not likely to spend time on this before 2021.

          Reply
    • here’s some more specfics
      tm_isdst int Daylight Saving Time flag
      The Daylight Saving Time flag (tm_isdst) is greater than zero if Daylight Saving Time is in effect, zero if Daylight Saving Time is not in effect, and less than zero if the information is not available
      Nov 1, 2020 – Daylight Saving Time Ended
      When local daylight time was about to reach
      Sunday, November 1, 2020, 2:00:00 am clocks were turned backward 1 hour
      Right how if I read
      Serial.print(“Structure of flag tm_isdst =”);
      Serial.println(timeinfo.tm_isdst);
      I get tm_isdst =0, meaning Daylight Savings Time is not in effect but the clock is still reading Daylight saving time. Do i need to do something to get correct time?
      high regards, love your work
      Tom Kibalo

      Reply
  8. This is yet another reason why everyone should have moved on to ESP32 boards. I know they’re not perfect, but internal RTC, WiFi and Bluetooth right on board… ? Arduino Uno what? 😉

    The last few days I’ve been trying to do exactly this with a DS3231. Connecting with the NTP server to ‘always’ provide correct time, despite DST, is what I’ve been after this past week.

    Now, I want to tie this in and have it displayed onto a 1637 4 digit 7 segment LED for my own little digital clock, that is always right.

    Reply
  9. Please help me resolve this. i set code to
    onst char* ntpServer = “pool.ntp.org”;
    const long gmtOffset_sec = -14400;
    for my location in US –works fine but I can’t compensate for day light saving time
    I used
    const int daylightOffset_sec = -3600 ;
    const int daylightOffset_sec = 3600 ;
    const int daylightOffset_sec = 0 ;

    and still get the same time using
    configTime(gmtOffset_sec, daylightOffset_sec, ntpServer);
    printLocalTime();

    please, please advise–what Am I doing wrong???

    Reply
    • Hi Thomas,
      If you have not gotten your issue resolved, please check out this link.
      mischianti.org/2020/08/08/network-time-protocol-ntp-timezone-and-daylight-saving-time-dst-with-esp8266-esp32-or-arduino/

      Reply
      • Hi Thomas,
        Forget what I said above! I live in USA GMT -8. My gmtOffset_sec = -28800. My daylightOffset_sec = 3600. I know my clock was running correctly several weeks ago during the time change from DST to ST. I recompile the code on this page. I used -3600 as the daylightOffset_sec. The time came back correctly with Standard Time. A question to you is: Do you have the correct time? My GUESS is that the daylightOffset_sec is used only during “time change”.

        Reply
  10. Hi!
    The line 38
    configTime(gmtOffset_sec, daylightOffset_sec, ntpServer);
    returns exit status 1 = ‘configTime’ was not declared in this scope

    In which library is this function declared?

    Thanks in advance
    Stephan

    Reply
    • Hi.
      Are you using our exact code or did you change something?
      Make sure you select an ESP32 board in Tools>Board after compiling the code.
      Regards,
      Sara

      Reply
  11. Hi,
    Unfortunately, no code works on ESP32 Devkit v1. Keeps writing “Failed to obtain time”. Tried all the suggestions on the internet (with and without static IP and daylight saving rules)?

    Reply
  12. Hello!! I’m Giovane (brazilian) and I need a big help!!
    For me it works different.
    It is printing in monitor serial:


    ets Jun 8 2016 00:22:57

    rest:0xc (SW_CPU_RESET),boot:0x13 (SPI_FAST_FLASH_BOOT)
    configsip:0, SPIWP:0xee
    clk_drv:0x00, q_drv:0x00,d_drv:0x00,cs0_drv:0x00,hd_drv:0x00,wp_drv:0x00
    mode:DIO, clock div:1
    load:0x3fff0018,len:4
    load:0x3fff001c,len:1044
    load: 0x40078000,len:10124
    load:0x40080400,len5856
    entry 0x400806a8

    And I don’t know its!!! I started with ESP32 a short time ago. I work a lot with ESP8266 but with ESP32 it’s being bad!

    Help!!

    Reply
  13. What is with the change to Summertime/Wintertime? My clock changed today which would be correct in the USA but not in Germany where it should change at the 28.3. Where can you change this.

    Reply
  14. Hi,
    I think i found a solution for europe dst issue. but i will know for sure after 28th of march..

    try this:

    put this line on top of your sketch.

    const char * defaultTimezone = “CET-1CEST,M3.5.0/2:00:00,M10.5.0/3:00:00”;

    (the -1 corresponds to utc plus 1 and you should change this to your timeZone).
    and set this
    const int gmtOffset_sec = 0;
    const int daylightOffset_sec = 0;
    now it should work ok.

    Reply
  15. forgot to mention that you should also ad this line to your main code:

    configTime(0,0, ntpServer);
    configTzTime(defaultTimezone, ntpServer);

    Reply
    • That’s it! I was looking for hours for a working example. With these lines i cloud compile it and get correct german time:

      #define MY_NTP_SERVER “fritz.box” //”de.pool.ntp.org”
      #define MY_TZ “CET-1CEST,M3.5.0/02,M10.5.0/03” //Timezone: Germany

      // Init and get the time
      configTime(0,0, MY_NTP_SERVER);
      configTzTime(MY_TZ, MY_NTP_SERVER);
      printLocalTime();

      Reply
  16. If copy and pasting some the strings here for various time zone info ( and other code )
    You will need to retype the Quote characters once pasted in to your sketch
    Otherwise you will end up with an error like this – I did !
    Stray \342 in program

    Reply
  17. Hi All,

    Reading through code I saw that we can extract the time and date using method below:

    Serial.println(“Time variables”);
    char timeHour[3];
    strftime(timeHour,3, “%H”, &timeinfo);
    Serial.println(timeHour);

    However, This is nice; but how would I reload the RTC on the ESP32; Above shows config, get and print. but no RTC load. It must be in the libraries. The code that initializes the registers for the time and date are where? If I don’t have internet I still would like to re-load the real time clock and let it RTC still run my timing. This would be useful as BT and WIFI don’t work together so far. I went to Expressif Tech docs nothing on RTC.

    Phil

    Reply
  18. I am using the following with my esp32 solar powered weather station to get the UTC time once a week and reset my RTC with it:

    #define NTP_SERVER_POOL “pool.ntp.org” // NTP pool

    const char* ntpServer = NTP_SERVER_POOL;
    struct tm timeinfo;

    bool SetTimeFromNTPServer() {

    bool ReturnValue = false;

    configTime(0, 0, ntpServer); // get the UTC time from an internet ntp server (try 2)

    if (getLocalTime(&timeinfo)) {

    if (DEBUG_ENABLED) {
    Serial.println("Setting time from NTP server");
    Serial.print("NTP UTC server time: ");
    Serial.println(&timeinfo, "%A, %B %d %Y %H:%M:%S");
    }

    int y = timeinfo.tm_year + 1900;
    int mo = timeinfo.tm_mon + 1;
    int d = timeinfo.tm_mday;
    int h = timeinfo.tm_hour;
    int m = timeinfo.tm_min;
    int s = timeinfo.tm_sec;

    setTime(h, m, s, d, mo, y);

    ReturnValue = (rtc.set(now()) == 0);

    };

    if (DEBUG_ENABLED)
    if (ReturnValue)
    Serial.println(“RTC set from NTP server”);
    else
    Serial.println(“Failed to set RTC from NTP server”);

    return ReturnValue;

    }

    Which works sometimes but not always, for some reason it sometimes sets the time but the time is off by several minutes (like between 5 and 15).

    Any ideas on what I may be doing wrong?

    Reply
    • I see this too. Immediately after initialisation the time is a few minutes out but then corrects itself:

      This is from info logged to ESP32 flash. Each log entry has a time stamp, but before NTP is working the time stamp is all question marks:

      ????-??-?? ??:??:?? File:”Main.cpp” Line:73 INF: Initialising
      ????-??-?? ??:??:?? File:”MyEeprom.cpp” Line:37 DBG: EEPROM signature correct 0xface0ff0
      ????-??-?? ??:??:?? File:”Mywifi.cpp” Line:14 DBG: Connecting
      ????-??-?? ??:??:?? File:”Mywifi.cpp” Line:26 DBG: WiFi connected.
      ????-??-?? ??:??:?? File:”Mywifi.cpp” Line:27 INF: IP address: 192.168.0.72
      ????-??-?? ??:??:?? File:”Mywifi.cpp” Line:28 INF: Mac address: 24:6F:28:79:DC:74
      ????-??-?? ??:??:?? File:”Main.cpp” Line:95 DBG: Calling ntp.init()
      2021-08-25 17:13:35 File:”Main.cpp” Line:97 DBG: Returned from ntp.init()
      2021-08-25 17:04:59 File:”Main.cpp” Line:143 DBG: Exiting setup()

      Reply
      • I forgot to say that the last line shows the correct time and the time between the calls in the next to last / last line is probably less than 1 second. Maybe on return from ntp.init() some background code has not completely finished filling out the time structures.

        Reply
  19. Thank you for the good tutorial. I successfully applied it as a part to update the date and time to an Arduino script for an Arduino Nano RP2040 Connect that I have connected to a DS3231 RTC. Btw: I also live in Portugal (Lisboa).

    Reply
  20. Very strange. At first it worked, then I made a non-blocking version, which also works, but now this code (in setup) doesn’t work anymore while my non-blocking code does (in loop, every 10 sec). There is no difference in operations, except the non-blocking code keeps the loop alive. WiFi connects, but no time is fetched.

    Reply
      • Yup, I got connected to the internet using the SIM800. Just found out that NTP time sync cannot be used if using GPRS. Now I am trying to connect to the internet using wifi, the compiler say ” wifi.h : no such file or directory”.

        Reply
  21. Hello,
    the example requires a predefined ntp-server, i.e.
    const char* ntpServer = “pool.ntp.org”;
    or at least const char* ntpServer = “192.168.0.1”;

    I wonder if there is a way to use the ntpserver address provided by the local dhcp server (dhcp option 42).

    This could make my life much easier, since internet access is blocked for port 123 by a firewall, and the address of the local ntp changes from time to time.
    (admins comment: that’s why you should use dhcp)

    Henning

    Reply
  22. How do I calculate the time difference in seconds between 2 events?
    I’m running ESP32 Huzzah , and ntpServer to get the time.
    Thanks.

    Reply
    • Do you want to use times obtained from NTP or would you be ok using e.g. millis() to get time of 1st event and then using mills() when 2nd event happens?
      It’s very easy to get difference in seconds between two events using the values obtained from millis(). For example:
      // 1st event happens
      unsigned long millis_1st_event = millis()

      // 2nd event happens
      unsigned long millis_2nd_event = millis();

      // You can obtain time diff in secs by
      unsigned long time_diff secs = (millis_2nd_event – millis 1st event) / 1000;

      If you want to find the difference between two times obtained from NTP then I don’t immediately know how to do that. I’d have to google.

      Reply
      • One more caveat, using millis as described is good for time differences up to 49.7 days. If you want to get a difference between two times further apart than that then the code I suggested won’t work

        Reply
  23. Thanks, David. How stupid of me. I should have known to do it with the millis function. I was deep in working with the NTP Time and tottaly fogot about millis. Thanks again.

    Reply
  24. “%A, %B %d %Y %H:%M:%S”
    Do i can add millisecond in there ?
    or there’s any possible way to add millisecond or microsecond ? Thank you so much.

    Reply
  25. Hi Rui,
    I’m using your NTP program and trying to display the hour, minutes and seconds to a 6-digit, seven segment display. My question is, how can I convert the %H, %M, %S to integer values? Can you write me a simple code to convert char to integer values?

    I look forward to your reply.
    Thanks!

    Reply
      • Hi Dave,
        Thanks for your comment / suggestion. I finally figured it out: I used the tm structure documentation to get the time (hr, min, sec), which were already type integer.
        However, you did gave me a new lesson to learn!

        Best Regards,
        Alberto F

        Reply
    • I think I’m having the same issue, I’m really struggling to convert the time into a string that I can use as a filename for photographs taken by the esp32-cam, can anyone give me any pointers?

      Reply
      • Hi.
        You can use something like this:

        struct tm timeinfo;
        char now[20];
        getLocalTime(&timeinfo);
        strftime(now,20,"%Y%m%d_%H%M%S",&timeinfo);

        // Path where new picture will be saved in SD Card or other filesystem
        String path = "/picture" + String(now) +".jpg";
        Serial.printf("Picture file name: %s\n", path.c_str());

        I hope this helps.
        Regards,
        Sara

        Reply
        • That works! Brilliant, I’d been trying to figure it out for a few days now but I’d not come across strftime() before. Thank you so much!

          Reply
  26. Hi All,
    Setting the Scene – If I have a ESP32 and it is set as an Access Point, then my phone connects to the ESP32 and displays a basic web page served by the ESP32. So basically the ESP32 Web server knows there has been an external connection.
    Can I now initiate a NTP server request to the internet via phone the phone connection?
    Idea being to automatically set the RTC either within the ESP32 or an external I2C RTC device.

    Thanks,
    Neil.

    Reply
    • Hi.
      The ESP32 needs to be able to connect to the internet to get time from NTP.
      If it is set as an access point, it is not connected to the internet. So, you can’t request the time.
      Regards,
      Sara

      Reply
  27. Hi,
    i m a hobbist so sorry for my silly questions:
    1) does it often ask to NTP server the time?
    2) if it doesnt, how can it work offline?
    3) in other examples i ve seen
    #define MYTZ “CET-1CEST,M3.5.0,M10.5.0/3”
    and
    configTzTime(MYTZ, “time.google.com”, “time.windows.com”, “pool.ntp.org”);

    and later
    time_t now = time(nullptr);
    struct tm t = *localtime(&now);

    what’s the difference between configTzTime and configTime?

    Reply
    • configTime specifies time offset and daylight offset in seconds.
      configTzTime uses TZ notation instead.

      Apart of that both are equivalent

      Reply
  28. Good evening team,
    how can i realise a project like:
    humidity and temperature with RTC/NTP wireless emitter and transmitter.

    Thank you.

    Reply
    • If you are writing the html client code you can get the date/time of the client e.g:
      – var now = new Date();
      Then you have to send it to the web server, maybe you could do it by encoding the information in a get request, or you could send it using a web socket.

      Reply
  29. Hi, thanks for the sketch. I’m trying it with a D1 mini. Getting: ‘getLocalTime’ was not declared in this scope; did you mean ‘printLocalTime’?
    Am I doing something wrong?

    Paul

    Reply
  30. Hi Sara, congratulations for your work, it is an inexhaustible source of suggestions.
    I was trying your https://randomnerdtutorials.com/esp32-date-time-ntp-client-server-arduino/ but it didn’t work properly, so I modified the printLocalTime() and setup() functions slightly.
    But in the end I discovered that there would be no problem if the WiFi connection happened in the usual network, while I use the GUEST network which creates a delay and a failure of the first read getLocalTime(&timeinfo)
    Good work

    #include <WiFi.h>
    #include “time.h”

    const char * ssid = “Guest”;
    const char * password = “@@@@@@@@”;

    const char * ntpServer = “pool.ntp.org”;
    const long gmtOffset_sec = 3600;
    const int daylightOffset_sec = 3600;

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

    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. “);
    Serial.println(WiFi.localIP());
    Serial.println(WiFi.gatewayIP());
    Serial.println(WiFi.SSID());
    Serial.println(WiFi.macAddress());
    // Init and get the time
    configTime(gmtOffset_sec, daylightOffset_sec, ntpServer);
    while (!printLocalTime()) {
    delay(500);
    }
    //disconnect WiFi as it’s no longer needed
    WiFi.disconnect(true);
    WiFi.mode(WIFI_OFF);

    }

    void loop(){
    delay(1000);
    printLocalTime();
    }

    Reply
  31. Hi,
    After having problems with NTPClient.h, I want to use this sketch to capture the current time.

    In my sketch I use in numerous places the string variable ‘formattedDate’ (and substrings) supplied by NTPClient.
    Now, I don’t want to change all the places in the code that rely on ‘formattedDate’, but rather convert the contents of ‘&timeinfo’ to the string variable ‘formattedDate’ and then process it as before.
    I am not experienced enough on how this can be done. Maybe someone can help me with this.

    Reply
  32. Hy,
    Learning by doing!

    Through much trial and error, I found the solution, which is more than simple.

    char zw_wert[24];
    Sting formmattedDate = “”;

    strftime(zw_value,24,”%Y-%m-%dT%H:%M:%SZ”, &timeinfo) ;
    formattedDate = zw_wert;
    Serial.println(formattedDate);

    The result = “2023-08-21T20:42:10Z”

    Thank you for your attention

    Reply
  33. Hello,
    I tried the example and it works well on ESP32 WROOM 32 but by forcing a static IP address when opening the Internet connection, the connection is well established but access to the ntp server no longer works and I constantly get the message “Failed to obtain time”.
    Does anyone have a solution to this problem? I absolutely need a static IP address.

    WiFi.config(ip, dns, gateway, subnet); // To set a static IP address
    WiFi.begin(ssid, password);

    Reply
  34. In setup, these last three lines lines don’t make sense to me:
    //disconnect WiFi as it’s no longer needed
    WiFi.disconnect(true);
    WiFi.mode(WIFI_OFF);

    The ESP32 is still connected to the internet via wifi. How can it be turned off?

    Reply
  35. Hello Sara.

    I like your sketch for the offline time update (main reason). I have a Wemos R1 D32 (with ESP32-WROOM-32) and on top I have a by myself modified W5100 Ethernetshield with SD working (original for Arduino). With Wifi from the ESP32 is it working great but not with the W5100 via cable. Then I get the error “Failed to obtain time”. I assume that “Wifi.h” does the job. But I use “Ethernet.h” instead ofcourse. Proberly I should add some more Ethernet libraries.

    So what is the suggestion to get the ESP32 working with a W5100 shield?

    Or back using the NTP-version with a timed update?

    Reply
    • Have already figured out. Just using the NTP-version and the ESP32time.h library. Directly calculate epoch time to normal time and set the RTC. This is in a void doing every hour a callback for keeping accuracy. Readout the RTC is every second (with millis as delay) on Core1. This is because requesting epoch can take several seconds. Stripped the libraries only to what is necessary to save more memory.

      Reply
  36. Hi All
    Have some experience with Arduino – but new to ESP range.
    Having read (lots!) about NTP on the ESP8266 and ESP32 I have a question…
    In the 8266 the time lib syncs every 60 mins – unless set differently.
    “Another standard value is the NTP polling interval. The default value is 60 minutes. This value can also be changed. You can find an example in the original sketch using the function sntp_update_delay_MS_rfc_not_less_than_15000. You have to return the polling interval in milliseconds:”
    You can also set a callback – to show when the time has re syncd.
    I’ve tried using this on the ESP32 – but it doesnt work!

    Does the time lib not sync automatically on the ESP32?

    Reply
    • I think it must sync automatically on the ESP32. I have a couple of always on ESP32 controlled devices in the house. I get the time from NTP in setup()

      configTime(0, 0, ntpServer); // Can use 0,0 because using TZ below now
      setenv(“TZ”,”GMTGMT-1,M3.4.0/01,M10.4.0/02″,1); // London
      tzset();

      Then they run for ever without any explicit calls from my code to sync with NTP. My code only calls NTP to get the time.

      getLocalTime(&timeinfo)

      Their time is always within a second if I check them against an atomic clock web page. I still haven’t worked out how to get the time to change when we change from GMT (no daylight saving) to BST (+1 hour). Both devices are permanently +1. That doesn’t bother me enough to spend more time on working out how to get it to work. Even if I had a good idea about how to fix it, I’d have to set up a local NTP server that I could use to switch daylight saving on and off to test it.

      Reply
      • Thanks Dave.
        Googling a bit more I found this…
        werner.rothschopf.net/microcontroller/202103_arduino_esp32_ntp_en.htm

        It shows you how to set a ‘callback’ function which tells you when the ESP has syncd to NTP.

        Ref your problem with GMT / BST try replacing your line in setenv(..) following GMT with GMT0BST,M3.5.0/1,M10.5.0.

        Look here…. github.com/nayarsystems/posix_tz_db/blob/master/zones.csv

        Andy

        Reply
        • Hi Andy,
          Thanks for the info. I might try it sometime. I’ve not had to touch the code in the devices using NTP for over a year. If I need to modify them for some other reason I may include the suggested change to cater for daylight saving.

          Reply

Leave a Comment

Download Our Free eBooks and Resources

Get instant access to our FREE eBooks, Resources, and Exclusive Electronics Projects by entering your email address below.