diff options
author | Tavian Barnes <tavianator@tavianator.com> | 2020-02-13 16:30:05 -0500 |
---|---|---|
committer | Tavian Barnes <tavianator@tavianator.com> | 2020-02-13 16:39:30 -0500 |
commit | 95f862fdd82a99e30bbf2c43009ec9a51e416804 (patch) | |
tree | 0edafaf7a69935d56dc4ce8b442325e12dfd88ff /util.c | |
parent | 2cdc648441794db0f84518f79e8aaf3ead68f110 (diff) | |
download | bfs-95f862fdd82a99e30bbf2c43009ec9a51e416804.tar.xz |
parse: Handle 1969-12-31T23:59:59Z
mktime() returns -1 on error, but also for one second before the epoch.
Compare the input against localtime(-1) to distinguish those cases.
Diffstat (limited to 'util.c')
-rw-r--r-- | util.c | 27 |
1 files changed, 24 insertions, 3 deletions
@@ -185,9 +185,30 @@ int xgmtime(const time_t *timep, struct tm *result) { } } -time_t xtimegm(struct tm *tm) { +int xmktime(struct tm *tm, time_t *timep) { + *timep = mktime(tm); + + if (*timep == -1) { + int error = errno; + + struct tm tmp; + if (xlocaltime(timep, &tmp) != 0) { + return -1; + } + + if (tm->tm_year != tmp.tm_year || tm->tm_yday != tmp.tm_yday + || tm->tm_hour != tmp.tm_hour || tm->tm_min != tmp.tm_min || tm->tm_sec != tmp.tm_sec) { + errno = error; + return -1; + } + } + + return 0; +} + +int xtimegm(struct tm *tm, time_t *timep) { // Some man pages for timegm() recommend this as a portable approach - time_t ret = -1; + int ret = -1; int error; char *old_tz = getenv("TZ"); @@ -204,7 +225,7 @@ time_t xtimegm(struct tm *tm) { goto fail; } - ret = mktime(tm); + ret = xmktime(tm, timep); error = errno; if (old_tz) { |