Correct the calculation of "a leap year" in parseDWM. The calculation
would only match a leap year every 400 years. The parseDWM code first showed up in April 2000, so the first time this bug would cause any confusion is in Feb 2004. MFC after: 18 days
This commit is contained in:
parent
5cd10ac5d9
commit
526d55a405
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=120046
@ -48,6 +48,42 @@ __FBSDID("$FreeBSD$");
|
||||
|
||||
#include "extern.h"
|
||||
|
||||
static int days_pmonth(int month, int year);
|
||||
|
||||
/*
|
||||
* Simple routine to calculate the number of days in a given month.
|
||||
*/
|
||||
static int
|
||||
days_pmonth(int month, int year)
|
||||
{
|
||||
static const int mtab[] = {31, 28, 31, 30, 31, 30, 31, 31,
|
||||
30, 31, 30, 31};
|
||||
int ndays;
|
||||
|
||||
ndays = mtab[month];
|
||||
|
||||
if (month == 1) {
|
||||
/*
|
||||
* We are usually called with a 'tm-year' value
|
||||
* (ie, the value = the number of years past 1900).
|
||||
*/
|
||||
if (year < 1900)
|
||||
year += 1900;
|
||||
if (year % 4 == 0) {
|
||||
/*
|
||||
* This is a leap year, as long as it is not a
|
||||
* multiple of 100, or if it is a multiple of
|
||||
* both 100 and 400.
|
||||
*/
|
||||
if (year % 100 != 0)
|
||||
ndays++; /* not multiple of 100 */
|
||||
else if (year % 400 == 0)
|
||||
ndays++; /* is multiple of 100 and 400 */
|
||||
}
|
||||
}
|
||||
return (ndays);
|
||||
}
|
||||
|
||||
/*-
|
||||
* Parse a limited subset of ISO 8601. The specific format is as follows:
|
||||
*
|
||||
@ -158,12 +194,11 @@ parse8601(const char *s, time_t *next_time)
|
||||
time_t
|
||||
parseDWM(char *s, time_t *next_time)
|
||||
{
|
||||
int daysmon;
|
||||
char *t;
|
||||
time_t tsecs;
|
||||
struct tm tm, *tmp;
|
||||
long l;
|
||||
int nd;
|
||||
static int mtab[] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
|
||||
int WMseen = 0;
|
||||
int Dseen = 0;
|
||||
|
||||
@ -172,17 +207,8 @@ parseDWM(char *s, time_t *next_time)
|
||||
if (next_time != NULL)
|
||||
*next_time = (time_t)-1;
|
||||
|
||||
/* set no. of days per month */
|
||||
|
||||
nd = mtab[tm.tm_mon];
|
||||
|
||||
if (tm.tm_mon == 1) {
|
||||
if (((tm.tm_year + 1900) % 4 == 0) &&
|
||||
((tm.tm_year + 1900) % 100 != 0) &&
|
||||
((tm.tm_year + 1900) % 400 == 0)) {
|
||||
nd++; /* leap year, 29 days in february */
|
||||
}
|
||||
}
|
||||
/* Save away the number of days in this month */
|
||||
daysmon = days_pmonth(tm.tm_mon, tm.tm_year);
|
||||
tm.tm_hour = tm.tm_min = tm.tm_sec = 0;
|
||||
|
||||
for (;;) {
|
||||
@ -218,9 +244,9 @@ parseDWM(char *s, time_t *next_time)
|
||||
|
||||
tm.tm_mday += save;
|
||||
|
||||
if (tm.tm_mday > nd) {
|
||||
if (tm.tm_mday > daysmon) {
|
||||
tm.tm_mon++;
|
||||
tm.tm_mday = tm.tm_mday - nd;
|
||||
tm.tm_mday = tm.tm_mday - daysmon;
|
||||
}
|
||||
}
|
||||
break;
|
||||
@ -231,7 +257,7 @@ parseDWM(char *s, time_t *next_time)
|
||||
WMseen++;
|
||||
s++;
|
||||
if (tolower(*s) == 'l') {
|
||||
tm.tm_mday = nd;
|
||||
tm.tm_mday = daysmon;
|
||||
s++;
|
||||
t = s;
|
||||
} else {
|
||||
@ -239,7 +265,7 @@ parseDWM(char *s, time_t *next_time)
|
||||
if (l < 1 || l > 31)
|
||||
return (-1);
|
||||
|
||||
if (l > nd)
|
||||
if (l > daysmon)
|
||||
return (-1);
|
||||
tm.tm_mday = l;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user