Fix handling of VTIMEZONEs with subcomponents with the same DTSTARTs

For VTIMEZONE subcomponents without a TZNAME we would construct a
TZNAME from their shared TZID and DTSTART, if their DTSTART was equal,
this would lead to the same TZNAME and with that to a broken timezone
object.

Fixes #217.
pull/220/head
Christian Geier 2017-03-23 00:38:00 +01:00
rodzic 0368e16faa
commit 5c269e1082
3 zmienionych plików z 23 dodań i 23 usunięć

Wyświetl plik

@ -17,6 +17,11 @@ Bug fixes:
- Don't break on parameter values which contain equal signs, e.g. base64 encoded - Don't break on parameter values which contain equal signs, e.g. base64 encoded
binary data [geier] binary data [geier]
- Fix handling of VTIMEZONEs with subcomponents with the same DTSTARTs.
[geier]
- *add item here*
3.11.3 (2017-02-15) 3.11.3 (2017-02-15)
------------------- -------------------

Wyświetl plik

@ -517,19 +517,11 @@ class Timezone(Component):
singletons = ('TZID', 'LAST-MODIFIED', 'TZURL',) singletons = ('TZID', 'LAST-MODIFIED', 'TZURL',)
@staticmethod @staticmethod
def _extract_offsets(component, zone): def _extract_offsets(component, tzname):
"""extract offsets and transition times from a VTIMEZONE component """extract offsets and transition times from a VTIMEZONE component
:param component: a STANDARD or DAYLIGHT component :param component: a STANDARD or DAYLIGHT component
:param zone: the name of the zone, used for constructing a TZNAME if :param tzname: the name of the zone
this component has none
""" """
try:
tzname = str(component['TZNAME'])
except KeyError:
tzname = '{0}_{1}'.format(
zone,
component['DTSTART'].to_ical().decode('utf-8')
)
offsetfrom = component['TZOFFSETFROM'].td offsetfrom = component['TZOFFSETFROM'].td
offsetto = component['TZOFFSETTO'].td offsetto = component['TZOFFSETTO'].td
dtstart = component['DTSTART'].dt dtstart = component['DTSTART'].dt
@ -586,12 +578,14 @@ class Timezone(Component):
try: try:
tzname = str(component['TZNAME']) tzname = str(component['TZNAME'])
except KeyError: except KeyError:
tzname = '{0}_{1}'.format( tzname = '{0}_{1}_{2}_{3}'.format(
zone, zone,
component['DTSTART'].to_ical().decode('utf-8') component['DTSTART'].to_ical().decode('utf-8'),
component['TZOFFSETFROM'].to_ical(), # for whatever reason this is str/unicode
component['TZOFFSETTO'].to_ical(), # for whatever reason this is str/unicode
) )
dst[tzname], component_transitions = self._extract_offsets( dst[tzname], component_transitions = self._extract_offsets(
component, zone component, tzname
) )
transitions.extend(component_transitions) transitions.extend(component_transitions)
@ -622,6 +616,7 @@ class Timezone(Component):
if not dst[transitions[index][3]]: # [3] is the name if not dst[transitions[index][3]]: # [3] is the name
dst_offset = osto - transitions[index][2] # [2] is osto # noqa dst_offset = osto - transitions[index][2] # [2] is osto # noqa
break break
assert dst_offset is not False
transition_info.append((osto, dst_offset, name)) transition_info.append((osto, dst_offset, name))
cls = type(zone, (DstTzInfo,), { cls = type(zone, (DstTzInfo,), {

Wyświetl plik

@ -266,39 +266,39 @@ class TestTimezoneCreation(unittest.TestCase):
[( [(
datetime.timedelta(0, 43200), datetime.timedelta(0, 43200),
datetime.timedelta(0), datetime.timedelta(0),
'custom_Pacific/Fiji_19151026T000000' 'custom_Pacific/Fiji_19151026T000000_+115544_+1200'
)] + )] +
3 * [( 3 * [(
datetime.timedelta(0, 46800), datetime.timedelta(0, 46800),
datetime.timedelta(0, 3600), datetime.timedelta(0, 3600),
'custom_Pacific/Fiji_19981101T020000' 'custom_Pacific/Fiji_19981101T020000_+1200_+1300'
), ( ), (
datetime.timedelta(0, 43200), datetime.timedelta(0, 43200),
datetime.timedelta(0), datetime.timedelta(0),
'custom_Pacific/Fiji_19990228T030000') 'custom_Pacific/Fiji_19990228T030000_+1300_+1200')
] + ] +
3 * [( 3 * [(
datetime.timedelta(0, 46800), datetime.timedelta(0, 46800),
datetime.timedelta(0, 3600), datetime.timedelta(0, 3600),
'custom_Pacific/Fiji_20101024T020000' 'custom_Pacific/Fiji_20101024T020000_+1200_+1300'
), ( ), (
datetime.timedelta(0, 43200), datetime.timedelta(0, 43200),
datetime.timedelta(0), datetime.timedelta(0),
'custom_Pacific/Fiji_19990228T030000' 'custom_Pacific/Fiji_19990228T030000_+1300_+1200'
)] + )] +
25 * [( 25 * [(
datetime.timedelta(0, 46800), datetime.timedelta(0, 46800),
datetime.timedelta(0, 3600), datetime.timedelta(0, 3600),
'custom_Pacific/Fiji_20101024T020000' 'custom_Pacific/Fiji_20101024T020000_+1200_+1300'
), ( ), (
datetime.timedelta(0, 43200), datetime.timedelta(0, 43200),
datetime.timedelta(0), datetime.timedelta(0),
'custom_Pacific/Fiji_20140119T020000' 'custom_Pacific/Fiji_20140119T020000_+1300_+1200'
)] + )] +
[( [(
datetime.timedelta(0, 46800), datetime.timedelta(0, 46800),
datetime.timedelta(0, 3600), datetime.timedelta(0, 3600),
'custom_Pacific/Fiji_20101024T020000' 'custom_Pacific/Fiji_20101024T020000_+1200_+1300'
)] )]
) )
@ -306,7 +306,7 @@ class TestTimezoneCreation(unittest.TestCase):
( (
datetime.timedelta(0, 46800), datetime.timedelta(0, 46800),
datetime.timedelta(0, 3600), datetime.timedelta(0, 3600),
'custom_Pacific/Fiji_19981101T020000' 'custom_Pacific/Fiji_19981101T020000_+1200_+1300'
), ),
tz._tzinfos.keys() tz._tzinfos.keys()
) )
@ -314,7 +314,7 @@ class TestTimezoneCreation(unittest.TestCase):
( (
datetime.timedelta(0, 43200), datetime.timedelta(0, 43200),
datetime.timedelta(0), datetime.timedelta(0),
'custom_Pacific/Fiji_19990228T030000' 'custom_Pacific/Fiji_19990228T030000_+1300_+1200'
), ),
tz._tzinfos.keys() tz._tzinfos.keys()
) )