============================
plone.event recurrence tests
============================


recurrence_sequence_ical - rrulestr test
========================================

Basic
-----

When no recurrence rule is given, the start date should be returned.
    >>> from plone.event.recurrence import recurrence_sequence_ical
    >>> from datetime import datetime
    >>> dates = recurrence_sequence_ical(start=datetime(2010,01,01,0,0))
    >>> list(dates)
    [datetime.datetime(2010, 1, 1, 0, 0, tzinfo=<UTC>)]

Timezone naive dates are converted to utc.
    >>> dates = recurrence_sequence_ical(
    ...     start=datetime(2010,01,01,0,0),
    ...     recrule="""RRULE:FREQ=DAILY;INTERVAL=10;COUNT=5""")
    >>> list(dates)
    [datetime.datetime(2010, 1, 1, 0, 0, tzinfo=<UTC>),
        datetime.datetime(2010, 1, 11, 0, 0, tzinfo=<UTC>),
        datetime.datetime(2010, 1, 21, 0, 0, tzinfo=<UTC>),
        datetime.datetime(2010, 1, 31, 0, 0, tzinfo=<UTC>),
        datetime.datetime(2010, 2, 10, 0, 0, tzinfo=<UTC>)]

The same with the timezone set beforehand.
    >>> import pytz
    >>> at = pytz.timezone('Europe/Vienna')
    >>> dates = recurrence_sequence_ical(
    ...     start=at.localize(datetime(2010,01,01,0,0)),
    ...     recrule="""RRULE:FREQ=DAILY;INTERVAL=10;COUNT=5""")
    >>> list(dates)
    [datetime.datetime(2010, 1, 1, 0, 0, tzinfo=<DstTzInfo 'Europe/Vienna' CET+1:00:00 STD>),
        datetime.datetime(2010, 1, 11, 0, 0, tzinfo=<DstTzInfo 'Europe/Vienna' CET+1:00:00 STD>),
        datetime.datetime(2010, 1, 21, 0, 0, tzinfo=<DstTzInfo 'Europe/Vienna' CET+1:00:00 STD>),
        datetime.datetime(2010, 1, 31, 0, 0, tzinfo=<DstTzInfo 'Europe/Vienna' CET+1:00:00 STD>),
        datetime.datetime(2010, 2, 10, 0, 0, tzinfo=<DstTzInfo 'Europe/Vienna' CET+1:00:00 STD>)]

Get the integer representations from this recurrence rule
    >>> dates = recurrence_sequence_ical(
    ...     start=at.localize(datetime(2010,01,01,0,0)),
    ...     recrule="""RRULE:FREQ=DAILY;INTERVAL=10;COUNT=5""")
    >>> from plone.event.recurrence import recurrence_int_sequence
    >>> list(recurrence_int_sequence(dates))
    [1076762820, 1076777220, 1076791620, 1076806020, 1076820420]


Crossing Daylight Saving Time Boundaries
----------------------------------------

Timezone aware Daylight Saving Time dates crossing
    >>> start = at.localize(datetime(2010,10,28,9,0))
    >>> rulestr = """RRULE:FREQ=DAILY;INTERVAL=1;COUNT=5"""

    >>> dates = recurrence_sequence_ical(start, recrule=rulestr)
    >>> list(dates)
    [datetime.datetime(2010, 10, 28, 9, 0, tzinfo=<DstTzInfo 'Europe/Vienna' CEST+2:00:00 DST>),
        datetime.datetime(2010, 10, 29, 9, 0, tzinfo=<DstTzInfo 'Europe/Vienna' CEST+2:00:00 DST>),
        datetime.datetime(2010, 10, 30, 9, 0, tzinfo=<DstTzInfo 'Europe/Vienna' CEST+2:00:00 DST>),
        datetime.datetime(2010, 10, 31, 9, 0, tzinfo=<DstTzInfo 'Europe/Vienna' CET+1:00:00 STD>),
        datetime.datetime(2010, 11, 1, 9, 0, tzinfo=<DstTzInfo 'Europe/Vienna' CET+1:00:00 STD>)]


