[PATCH 10/10] timegm: add portable implementation (Solaris support)
Tomi Ollila
tomi.ollila at iki.fi
Mon Nov 5 04:09:33 PST 2012
On Sun, Nov 04 2012, Blake Jones wrote:
> Hi Jani,
>
>> I'd prefer to use timegm() where available, and the suggested
>> alternative [1] elsewhere.
>>
>> [1] http://www.kernel.org/doc/man-pages/online/pages/man3/timegm.3.html
>
> I considered this alternative, but decided against it because it's
> completely MT-unsafe. I don't know whether libnotmuch itself is
> MT-safe, but a process which called this routine in one thread would
> temporarily throw off any timezone-related work that any other threads
> were doing, even if they weren't using libnotmuch.
Yet another idea for an alternative. Compile by entering 'sh xtimegm.c'
and then run ./xtimegm
Simple cases seems to work. Dst change may (or then may not) give one
hour difference to the expected. The test "coverage" could be easily
expanded to that ;)
Hmm, I also found this:
http://lists.gnu.org/archive/html/bug-gnulib/2003-09/msg00004.html
which does 2 mktime's and one gmtime_r (without allocating tg!)...
Pick any of these 3 -- or something different (e.g. less NIH if there is)
> Blake
Tomi
-------------- next part --------------
#if 0 /* -*- mode: c; c-file-style: "stroustrup"; tab-width: 8; -*-
set -eu; trg=`basename "$0" .c`; rm -f "$trg"
WARN="-Wall -Wno-long-long -Wstrict-prototypes -pedantic"
WARN="$WARN -Wcast-align -Wpointer-arith " # -Wfloat-equal #-Werror
WARN="$WARN -W -Wwrite-strings -Wcast-qual -Wshadow" # -Wconversion
case ${1-} in '') set x -O2; shift; esac
#case ${1-} in '') set x -ggdb; shift; esac
set -x; exec ${CC:-gcc} -std=c99 $WARN "$@" -o "$trg" "$0"
exit $?
*/
#endif
/*
* $ xtimegm.c $
*
* Author: Tomi Ollila -- too ?t iki piste fi
*
* Created: Mon 05 Nov 2012 07:54:35 EET too
* Last modified: Mon 05 Nov 2012 08:27:52 EET too
*
* Public domain.
*/
#define _POSIX_SOURCE
#include <time.h>
time_t xtimegm(struct tm * atm)
{
struct tm ltm;
time_t t = mktime(atm);
int sd;
int dd;
(void)gmtime_r(&t, <m);
sd = (atm->tm_hour - ltm.tm_hour) * 3600 + (atm->tm_min - ltm.tm_min) * 60
+ (atm->tm_sec - ltm.tm_sec);
dd = (atm->tm_mday - ltm.tm_mday);
if (dd == 0)
;
else if (dd == -1) sd -= 86400; /* e.g. 3, 2 */
else if (dd == 1) sd += 86400; /* e.g. 2, 3 */
else if (dd > 1) sd -= 86400; /* e.g. 1, 31 */
else /* dd < 1 */ sd += 86400; /* e.g. 31, 1 */
printf("sd: %d\n", sd); // test line.
return t + sd;
}
#include <stdio.h>
void test(int hour, int mday)
{
struct tm mtm;
time_t t;
struct tm * otm;
mtm.tm_sec = 0;
mtm.tm_min = 0;
mtm.tm_hour = hour;
mtm.tm_mday = mday;
mtm.tm_mon = 11;
mtm.tm_year = 100;
mtm.tm_isdst = -1;
t = xtimegm(&mtm);
otm = gmtime(&t);
printf("%2d %02d:%02d:%02d\n", otm->tm_mday,
otm->tm_hour, otm->tm_min, otm->tm_sec);
}
void tests(const char * tz)
{
printf("TZ: %s\n", tz);
setenv("TZ", tz, 1);
tzset();
test(23, 30);
test(23, 31);
test(23, 1);
test(23, 2);
printf("--\n");
test(1, 30);
test(1, 31);
test(1, 1);
test(1, 2);
}
int main(int argc, char * argv[])
{
// ls /usr/share/zoneinfo...
tests("EET");
tests("MST");
tests("HST");
tests("NZ");
return 0;
}
More information about the notmuch
mailing list