523 lines
19 KiB
Python
523 lines
19 KiB
Python
# -*- coding: utf-8 -*-
|
|
from __future__ import unicode_literals
|
|
|
|
from datetime import date
|
|
from datetime import datetime
|
|
from datetime import time
|
|
from datetime import timedelta
|
|
from icalendar.parser import Parameters
|
|
import unittest
|
|
from icalendar.prop import vDatetime
|
|
from icalendar.windows_to_olson import WINDOWS_TO_OLSON
|
|
|
|
import pytz
|
|
|
|
|
|
class TestProp(unittest.TestCase):
|
|
|
|
def test_prop_vBinary(self):
|
|
from ..prop import vBinary
|
|
|
|
txt = b'This is gibberish'
|
|
txt_ical = b'VGhpcyBpcyBnaWJiZXJpc2g='
|
|
self.assertEqual(vBinary(txt).to_ical(), txt_ical)
|
|
self.assertEqual(vBinary.from_ical(txt_ical), txt)
|
|
|
|
# The roundtrip test
|
|
txt = b'Binary data \x13 \x56'
|
|
txt_ical = b'QmluYXJ5IGRhdGEgEyBW'
|
|
self.assertEqual(vBinary(txt).to_ical(), txt_ical)
|
|
self.assertEqual(vBinary.from_ical(txt_ical), txt)
|
|
|
|
self.assertIsInstance(vBinary('txt').params, Parameters)
|
|
self.assertEqual(
|
|
vBinary('txt').params, {'VALUE': 'BINARY', 'ENCODING': 'BASE64'}
|
|
)
|
|
|
|
# Long data should not have line breaks, as that would interfere
|
|
txt = b'a' * 99
|
|
txt_ical = b'YWFh' * 33
|
|
self.assertEqual(vBinary(txt).to_ical(), txt_ical)
|
|
self.assertEqual(vBinary.from_ical(txt_ical), txt)
|
|
|
|
def test_prop_vBoolean(self):
|
|
from ..prop import vBoolean
|
|
|
|
self.assertEqual(vBoolean(True).to_ical(), b'TRUE')
|
|
self.assertEqual(vBoolean(0).to_ical(), b'FALSE')
|
|
|
|
# The roundtrip test
|
|
self.assertEqual(vBoolean.from_ical(vBoolean(True).to_ical()), True)
|
|
self.assertEqual(vBoolean.from_ical('true'), True)
|
|
|
|
def test_prop_vCalAddress(self):
|
|
from ..prop import vCalAddress
|
|
txt = b'MAILTO:maxm@mxm.dk'
|
|
a = vCalAddress(txt)
|
|
a.params['cn'] = 'Max M'
|
|
|
|
self.assertEqual(a.to_ical(), txt)
|
|
self.assertIsInstance(a.params, Parameters)
|
|
self.assertEqual(a.params, {'CN': 'Max M'})
|
|
self.assertEqual(vCalAddress.from_ical(txt), 'MAILTO:maxm@mxm.dk')
|
|
|
|
def test_prop_vFloat(self):
|
|
from ..prop import vFloat
|
|
self.assertEqual(vFloat(1.0).to_ical(), b'1.0')
|
|
self.assertEqual(vFloat.from_ical('42'), 42.0)
|
|
self.assertEqual(vFloat(42).to_ical(), b'42.0')
|
|
|
|
def test_prop_vInt(self):
|
|
from ..prop import vInt
|
|
self.assertEqual(vInt(42).to_ical(), b'42')
|
|
self.assertEqual(vInt.from_ical('13'), 13)
|
|
self.assertRaises(ValueError, vInt.from_ical, '1s3')
|
|
|
|
def test_prop_vDDDLists(self):
|
|
from ..prop import vDDDLists
|
|
|
|
dt_list = vDDDLists.from_ical('19960402T010000Z')
|
|
self.assertTrue(isinstance(dt_list, list))
|
|
self.assertEqual(len(dt_list), 1)
|
|
self.assertTrue(isinstance(dt_list[0], datetime))
|
|
self.assertEqual(str(dt_list[0]), '1996-04-02 01:00:00+00:00')
|
|
|
|
p = '19960402T010000Z,19960403T010000Z,19960404T010000Z'
|
|
dt_list = vDDDLists.from_ical(p)
|
|
self.assertEqual(len(dt_list), 3)
|
|
self.assertEqual(str(dt_list[0]), '1996-04-02 01:00:00+00:00')
|
|
self.assertEqual(str(dt_list[2]), '1996-04-04 01:00:00+00:00')
|
|
|
|
dt_list = vDDDLists([])
|
|
self.assertEqual(dt_list.to_ical(), b'')
|
|
|
|
dt_list = vDDDLists([datetime(2000, 1, 1)])
|
|
self.assertEqual(dt_list.to_ical(), b'20000101T000000')
|
|
|
|
dt_list = vDDDLists([datetime(2000, 1, 1), datetime(2000, 11, 11)])
|
|
self.assertEqual(dt_list.to_ical(), b'20000101T000000,20001111T000000')
|
|
|
|
def test_prop_vDDDTypes(self):
|
|
from ..prop import vDDDTypes
|
|
|
|
self.assertTrue(isinstance(vDDDTypes.from_ical('20010101T123000'),
|
|
datetime))
|
|
|
|
self.assertEqual(vDDDTypes.from_ical('20010101T123000Z'),
|
|
pytz.utc.localize(datetime(2001, 1, 1, 12, 30)))
|
|
|
|
self.assertTrue(isinstance(vDDDTypes.from_ical('20010101'), date))
|
|
|
|
self.assertEqual(vDDDTypes.from_ical('P31D'), timedelta(31))
|
|
|
|
self.assertEqual(vDDDTypes.from_ical('-P31D'), timedelta(-31))
|
|
|
|
# Bad input
|
|
self.assertRaises(ValueError, vDDDTypes, 42)
|
|
|
|
def test_prop_vDate(self):
|
|
from ..prop import vDate
|
|
|
|
self.assertEqual(vDate(date(2001, 1, 1)).to_ical(), b'20010101')
|
|
self.assertEqual(vDate(date(1899, 1, 1)).to_ical(), b'18990101')
|
|
|
|
self.assertEqual(vDate.from_ical('20010102'), date(2001, 1, 2))
|
|
|
|
self.assertRaises(ValueError, vDate, 'd')
|
|
|
|
def test_prop_vDatetime(self):
|
|
from ..prop import vDatetime
|
|
|
|
dt = datetime(2001, 1, 1, 12, 30, 0)
|
|
self.assertEqual(vDatetime(dt).to_ical(), b'20010101T123000')
|
|
|
|
self.assertEqual(vDatetime.from_ical('20000101T120000'),
|
|
datetime(2000, 1, 1, 12, 0))
|
|
|
|
dutc = pytz.utc.localize(datetime(2001, 1, 1, 12, 30, 0))
|
|
self.assertEqual(vDatetime(dutc).to_ical(), b'20010101T123000Z')
|
|
|
|
dutc = pytz.utc.localize(datetime(1899, 1, 1, 12, 30, 0))
|
|
self.assertEqual(vDatetime(dutc).to_ical(), b'18990101T123000Z')
|
|
|
|
self.assertEqual(vDatetime.from_ical('20010101T000000'),
|
|
datetime(2001, 1, 1, 0, 0))
|
|
|
|
self.assertRaises(ValueError, vDatetime.from_ical, '20010101T000000A')
|
|
|
|
utc = vDatetime.from_ical('20010101T000000Z')
|
|
self.assertEqual(vDatetime(utc).to_ical(), b'20010101T000000Z')
|
|
|
|
# 1 minute before transition to DST
|
|
dat = vDatetime.from_ical('20120311T015959', 'America/Denver')
|
|
self.assertEqual(dat.strftime('%Y%m%d%H%M%S %z'),
|
|
'20120311015959 -0700')
|
|
|
|
# After transition to DST
|
|
dat = vDatetime.from_ical('20120311T030000', 'America/Denver')
|
|
self.assertEqual(dat.strftime('%Y%m%d%H%M%S %z'),
|
|
'20120311030000 -0600')
|
|
|
|
dat = vDatetime.from_ical('20101010T000000', 'Europe/Vienna')
|
|
self.assertEqual(vDatetime(dat).to_ical(), b'20101010T000000')
|
|
|
|
def test_prop_vDuration(self):
|
|
from ..prop import vDuration
|
|
|
|
self.assertEqual(vDuration(timedelta(11)).to_ical(), b'P11D')
|
|
self.assertEqual(vDuration(timedelta(-14)).to_ical(), b'-P14D')
|
|
self.assertEqual(
|
|
vDuration(timedelta(1, 7384)).to_ical(),
|
|
b'P1DT2H3M4S'
|
|
)
|
|
self.assertEqual(vDuration(timedelta(1, 7380)).to_ical(), b'P1DT2H3M')
|
|
self.assertEqual(vDuration(timedelta(1, 7200)).to_ical(), b'P1DT2H')
|
|
self.assertEqual(vDuration(timedelta(0, 7200)).to_ical(), b'PT2H')
|
|
self.assertEqual(vDuration(timedelta(0, 7384)).to_ical(), b'PT2H3M4S')
|
|
self.assertEqual(vDuration(timedelta(0, 184)).to_ical(), b'PT3M4S')
|
|
self.assertEqual(vDuration(timedelta(0, 22)).to_ical(), b'PT22S')
|
|
self.assertEqual(vDuration(timedelta(0, 3622)).to_ical(), b'PT1H0M22S')
|
|
self.assertEqual(vDuration(timedelta(days=1, hours=5)).to_ical(),
|
|
b'P1DT5H')
|
|
self.assertEqual(vDuration(timedelta(hours=-5)).to_ical(), b'-PT5H')
|
|
self.assertEqual(vDuration(timedelta(days=-1, hours=-5)).to_ical(),
|
|
b'-P1DT5H')
|
|
|
|
# How does the parsing work?
|
|
self.assertEqual(vDuration.from_ical('PT1H0M22S'), timedelta(0, 3622))
|
|
|
|
self.assertRaises(ValueError, vDuration.from_ical, 'kox')
|
|
|
|
self.assertEqual(vDuration.from_ical('-P14D'), timedelta(-14))
|
|
|
|
self.assertRaises(ValueError, vDuration, 11)
|
|
|
|
def test_prop_vPeriod(self):
|
|
from ..prop import vPeriod
|
|
|
|
# One day in exact datetimes
|
|
per = (datetime(2000, 1, 1), datetime(2000, 1, 2))
|
|
self.assertEqual(vPeriod(per).to_ical(),
|
|
b'20000101T000000/20000102T000000')
|
|
|
|
per = (datetime(2000, 1, 1), timedelta(days=31))
|
|
self.assertEqual(vPeriod(per).to_ical(), b'20000101T000000/P31D')
|
|
|
|
# Roundtrip
|
|
p = vPeriod.from_ical('20000101T000000/20000102T000000')
|
|
self.assertEqual(
|
|
p,
|
|
(datetime(2000, 1, 1, 0, 0), datetime(2000, 1, 2, 0, 0))
|
|
)
|
|
self.assertEqual(vPeriod(p).to_ical(),
|
|
b'20000101T000000/20000102T000000')
|
|
|
|
self.assertEqual(vPeriod.from_ical('20000101T000000/P31D'),
|
|
(datetime(2000, 1, 1, 0, 0), timedelta(31)))
|
|
|
|
# Roundtrip with absolute time
|
|
p = vPeriod.from_ical('20000101T000000Z/20000102T000000Z')
|
|
self.assertEqual(vPeriod(p).to_ical(),
|
|
b'20000101T000000Z/20000102T000000Z')
|
|
|
|
# And an error
|
|
self.assertRaises(ValueError,
|
|
vPeriod.from_ical, '20000101T000000/Psd31D')
|
|
|
|
# Timezoned
|
|
dk = pytz.timezone('Europe/Copenhagen')
|
|
start = dk.localize(datetime(2000, 1, 1))
|
|
end = dk.localize(datetime(2000, 1, 2))
|
|
per = (start, end)
|
|
self.assertEqual(vPeriod(per).to_ical(),
|
|
b'20000101T000000/20000102T000000')
|
|
self.assertEqual(vPeriod(per).params['TZID'],
|
|
'Europe/Copenhagen')
|
|
|
|
p = vPeriod((dk.localize(datetime(2000, 1, 1)), timedelta(days=31)))
|
|
self.assertEqual(p.to_ical(), b'20000101T000000/P31D')
|
|
|
|
def test_prop_vWeekday(self):
|
|
from ..prop import vWeekday
|
|
|
|
self.assertEqual(vWeekday('mo').to_ical(), b'MO')
|
|
self.assertRaises(ValueError, vWeekday, 'erwer')
|
|
self.assertEqual(vWeekday.from_ical('mo'), 'MO')
|
|
self.assertEqual(vWeekday.from_ical('+3mo'), '+3MO')
|
|
self.assertRaises(ValueError, vWeekday.from_ical, 'Saturday')
|
|
self.assertEqual(vWeekday('+mo').to_ical(), b'+MO')
|
|
self.assertEqual(vWeekday('+3mo').to_ical(), b'+3MO')
|
|
self.assertEqual(vWeekday('-tu').to_ical(), b'-TU')
|
|
|
|
def test_prop_vFrequency(self):
|
|
from ..prop import vFrequency
|
|
|
|
self.assertRaises(ValueError, vFrequency, 'bad test')
|
|
self.assertEqual(vFrequency('daily').to_ical(), b'DAILY')
|
|
self.assertEqual(vFrequency('daily').from_ical('MONTHLY'), 'MONTHLY')
|
|
|
|
def test_prop_vRecur(self):
|
|
from ..prop import vRecur
|
|
|
|
# Let's see how close we can get to one from the rfc:
|
|
# FREQ=YEARLY;INTERVAL=2;BYMONTH=1;BYDAY=SU;BYHOUR=8,9;BYMINUTE=30
|
|
|
|
r = dict({'freq': 'yearly', 'interval': 2})
|
|
r.update({
|
|
'bymonth': 1,
|
|
'byday': 'su',
|
|
'byhour': [8, 9],
|
|
'byminute': 30
|
|
})
|
|
self.assertEqual(
|
|
vRecur(r).to_ical(),
|
|
b'FREQ=YEARLY;INTERVAL=2;BYMINUTE=30;BYHOUR=8,9;BYDAY=SU;BYMONTH=1'
|
|
)
|
|
|
|
r = vRecur(FREQ='yearly', INTERVAL=2)
|
|
r.update({
|
|
'BYMONTH': 1,
|
|
'BYDAY': 'su',
|
|
'BYHOUR': [8, 9],
|
|
'BYMINUTE': 30,
|
|
})
|
|
self.assertEqual(
|
|
r.to_ical(),
|
|
b'FREQ=YEARLY;INTERVAL=2;BYMINUTE=30;BYHOUR=8,9;BYDAY=SU;BYMONTH=1'
|
|
)
|
|
|
|
r = vRecur(freq='DAILY', count=10)
|
|
r['bysecond'] = [0, 15, 30, 45]
|
|
self.assertEqual(r.to_ical(),
|
|
b'FREQ=DAILY;COUNT=10;BYSECOND=0,15,30,45')
|
|
|
|
r = vRecur(freq='DAILY', until=datetime(2005, 1, 1, 12, 0, 0))
|
|
self.assertEqual(r.to_ical(), b'FREQ=DAILY;UNTIL=20050101T120000')
|
|
|
|
# How do we fare with regards to parsing?
|
|
r = vRecur.from_ical('FREQ=DAILY;INTERVAL=2;COUNT=10')
|
|
self.assertEqual(r,
|
|
{'COUNT': [10], 'FREQ': ['DAILY'], 'INTERVAL': [2]})
|
|
self.assertEqual(
|
|
vRecur(r).to_ical(),
|
|
b'FREQ=DAILY;COUNT=10;INTERVAL=2'
|
|
)
|
|
|
|
r = vRecur.from_ical('FREQ=YEARLY;INTERVAL=2;BYMONTH=1;BYDAY=-SU;'
|
|
'BYHOUR=8,9;BYMINUTE=30')
|
|
self.assertEqual(
|
|
r,
|
|
{'BYHOUR': [8, 9], 'BYDAY': ['-SU'], 'BYMINUTE': [30],
|
|
'BYMONTH': [1], 'FREQ': ['YEARLY'], 'INTERVAL': [2]}
|
|
)
|
|
|
|
self.assertEqual(
|
|
vRecur(r).to_ical(),
|
|
b'FREQ=YEARLY;INTERVAL=2;BYMINUTE=30;BYHOUR=8,9;BYDAY=-SU;'
|
|
b'BYMONTH=1'
|
|
)
|
|
|
|
# Some examples from the spec
|
|
r = vRecur.from_ical('FREQ=MONTHLY;BYDAY=MO,TU,WE,TH,FR;BYSETPOS=-1')
|
|
self.assertEqual(vRecur(r).to_ical(),
|
|
b'FREQ=MONTHLY;BYDAY=MO,TU,WE,TH,FR;BYSETPOS=-1')
|
|
|
|
p = 'FREQ=YEARLY;INTERVAL=2;BYMONTH=1;BYDAY=SU;BYHOUR=8,9;BYMINUTE=30'
|
|
r = vRecur.from_ical(p)
|
|
self.assertEqual(
|
|
vRecur(r).to_ical(),
|
|
b'FREQ=YEARLY;INTERVAL=2;BYMINUTE=30;BYHOUR=8,9;BYDAY=SU;BYMONTH=1'
|
|
)
|
|
|
|
# and some errors
|
|
self.assertRaises(ValueError, vRecur.from_ical, 'BYDAY=12')
|
|
|
|
# when key is not RFC-compliant, parse it as vText
|
|
r = vRecur.from_ical('FREQ=MONTHLY;BYOTHER=TEXT;BYEASTER=-3')
|
|
self.assertEqual(vRecur(r).to_ical(),
|
|
b'FREQ=MONTHLY;BYEASTER=-3;BYOTHER=TEXT')
|
|
|
|
def test_prop_vText(self):
|
|
from ..prop import vText
|
|
|
|
self.assertEqual(vText('Simple text').to_ical(), b'Simple text')
|
|
|
|
# Escaped text
|
|
t = vText('Text ; with escaped, chars')
|
|
self.assertEqual(t.to_ical(), b'Text \\; with escaped\\, chars')
|
|
|
|
# Escaped newlines
|
|
self.assertEqual(vText('Text with escaped\\N chars').to_ical(),
|
|
b'Text with escaped\\n chars')
|
|
|
|
# If you pass a unicode object, it will be utf-8 encoded. As this is
|
|
# the (only) standard that RFC 2445 support.
|
|
t = vText('international chars \xe4\xf6\xfc')
|
|
self.assertEqual(t.to_ical(),
|
|
b'international chars \xc3\xa4\xc3\xb6\xc3\xbc')
|
|
|
|
# and parsing?
|
|
self.assertEqual(vText.from_ical('Text \\; with escaped\\, chars'),
|
|
'Text ; with escaped, chars')
|
|
|
|
t = vText.from_ical('A string with\\; some\\\\ characters in\\it')
|
|
self.assertEqual(t, "A string with; some\\ characters in\\it")
|
|
|
|
# We are forgiving to utf-8 encoding errors:
|
|
# We intentionally use a string with unexpected encoding
|
|
#
|
|
self.assertEqual(vText.from_ical(b'Ol\xe9'), 'Ol\ufffd')
|
|
|
|
# Notice how accented E character, encoded with latin-1, got replaced
|
|
# with the official U+FFFD REPLACEMENT CHARACTER.
|
|
|
|
def test_prop_vTime(self):
|
|
from ..prop import vTime
|
|
|
|
self.assertEqual(vTime(12, 30, 0).to_ical(), '123000')
|
|
self.assertEqual(vTime.from_ical('123000'), time(12, 30))
|
|
|
|
# We should also fail, right?
|
|
self.assertRaises(ValueError, vTime.from_ical, '263000')
|
|
|
|
def test_prop_vUri(self):
|
|
from ..prop import vUri
|
|
|
|
self.assertEqual(vUri('http://www.example.com/').to_ical(),
|
|
b'http://www.example.com/')
|
|
self.assertEqual(vUri.from_ical('http://www.example.com/'),
|
|
'http://www.example.com/')
|
|
|
|
def test_prop_vGeo(self):
|
|
from ..prop import vGeo
|
|
|
|
# Pass a list
|
|
self.assertEqual(vGeo([1.2, 3.0]).to_ical(), '1.2;3.0')
|
|
|
|
# Pass a tuple
|
|
self.assertEqual(vGeo((1.2, 3.0)).to_ical(), '1.2;3.0')
|
|
|
|
g = vGeo.from_ical('37.386013;-122.082932')
|
|
self.assertEqual(g, (float('37.386013'), float('-122.082932')))
|
|
|
|
self.assertEqual(vGeo(g).to_ical(), '37.386013;-122.082932')
|
|
|
|
self.assertRaises(ValueError, vGeo, 'g')
|
|
|
|
def test_prop_vUTCOffset(self):
|
|
from ..prop import vUTCOffset
|
|
|
|
self.assertEqual(vUTCOffset(timedelta(hours=2)).to_ical(), '+0200')
|
|
|
|
self.assertEqual(vUTCOffset(timedelta(hours=-5)).to_ical(), '-0500')
|
|
|
|
self.assertEqual(vUTCOffset(timedelta()).to_ical(), '+0000')
|
|
|
|
self.assertEqual(vUTCOffset(timedelta(minutes=-30)).to_ical(),
|
|
'-0030')
|
|
|
|
self.assertEqual(
|
|
vUTCOffset(timedelta(hours=2, minutes=-30)).to_ical(),
|
|
'+0130'
|
|
)
|
|
|
|
self.assertEqual(vUTCOffset(timedelta(hours=1, minutes=30)).to_ical(),
|
|
'+0130')
|
|
|
|
# Support seconds
|
|
self.assertEqual(vUTCOffset(timedelta(hours=1,
|
|
minutes=30,
|
|
seconds=7)).to_ical(), '+013007')
|
|
|
|
# Parsing
|
|
|
|
self.assertEqual(vUTCOffset.from_ical('0000'), timedelta(0))
|
|
self.assertEqual(vUTCOffset.from_ical('-0030'), timedelta(-1, 84600))
|
|
self.assertEqual(vUTCOffset.from_ical('+0200'), timedelta(0, 7200))
|
|
self.assertEqual(vUTCOffset.from_ical('+023040'), timedelta(0, 9040))
|
|
|
|
self.assertEqual(vUTCOffset(vUTCOffset.from_ical('+0230')).to_ical(),
|
|
'+0230')
|
|
|
|
# And a few failures
|
|
self.assertRaises(ValueError, vUTCOffset.from_ical, '+323k')
|
|
|
|
self.assertRaises(ValueError, vUTCOffset.from_ical, '+2400')
|
|
|
|
def test_prop_vInline(self):
|
|
from ..prop import vInline
|
|
|
|
self.assertEqual(vInline('Some text'), 'Some text')
|
|
self.assertEqual(vInline.from_ical('Some text'), 'Some text')
|
|
|
|
t2 = vInline('other text')
|
|
t2.params['cn'] = 'Test Osterone'
|
|
self.assertIsInstance(t2.params, Parameters)
|
|
self.assertEqual(t2.params, {'CN': 'Test Osterone'})
|
|
|
|
def test_prop_TypesFactory(self):
|
|
from ..prop import TypesFactory
|
|
|
|
# To get a type you can use it like this.
|
|
factory = TypesFactory()
|
|
datetime_parser = factory['date-time']
|
|
self.assertEqual(datetime_parser(datetime(2001, 1, 1)).to_ical(),
|
|
b'20010101T000000')
|
|
|
|
# A typical use is when the parser tries to find a content type and use
|
|
# text as the default
|
|
value = '20050101T123000'
|
|
value_type = 'date-time'
|
|
self.assertEqual(factory.get(value_type, 'text').from_ical(value),
|
|
datetime(2005, 1, 1, 12, 30))
|
|
|
|
# It can also be used to directly encode property and parameter values
|
|
self.assertEqual(
|
|
factory.to_ical('comment', 'by Rasmussen, Max M\xfcller'),
|
|
b'by Rasmussen\\, Max M\xc3\xbcller'
|
|
)
|
|
self.assertEqual(factory.to_ical('priority', 1), b'1')
|
|
self.assertEqual(factory.to_ical('cn', 'Rasmussen, Max M\xfcller'),
|
|
b'Rasmussen\\, Max M\xc3\xbcller')
|
|
self.assertEqual(
|
|
factory.from_ical('cn', b'Rasmussen\\, Max M\xc3\xb8ller'),
|
|
'Rasmussen, Max M\xf8ller'
|
|
)
|
|
|
|
|
|
class TestPropertyValues(unittest.TestCase):
|
|
|
|
def test_vDDDLists_timezone(self):
|
|
"""Test vDDDLists with timezone information.
|
|
"""
|
|
from .. import Event
|
|
vevent = Event()
|
|
at = pytz.timezone('Europe/Vienna')
|
|
dt1 = at.localize(datetime(2013, 1, 1))
|
|
dt2 = at.localize(datetime(2013, 1, 2))
|
|
dt3 = at.localize(datetime(2013, 1, 3))
|
|
vevent.add('rdate', [dt1, dt2])
|
|
vevent.add('exdate', dt3)
|
|
ical = vevent.to_ical()
|
|
|
|
self.assertTrue(
|
|
b'RDATE;TZID=Europe/Vienna:20130101T000000,20130102T000000' in ical
|
|
)
|
|
self.assertTrue(b'EXDATE;TZID=Europe/Vienna:20130103T000000' in ical)
|
|
|
|
|
|
class TestWindowsOlsonMapping(unittest.TestCase):
|
|
"""Test the mappings from windows to olson tzids"""
|
|
|
|
def test_windows_timezone(self):
|
|
"""test that an example"""
|
|
self.assertEqual(
|
|
vDatetime.from_ical('20170507T181920', 'Eastern Standard Time'),
|
|
pytz.timezone('America/New_York').localize(datetime(2017, 5, 7, 18, 19, 20))
|
|
)
|
|
|
|
def test_all(self):
|
|
"""test if all mappings actually map to valid pytz tzids"""
|
|
for olson in WINDOWS_TO_OLSON.values():
|
|
pytz.timezone(olson)
|