Note, that recurrence_sequence_ical calculates occurences timezone naively and
applies timezones afterwards. This leads into a problem in corner cases:
    >>> list(recurrence_sequence_ical(
    ...      start=at.localize(datetime(2010,10,30,23,0,0,0)),
    ...      recrule="""RRULE:FREQ=HOURLY;INTERVAL=1;COUNT=7"""
    ...      ))
    [datetime.datetime(2010, 10, 30, 23, 0, tzinfo=<DstTzInfo 'Europe/Vienna' CEST+2:00:00 DST>),
        datetime.datetime(2010, 10, 31, 0, 0, tzinfo=<DstTzInfo 'Europe/Vienna' CEST+2:00:00 DST>),
        datetime.datetime(2010, 10, 31, 1, 0, tzinfo=<DstTzInfo 'Europe/Vienna' CEST+2:00:00 DST>),
        datetime.datetime(2010, 10, 31, 2, 0, tzinfo=<DstTzInfo 'Europe/Vienna' CET+1:00:00 STD>),
        datetime.datetime(2010, 10, 31, 3, 0, tzinfo=<DstTzInfo 'Europe/Vienna' CET+1:00:00 STD>),
        datetime.datetime(2010, 10, 31, 4, 0, tzinfo=<DstTzInfo 'Europe/Vienna' CET+1:00:00 STD>),
        datetime.datetime(2010, 10, 31, 5, 0, tzinfo=<DstTzInfo 'Europe/Vienna' CET+1:00:00 STD>)]

Here is an hour missing, because at 3:00 in the morning, the clock is turned an hour
back. Correct would be:
[datetime.datetime(2010, 10, 30, 23, 0, tzinfo=<DstTzInfo 'CET' CEST+2:00:00 DST>),
datetime.datetime(2010, 10, 31, 0, 0, tzinfo=<DstTzInfo 'CET' CEST+2:00:00 DST>),
datetime.datetime(2010, 10, 31, 1, 0, tzinfo=<DstTzInfo 'CET' CEST+2:00:00 DST>),
datetime.datetime(2010, 10, 31, 2, 0, tzinfo=<DstTzInfo 'CET' CEST+2:00:00 DST>),
datetime.datetime(2010, 10, 31, 2, 0, tzinfo=<DstTzInfo 'CET' CET+1:00:00 STD>),
datetime.datetime(2010, 10, 31, 3, 0, tzinfo=<DstTzInfo 'CET' CET+1:00:00 STD>),
datetime.datetime(2010, 10, 31, 4, 0, tzinfo=<DstTzInfo 'CET' CET+1:00:00 STD>)]



Multiple Ruleset
----------------

    >>> start = at.localize(datetime(2010,01,01,0,0))
    >>> rulestr = """RRULE:FREQ=DAILY;INTERVAL=1;UNTIL=20100110T000000
    ... RDATE:20100120T000000
    ... EXRULE:FREQ=DAILY;INTERVAL=2;UNTIL=20100110T000000
    ... EXDATE:20100102T000000"""

    >>> dates = recurrence_sequence_ical(start, recrule=rulestr)
    >>> list(dates)
    [datetime.datetime(2010, 1, 4, 0, 0, tzinfo=<DstTzInfo 'Europe/Vienna' CET+1:00:00 STD>),
        datetime.datetime(2010, 1, 6, 0, 0, tzinfo=<DstTzInfo 'Europe/Vienna' CET+1:00:00 STD>),
        datetime.datetime(2010, 1, 8, 0, 0, tzinfo=<DstTzInfo 'Europe/Vienna' CET+1:00:00 STD>),
        datetime.datetime(2010, 1, 10, 0, 0, tzinfo=<DstTzInfo 'Europe/Vienna' CET+1:00:00 STD>),
        datetime.datetime(2010, 1, 20, 0, 0, tzinfo=<DstTzInfo 'Europe/Vienna' CET+1:00:00 STD>)]


Limiting number of occurences
-----------------------------

Until (date until recurrence happens) and count (Number of occurences) can also
be given in recurrence_sequence_ical, instead of defining it in the rrule.
But defining it in a rrule gives more flexibility since you can set it for each
rrule individually.
If MAXCOUNT is exceeded, recurrence generation will stop regardless of any other
setting.

...init
    >>> rulestr = """RRULE:FREQ=DAILY;INTERVAL=1"""
    >>> start = at.localize(datetime(2010,01,01,0,0))
    >>> until = at.localize(datetime(2010,01,02,0,0))

