# HG changeset patch # User Richard Laager # Date 1139297145 0 # Node ID 4bb701a8736f42c6857fd75a999774b64695807a # Parent 1646cd4f00adb40b60bd37e1fba5ce73e78c667f [gaim-migrate @ 15515] gaim_utf8_strftime() will now provide %z itself if your C library doesn't have it. I'm going to use this shortly. committer: Tailor Script diff -r 1646cd4f00ad -r 4bb701a8736f config.h.mingw --- a/config.h.mingw Tue Feb 07 07:17:09 2006 +0000 +++ b/config.h.mingw Tue Feb 07 07:25:45 2006 +0000 @@ -373,6 +373,9 @@ /* Define to 1 if you have the `strftime' function. */ #define HAVE_STRFTIME 1 +/* Define to 1 if you have a strftime() that supports the %z format string. */ +/* #undef HAVE_STRFTIME_Z_FORMAT */ + /* Define to 1 if you have the header file. */ #define HAVE_STRINGS_H 1 diff -r 1646cd4f00ad -r 4bb701a8736f configure.ac --- a/configure.ac Tue Feb 07 07:17:09 2006 +0000 +++ b/configure.ac Tue Feb 07 07:25:45 2006 +0000 @@ -108,6 +108,41 @@ dnl FreeBSD doesn't have libdl, dlopen is provided by libc AC_CHECK_FUNC(dlopen, LIBDL="", [AC_CHECK_LIB(dl, dlopen, LIBDL="-ldl")]) +AC_MSG_CHECKING(for the %z format string in strftime()) +AC_TRY_RUN([ +#ifdef HAVE_SYS_TIME_H +#include +#endif +#include +#include + +int main() +{ + char buf[6]; + time_t t = time(NULL); + + if (strftime(buf, sizeof(buf), "%z", localtime(&t)) != 5) + return 1; + + fprintf(stderr, "strftime(\"%%z\") yields: \"%s\"\n", buf); + + return !((buf[0] == '-' || buf[0] == '+') && + (buf[1] >= '0' && buf[1] <= '9') && + (buf[2] >= '0' && buf[2] <= '9') && + (buf[3] >= '0' && buf[3] <= '9') && + (buf[4] >= '0' && buf[4] <= '9') + ); +} +], +[ + AC_MSG_RESULT(yes) + AC_DEFINE([HAVE_STRFTIME_Z_FORMAT], [1], + [Define to 1 if you have a strftime() that supports the %z format string.]) +], +[ + AC_MSG_RESULT(no) +] +) dnl ####################################################################### diff -r 1646cd4f00ad -r 4bb701a8736f src/util.c --- a/src/util.c Tue Feb 07 07:17:09 2006 +0000 +++ b/src/util.c Tue Feb 07 07:25:45 2006 +0000 @@ -484,6 +484,109 @@ /************************************************************************** * Date/Time Functions **************************************************************************/ + +#ifndef HAVE_STRFTIME_Z_FORMAT +static const char *get_tmoff(const struct tm *tm) +{ + static char buf[6]; + long off; + gint8 min; + gint8 hrs; + struct tm new_tm = *tm; + + mktime(&new_tm); + + if (new_tm.tm_isdst < 0) + g_return_val_if_reached(""); + +#ifdef _WIN32 + TIME_ZONE_INFORMATION tzi; + DWORD ret; + if ((ret = GetTimeZoneInformation(&tzi)) != TIME_ZONE_ID_INVALID) + { + off = tzi.Bias * 60; + if (ret == TIME_ZONE_ID_DAYLIGHT) + off -= tzi.DaylightBias * 60; + } + else + return ""; +#else +# ifdef HAVE_TM_GMTOFF + off = new_tm.tm_gmtoff; +# else +# ifdef HAVE_TIMEZONE + tzset(); + off = -timezone; +# endif /* HAVE_TIMEZONE */ +# endif /* !HAVE_TM_GMTOFF */ +#endif /* _WIN32 */ + + min = (off / 60) % 60; + hrs = ((off / 60) - min) / 60; + + if (g_snprintf(buf, sizeof(buf), "%+03d%02d", hrs, ABS(min)) > 5) + g_return_val_if_reached(""); + + return buf; +} + +static size_t gaim_internal_strftime(char *s, size_t max, const char *format, const struct tm *tm) +{ + const char *start; + const char *c; + char *fmt = NULL; + + /* Yes, this is checked in gaim_utf8_strftime(), + * but better safe than sorry. -- rlaager */ + g_return_val_if_fail(format != NULL, 0); + + /* This is fairly efficient, and it only gets + * executed if the underlying system doesn't + * support the %z format string for strftime(), + * so I think it's good enough. -- rlaager */ + for (c = start = format; *c ; c++) + { + if (*c != '%') + continue; + + c++; + + if (*c == 'z') + { + char *tmp = g_strdup_printf("%s%.*s%s", + fmt ? fmt : "", + c - start - 1, + start, + get_tmoff(tm)); + g_free(fmt); + fmt = tmp; + start = c + 1; + } + } + + if (fmt != NULL) + { + size_t ret; + + if (*start) + { + char *tmp = g_strconcat(fmt, start, NULL); + g_free(fmt); + fmt = tmp; + } + + ret = strftime(s, max, fmt, tm); + g_free(fmt); + + return ret; + } + + return strftime(s, max, format, tm); +} +#else /* !HAVE_STRFTIME_Z_FORMAT */ +#define gaim_internal_strftime strftime +#endif + const char * gaim_utf8_strftime(const char *format, const struct tm *tm) { @@ -502,7 +605,7 @@ * which case, the contents of the buffer are * undefined) or the empty string (in which * case, no harm is done here). */ - if (strftime(buf, sizeof(buf), format, tm) == 0) + if (gaim_internal_strftime(buf, sizeof(buf), format, tm) == 0) { buf[0] = '\0'; return buf; diff -r 1646cd4f00ad -r 4bb701a8736f src/util.h --- a/src/util.h Tue Feb 07 07:17:09 2006 +0000 +++ b/src/util.h Tue Feb 07 07:25:45 2006 +0000 @@ -216,6 +216,13 @@ * This is essentially strftime(), but it has a static buffer * and handles the UTF-8 conversion for the caller. * + * This function also provides the GNU %z formatter if the underlying C + * library doesn't. However, the format string parser is very naive, which + * means that conversions specifiers to %z cannot be guaranteed. The GNU + * strftime(3) man page describes %z as: 'The time-zone as hour offset from + * GMT. Required to emit RFC822-conformant dates + * (using "%a, %d %b %Y %H:%M:%S %z"). (GNU)' + * * @param format The format string * @param tm The time to format, or @c NULL to use the current local time *