parsedate: clarify time2epoch and add more variations to test 517

Polish the time2epoch function to become a little more readable.

Corrected the military time zones: they were going in the wrong
direction.

Add more curl_getdate() input varations to test 517

Closes #21251
This commit is contained in:
Daniel Stenberg 2026-04-07 11:11:38 +02:00
parent 09f9035045
commit 3536730f33
No known key found for this signature in database
GPG key ID: 5CC908FDB71E12C2
2 changed files with 109 additions and 33 deletions

View file

@ -164,33 +164,33 @@ static const struct tzinfo tz[] = {
RFC 1123) had their signs wrong. Here we use the correct signs to match RFC 1123) had their signs wrong. Here we use the correct signs to match
actual military usage. actual military usage.
*/ */
{ "A", 1 * 60 }, /* Alpha */ { "A", -1 * 60 }, /* Alpha */
{ "B", 2 * 60 }, /* Bravo */ { "B", -2 * 60 }, /* Bravo */
{ "C", 3 * 60 }, /* Charlie */ { "C", -3 * 60 }, /* Charlie */
{ "D", 4 * 60 }, /* Delta */ { "D", -4 * 60 }, /* Delta */
{ "E", 5 * 60 }, /* Echo */ { "E", -5 * 60 }, /* Echo */
{ "F", 6 * 60 }, /* Foxtrot */ { "F", -6 * 60 }, /* Foxtrot */
{ "G", 7 * 60 }, /* Golf */ { "G", -7 * 60 }, /* Golf */
{ "H", 8 * 60 }, /* Hotel */ { "H", -8 * 60 }, /* Hotel */
{ "I", 9 * 60 }, /* India */ { "I", -9 * 60 }, /* India */
/* "J", Juliet is not used as a timezone, to indicate the observer's local /* "J", Juliet is not used as a timezone, to indicate the observer's local
time */ time */
{ "K", 10 * 60 }, /* Kilo */ { "K", -10 * 60 }, /* Kilo */
{ "L", 11 * 60 }, /* Lima */ { "L", -11 * 60 }, /* Lima */
{ "M", 12 * 60 }, /* Mike */ { "M", -12 * 60 }, /* Mike */
{ "N", -1 * 60 }, /* November */ { "N", 1 * 60 }, /* November */
{ "O", -2 * 60 }, /* Oscar */ { "O", 2 * 60 }, /* Oscar */
{ "P", -3 * 60 }, /* Papa */ { "P", 3 * 60 }, /* Papa */
{ "Q", -4 * 60 }, /* Quebec */ { "Q", 4 * 60 }, /* Quebec */
{ "R", -5 * 60 }, /* Romeo */ { "R", 5 * 60 }, /* Romeo */
{ "S", -6 * 60 }, /* Sierra */ { "S", 6 * 60 }, /* Sierra */
{ "T", -7 * 60 }, /* Tango */ { "T", 7 * 60 }, /* Tango */
{ "U", -8 * 60 }, /* Uniform */ { "U", 8 * 60 }, /* Uniform */
{ "V", -9 * 60 }, /* Victor */ { "V", 9 * 60 }, /* Victor */
{ "W", -10 * 60 }, /* Whiskey */ { "W", 10 * 60 }, /* Whiskey */
{ "X", -11 * 60 }, /* X-ray */ { "X", 11 * 60 }, /* X-ray */
{ "Y", -12 * 60 }, /* Yankee */ { "Y", 12 * 60 }, /* Yankee */
{ "Z", 0 }, /* Zulu, zero meridian, a.k.a. UTC */ { "Z", 0 }, /* Zulu, zero meridian, a.k.a. UTC */
}; };
/* returns: /* returns:
@ -266,6 +266,9 @@ enum assume {
DATE_TIME DATE_TIME
}; };
/* (1969 / 4) - (1969 / 100) + (1969 / 400) = 492 - 19 + 4 = 477 */
#define LEAP_DAYS_BEFORE_1969 477
/* /*
* time2epoch: time stamp to seconds since epoch in GMT time zone. Similar to * time2epoch: time stamp to seconds since epoch in GMT time zone. Similar to
* mktime but for GMT only. * mktime but for GMT only.
@ -273,16 +276,15 @@ enum assume {
static time_t time2epoch(int sec, int min, int hour, static time_t time2epoch(int sec, int min, int hour,
int mday, int mon, int year) int mday, int mon, int year)
{ {
static const int month_days_cumulative[12] = { static const int cumulative_days[12] = {
0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334
}; };
int leap_days = year - (mon <= 1); int y = year - (mon <= 1);
leap_days = ((leap_days / 4) - (leap_days / 100) + (leap_days / 400) int leap_days = (y / 4) - (y / 100) + (y / 400) - LEAP_DAYS_BEFORE_1969;
- (1969 / 4) + (1969 / 100) - (1969 / 400)); time_t days = (time_t)(year - 1970) * 365 + leap_days +
return ((((((((time_t)(year - 1970) * 365) cumulative_days[mon] + mday - 1;
+ leap_days + month_days_cumulative[mon] + mday - 1) * 24)
+ hour) * 60) return (((days * 24 + hour) * 60 + min) * 60) + sec;
+ min) * 60) + sec;
} }
/* Returns the value of a single-digit or two-digit decimal number, return /* Returns the value of a single-digit or two-digit decimal number, return

View file

@ -156,6 +156,80 @@ static CURLcode test_lib517(const char *URL)
#ifndef HAVE_TIME_T_UNSIGNED #ifndef HAVE_TIME_T_UNSIGNED
{ "Sun, 06 Nov 1968 08:49:37 GMT", -36342623 }, { "Sun, 06 Nov 1968 08:49:37 GMT", -36342623 },
#endif /* !HAVE_TIME_T_UNSIGNED */ #endif /* !HAVE_TIME_T_UNSIGNED */
#if SIZEOF_TIME_T > 4
{ "2094 Nov 6 08:49:37", 3939871777 },
#endif
{ "01 Jan 2001 8:0:0", 978336000},
{ "01 Jan 2001 8:00:0", 978336000},
/* Out-of-range day-of-month Cases */
{ "29 Feb 2023 12:00:00 GMT", 1677672000},
{ "31 Apr 2024 12:00:00 GMT", 1714564800},
{ "30 Feb 2024 12:00:00 GMT", 1709294400},
{ "01-13-2024", -1},
{ "32 Jan 2024", -1},
{ "31 Jan 2024", 1706659200},
{ "32 Feb 2024", -1},
{ "32 Mar 2024", -1},
{ "32 Apr 2024", -1},
{ "32 May 2024", -1},
{ "32 Jun 2024", -1},
{ "32 Jul 2024", -1},
{ "32 Aug 2024", -1},
{ "32 Sep 2024", -1},
{ "32 Oct 2024", -1},
{ "32 Nov 2024", -1},
{ "32 Dec 2024", -1},
/* Timezone Offsets */
{ "Sun, 06 Nov 1994 08:49:37 +0530", 784091977 },
{ "Sun, 06 Nov 1994 08:49:37 +0545", 784091077 },
{ "06 Nov 1994 08:49:37 Z", 784111777 },
{ "06 Nov 1994 08:49:37 A", 784108177 },
{ "06 Nov 1994 08:49:37 B", 784104577 },
{ "06 Nov 1994 08:49:37 C", 784100977 },
{ "06 Nov 1994 08:49:37 D", 784097377 },
{ "06 Nov 1994 08:49:37 E", 784093777 },
{ "06 Nov 1994 08:49:37 F", 784090177 },
{ "06 Nov 1994 08:49:37 G", 784086577 },
{ "06 Nov 1994 08:49:37 H", 784082977 },
{ "06 Nov 1994 08:49:37 I", 784079377 },
{ "06 Nov 1994 08:49:37 J", -1 }, /* not a valid time zone */
{ "06 Nov 1994 08:49:37 K", 784075777 },
{ "06 Nov 1994 08:49:37 L", 784072177 },
{ "06 Nov 1994 08:49:37 M", 784068577 },
{ "06 Nov 1994 08:49:37 N", 784115377 },
{ "06 Nov 1994 08:49:37 O", 784118977 },
{ "06 Nov 1994 08:49:37 P", 784122577 },
{ "06 Nov 1994 08:49:37 Q", 784126177 },
{ "06 Nov 1994 08:49:37 R", 784129777 },
{ "06 Nov 1994 08:49:37 S", 784133377 },
{ "06 Nov 1994 08:49:37 T", 784136977 },
{ "06 Nov 1994 08:49:37 U", 784140577 },
{ "06 Nov 1994 08:49:37 V", 784144177 },
{ "06 Nov 1994 08:49:37 W", 784147777 },
{ "06 Nov 1994 08:49:37 X", 784151377 },
{ "06 Nov 1994 08:49:37 Y", 784154977 },
{ "GMT+05:30", -1 },
{ "GMT-08:00", -1 },
/* ISO 8601 & Variations - not supported */
{ "1994-11-06T08:49:37Z", -1 },
{ "1994-11-06 08:49:37.123 GMT", -1 },
{ "19941106T084937Z", -1 },
/* Y2K38 & Historical Boundaries */
#if SIZEOF_TIME_T > 4
/* for 32 bit time_t, we bail on >year 2037 */
{ "19 Jan 2038 03:14:07 GMT", 2147483647},
{ "19 Jan 2038 03:14:08 GMT", 2147483648},
{ "01 Jan 69 00:00:00 GMT", 3124224000},
#endif
{ "01 Jan 1500 00:00:00 GMT", -1},
/* Formatting & Malformed Junk */
{ "Sun, 06-Nov/1994 08:49:37", 784111777},
{ "Sun, 06 Nov 1994 08:49:37 GMT", 784111777},
{ " Sun, 06 Nov 1994 08:49:37 GMT ", 784111777},
{ "Date: Sun, 06 Nov 1994 08:49:37 GMT", -1},
/* wrong day name is ignored */
{ "Monday, 06 Nov 1994 08:49:37 GMT", 784111777},
{ NULL, 0 } { NULL, 0 }
}; };