mirror of
https://github.com/letscontrolit/ESPEasy.git
synced 2026-07-28 04:07:47 +00:00
[Time] Fix tm_mon starting at 0 and tm_year at 1900
All over the code there were incorrect assumptions about the offsets in `struct tm`
This commit is contained in:
@@ -486,7 +486,7 @@ void TinyGPSDate::commit()
|
||||
}
|
||||
{
|
||||
const uint16_t newyear = year();
|
||||
if (newyear < 2020) {
|
||||
if (newyear < 2021) {
|
||||
// Looks like it is an old GPS unit not working well with the 1024 week rollover.
|
||||
struct tm tm;
|
||||
tm.tm_year = newyear - 1900;
|
||||
|
||||
@@ -71,8 +71,8 @@ String Command_DateTime(struct EventStruct *event, const char *Line)
|
||||
struct tm tm;
|
||||
int yr, mnth, d;
|
||||
sscanf(TmpStr1.c_str(), "%4d-%2d-%2d", &yr, &mnth, &d);
|
||||
tm.tm_year = yr - 1970;
|
||||
tm.tm_mon = mnth;
|
||||
tm.tm_year = yr - 1900;
|
||||
tm.tm_mon = mnth - 1; // tm_mon starts at 0
|
||||
tm.tm_mday = d;
|
||||
|
||||
if (GetArgv(Line, TmpStr1, 3)) {
|
||||
|
||||
@@ -40,13 +40,9 @@ struct tm ESPEasy_time::addSeconds(const struct tm& ts, int seconds, bool toLoca
|
||||
|
||||
|
||||
void ESPEasy_time::breakTime(unsigned long timeInput, struct tm& tm) {
|
||||
uint8_t year;
|
||||
uint8_t month, monthLength;
|
||||
uint32_t time;
|
||||
unsigned long days;
|
||||
const uint8_t monthDays[] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
|
||||
|
||||
time = (uint32_t)timeInput;
|
||||
uint32_t time = (uint32_t)timeInput;
|
||||
tm.tm_sec = time % 60;
|
||||
time /= 60; // now it is minutes
|
||||
tm.tm_min = time % 60;
|
||||
@@ -55,30 +51,21 @@ void ESPEasy_time::breakTime(unsigned long timeInput, struct tm& tm) {
|
||||
time /= 24; // now it is days
|
||||
tm.tm_wday = ((time + 4) % 7) + 1; // Sunday is day 1
|
||||
|
||||
year = 0;
|
||||
days = 0;
|
||||
|
||||
int year = 1970;
|
||||
unsigned long days = 0;
|
||||
while ((unsigned)(days += (isLeapYear(year) ? 366 : 365)) <= time) {
|
||||
year++;
|
||||
}
|
||||
tm.tm_year = year; // year is offset from 1970
|
||||
tm.tm_year = year - 1900; // tm_year starts at 1900
|
||||
|
||||
days -= isLeapYear(year) ? 366 : 365;
|
||||
time -= days; // now it is days in this year, starting at 0
|
||||
|
||||
days = 0;
|
||||
month = 0;
|
||||
monthLength = 0;
|
||||
|
||||
uint8_t month = 0;
|
||||
for (month = 0; month < 12; month++) {
|
||||
if (month == 1) { // february
|
||||
if (isLeapYear(year)) {
|
||||
monthLength = 29;
|
||||
} else {
|
||||
monthLength = 28;
|
||||
}
|
||||
} else {
|
||||
monthLength = monthDays[month];
|
||||
uint8_t monthLength = monthDays[month];
|
||||
if (month == 1 && isLeapYear(year)) { // February
|
||||
monthLength = 29;
|
||||
}
|
||||
|
||||
if (time >= monthLength) {
|
||||
@@ -87,8 +74,8 @@ void ESPEasy_time::breakTime(unsigned long timeInput, struct tm& tm) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
tm.tm_mon = month + 1; // jan is month 1
|
||||
tm.tm_mday = time + 1; // day of month
|
||||
tm.tm_mon = month; // Jan is month 0
|
||||
tm.tm_mday = time + 1; // day of month start at 1
|
||||
}
|
||||
|
||||
|
||||
@@ -415,9 +402,9 @@ String ESPEasy_time::getDateString(char delimiter) const
|
||||
String ESPEasy_time::getDateString(const struct tm& ts, char delimiter) {
|
||||
// time format example with ':' delimiter: 23:59:59 (HH:MM:SS)
|
||||
char DateString[20]; // 19 digits plus the null char
|
||||
const int year = 1970 + ts.tm_year;
|
||||
const int year = 1900 + ts.tm_year;
|
||||
|
||||
sprintf_P(DateString, PSTR("%4d%c%02d%c%02d"), year, delimiter, ts.tm_mon, delimiter, ts.tm_mday);
|
||||
sprintf_P(DateString, PSTR("%4d%c%02d%c%02d"), year, delimiter, ts.tm_mon + 1, delimiter, ts.tm_mday);
|
||||
return DateString;
|
||||
}
|
||||
|
||||
@@ -494,7 +481,7 @@ int ESPEasy_time::year(unsigned long t)
|
||||
struct tm tmp;
|
||||
|
||||
breakTime(t, tmp);
|
||||
return 1970 + tmp.tm_year;
|
||||
return 1900 + tmp.tm_year;
|
||||
}
|
||||
|
||||
int ESPEasy_time::weekday(unsigned long t)
|
||||
@@ -615,7 +602,7 @@ int ESPEasy_time::dayOfYear(int year, int month, int day) {
|
||||
}
|
||||
|
||||
void ESPEasy_time::calcSunRiseAndSet() {
|
||||
int doy = dayOfYear(tm.tm_year, tm.tm_mon, tm.tm_mday);
|
||||
int doy = dayOfYear(tm.tm_year, tm.tm_mon + 1, tm.tm_mday);
|
||||
float eqt = equationOfTime(doy);
|
||||
float dec = sunDeclination(doy);
|
||||
float da = diurnalArc(dec, Settings.Latitude);
|
||||
|
||||
@@ -94,13 +94,13 @@ static String weekday_str(int wday);
|
||||
// Get current year.
|
||||
int year() const
|
||||
{
|
||||
return 1970 + tm.tm_year;
|
||||
return 1900 + tm.tm_year;
|
||||
}
|
||||
|
||||
// Get current month
|
||||
byte month() const
|
||||
{
|
||||
return tm.tm_mon;
|
||||
return tm.tm_mon + 1; // tm_mon starts at 0
|
||||
}
|
||||
|
||||
// Get current day of the month
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
|
||||
|
||||
bool isLeapYear(int year) {
|
||||
return (((1970 + year) > 0) && !((1970 + year) % 4) && (((1970 + year) % 100) || !((1970 + year) % 400)));
|
||||
return ((year > 0) && !(year % 4) && ((year % 100) || !(year % 400)));
|
||||
}
|
||||
|
||||
/********************************************************************************************\
|
||||
@@ -25,24 +25,24 @@ uint32_t makeTime(const struct tm& tm) {
|
||||
// note year argument is offset from 1970 (see macros in time.h to convert to other formats)
|
||||
// previous version used full four digit year (or digits since 2000),i.e. 2009 was 2009 or 9
|
||||
const uint8_t monthDays[] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
|
||||
int i;
|
||||
uint32_t seconds;
|
||||
|
||||
// seconds from 1970 till 1 jan 00:00:00 of the given year
|
||||
seconds = tm.tm_year * (SECS_PER_DAY * 365);
|
||||
|
||||
for (i = 0; i < tm.tm_year; i++) {
|
||||
// tm_year starts at 1900
|
||||
uint32_t seconds = 1577836800; // 01/01/2020 @ 12:00am (UTC)
|
||||
for (int i = 2020; i < (tm.tm_year + 1900); ++i) {
|
||||
seconds += SECS_PER_DAY * 365;
|
||||
if (isLeapYear(i)) {
|
||||
seconds += SECS_PER_DAY; // add extra days for leap years
|
||||
seconds += SECS_PER_DAY; // add extra days for leap years
|
||||
}
|
||||
}
|
||||
|
||||
// add days for this year, months start from 1
|
||||
for (i = 1; i < tm.tm_mon; i++) {
|
||||
if ((i == 2) && isLeapYear(tm.tm_year)) {
|
||||
// add days for this year, months start from 0
|
||||
for (int i = 0; i < tm.tm_mon; i++) {
|
||||
// Check for February
|
||||
if ((i == 1) && isLeapYear(tm.tm_year + 1900)) {
|
||||
seconds += SECS_PER_DAY * 29;
|
||||
} else {
|
||||
seconds += SECS_PER_DAY * monthDays[i - 1]; // monthDay array starts from 0
|
||||
seconds += SECS_PER_DAY * monthDays[i];
|
||||
}
|
||||
}
|
||||
seconds += (tm.tm_mday - 1) * SECS_PER_DAY;
|
||||
|
||||
@@ -90,7 +90,7 @@ void ESPEasy_time_zone::logTimeZoneInfo() {
|
||||
// *----------------------------------------------------------------------*/
|
||||
uint32_t ESPEasy_time_zone::calcTimeChangeForRule(const TimeChangeRule& r, int yr)
|
||||
{
|
||||
uint8_t m = r.month; // temp copies of r.month and r.week
|
||||
uint8_t m = r.month;
|
||||
uint8_t w = r.week;
|
||||
|
||||
if (w == 0) // is this a "Last week" rule?
|
||||
@@ -109,8 +109,8 @@ uint32_t ESPEasy_time_zone::calcTimeChangeForRule(const TimeChangeRule& r, int y
|
||||
tm.tm_min = 0;
|
||||
tm.tm_sec = 0;
|
||||
tm.tm_mday = 1;
|
||||
tm.tm_mon = m;
|
||||
tm.tm_year = yr - 1970;
|
||||
tm.tm_mon = m - 1; // TimeChangeRule month starts at 1
|
||||
tm.tm_year = yr - 1900;
|
||||
uint32_t t = makeTime(tm);
|
||||
|
||||
// add offset from the first of the month to r.dow, and offset for the given week
|
||||
|
||||
@@ -161,8 +161,8 @@ bool P082_data_struct::getDateTime(struct tm& dateTime, uint32_t& age, bool& pps
|
||||
if (!gps->date.isValid() || !gps->time.isValid()) {
|
||||
return false;
|
||||
}
|
||||
dateTime.tm_year = gps->date.year() - 1970;
|
||||
dateTime.tm_mon = gps->date.month();
|
||||
dateTime.tm_year = gps->date.year() - 1900;
|
||||
dateTime.tm_mon = gps->date.month() - 1; // GPS month starts at 1, tm_mon at 0
|
||||
dateTime.tm_mday = gps->date.day();
|
||||
|
||||
dateTime.tm_hour = gps->time.hour();
|
||||
|
||||
Reference in New Issue
Block a user