Open
Description
I don't want to fork, so here:
Since the NTP servers should not provide data before 2020:
Add in NTPClient.h:
#define DAYSOF4YEARS 1461UL // 4*year plus leap day
#define DAYSOFAYEAR 365UL
#define SEC20200101 1577750400UL // 2020/01/01 - 1 day (86400s) because the result of the integer division is rounded off
class NTPClient {
private:
...
uint16_t _date = 0;
uint16_t _month = 0;
uint16_t _year = 0;
bool _isLeapYear = false;
...
public:
...
bool isLeapYear() const;
int getYear() const;
int getMonth() const;
int getDate() const;
...
Add in NTPClient.cpp:
bool NTPClient::forceUpdate() {
[...]
// at the end add:
uint32_t _days2k = (_currentEpoc - SEC20200101)/86400; // distance to today in days
if (_days2k > DAYSOF4YEARS) { // how many four-year packages + remaining days, from 2050 faster than subtraction on an esp8266 ;)
_year = _days2k / DAYSOF4YEARS;
_days2k = _days2k - _year * DAYSOF4YEARS;
_year *= 4;
}
if (_days2k > DAYSOFAYEAR + 1) { //2020 was a leap year, how many years + remaining days
_days2k--;
while (_days2k > DAYSOFAYEAR) { //three times at most
_days2k -= DAYSOFAYEAR;
_year++;
}
} else _isLeapYear = true;
_year += 20; // + 2020
if (_isLeapYear && _days2k > 60) _days2k--; // subtract the possible leap day when February passed
if (_days2k > 334) { _month = 12; _date = _days2k - 334; } //boring but quick
else if (_days2k > 304) { _month = 11; _date = _days2k - 304; }
else if (_days2k > 273) { _month = 10; _date = _days2k - 273; }
else if (_days2k > 243) { _month = 9; _date = _days2k - 243; }
else if (_days2k > 212) { _month = 8; _date = _days2k - 212; }
else if (_days2k > 181) { _month = 7; _date = _days2k - 181; }
else if (_days2k > 151) { _month = 6; _date = _days2k - 151; }
else if (_days2k > 120) { _month = 5; _date = _days2k - 120; }
else if (_days2k > 90) { _month = 4; _date = _days2k - 90; }
else if (_days2k > 59) { _month = 3; _date = _days2k - 59; }
else if (_days2k > 31) { _month = 2; _date = _days2k - 31; }
else { _month = 1; _date = _days2k; }
return true;
}
// and then you can add:
bool NTPClient::isLeapYear() const {
return this->_isLeapYear;
}
int NTPClient::getYear() const {
return this->_year;
}
int NTPClient::getMonth() const {
return this->_month;
}
int NTPClient::getDate() const {
return this->_date;
}
it works to 2099/12/31 ;-)
You can now use the methods
- isLeapYear()
- getYear()
- getMonth()
- getDay()
which makes it easier to set an RTC like the DS3231 without time.h - because for some stupid reason it (DS3231) does not understand a timestamp, but has actually stored the "normal" western date format in its registers.
Remark
There is still potential for optimization, because some divisions are redundant now, if you could evaluate temporary variables for getDay, getHours, getMinutes and getSeconds.