...until
    >>> dates = recurrence_sequence_ical(start, recrule=rulestr, until=until)
    >>> list(dates)
    [datetime.datetime(2010, 1, 1, 0, 0, tzinfo=<DstTzInfo 'Europe/Vienna' CET+1:00:00 STD>),
        datetime.datetime(2010, 1, 2, 0, 0, tzinfo=<DstTzInfo 'Europe/Vienna' CET+1:00:00 STD>)]

...count
    >>> dates = recurrence_sequence_ical(start, recrule=rulestr, count=3)
    >>> list(dates)
    [datetime.datetime(2010, 1, 1, 0, 0, tzinfo=<DstTzInfo 'Europe/Vienna' CET+1:00:00 STD>),
        datetime.datetime(2010, 1, 2, 0, 0, tzinfo=<DstTzInfo 'Europe/Vienna' CET+1:00:00 STD>),
        datetime.datetime(2010, 1, 3, 0, 0, tzinfo=<DstTzInfo 'Europe/Vienna' CET+1:00:00 STD>)]

...until and count
You can mix both until and count. What happens earlier will stop recurrence
    >>> dates = recurrence_sequence_ical(start, rulestr, until=until, count=3)
    >>> list(dates)
    [datetime.datetime(2010, 1, 1, 0, 0, tzinfo=<DstTzInfo 'Europe/Vienna' CET+1:00:00 STD>),
        datetime.datetime(2010, 1, 2, 0, 0, tzinfo=<DstTzInfo 'Europe/Vienna' CET+1:00:00 STD>)]

...MAXCOUNT is important to prevent (unintentional/intentional) abuse. It's
a constant, is configurable (TODO) or - for this test - set from outside...
    >>> from plone.event import recurrence
    >>> orig_maxcount = recurrence.MAXCOUNT
    >>> recurrence.MAXCOUNT = 5
    >>> dates = recurrence_sequence_ical(start, rulestr)
    >>> list(dates)
    [datetime.datetime(2010, 1, 1, 0, 0, tzinfo=<DstTzInfo 'Europe/Vienna' CET+1:00:00 STD>),
        datetime.datetime(2010, 1, 2, 0, 0, tzinfo=<DstTzInfo 'Europe/Vienna' CET+1:00:00 STD>),
        datetime.datetime(2010, 1, 3, 0, 0, tzinfo=<DstTzInfo 'Europe/Vienna' CET+1:00:00 STD>),
        datetime.datetime(2010, 1, 4, 0, 0, tzinfo=<DstTzInfo 'Europe/Vienna' CET+1:00:00 STD>),
        datetime.datetime(2010, 1, 5, 0, 0, tzinfo=<DstTzInfo 'Europe/Vienna' CET+1:00:00 STD>)]
    >>> recurrence.MAXCOUNT = orig_maxcount



recurrence_sequence_timedelta test
==================================
    >>> from plone.event.utils import DSTKEEP, DSTADJUST, DSTAUTO 
    >>> from plone.event.recurrence import recurrence_sequence_timedelta
    >>> from datetime import timedelta

The simplest case is to just have a one-time event.
    >>> start = datetime(2008,01,01,0,0,0,0,pytz.timezone('CET'))
    >>> dates = recurrence_sequence_timedelta(start)
    >>> list(dates)
    [datetime.datetime(2008, 1, 1, 0, 0, tzinfo=<DstTzInfo 'CET' CET+1:00:00 STD>)]

