GNOME Bugzilla – Bug 780594
GDateTime/GTimeZone problems
Last modified: 2017-04-04 08:45:30 UTC
I'm trying to migrate GMime over to using GDateTime instead of time_t & an int tz_offset. Here's the problem: When parsing a date/time with a timezone of "-0400" or "EDT", g_time_zone_new() seems to gobble that up just fine. I then pass that off to g_date_time_new() along with the parsed year/month/day/hour/minute/second values that I parsed from the Date header. So far so good... However, when I go to format the GDateTime, g_date_time_get_utc_offset() is returning 0. If I modify the Date header and replace "EDT" with "EST" and/or replace "-0400" with "-0500", then I get the expected UTC offset (-5 hours). Why?
Some example code which reproduces the problem (ideally in the form of a unit test) would help here.
#include <stdio.h> #include <glib.h> static char *tm_months[] = { "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" }; static char *tm_days[] = { "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" }; static char * format_date (GDateTime *date) { int wday, year, month, day, hour, min, sec, tz_offset, sign; GTimeSpan tz; wday = g_date_time_get_day_of_week (date); year = g_date_time_get_year (date); month = g_date_time_get_month (date); day = g_date_time_get_day_of_month (date); hour = g_date_time_get_hour (date); min = g_date_time_get_minute (date); sec = g_date_time_get_second (date); tz = g_date_time_get_utc_offset (date); printf ("tz = %lld\n", tz); sign = tz < 0 ? -1 : 1; tz *= sign; tz_offset = 100 * (tz / G_TIME_SPAN_HOUR); tz_offset += (tz % G_TIME_SPAN_HOUR) / G_TIME_SPAN_MINUTE; tz_offset *= sign; return g_strdup_printf ("%s, %02d %s %04d %02d:%02d:%02d %+05d", tm_days[wday % 7], day, tm_months[month - 1], year, hour, min, sec, tz_offset); } int main (int argc, char **argv) { GTimeZone *tz = g_time_zone_new ("EDT"); GDateTime *date = g_date_time_new (tz, 2017, 3, 27, 9, 51, 27); char *str = format_date (date); printf ("%s\n", str); g_free (str); return 0; }
Output: [fejj@localhost gmime]$ ./test-case tz = 0 Mon, 27 Mar 2017 09:51:27 +0000
[fejj@localhost gmime]$ pkg-config --modversion glib-2.0 2.50.3
FWIW, in this simple test case, a string of "-0400" seems to work fine, but as you can see, "EDT" does not. I might have to double-check my parsing code to make sure that the cases where I thought "-0400" were failing weren't due to something else. It's odd tho because my own GMime unit tests have exactly the same dates where I use -0500 and -0400 and the one with -0400 fails while -0500 doesn't. Same with EDT vs EST which is how I noticed this problem. Perhaps the -0400 issue is due to me using a different OS? This test case was written/run on Fedora 25 but I was writing the patch for GMime on Mac OS X with glib 2.50.3 (from brew).
Hmmm, nope, test case produces the same results on Mac OS X. I guess never mind about the "-0400" thing.
Re-examined my GMime unit tests and I was wrong, it was only failing when EDT was specified, not "-0400". I was confused because I was looking at the expected output string (the expected date string after it had been parsed + re-formatted) and not the input string. I'm now working around this EDT issue by mapping timezone names like "EDT" to "-0400" and then passing "-0400" to g_time_zone_new().
https://github.com/jstedfast/gmime/commit/0a7954b26e3b0d9951691f72f5b53284b75401a1#diff-2046426d41e2a4b6e9e2f42e773603d5R488
I think this is not a bug: the ‘EDT’ timezone doesn’t exist in the tz database. You might want ‘EST5EDT’ instead, or to use hour offsets as your workaround does already. $ find /usr/share/zoneinfo/ -name '*EDT*' /usr/share/zoneinfo/right/EST5EDT /usr/share/zoneinfo/posix/EST5EDT /usr/share/zoneinfo/EST5EDT See bug #677522 for the fact that g_time_zone_new() doesn’t provide any feedback when passed an invalid tz identifier.