NTPClient.h
#pragma once

/*F********************************************************************
*
**********************************************************************/
#include "Arduino.h"
#include <Udp.h>

//************************* DEFINES ************************************
#define SEVENZYYEARS 2208988800UL
#define NTP_PACKET_SIZE 48
#define NTP_DEFAULT_LOCAL_PORT 1337
#define LEAP_YEAR(Y)     ( (Y>0) && !(Y%4) && ( (Y%100) || !(Y%400) ) )

//************************* PROTOTYPES ************************************

//************************* VARIABLES ************************************

class NTPClient {
private:
UDP*          _udp;
bool          _udpSetup       = false;
const char*   _poolServerName = "pool.ntp.org"; // Default time server
int           _port           = NTP_DEFAULT_LOCAL_PORT;
int           _timeOffset     = 0;
unsigned long _updateInterval = 60000;  // In ms
unsigned long _currentEpoc    = 0;      // In s
unsigned long _lastUpdate     = 0;      // In ms
byte          _packetBuffer[NTP_PACKET_SIZE];
void          sendNTPPacket();
bool          isValid(byte * ntpPacket);
public:
NTPClient(UDP& udp);
NTPClient(UDP& udp, int timeOffset);
NTPClient(UDP& udp, const char* poolServerName);
NTPClient(UDP& udp, const char* poolServerName, int timeOffset);
NTPClient(UDP& udp, const char* poolServerName, int timeOffset, unsigned long updateInterval);

/*F********************************************************************
* Starts underlying UDP client with default local port
**********************************************************************/
void begin();

/*F********************************************************************
* Starts underlying UDP client with specified local port
**********************************************************************/
void begin( int port );

/*F********************************************************************
* This should be called in main loop of your application. 
 By default an update from NTP Server is only
* made every 60 seconds. This can be configured in NTPClient constructor.
* @return true on success, false on failure
**********************************************************************/
bool update();

/*F********************************************************************
* This will force update from NTP Server.
* @return true on success, false on failure
**********************************************************************/
bool forceUpdate();

/*F********************************************************************
*
**********************************************************************/
int getDay();
int getHours();
int getMinutes();
int getSeconds();

/*F********************************************************************
* Changes time offset. Useful for changing timezones dynamically
**********************************************************************/
void setTimeOffset( int timeOffset);

/*F********************************************************************
* Set update interval to another frequency. E.g. useful when 
* timeOffset should not be set in constructor
**********************************************************************/
void setUpdateInterval( unsigned long updateInterval);

/*F********************************************************************
* @return secs argument (or 0 for current time) formatted like `hh:mm:ss`
**********************************************************************/
String getFormattedTime( unsigned long secs = 0);

/*F********************************************************************
* @return time in seconds since Jan. 1, 1970
**********************************************************************/
unsigned long getEpochTime();

/*F********************************************************************
* @return secs argument (or 0 for current date) formatted to ISO 8601
* like `2004-02-12T15:19:21+00:00`
**********************************************************************/
String getFormattedDate( unsigned long secs = 0);

/*F********************************************************************
* Stops underlying UDP client
**********************************************************************/
void end();

/*F********************************************************************
* Replace NTP-fetched time with seconds since Jan. 1, 1970
**********************************************************************/
void setEpochTime( unsigned long secs);
};