We want all hours of a day:
    >>> until = start + timedelta(days=1) - timedelta(microseconds=1)
    >>> dates = recurrence_sequence_timedelta(start, delta=60, until=until)
    >>> list(dates)
    [datetime.datetime(2008, 1, 1, 0, 0, tzinfo=<DstTzInfo 'CET' CET+1:00:00 STD>),
        datetime.datetime(2008, 1, 1, 1, 0, tzinfo=<DstTzInfo 'CET' CET+1:00:00 STD>),
        datetime.datetime(2008, 1, 1, 2, 0, tzinfo=<DstTzInfo 'CET' CET+1:00:00 STD>),
        datetime.datetime(2008, 1, 1, 3, 0, tzinfo=<DstTzInfo 'CET' CET+1:00:00 STD>),
        datetime.datetime(2008, 1, 1, 4, 0, tzinfo=<DstTzInfo 'CET' CET+1:00:00 STD>),
        datetime.datetime(2008, 1, 1, 5, 0, tzinfo=<DstTzInfo 'CET' CET+1:00:00 STD>),
        datetime.datetime(2008, 1, 1, 6, 0, tzinfo=<DstTzInfo 'CET' CET+1:00:00 STD>),
        datetime.datetime(2008, 1, 1, 7, 0, tzinfo=<DstTzInfo 'CET' CET+1:00:00 STD>),
        datetime.datetime(2008, 1, 1, 8, 0, tzinfo=<DstTzInfo 'CET' CET+1:00:00 STD>),
        datetime.datetime(2008, 1, 1, 9, 0, tzinfo=<DstTzInfo 'CET' CET+1:00:00 STD>),
        datetime.datetime(2008, 1, 1, 10, 0, tzinfo=<DstTzInfo 'CET' CET+1:00:00 STD>),
        datetime.datetime(2008, 1, 1, 11, 0, tzinfo=<DstTzInfo 'CET' CET+1:00:00 STD>),
        datetime.datetime(2008, 1, 1, 12, 0, tzinfo=<DstTzInfo 'CET' CET+1:00:00 STD>),
        datetime.datetime(2008, 1, 1, 13, 0, tzinfo=<DstTzInfo 'CET' CET+1:00:00 STD>),
        datetime.datetime(2008, 1, 1, 14, 0, tzinfo=<DstTzInfo 'CET' CET+1:00:00 STD>),
        datetime.datetime(2008, 1, 1, 15, 0, tzinfo=<DstTzInfo 'CET' CET+1:00:00 STD>),
        datetime.datetime(2008, 1, 1, 16, 0, tzinfo=<DstTzInfo 'CET' CET+1:00:00 STD>),
        datetime.datetime(2008, 1, 1, 17, 0, tzinfo=<DstTzInfo 'CET' CET+1:00:00 STD>),
        datetime.datetime(2008, 1, 1, 18, 0, tzinfo=<DstTzInfo 'CET' CET+1:00:00 STD>),
        datetime.datetime(2008, 1, 1, 19, 0, tzinfo=<DstTzInfo 'CET' CET+1:00:00 STD>),
        datetime.datetime(2008, 1, 1, 20, 0, tzinfo=<DstTzInfo 'CET' CET+1:00:00 STD>),
        datetime.datetime(2008, 1, 1, 21, 0, tzinfo=<DstTzInfo 'CET' CET+1:00:00 STD>),
        datetime.datetime(2008, 1, 1, 22, 0, tzinfo=<DstTzInfo 'CET' CET+1:00:00 STD>),
        datetime.datetime(2008, 1, 1, 23, 0, tzinfo=<DstTzInfo 'CET' CET+1:00:00 STD>)]


different daylight saving time behaviours
-----------------------------------------

First lets change from winter to summertime (EU rules with CET):

    >>> start = datetime(2008,03,29,21,0,0,0,pytz.timezone('CET'))
    >>> until = datetime(2008,03,30,21,0,0,0,pytz.timezone('CET')) - timedelta(microseconds=1)

    >>> from plone.event.utils import utcoffset_normalize, DSTADJUST
    >>> until = utcoffset_normalize(until, dstmode=DSTADJUST)
    >>> until
    datetime.datetime(2008, 3, 30, 20, 59, 59, 999999, tzinfo=<DstTzInfo 'CET' CEST+2:00:00 DST>)

    >>> dates = recurrence_sequence_timedelta(start, delta=60, until=until, dst=DSTADJUST)
    >>> dates = list(dates)
    >>> len(dates)
    24

