dbae39b0

By: Tom Sydney Kerckhove <syd@cs-syd.eu>

ical-recurrence: ignore a generated leap second whatever DTSTART is

GREEN for the tests in the previous commit.

'localTimeExists' answered 'const True' for anything that was not a zoned
DATE-TIME, because the resolve/unresolve round trip it uses needs a time
zone.  A leap second needs no time zone to rule out, so it is now ruled
out in every branch, and BYSECOND=60 produces no instance whatever
DTSTART's value type is.

The predicate is a syntactic check on the local time:

    isLeapSecond = (>= 60) . Time.todSec . Time.localTimeOfDay

Honouring second 60 was never coherent.  Whether such a local time
survives resolving and unresolving depends on the time of day and on the
offset -- 23:59:60 at a zero offset survives, 00:59:60 does in a +01:00
zone, everything else normalises into the following minute -- so the
recurrence set came to depend on facts about neither the rule nor the
calendar.  The cost is that BYSECOND=60 never generates an instance, which
is the honest outcome: real leap seconds are announced for particular
dates and nothing here knows which.

'ICal.Recurrence.TimeZoneSpec' had its own copy of this predicate as a
let-binding, added when that property was revived.  It now uses the
exported one, so the concept has one definition.  That does not make the
property tautological: 'isLeapSecond' is a syntactic check, not something
derived from the round trip, and the three concrete cases in that file
still pin what actually happens to a leap second independently.