yaml2ical/yaml2ical/recurrence.py

80 lines
2.5 KiB
Python

# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
import datetime
WEEKDAYS = {'Monday': 0, 'Tuesday': 1, 'Wednesday': 2, 'Thursday': 3,
'Friday': 4, 'Saturday': 5, 'Sunday': 6}
class WeeklyRecurrence(object):
"""Meetings occuring every week."""
def __init__(self):
pass
def next_occurence(self, current_date_time, day):
"""Return the date of the next meeting.
:param ref_date: datetime object of meeting
:param day: weekday the meeting is held on
:returns: datetime object of the next meeting time
"""
weekday = WEEKDAYS[day]
days_ahead = weekday - current_date_time.weekday()
if days_ahead < 0: # target day already happened this week
days_ahead += 7
return current_date_time + datetime.timedelta(days_ahead)
def rrule(self):
return {'freq': 'weekly'}
class BiWeeklyRecurrence(object):
"""Meetings occuring on alternate weeks.
Can be either on odd weeks or on even weeks
"""
def __init__(self, style='even'):
self.style = style
def next_occurence(self, current_date, day):
"""Calculate the next biweekly meeting.
:param current_date: the current date
:param day: scheduled day of the meeting
:returns: datetime object of next meeting
"""
nextweek_day = WeeklyRecurrence().next_occurence(current_date, day)
if nextweek_day.isocalendar()[1] % 2:
## ISO week is odd
if self.style == 'odd':
return nextweek_day
else:
## ISO week is even
if self.style == 'even':
return nextweek_day
# If week doesn't match rule, skip one week
return nextweek_day + datetime.timedelta(7)
def rrule(self):
return {'freq': 'weekly', 'interval': 2}
supported_recurrences = {
'weekly': WeeklyRecurrence(),
'biweekly-odd': BiWeeklyRecurrence(style='odd'),
'biweekly-even': BiWeeklyRecurrence(),
}