* europe (Atlantic/Azores, Atlantic/Madeira): Add comments containing a vanguard equivalent. * ziguard.awk (get_minutes, offset_abbr): New functions. Support the special case for the Azores and Madeira. Convert to and from %z form. --- NEWS | 9 ++++++ europe | 12 ++++++-- ziguard.awk | 83 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 102 insertions(+), 2 deletions(-) diff --git a/NEWS b/NEWS index 4904819..33261ee 100644 --- a/NEWS +++ b/NEWS @@ -6,6 +6,7 @@ Unreleased, experimental changes Iran no longer observes DST after 2022. Rename Europe/Kiev to Europe/Kyiv. New zic -R option + Vanguard form now uses %z. Changes to future timestamps @@ -61,6 +62,14 @@ Unreleased, experimental changes Changes to build procedure + Source data in vanguard form now uses the %z notation, introduced + in release 2015f. For example, for America/Sao_Paulo vanguard + form contains the zone continuation line "-3:00 Brazil %z", which + is simpler and more reliable than the line "-3:00 Brazil -03/-02" + used in main and rearguard forms. The plan is for the main form + to use %z eventually; in the meantime maintainers of zi parsers + are encouraged to test the parsers on vanguard.zi. + 'make install' now defaults LOCALTIME to Factory not GMT, which means the default abbreviation is now "-00" not "GMT". diff --git a/europe b/europe index 0c008b4..776504d 100644 --- a/europe +++ b/europe @@ -2399,9 +2399,13 @@ Zone Europe/Lisbon -0:36:45 - LMT 1884 0:00 W-Eur WE%sT 1992 Sep 27 1:00s 1:00 EU CE%sT 1996 Mar 31 1:00u 0:00 EU WE%sT -# This Zone can be simplified once we assume zic %z. Zone Atlantic/Azores -1:42:40 - LMT 1884 # Ponta Delgada -1:54:32 - HMT 1912 Jan 1 2:00u # Horta MT +# Vanguard section, for zic and other parsers that support %z. +# -2:00 Port %z 1966 Apr 3 2:00 +# -1:00 Port %z 1983 Sep 25 1:00s +# -1:00 W-Eur %z 1992 Sep 27 1:00s +# Rearguard section, for parsers lacking %z; see ziguard.awk. -2:00 Port -02/-01 1942 Apr 25 22:00s -2:00 Port +00 1942 Aug 15 22:00s -2:00 Port -02/-01 1943 Apr 17 22:00s @@ -2413,11 +2417,14 @@ Zone Atlantic/Azores -1:42:40 - LMT 1884 # Ponta Delgada -2:00 Port -02/-01 1966 Apr 3 2:00 -1:00 Port -01/+00 1983 Sep 25 1:00s -1:00 W-Eur -01/+00 1992 Sep 27 1:00s +# End of rearguard section. 0:00 EU WE%sT 1993 Mar 28 1:00u -1:00 EU -01/+00 -# This Zone can be simplified once we assume zic %z. Zone Atlantic/Madeira -1:07:36 - LMT 1884 # Funchal -1:07:36 - FMT 1912 Jan 1 1:00u # Funchal MT +# Vanguard section, for zic and other parsers that support %z. +# -1:00 Port %z +# Rearguard section, for parsers lacking %z; see ziguard.awk. -1:00 Port -01/+00 1942 Apr 25 22:00s -1:00 Port +01 1942 Aug 15 22:00s -1:00 Port -01/+00 1943 Apr 17 22:00s @@ -2427,6 +2434,7 @@ Zone Atlantic/Madeira -1:07:36 - LMT 1884 # Funchal -1:00 Port -01/+00 1945 Apr 21 22:00s -1:00 Port +01 1945 Aug 25 22:00s -1:00 Port -01/+00 1966 Apr 3 2:00 +# End of rearguard section. 0:00 Port WE%sT 1983 Sep 25 1:00s 0:00 EU WE%sT diff --git a/ziguard.awk b/ziguard.awk index 25de617..91f6896 100644 --- a/ziguard.awk +++ b/ziguard.awk @@ -23,6 +23,33 @@ # of the input data as best it can within the constraints of the # rearguard format. +# Given a FIELD like "-0:30", return a minute count like -30. +function get_minutes(field, \ + sign, hours, minutes) +{ + sign = field ~ /^-/ ? -1 : 1 + hours = +field + if (field ~ /:/) { + minutes = field + sub(/[^:]*:/, "", minutes) + } + return 60 * hours + sign * minutes +} + +# Given an OFFSET, which is a minute count like 300 or 330, +# return a %z-style abbreviation like "+05" or "+0530". +function offset_abbr(offset, \ + hours, minutes, sign) +{ + hours = int(offset / 60) + minutes = offset % 60 + if (minutes) { + return sprintf("%+.4d", hours * 100 + minutes); + } else { + return sprintf("%+.2d", hours) + } +} + BEGIN { dataform_type["vanguard"] = 1 dataform_type["main"] = 1 @@ -85,6 +112,16 @@ DATAFORM != "main" { } } + # If this line should differ due to Portugal benefiting from %z if supported, + # uncomment the desired version and comment out the undesired one. + if (/^#?[\t ]+-[12]:00[\t ]+Port[\t ]+[%+-]/) { + if (/%z/ == (DATAFORM == "vanguard")) { + uncomment = in_comment + } else { + comment_out = !in_comment + } + } + if (uncomment) { sub(/^#/, "") } @@ -92,6 +129,52 @@ DATAFORM != "main" { sub(/^/, "#") } + # Prefer %z in vanguard form, explicit abbreviations otherwise. + if (DATAFORM == "vanguard") { + sub(/^(Zone[\t ]+[^\t ]+)?[\t ]+[^\t ]+[\t ]+[^\t ]+[\t ]+[-+][^\t ]+/, \ + "&CHANGE-TO-%z") + sub(/-00CHANGE-TO-%z/, "-00") + sub(/[-+][^\t ]+CHANGE-TO-/, "") + } else { + if (/^[^#]*%z/) { + stdoff_column = 2 * /^Zone/ + 1 + rules_column = stdoff_column + 1 + stdoff = get_minutes($stdoff_column) + rules = $rules_column + stdabbr = offset_abbr(stdoff) + if (rules == "-") { + abbr = stdabbr + } else { + dstabbr_only = rules ~ /^[+0-9-]/ + if (dstabbr_only) { + dstoff = get_minutes(rules) + } else { + # The DST offset is normally an hour, but there are special cases. + if (rules == "Morocco" && NF == 3) { + dstoff = -60 + } else if (rules == "NBorneo") { + dstoff = 20 + } else if (((rules == "Cook" || rules == "LH") && NF == 3) \ + || (rules == "Uruguay" \ + && /[\t ](1942 Dec 14|1960|1970|1974 Dec 22)$/)) { + dstoff = 30 + } else if (rules == "Uruguay" && /[\t ]1974 Mar 10$/) { + dstoff = 90 + } else { + dstoff = 60 + } + } + dstabbr = offset_abbr(stdoff + dstoff) + if (dstabbr_only) { + abbr = dstabbr + } else { + abbr = stdabbr "/" dstabbr + } + } + sub(/%z/, abbr) + } + } + if (DATAFORM == "rearguard") { # In rearguard form, change the Japan rule line with "Sat>=8 25:00" -- 2.36.1