mirror of
https://github.com/curl/curl.git
synced 2026-04-14 22:51:53 +03:00
parsedate: bsearch the time zones
There are 69 entries, bsearch is faster than linear search for random access. This now also makes the matching case sensitive (zone names always in uppercase). No docs said otherwise and all tests assumed uppercase. Extended test 517 Closes #21266
This commit is contained in:
parent
5d84aa41a0
commit
283db12e05
2 changed files with 84 additions and 84 deletions
131
lib/parsedate.c
131
lib/parsedate.c
|
|
@ -25,6 +25,7 @@
|
||||||
|
|
||||||
#include "parsedate.h"
|
#include "parsedate.h"
|
||||||
#include "curlx/strparse.h"
|
#include "curlx/strparse.h"
|
||||||
|
#include "curlx/strcopy.h"
|
||||||
|
|
||||||
/*
|
/*
|
||||||
A brief summary of the date string formats this parser groks:
|
A brief summary of the date string formats this parser groks:
|
||||||
|
|
@ -108,88 +109,82 @@ static const char * const weekday[] = {
|
||||||
|
|
||||||
struct tzinfo {
|
struct tzinfo {
|
||||||
char name[5];
|
char name[5];
|
||||||
int offset; /* +/- in minutes */
|
int16_t offset; /* +/- in minutes */
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Here's a bunch of frequently used time zone names. These were supported
|
|
||||||
by the old getdate parser. */
|
|
||||||
#define tDAYZONE (-60) /* offset for daylight savings time */
|
#define tDAYZONE (-60) /* offset for daylight savings time */
|
||||||
|
|
||||||
|
/* alpha-sorted list of time zones */
|
||||||
static const struct tzinfo tz[] = {
|
static const struct tzinfo tz[] = {
|
||||||
{ "GMT", 0 }, /* Greenwich Mean */
|
|
||||||
{ "UT", 0 }, /* Universal Time */
|
|
||||||
{ "UTC", 0 }, /* Universal (Coordinated) */
|
|
||||||
{ "WET", 0 }, /* Western European */
|
|
||||||
{ "BST", 0 + tDAYZONE }, /* British Summer */
|
|
||||||
{ "WAT", 60 }, /* West Africa */
|
|
||||||
{ "AST", 240 }, /* Atlantic Standard */
|
|
||||||
{ "ADT", 240 + tDAYZONE }, /* Atlantic Daylight */
|
|
||||||
{ "EST", 300 }, /* Eastern Standard */
|
|
||||||
{ "EDT", 300 + tDAYZONE }, /* Eastern Daylight */
|
|
||||||
{ "CST", 360 }, /* Central Standard */
|
|
||||||
{ "CDT", 360 + tDAYZONE }, /* Central Daylight */
|
|
||||||
{ "MST", 420 }, /* Mountain Standard */
|
|
||||||
{ "MDT", 420 + tDAYZONE }, /* Mountain Daylight */
|
|
||||||
{ "PST", 480 }, /* Pacific Standard */
|
|
||||||
{ "PDT", 480 + tDAYZONE }, /* Pacific Daylight */
|
|
||||||
{ "YST", 540 }, /* Yukon Standard */
|
|
||||||
{ "YDT", 540 + tDAYZONE }, /* Yukon Daylight */
|
|
||||||
{ "HST", 600 }, /* Hawaii Standard */
|
|
||||||
{ "HDT", 600 + tDAYZONE }, /* Hawaii Daylight */
|
|
||||||
{ "CAT", 600 }, /* Central Alaska */
|
|
||||||
{ "AHST", 600 }, /* Alaska-Hawaii Standard */
|
|
||||||
{ "NT", 660 }, /* Nome */ /* spellchecker:disable-line */
|
|
||||||
{ "IDLW", 720 }, /* International Date Line West */
|
|
||||||
{ "CET", -60 }, /* Central European */
|
|
||||||
{ "MET", -60 }, /* Middle European */
|
|
||||||
{ "MEWT", -60 }, /* Middle European Winter */
|
|
||||||
{ "MEST", -60 + tDAYZONE }, /* Middle European Summer */
|
|
||||||
{ "CEST", -60 + tDAYZONE }, /* Central European Summer */
|
|
||||||
{ "MESZ", -60 + tDAYZONE }, /* Middle European Summer */
|
|
||||||
{ "FWT", -60 }, /* French Winter */
|
|
||||||
{ "FST", -60 + tDAYZONE }, /* French Summer */
|
|
||||||
{ "EET", -120 }, /* Eastern Europe, USSR Zone 1 */
|
|
||||||
{ "WAST", -420 }, /* spellchecker:disable-line */
|
|
||||||
/* West Australian Standard */
|
|
||||||
{ "WADT", -420 + tDAYZONE }, /* West Australian Daylight */
|
|
||||||
{ "CCT", -480 }, /* China Coast, USSR Zone 7 */
|
|
||||||
{ "JST", -540 }, /* Japan Standard, USSR Zone 8 */
|
|
||||||
{ "EAST", -600 }, /* Eastern Australian Standard */
|
|
||||||
{ "EADT", -600 + tDAYZONE }, /* Eastern Australian Daylight */
|
|
||||||
{ "GST", -600 }, /* Guam Standard, USSR Zone 9 */
|
|
||||||
{ "NZT", -720 }, /* New Zealand */
|
|
||||||
{ "NZST", -720 }, /* New Zealand Standard */
|
|
||||||
{ "NZDT", -720 + tDAYZONE }, /* New Zealand Daylight */
|
|
||||||
{ "IDLE", -720 }, /* International Date Line East */
|
|
||||||
/* Next up: Military timezone names. RFC822 allowed these, but (as noted in
|
|
||||||
RFC 1123) had their signs wrong. Here we use the correct signs to match
|
|
||||||
actual military usage.
|
|
||||||
*/
|
|
||||||
{ "A", -1 * 60 }, /* Alpha */
|
{ "A", -1 * 60 }, /* Alpha */
|
||||||
|
{ "ADT", 240 + tDAYZONE }, /* Atlantic Daylight */
|
||||||
|
{ "AHST", 600 }, /* Alaska-Hawaii Standard */
|
||||||
|
{ "AST", 240 }, /* Atlantic Standard */
|
||||||
{ "B", -2 * 60 }, /* Bravo */
|
{ "B", -2 * 60 }, /* Bravo */
|
||||||
|
{ "BST", 0 + tDAYZONE }, /* British Summer */
|
||||||
{ "C", -3 * 60 }, /* Charlie */
|
{ "C", -3 * 60 }, /* Charlie */
|
||||||
|
{ "CAT", 600 }, /* Central Alaska */
|
||||||
|
{ "CCT", -480 }, /* China Coast, USSR Zone 7 */
|
||||||
|
{ "CDT", 360 + tDAYZONE }, /* Central Daylight */
|
||||||
|
{ "CEST", -60 + tDAYZONE }, /* Central European Summer */
|
||||||
|
{ "CET", -60 }, /* Central European */
|
||||||
|
{ "CST", 360 }, /* Central Standard */
|
||||||
{ "D", -4 * 60 }, /* Delta */
|
{ "D", -4 * 60 }, /* Delta */
|
||||||
{ "E", -5 * 60 }, /* Echo */
|
{ "E", -5 * 60 }, /* Echo */
|
||||||
|
{ "EADT", -600 + tDAYZONE }, /* Eastern Australian Daylight */
|
||||||
|
{ "EAST", -600 }, /* Eastern Australian Standard */
|
||||||
|
{ "EDT", 300 + tDAYZONE }, /* Eastern Daylight */
|
||||||
|
{ "EET", -120 }, /* Eastern Europe, USSR Zone 1 */
|
||||||
|
{ "EST", 300 }, /* Eastern Standard */
|
||||||
{ "F", -6 * 60 }, /* Foxtrot */
|
{ "F", -6 * 60 }, /* Foxtrot */
|
||||||
|
{ "FST", -60 + tDAYZONE }, /* French Summer */
|
||||||
|
{ "FWT", -60 }, /* French Winter */
|
||||||
{ "G", -7 * 60 }, /* Golf */
|
{ "G", -7 * 60 }, /* Golf */
|
||||||
|
{ "GMT", 0 }, /* Greenwich Mean */
|
||||||
|
{ "GST", -600 }, /* Guam Standard, USSR Zone 9 */
|
||||||
{ "H", -8 * 60 }, /* Hotel */
|
{ "H", -8 * 60 }, /* Hotel */
|
||||||
|
{ "HDT", 600 + tDAYZONE }, /* Hawaii Daylight */
|
||||||
|
{ "HST", 600 }, /* Hawaii Standard */
|
||||||
{ "I", -9 * 60 }, /* India */
|
{ "I", -9 * 60 }, /* India */
|
||||||
/* "J", Juliet is not used as a timezone, to indicate the observer's local
|
{ "IDLE", -720 }, /* International Date Line East */
|
||||||
time */
|
{ "IDLW", 720 }, /* International Date Line West */
|
||||||
|
{ "JST", -540 }, /* Japan Standard, USSR Zone 8 */
|
||||||
{ "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 */
|
{ "MDT", 420 + tDAYZONE }, /* Mountain Daylight */
|
||||||
|
{ "MEST", -60 + tDAYZONE }, /* Middle European Summer */
|
||||||
|
{ "MESZ", -60 + tDAYZONE }, /* Middle European Summer */
|
||||||
|
{ "MET", -60 }, /* Middle European */
|
||||||
|
{ "MEWT", -60 }, /* Middle European Winter */
|
||||||
|
{ "MST", 420 }, /* Mountain Standard */
|
||||||
|
{ "N", 60 }, /* November */
|
||||||
|
{ "NT", 660 }, /* Nome */ /* spellchecker:disable-line */
|
||||||
|
{ "NZDT", -720 + tDAYZONE }, /* New Zealand Daylight */
|
||||||
|
{ "NZST", -720 }, /* New Zealand Standard */
|
||||||
|
{ "NZT", -720 }, /* New Zealand */
|
||||||
{ "O", 2 * 60 }, /* Oscar */
|
{ "O", 2 * 60 }, /* Oscar */
|
||||||
{ "P", 3 * 60 }, /* Papa */
|
{ "P", 3 * 60 }, /* Papa */
|
||||||
|
{ "PDT", 480 + tDAYZONE }, /* Pacific Daylight */
|
||||||
|
{ "PST", 480 }, /* Pacific Standard */
|
||||||
{ "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 */
|
||||||
|
{ "UT", 0 }, /* Universal Time */
|
||||||
|
{ "UTC", 0 }, /* Universal (Coordinated) */
|
||||||
{ "V", 9 * 60 }, /* Victor */
|
{ "V", 9 * 60 }, /* Victor */
|
||||||
{ "W", 10 * 60 }, /* Whiskey */
|
{ "W", 10 * 60 }, /* Whiskey */
|
||||||
|
{ "WADT", -420 + tDAYZONE }, /* West Australian Daylight */
|
||||||
|
{ "WAST", -420 }, /* spellchecker:disable-line */
|
||||||
|
/* West Australian Standard */
|
||||||
|
{ "WAT", 60 }, /* West Africa */
|
||||||
|
{ "WET", 0 }, /* Western European */
|
||||||
{ "X", 11 * 60 }, /* X-ray */
|
{ "X", 11 * 60 }, /* X-ray */
|
||||||
{ "Y", 12 * 60 }, /* Yankee */
|
{ "Y", 12 * 60 }, /* Yankee */
|
||||||
|
{ "YDT", 540 + tDAYZONE }, /* Yukon Daylight */
|
||||||
|
{ "YST", 540 }, /* Yukon Standard */
|
||||||
{ "Z", 0 }, /* Zulu, zero meridian, a.k.a. UTC */
|
{ "Z", 0 }, /* Zulu, zero meridian, a.k.a. UTC */
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -233,22 +228,24 @@ static int checkmonth(const char *check, size_t len)
|
||||||
return -1; /* return the offset or -1, no real offset is -1 */
|
return -1; /* return the offset or -1, no real offset is -1 */
|
||||||
}
|
}
|
||||||
|
|
||||||
/* return the time zone offset between GMT and the input one, in number
|
static int tzcompare(const void *m1, const void *m2)
|
||||||
of seconds or -1 if the timezone was not found/legal */
|
{
|
||||||
|
const struct tzinfo *tz1 = m1;
|
||||||
|
const struct tzinfo *tz2 = m2;
|
||||||
|
return strcmp(tz1->name, tz2->name);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* return the time zone offset between GMT and the input one, in number of
|
||||||
|
seconds or -1 if the timezone was not found/legal */
|
||||||
static int checktz(const char *check, size_t len)
|
static int checktz(const char *check, size_t len)
|
||||||
{
|
{
|
||||||
unsigned int i;
|
if(len <= 4) {
|
||||||
const struct tzinfo *what = tz;
|
const struct tzinfo *what;
|
||||||
if(len > 4) /* longer than any valid timezone */
|
struct tzinfo find;
|
||||||
return -1;
|
curlx_strcopy(find.name, sizeof(find.name), check, len);
|
||||||
|
what = bsearch(&find, tz, CURL_ARRAYSIZE(tz), sizeof(tz[0]), tzcompare);
|
||||||
for(i = 0; i < CURL_ARRAYSIZE(tz); i++) {
|
if(what)
|
||||||
size_t ilen = strlen(what->name);
|
|
||||||
if((ilen == len) &&
|
|
||||||
curl_strnequal(check, what->name, len))
|
|
||||||
return what->offset * 60;
|
return what->offset * 60;
|
||||||
what++;
|
|
||||||
}
|
}
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -52,6 +52,9 @@ static CURLcode test_lib517(const char *URL)
|
||||||
{ "1994.Nov.6", 784080000 },
|
{ "1994.Nov.6", 784080000 },
|
||||||
{ "Sun/Nov/6/94/GMT", 784080000 },
|
{ "Sun/Nov/6/94/GMT", 784080000 },
|
||||||
{ "Sun, 06 Nov 1994 08:49:37 CET", 784108177 },
|
{ "Sun, 06 Nov 1994 08:49:37 CET", 784108177 },
|
||||||
|
{ "Sun, 06 Nov 1994 08:49:37 cet", -1 }, /* lowercase time zone */
|
||||||
|
{ "Sun, 06 Nov 1994 08:49:37 utc", -1 }, /* lowercase time zone */
|
||||||
|
{ "Sun, 06 Nov 1994 08:49:37 gmt", -1 }, /* lowercase time zone */
|
||||||
{ "06 Nov 1994 08:49:37 EST", 784129777 },
|
{ "06 Nov 1994 08:49:37 EST", 784129777 },
|
||||||
{ "Sun, 06 Nov 1994 08:49:37 UT", 784111777 },
|
{ "Sun, 06 Nov 1994 08:49:37 UT", 784111777 },
|
||||||
{ "Sun, 12 Sep 2004 15:05:58 -0700", 1095026758 },
|
{ "Sun, 12 Sep 2004 15:05:58 -0700", 1095026758 },
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue