Clicky

20210406

ESP + NTP to DST

This ESP code pulls the date from NTP and calculates if today is DST. The DST algorithm is based on this post.

The output will look something like:

09:38:57.832 -> *** Connecting to SSID: {SSID}
09:38:57.832 -> ...
09:38:57.979 -> *** WiFi connected.
09:38:57.979 -> IP address: 192.168.x.111
09:38:58.032 -> DST: 1

//--- Libraries...
  //--- WiFi + NTP...
  #include <ESP8266WiFi.h>
  #include <NTPClient.h>
  #include <WiFiUdp.h> 

  //--- Date to epoch...
  #include <TimeLib.h>


//--- WiFi and network...
  const char* ssid     = "{SSID}";
  const char* password = "{password}";


//--- NTP...
  WiFiUDP ntpUDP;
  const int CETtoGMToffset = 3600; //--- Central European Time (CET) offset to GMT...
  NTPClient timeClient(ntpUDP"time.kriss.re.kr",CETtoGMToffset,60000);


//--- setup() ----------------------------------------------------------------------------
void setup(){
  

  Serial.begin(74880); //--- Prevent garbled output, show ESP8266 boot output...
  delay(500);
  Serial.println();


//--- Start WiFi...
  pinMode(LED_BUILTIN, OUTPUT);

  Serial.println("*** Connecting to SSID: " + String(ssid));
  WiFi.mode(WIFI_STA);
  WiFi.begin(ssidpassword);

  while (WiFi.status() != WL_CONNECTED) {

    digitalWrite(LED_BUILTIN, !digitalRead(LED_BUILTIN));
    Serial.print(".");
    delay(50);

  }

  digitalWrite(LED_BUILTIN,HIGH);
  Serial.println("\r\n*** WiFi connected.");
  Serial.print("IP address: ");
  Serial.println(WiFi.localIP());
//--- WiFi connection established...


// Initialize a NTPClient to get time from NTP server...
  timeClient.begin();

//--- Is today in DST?
  Serial.println("DST: " + String(nowInDST()));

}    


//--- loop() ----------------------------------------------------------------------------

void loop(){
    
}


boolean nowInDST()
{

  boolean isInDST = false;

  //--- Retrieve epoch from NTP server...  
  timeClient.update();  
  unsigned long epochTime = timeClient.getEpochTime();
  
  //--- Destil current year...  
  struct tm *ptm = gmtime ((time_t *)&epochTime); 
  int y = ptm->tm_year+1900;

  //--- Calculate epoch values for start and end of DST for this year...
  unsigned long firstDSTepoch = toEpoch(y,3lastSundayOfMonth(y,3) ,2,0,0); //--- Start of CET DST in epoch...
  unsigned long lastDSTepoch  = toEpoch(y,10,lastSundayOfMonth(y,10),2,0,0); //--- End of CET DST in epoch...

  //--- Check epoch if in DST...  
  if (epochTime >= firstDSTepoch && epochTime < lastDSTepoch
  {
    isInDST = true;
  }
  
  return isInDST;

}


//--- Calculate the date of the last Sunday in a given month...
int lastSundayOfMonth(int yint M)
{
  //--- Take care of leap years...
  int daysInMonth[] = {31,28,31,30,31,30,31,31,30,31,30,31};
  if (y % 4  == 0 && y % 100 != 0) {daysInMonth[1= 29;}

  //--- Last day of month M to epoch...
  unsigned long epoch = toEpoch(y,M,daysInMonth[M-1],0,0,0);

  //--- Day of week, based on ISO8601...
  int dayOfWeek = ((epoch / 86400+ 4% 7;

  //--- Calculate date of last Sunday...
  int lastSundayOfMonth = daysInMonth[M-1- dayOfWeek;
  return lastSundayOfMonth;
  
}

//--- Converts a date to epoch (TimeLib.h)...
unsigned long toEpoch(int ybyte M , byte dbyte hbyte mbyte s)
{
  
  tmElements_t tmSet;
  tmSet.Year = y - 1970;
  tmSet.Month = M;
  tmSet.Day = d;
  tmSet.Hour = h;
  tmSet.Minute = m;
  tmSet.Second = s;
  return makeTime(tmSet);
  
}

20210402

Arduino/ESP function: inEuropeanDST

There are many other, most likely better, functions to calculate if a given date/time is in European Daylight Saving Time. But the function below is simpler to understand because most calculations are done in-line. Only the "toEpoch" function is used from the "TimeLib.h" library.

This function calculates the epoch at 2AM of the last Sunday of March (start of EU DST) and the epoch at 2AM on the last Sunday of October (end of EU DST) and checks if the given date is in between (summertime) or not (wintertime).

#include <TimeLib.h>

void setup()
{
  Serial.begin(74880);
  delay(1000);
  Serial.println();

  //--- Begin of EU DST in 2021...
  Serial.println(inDST(2021,3,28,1,59,59));
  Serial.println(inDST(2021,3,28,2,0,0));

  //--- End of EU DST in 2021...
  Serial.println(inDST(2021,10,31,1,59,59));
  Serial.println(inDST(2021,10,31,2,0,0));
  
}

void loop()
{
}

boolean inDST(int yint Mint dint hint mint s)
{

  boolean isInDST = false;
  
  unsigned long parsedDate    = toEpoch(yMdhms);                   //--- Parsed date to epoch...
  unsigned long firstDSTepoch = toEpoch(y,3lastSundayOfMonth(y,3) ,2,0,0); //--- Start of DST in epoch...
  unsigned long lastDSTepoch  = toEpoch(y,10,lastSundayOfMonth(y,10),2,0,0); //--- End of DST in epoch...
  
  if (parsedDate >= firstDSTepoch && parsedDate < lastDSTepoch
  {
    isInDST = true;
  }
  
  return isInDST;

}


//--- Calculate the day of the last Sunday of a given month...
int lastSundayOfMonth(int yint M)
{
  //--- Take care of leap years...
  int daysInMonth[] = {31,28,31,30,31,30,31,31,30,31,30,31};
  if (y % 4  == 0 && y % 100 != 0) {daysInMonth[1= 29;}

  //--- Last day of month M to epoch...
  unsigned long epoch = toEpoch(y,M,daysInMonth[M-1],0,0,0);

  //--- Day of week, based on ISO8601...
  int dayOfWeek = ((epoch / 86400+ 4% 7;

  //--- Calculate date of last Sunday...
  return (daysInMonth[M-1- dayOfWeek);
  
}

//--- Converts a date to epoch (TimeLib.h)...
unsigned long toEpoch(int ybyte M , byte dbyte hbyte mbyte s)
{
  
  tmElements_t tmSet;
  tmSet.Year = y - 1970;
  tmSet.Month = M;
  tmSet.Day = d;
  tmSet.Hour = h;
  tmSet.Minute = m;
  tmSet.Second = s;
  return makeTime(tmSet);
  
}

 The output shows the second before and after the change to/from DST in 2021:

07:16:31.652 ->
07:16:31.652 ->  ets Jan  8 2013,rst cause:2, boot mode:(3,6)
07:16:31.652 ->
07:16:31.652 -> load 0x4010f000, len 3584, room 16
07:16:31.652 -> tail 0
07:16:31.652 -> chksum 0xb0
07:16:31.652 -> csum 0xb0
07:16:31.652 -> v2843a5ac
07:16:31.652 -> ~ld
07:16:32.755 ->
07:16:32.755 -> 0
07:16:32.755 -> 1
07:16:32.755 -> 1
07:16:32.755 -> 0







Real Time Web Analytics