This sequence has one hour to much, so DSTADJUST on a granularity below one day
is wrong! 1:00 CET is the same as 2:00 CEST!

    >>> dates
    [datetime.datetime(2008, 3, 29, 21, 0, tzinfo=<DstTzInfo 'CET' CET+1:00:00 STD>),
        datetime.datetime(2008, 3, 29, 22, 0, tzinfo=<DstTzInfo 'CET' CET+1:00:00 STD>),
        datetime.datetime(2008, 3, 29, 23, 0, tzinfo=<DstTzInfo 'CET' CET+1:00:00 STD>),
        datetime.datetime(2008, 3, 30, 0, 0, tzinfo=<DstTzInfo 'CET' CET+1:00:00 STD>),
        datetime.datetime(2008, 3, 30, 1, 0, tzinfo=<DstTzInfo 'CET' CET+1:00:00 STD>),
        datetime.datetime(2008, 3, 30, 2, 0, tzinfo=<DstTzInfo 'CET' CEST+2:00:00 DST>),
        datetime.datetime(2008, 3, 30, 3, 0, tzinfo=<DstTzInfo 'CET' CEST+2:00:00 DST>),
        datetime.datetime(2008, 3, 30, 4, 0, tzinfo=<DstTzInfo 'CET' CEST+2:00:00 DST>),
        datetime.datetime(2008, 3, 30, 5, 0, tzinfo=<DstTzInfo 'CET' CEST+2:00:00 DST>),
        datetime.datetime(2008, 3, 30, 6, 0, tzinfo=<DstTzInfo 'CET' CEST+2:00:00 DST>),
        datetime.datetime(2008, 3, 30, 7, 0, tzinfo=<DstTzInfo 'CET' CEST+2:00:00 DST>),
        datetime.datetime(2008, 3, 30, 8, 0, tzinfo=<DstTzInfo 'CET' CEST+2:00:00 DST>),
        datetime.datetime(2008, 3, 30, 9, 0, tzinfo=<DstTzInfo 'CET' CEST+2:00:00 DST>),
        datetime.datetime(2008, 3, 30, 10, 0, tzinfo=<DstTzInfo 'CET' CEST+2:00:00 DST>),
        datetime.datetime(2008, 3, 30, 11, 0, tzinfo=<DstTzInfo 'CET' CEST+2:00:00 DST>),
        datetime.datetime(2008, 3, 30, 12, 0, tzinfo=<DstTzInfo 'CET' CEST+2:00:00 DST>),
        datetime.datetime(2008, 3, 30, 13, 0, tzinfo=<DstTzInfo 'CET' CEST+2:00:00 DST>),
        datetime.datetime(2008, 3, 30, 14, 0, tzinfo=<DstTzInfo 'CET' CEST+2:00:00 DST>),
        datetime.datetime(2008, 3, 30, 15, 0, tzinfo=<DstTzInfo 'CET' CEST+2:00:00 DST>),
        datetime.datetime(2008, 3, 30, 16, 0, tzinfo=<DstTzInfo 'CET' CEST+2:00:00 DST>),
        datetime.datetime(2008, 3, 30, 17, 0, tzinfo=<DstTzInfo 'CET' CEST+2:00:00 DST>),
        datetime.datetime(2008, 3, 30, 18, 0, tzinfo=<DstTzInfo 'CET' CEST+2:00:00 DST>),
        datetime.datetime(2008, 3, 30, 19, 0, tzinfo=<DstTzInfo 'CET' CEST+2:00:00 DST>),
        datetime.datetime(2008, 3, 30, 20, 0, tzinfo=<DstTzInfo 'CET' CEST+2:00:00 DST>)]

Anyway, we want this behaviour on a day-level, see next example, a event should
recurr every day 11:00am.
    >>> start = datetime(2008,03,29,11,0,0,0,pytz.timezone('CET'))
    >>> until = datetime(2008,03,31,11,0,0,0,pytz.timezone('CET'))
    >>> until = utcoffset_normalize(until, dstmode=DSTADJUST)
    >>> dates = recurrence_sequence_timedelta(start, delta=24*60, until=until, dst=DSTADJUST)
    >>> list(dates)
    [datetime.datetime(2008, 3, 29, 11, 0, tzinfo=<DstTzInfo 'CET' CET+1:00:00 STD>),
        datetime.datetime(2008, 3, 30, 11, 0, tzinfo=<DstTzInfo 'CET' CEST+2:00:00 DST>),
        datetime.datetime(2008, 3, 31, 11, 0, tzinfo=<DstTzInfo 'CET' CEST+2:00:00 DST>)]

