diff options
author | Daniel Stenberg <daniel@haxx.se> | 2020-09-21 12:55:38 +0200 |
---|---|---|
committer | Daniel Stenberg <daniel@haxx.se> | 2020-09-21 16:46:41 +0200 |
commit | 2e645e21de1b3faef108569a8819778b6755c2f0 (patch) | |
tree | fc9ccb379c0eae895d81eee9e8d1dad5fc84f70c /lib/parsedate.c | |
parent | be238394770b3e536687e6d6120283f8b5959777 (diff) | |
download | curl-2e645e21de1b3faef108569a8819778b6755c2f0.tar.gz |
parsedate: tune the date to epoch conversion
By avoiding an unnecessary error check and the temp use of the tm
struct, the time2epoch conversion function gets a little bit faster.
When repeating test 517, the updated version is perhaps 1% faster (on
one particular build on one particular architecture).
Closes #5985
Diffstat (limited to 'lib/parsedate.c')
-rw-r--r-- | lib/parsedate.c | 57 |
1 files changed, 11 insertions, 46 deletions
diff --git a/lib/parsedate.c b/lib/parsedate.c index 4c7a40c4c..dd6150b44 100644 --- a/lib/parsedate.c +++ b/lib/parsedate.c @@ -275,48 +275,21 @@ enum assume { DATE_TIME }; -/* this is a clone of 'struct tm' but with all fields we don't need or use - cut out */ -struct my_tm { - int tm_sec; - int tm_min; - int tm_hour; - int tm_mday; - int tm_mon; - int tm_year; /* full year */ -}; - -/* struct tm to time since epoch in GMT time zone. - * This is similar to the standard mktime function but for GMT only, and - * doesn't suffer from the various bugs and portability problems that - * some systems' implementations have. - * - * Returns 0 on success, otherwise non-zero. +/* + * time2epoch: time stamp to seconds since epoch in GMT time zone. Similar to + * mktime but for GMT only. */ -static void my_timegm(struct my_tm *tm, time_t *t) +static time_t time2epoch(int sec, int min, int hour, + int mday, int mon, int year) { static const int month_days_cumulative [12] = { 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334 }; - int month, year, leap_days; - - year = tm->tm_year; - month = tm->tm_mon; - if(month < 0) { - year += (11 - month) / 12; - month = 11 - (11 - month) % 12; - } - else if(month >= 12) { - year -= month / 12; - month = month % 12; - } - - leap_days = year - (tm->tm_mon <= 1); + int leap_days = year - (mon <= 1); leap_days = ((leap_days / 4) - (leap_days / 100) + (leap_days / 400) - (1969 / 4) + (1969 / 100) - (1969 / 400)); - - *t = ((((time_t) (year - 1970) * 365 - + leap_days + month_days_cumulative[month] + tm->tm_mday - 1) * 24 - + tm->tm_hour) * 60 + tm->tm_min) * 60 + tm->tm_sec; + return ((((time_t) (year - 1970) * 365 + + leap_days + month_days_cumulative[mon] + mday - 1) * 24 + + hour) * 60 + min) * 60 + sec; } /* @@ -341,7 +314,6 @@ static int parsedate(const char *date, time_t *output) int secnum = -1; int yearnum = -1; int tzoff = -1; - struct my_tm tm; enum assume dignext = DATE_MDAY; const char *indate = date; /* save the original pointer */ int part = 0; /* max 6 parts */ @@ -533,18 +505,11 @@ static int parsedate(const char *date, time_t *output) (hournum > 23) || (minnum > 59) || (secnum > 60)) return PARSEDATE_FAIL; /* clearly an illegal date */ - tm.tm_sec = secnum; - tm.tm_min = minnum; - tm.tm_hour = hournum; - tm.tm_mday = mdaynum; - tm.tm_mon = monnum; - tm.tm_year = yearnum; - - /* my_timegm() returns a time_t. time_t is often 32 bits, sometimes even on + /* time2epoch() returns a time_t. time_t is often 32 bits, sometimes even on architectures that feature 64 bit 'long' but ultimately time_t is the correct data type to use. */ - my_timegm(&tm, &t); + t = time2epoch(secnum, minnum, hournum, mdaynum, monnum, yearnum); /* Add the time zone diff between local time zone and GMT. */ if(tzoff == -1) |