Russia recently moved on to permanent DST, so there was no DST->STD transition in October.
However, libical thinks there was:
Using the following test program:
#include <libical/icaltimezone.h>
#include <stdio.h>
int main(int argc, char **argv)
{
icaltimezone *tz = icaltimezone_get_builtin_timezone (argv[1]);
icaltimezone_dump_changes (tz, 2012, stdout);
}
$ ./tztest Europe/Moscow | tail -5
Europe/Moscow 30 Oct 2010 23:00:00 +0300
Europe/Moscow 26 Mar 2011 23:00:00 +0400
Europe/Moscow 29 Oct 2011 23:00:00 +0300
Europe/Moscow 24 Mar 2012 23:00:00 +0400
Europe/Moscow 27 Oct 2012 23:00:00 +0300
zdump seems to get this right:
$zdump -c2010,2012 -v Europe/Moscow
Europe/Moscow -9223372036854775808 = NULL
Europe/Moscow -9223372036854689408 = NULL
Europe/Moscow Sat Mar 27 22:59:59 2010 UTC = Sun Mar 28 01:59:59 2010 MSK isdst=0 gmtoff=10800
Europe/Moscow Sat Mar 27 23:00:00 2010 UTC = Sun Mar 28 03:00:00 2010 MSD isdst=1 gmtoff=14400
Europe/Moscow Sat Oct 30 22:59:59 2010 UTC = Sun Oct 31 02:59:59 2010 MSD isdst=1 gmtoff=14400
Europe/Moscow Sat Oct 30 23:00:00 2010 UTC = Sun Oct 31 02:00:00 2010 MSK isdst=0 gmtoff=10800
Europe/Moscow Sat Mar 26 22:59:59 2011 UTC = Sun Mar 27 01:59:59 2011 MSK isdst=0 gmtoff=10800
Europe/Moscow Sat Mar 26 23:00:00 2011 UTC = Sun Mar 27 03:00:00 2011 MSK isdst=0 gmtoff=14400
Europe/Moscow 9223372036854689407 = NULL
Europe/Moscow 9223372036854775807 = NULL
It looks like the problem is in icaltz-util.c:find_transidx() There we assume that if there are daylight transitions in the timezone, we can just use the previous year's one as an indicator for the next. This is wrong in a zone like Europe/Moscow where the zone stopped in permanent DST
It looks like the fix should be to project the transitions forwards and use that to see if there is a DST transition in the current year (and don't add a DST RRULE if there aren't).
View and moderate all "bugs Discussion" comments posted by this user
Mark all as spam, and block user from posting to "Bugs"
The problem here is that we are using heuristics at all. Version 2 (since 2005) of the tz file binary format includes a string in the style of a POSIX $TZ environment variable, "for use in handling instants after the last transition time stored in the file". For example:
$ strings /usr/share/zoneinfo/US/Pacific | tail -1
PST8PDT,M3.2.0,M11.1.0
$ strings /usr/share/zoneinfo/Europe/London | tail -1
GMT0BST,M3.5.0/1,M10.5.0
In the case of future recurrence we might have to infer the precise time-of-day for the transition from previous transitions, but the fact that there *is* future recurrence is explicitly specified and we should not have to guess.
I don't want to see a "fix" which merely improves our guesswork. That seems like the wrong solution.
Last edit: Anonymous 2013-09-26
Fix for the problem by making VTIMEZONE an exact mirror of the transition rules
Fix is attached for review. It makes the VTIMEZONE specifier an exact mirror of the transitions in the zone files, so it now uses absolute dates rather than trying to calculate a RRULE.
This fixes the Europe/Moscow problem
See http://www.gnu.org/s/hello/manual/libc/TZ-Variable.html for how to decode the TZ string
with the current development version in svn, when I run your test program I get:
$ ./tztest Europe/Moscow
Europe/Moscow 26 Mar 1970 23:00:00 +0400
Is that correct??
Thanks for the patch! seems to work great.
committed in r1130
I can't reproduce the original problem using the original, heuristic-based icaltz-util.c and tzdata 2013i-0wheezy1 on Debian Wheezy. I get the correct timezone component:
BEGIN:VTIMEZONE
TZID:/freeassociation.sourceforge.net/Tzfile/Europe/Moscow
X-LIC-LOCATION:Europe/Moscow
BEGIN:STANDARD
TZNAME:MSK
DTSTART:19700327T030000
TZOFFSETFROM:+0400
TZOFFSETTO:+0400
END:STANDARD
END:VTIMEZONE
Just FYI. As mentioned in #95, the new code causes interoperability issues.