see what DSTKEEP does:
    >>> dates = recurrence_sequence_timedelta(start, delta=24*60, until=until, dst=DSTKEEP)
    >>> list(dates)
    [datetime.datetime(2008, 3, 29, 11, 0, tzinfo=<DstTzInfo 'CET' CET+1:00:00 STD>),
        datetime.datetime(2008, 3, 30, 12, 0, tzinfo=<DstTzInfo 'CET' CEST+2:00:00 DST>)]

Here the correct behaviour on day level with DSTKEEP.

    >>> start = datetime(2008,03,29,21,0,0,0,pytz.timezone('CET'))
    >>> until = datetime(2008,03,30,21,0,0,0,pytz.timezone('CET')) - timedelta(microseconds=1)
    >>> until = utcoffset_normalize(until, dstmode=DSTADJUST)

    >>> dates = recurrence_sequence_timedelta(start, delta=60, until=until, dst=DSTKEEP)
    >>> dates = list(dates)
    >>> len(dates)
    23
    >>> dates
    [datetime.datetime(2008, 3, 29, 21, 0, tzinfo=<DstTzInfo 'CET' CET+1:00:00 STD>),
        datetime.datetime(2008, 3, 29, 22, 0, tzinfo=<DstTzInfo 'CET' CET+1:00:00 STD>),
        datetime.datetime(2008, 3, 29, 23, 0, tzinfo=<DstTzInfo 'CET' CET+1:00:00 STD>),
        datetime.datetime(2008, 3, 30, 0, 0, tzinfo=<DstTzInfo 'CET' CET+1:00:00 STD>),
        datetime.datetime(2008, 3, 30, 1, 0, tzinfo=<DstTzInfo 'CET' CET+1:00:00 STD>),
        datetime.datetime(2008, 3, 30, 3, 0, tzinfo=<DstTzInfo 'CET' CEST+2:00:00 DST>),
        datetime.datetime(2008, 3, 30, 4, 0, tzinfo=<DstTzInfo 'CET' CEST+2:00:00 DST>),
        datetime.datetime(2008, 3, 30, 5, 0, tzinfo=<DstTzInfo 'CET' CEST+2:00:00 DST>),
        datetime.datetime(2008, 3, 30, 6, 0, tzinfo=<DstTzInfo 'CET' CEST+2:00:00 DST>),
        datetime.datetime(2008, 3, 30, 7, 0, tzinfo=<DstTzInfo 'CET' CEST+2:00:00 DST>),
        datetime.datetime(2008, 3, 30, 8, 0, tzinfo=<DstTzInfo 'CET' CEST+2:00:00 DST>),
        datetime.datetime(2008, 3, 30, 9, 0, tzinfo=<DstTzInfo 'CET' CEST+2:00:00 DST>),
        datetime.datetime(2008, 3, 30, 10, 0, tzinfo=<DstTzInfo 'CET' CEST+2:00:00 DST>),
        datetime.datetime(2008, 3, 30, 11, 0, tzinfo=<DstTzInfo 'CET' CEST+2:00:00 DST>),
        datetime.datetime(2008, 3, 30, 12, 0, tzinfo=<DstTzInfo 'CET' CEST+2:00:00 DST>),
        datetime.datetime(2008, 3, 30, 13, 0, tzinfo=<DstTzInfo 'CET' CEST+2:00:00 DST>),
        datetime.datetime(2008, 3, 30, 14, 0, tzinfo=<DstTzInfo 'CET' CEST+2:00:00 DST>),
        datetime.datetime(2008, 3, 30, 15, 0, tzinfo=<DstTzInfo 'CET' CEST+2:00:00 DST>),
        datetime.datetime(2008, 3, 30, 16, 0, tzinfo=<DstTzInfo 'CET' CEST+2:00:00 DST>),
        datetime.datetime(2008, 3, 30, 17, 0, tzinfo=<DstTzInfo 'CET' CEST+2:00:00 DST>),
        datetime.datetime(2008, 3, 30, 18, 0, tzinfo=<DstTzInfo 'CET' CEST+2:00:00 DST>),
        datetime.datetime(2008, 3, 30, 19, 0, tzinfo=<DstTzInfo 'CET' CEST+2:00:00 DST>),
        datetime.datetime(2008, 3, 30, 20, 0, tzinfo=<DstTzInfo 'CET' CEST+2:00:00 DST>)]

