diff options
| author | Tatsuhiro Tsujikawa <tatsuhiro.t@gmail.com> | 2012-07-06 00:34:37 +0900 |
|---|---|---|
| committer | Tatsuhiro Tsujikawa <tatsuhiro.t@gmail.com> | 2012-07-06 00:34:37 +0900 |
| commit | f04090199f8c7bb25ebfca452f4bbe3d29904aad (patch) | |
| tree | ae05276bab8f196dd06488f62fbecb3bbb686afe /src/timegm.c | |
| parent | 4046f27ea9acc08180455900c20d2bd4c02f6f62 (diff) | |
Rewritten timegm replacement function
The algorithm is based on Python 2.7 calendar.timegm.
Diffstat (limited to 'src/timegm.c')
| -rw-r--r-- | src/timegm.c | 109 |
1 files changed, 59 insertions, 50 deletions
diff --git a/src/timegm.c b/src/timegm.c index 32d2c27c..655d73b4 100644 --- a/src/timegm.c +++ b/src/timegm.c @@ -1,71 +1,80 @@ -/* timegm.c - libc replacement function - * Copyright (C) 2004 Free Software Foundation, Inc. +/* + * aria2 - The high speed download utility * - * This file is part of GnuPG. + * Copyright (C) 2012 Tatsuhiro Tsujikawa * - * GnuPG is free software; you can redistribute it and/or modify + * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * - * GnuPG is distributed in the hope that it will be useful, + * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, - * USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * In addition, as a special exception, the copyright holders give + * permission to link the code of portions of this program with the + * OpenSSL library under certain conditions as described in each + * individual source file, and distribute linked combinations + * including the two. + * You must obey the GNU General Public License in all respects + * for all of the code used other than OpenSSL. If you modify + * file(s) with this exception, you may extend this exception to your + * version of the file(s), but you are not obligated to do so. If you + * do not wish to do so, delete this exception statement from your + * version. If you delete this exception statement from all source + * files in the program, then also delete it here. */ +/* copyright --> */ +#include "timegm.h" -/* - timegm() is a GNU function that might not be available everywhere. - It's basically the inverse of gmtime() - you give it a struct tm, - and get back a time_t. It differs from mktime() in that it handles - the case where the struct tm is UTC and the local environment isn't. - - Some BSDs don't handle the putenv("foo") case properly, so we use - unsetenv if the platform has it to remove environment variables. -*/ - -#ifdef HAVE_CONFIG_H -# include "config.h" -#endif // HAVE_CONFIG_H +#include <stdint.h> -#include <time.h> -#include <stdlib.h> -#include <string.h> +/* Counter the number of leap year in the range [0, y). The |y| is the + year, including century (e.g., 2012) */ +static int count_leap_year(int y) +{ + y -= 1; + return y/4-y/100+y/400; +} -time_t -timegm(struct tm *tm) +/* Returns nonzero if the |y| is the leap year. The |y| is the year, + including century (e.g., 2012) */ +static int is_leap_year(int y) { - time_t answer; - char *zone; + return y%4 == 0 && (y%100 != 0 || y%400 == 0); +} - zone=getenv("TZ"); - putenv("TZ=UTC"); - tzset(); - answer=mktime(tm); - if(zone) - { - char *old_zone; +/* The number of days before ith month begins */ +static int daysum[] = { + 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334 +}; - old_zone=malloc(3+strlen(zone)+1); - if(old_zone) - { - strcpy(old_zone,"TZ="); - strcat(old_zone,zone); - putenv(old_zone); - } +// Based on the algorithm of Python 2.7 calendar.timegm. +time_t timegm(struct tm *tm) +{ + int days; + int num_leap_year; + int64_t t; + if(tm->tm_mon > 11) { + return -1; + } + num_leap_year = count_leap_year(tm->tm_year + 1900) - count_leap_year(1970); + days = (tm->tm_year - 70) * 365 + + num_leap_year + daysum[tm->tm_mon] + tm->tm_mday-1; + if(tm->tm_mon >= 2 && is_leap_year(tm->tm_year + 1900)) { + ++days; + } + t = ((int64_t)days * 24 + tm->tm_hour) * 3600 + tm->tm_min * 60 + tm->tm_sec; + if(sizeof(time_t) == 4) { + if(t < INT32_MIN || t > INT32_MAX) { + return -1; } - else -#ifdef HAVE_UNSETENV - unsetenv("TZ"); -#else - putenv("TZ="); -#endif - - tzset(); - return answer; + } + return t; } |