Usally we want an clever behaviour, dependend on delta. This is implemented
with DSTAUTO, which is the default behaviour.

Here the correct behaviour on day level or above: DSTADJUST is choosen.

    >>> start = datetime(2008,03,29,11,0,0,0,pytz.timezone('CET'))
    >>> until = datetime(2008,03,31,11,0,0,0,pytz.timezone('CET'))
    >>> until = utcoffset_normalize(until, dstmode=DSTADJUST)
    >>> until
    datetime.datetime(2008, 3, 31, 11, 0, tzinfo=<DstTzInfo 'CET' CEST+2:00:00 DST>)

    >>> dates = recurrence_sequence_timedelta(start, delta=24*60, until=until)
    >>> list(dates)
    [datetime.datetime(2008, 3, 29, 11, 0, tzinfo=<DstTzInfo 'CET' CET+1:00:00 STD>),
        datetime.datetime(2008, 3, 30, 11, 0, tzinfo=<DstTzInfo 'CET' CEST+2:00:00 DST>),
        datetime.datetime(2008, 3, 31, 11, 0, tzinfo=<DstTzInfo 'CET' CEST+2:00:00 DST>)]


The correct behaviour on below day level: DSTKEEP is choosen.

    >>> start = datetime(2008,03,29,21,0,0,0,pytz.timezone('CET'))
    >>> until = datetime(2008,03,30,21,0,0,0,pytz.timezone('CET')) - timedelta(microseconds=1)
    >>> until = utcoffset_normalize(until, dstmode=DSTADJUST)
    >>> dates = recurrence_sequence_timedelta(start, delta=60, until=until)
    >>> len(list(dates))
    23

recurringIntSequence
--------------------

taking the above results in integers if recurringIntSequence is called:


    >>> from plone.event.recurrence import recurrence_int_sequence
    >>> dates = recurrence_sequence_timedelta(start, 60, until)
    >>> list(recurrence_int_sequence(dates))
    [1075822320,
        1075822380,
        1075822440,
        1075822500,
        1075822560,
        1075822620,
        1075822680,
        1075822740,
        1075822800,
        1075822860,
        1075822920,
        1075822980,
        1075823040,
        1075823100,
        1075823160,
        1075823220,
        1075823280,
        1075823340,
        1075823400,
        1075823460,
        1075823520,
        1075823580,
        1075823640]


Zope DateTime support
=====================

Now some tests with Zopes ugly DateTime

    >>> from DateTime import DateTime

First with UTC

    >>> DT = DateTime('2008-08-26 23:59:00 GMT+0')
    >>> dt = datetime(2008, 8, 26, 23, 59, 0, 0, pytz.timezone('utc'))

    >>> seqDT = list(recurrence_int_sequence(recurrence_sequence_timedelta(DT, 0, None)))
    >>> seqdt = list(recurrence_int_sequence(recurrence_sequence_timedelta(dt, 0, None)))
    >>> seqDT[0] == seqdt[0]
    True

Now with GMT+2 (CET with DST)

    >>> DT = DateTime('2008-08-26 23:59:00 GMT+2')
    >>> dt = datetime(2008, 8, 26, 23, 59, 0, 0, pytz.timezone('CET'))
    >>> seqDT = list(recurrence_sequence_timedelta(DT, 0, None))

seqDT shows now a hour of 21 because it's converted to UTC
    >>> seqDT
    [datetime.datetime(2008, 8, 26, 21, 59, tzinfo=<UTC>)]

    >>> seqdt = list(recurrence_sequence_timedelta(dt, 0, None))
    >>> seqdt
    [datetime.datetime(2008, 8, 26, 23, 59, tzinfo=<DstTzInfo 'CET' CEST+2:00:00 DST>)]

Comparison of two datetime with same time related to UTC but in different
timezones works.
    >>> seqDT[0] == seqdt[0]
    True

Does integer represenation work?
    >>> seqDT = list(recurrence_int_sequence(recurrence_sequence_timedelta(DT, 0, None)))
    >>> seqdt = list(recurrence_int_sequence(recurrence_sequence_timedelta(dt, 0, None)))

Integer sequences are the same anyways, because dates are converted to UTC first.
    >>> seqDT[0] == seqdt[0]
    True

