Пример #1
0
def main(argv):
    conference_schedules = defaultdict(dict)

    # Download the schedule details for each channel and group into
    # conferences.
    for channel in CONFIG.groups():
        config = CONFIG.config(channel)

    	if 'schedule' not in config or not config['schedule']:
            sys.stderr.write("Channel %s doesn't have a schedule.\n" % channel)
            continue

        tzinfo = None
        if config['schedule-timezone']:
            tzinfo = pytz.timezone(config['schedule-timezone'])

        channel_schedule = get_schedule_json(config['schedule'], tzinfo)
        if config['schedule-key'] not in channel_schedule:
            raise IOError()

        conference = config['group']
        if config['conference']:
            conference = config['conference']

        schedule = []
        for schedule_key in [config['schedule-key']] + config['schedule-see-also']:
            for item in channel_schedule[schedule_key]:
                if item['title'] in ("miniconf schedules to be determined",):
                    continue

                data = {
                    'start': item['start'],
                    'end': item['end'],
                    'title': item['title'],
                    'abstract': item['abstract'],
                    'url': '',
                    }

                if 'url' in item:
                    data['url'] = item['url']

                if schedule_key == 'uncatered':
                    data['via'] = schedule_key
                    data['title'] = "Lunch Break"
                elif schedule_key != config['schedule-key']:
                    data['via'] = schedule_key
                    data['title'] = "Move to %s for %s" % (schedule_key, item['title'])

                schedule.append(data)

        schedule.sort(key=lambda i: i['start'])
        conference_schedules[conference][channel] = schedule

    # Fill in day start / day end events for each conference day.
    # (We need to work in the schedule's timezone for this to work properly.)
    for conference in conference_schedules:
        # First earliest and latest event in a conference.
        all_events = []
        for channel_schedule in conference_schedules[conference].values():
            all_events.extend(channel_schedule)
        all_events.sort(key=lambda i: i['start'])

        starting_event = all_events[0]
        ending_event = all_events[-1]

        for channel in conference_schedules[conference]:
            oldevents = conference_schedules[conference][channel]

            config = CONFIG.config(channel)
            if not config['schedule-timezone']:
                sys.stderr.write("%s has not timezone, can't add conference day events\n" % channel)
                continue
            tzinfo = pytz.timezone(config['schedule-timezone'])

            # Group events onto days
            perday_events = defaultdict(list)
            for event in oldevents:
                perday_events[event['end'].astimezone(tzinfo).date()].append(event)

            # Remove any days which are 100% via another schedule.
            for day in list(perday_events.keys()):
                for event in perday_events[day]:
                    if not event.get('via', False):
                        break
                else:
                    # All generated
                    del perday_events[day]

            # Add in any missing days
            startdate = datetime_tz.combine(
                starting_event['start'].astimezone(tzinfo).date(),
                datetime_tz.min.time(),
                tzinfo)
            enddate = datetime_tz.combine(
                ending_event['start'].astimezone(tzinfo).date(),
                datetime_tz.min.time(),
                tzinfo)
            for day in dt_iterate.days(startdate, enddate):
                if day.date() not in perday_events:
                    day_skipped_event = {
                        'start': datetime_tz.combine(day, datetime_tz.min.time(), tzinfo).astimezone(pytz.utc),
                        'end': datetime_tz.combine(day, datetime_tz.max.time(), tzinfo).astimezone(pytz.utc),
                        'title': '<i>Nothing in %s today</i>' % config['title'],
                        'abstract': '',
                        'generated': True,
                        }

                    perday_events[day.date()].append(day_skipped_event)

            # Add start of day / end of day events
            for day, events in perday_events.items():
                if day > startdate.date() and events[0]['start'].astimezone(tzinfo).time() != datetime_tz.min.time():
                    events.insert(0, {
                        'start': datetime_tz.combine(day, datetime_tz.min.time(), tzinfo).astimezone(pytz.utc),
                        'end': events[0]['start'],
                        'title': '<i>Not yet started in %s</i>' % config['title'],
                        'abstract': '',
                        'generated': True,
                        })

                if day < enddate.date() and events[-1]['end'].astimezone(tzinfo).time() != datetime_tz.max.time():
                    events.append({
                        'start': events[-1]['end'],
                        'end': datetime_tz.combine(day, datetime_tz.max.time(), tzinfo).astimezone(pytz.utc),
                        'title': '<i>Finished for the day in %s</i>' % config['title'],
                        'abstract': '',
                        'generated': True,
                        })

            # Create a before conference start event.
            before_event = {
                'start': datetime_tz(datetime_tz.min.asdatetime(naive=True), tzinfo).astimezone(pytz.utc),
                'end': starting_event['start'],
                'title': '<i>%s not yet started</i>' % conference,
                'abstract': '',
                'generated': True,
                }
            # Create an after conference end event.
            after_event = {
                'start': ending_event['end'],
                'end': datetime_tz(datetime_tz.max.asdatetime(naive=True), tzinfo).astimezone(pytz.utc),
                'title': '<i>%s finished :(</i>' % conference,
                'abstract': '',
                'generated': True,
                }

            # Put everything back together
            newevents = [before_event]
            for day in sorted(perday_events.keys()):
                newevents.extend(perday_events[day])
            newevents.append(after_event)

            conference_schedules[conference][channel] = newevents

    # Fill in any gaps
    for conference in conference_schedules:
        for channel in conference_schedules[conference]:
            oldevents = conference_schedules[conference][channel]

            newevents = [oldevents.pop(0)]
            conference_schedules[conference][channel] = newevents

            while len(oldevents) > 0:
                delta = oldevents[0]['start'] - newevents[-1]['end']

                if delta.seconds > (5*60):
                    unknown_event = {
                        'start': newevents[-1]['end'],
                        'end': oldevents[0]['start'],
                        'abstract': '',
                        'generated': True,
                        }
                    unknown_event['title'] = '<i>%i minute break</i>' % ((unknown_event['end'] - unknown_event['start']).seconds/60)
                    newevents.append(unknown_event)
                newevents.append(oldevents.pop(0))

    # Add guid to each event
    for conference in conference_schedules:
        for channel in conference_schedules[conference]:
            for item in conference_schedules[conference][channel]:
                if 'guid' not in item:
                    item['guid'] = hashlib.md5(str(item['start'])+channel).hexdigest()

    print_schedule(conference_schedules)

    output_data = {}
    for conference in conference_schedules:
        for channel in conference_schedules[conference]:
            output_data[channel] = conference_schedules[conference][channel]

    out = StringIO.StringIO()
    pprint.pprint(output_data, stream=out)
    print """\
from datetime_tz import datetime_tz
import pytz

data = \\"""
    print out.getvalue()
def main(argv):
    if CONFIG['config']['schedule-format']:
        if CONFIG['config']['schedule-format'] == 'pycon':
            return os.system('python pycon2internal.py')
        if CONFIG['config']['schedule-format'] == 'veyepar':
            return os.system('python veyepar2internal.py')
        if CONFIG['config']['schedule-format'] == 'symposion':
            return os.system('python symposion2internal.py')

    conference_schedules = defaultdict(dict)

    # Download the schedule details for each channel and group into
    # conferences.
    for channel in CONFIG.groups():
        config = CONFIG.config(channel)

        if 'schedule' not in config or not config['schedule']:
            sys.stderr.write("Channel %s doesn't have a schedule.\n" % channel)
            continue

        tzinfo = None
        if config['schedule-timezone']:
            tzinfo = pytz.timezone(config['schedule-timezone'])

        channel_schedule = get_schedule_json(config['schedule'], tzinfo)

        conference = config['group']
        if config['conference']:
            conference = config['conference']

        schedule = []
        for item in channel_schedule:
            if 'Title' not in item or not item['Title'] or item['Title'] in BLACKLISTED_EVENTS:
                continue

            if item['Room Name'] != config['schedule-key'] and item['Room Name'] != config['schedule-see-also']:
                # Event is not in this room
                continue

            data = {
                'start': item['Start'],
                'title': item['Title'].strip(),
                'abstract': item['Description'],
                'url': None,
                }

            if 'End' in item:
                data['end'] = item['End']
            elif 'Duration' in item:
                data['end'] = data['start'] + parse_pytimedelta(item['Duration'])
            else:
                sys.stderr.write('Event %r does not have a End time or Duration, dropped.\n' % item['Title'])
                continue
            if 'URL' in item:
                data['url'] = item['URL']

            schedule.append(data)

        schedule.sort(key=lambda i: i['start'])
        conference_schedules[conference][channel] = schedule

    # Fill in day start / day end events for each conference day.
    # (We need to work in the schedule's timezone for this to work properly.)
    for conference in conference_schedules:
        # First earliest and latest event in a conference.
        all_events = []
        for channel_schedule in conference_schedules[conference].values():
            all_events.extend(channel_schedule)
        all_events.sort(key=lambda i: i['start'])

        if len(all_events) == 0:
            # No events this day
            sys.stderr.write("There are no events in %r\n" % (conference,))
            continue
        starting_event = all_events[0]
        ending_event = all_events[-1]

        for channel in conference_schedules[conference]:
            oldevents = conference_schedules[conference][channel]

            config = CONFIG.config(channel)
            if not config['schedule-timezone']:
                sys.stderr.write("%s has not timezone, can't add conference day events\n" % channel)
                continue
            tzinfo = pytz.timezone(config['schedule-timezone'])

            # Group events onto days
            perday_events = defaultdict(list)
            for event in oldevents:
                perday_events[event['end'].astimezone(tzinfo).date()].append(event)

            # Remove any days which are 100% via another schedule.
            for day in list(perday_events.keys()):
                for event in perday_events[day]:
                    if not event.get('via', False):
                        break
                else:
                    # All generated
                    del perday_events[day]

            # Add in any missing days
            startdate = datetime_tz.combine(
                starting_event['start'].astimezone(tzinfo).date(),
                datetime_tz.min.time(),
                tzinfo)
            enddate = datetime_tz.combine(
                ending_event['start'].astimezone(tzinfo).date(),
                datetime_tz.min.time(),
                tzinfo)
            for day in dt_iterate.days(startdate, enddate):
                if day.date() not in perday_events:
                    day_skipped_event = {
                        'start': datetime_tz.combine(day, datetime_tz.min.time(), tzinfo).astimezone(pytz.utc),
                        'end': datetime_tz.combine(day, datetime_tz.max.time(), tzinfo).astimezone(pytz.utc),
                        'title': 'Nothing in %s today' % config['title'],
                        'abstract': '',
                        'generated': True,
                        }

                    perday_events[day.date()].append(day_skipped_event)

            # Add start of day / end of day events
            for day, events in perday_events.items():
                if day > startdate.date() and events[0]['start'].astimezone(tzinfo).time() != datetime_tz.min.time():
                    events.insert(0, {
                        'start': datetime_tz.combine(day, datetime_tz.min.time(), tzinfo).astimezone(pytz.utc),
                        'end': events[0]['start'],
                        'title': 'Not yet started in %s' % config['title'],
                        'abstract': '',
                        'generated': True,
                        })

                if day < enddate.date() and events[-1]['end'].astimezone(tzinfo).time() != datetime_tz.max.time():
                    events.append({
                        'start': events[-1]['end'],
                        'end': datetime_tz.combine(day, datetime_tz.max.time(), tzinfo).astimezone(pytz.utc),
                        'title': 'Finished for the day in %s' % config['title'],
                        'abstract': '',
                        'generated': True,
                        })

            # Create a before conference start event.
            before_event = {
                'start': datetime_tz(datetime_tz.min.asdatetime(naive=True), tzinfo).astimezone(pytz.utc),
                'end': starting_event['start'],
                'title': '%s not yet started' % conference,
                'abstract': '',
                'generated': True,
                }
            # Create an after conference end event.
            after_event = {
                'start': ending_event['end'],
                'end': datetime_tz(datetime_tz.max.asdatetime(naive=True), tzinfo).astimezone(pytz.utc),
                'title': '%s finished :(' % conference,
                'abstract': '',
                'generated': True,
                }

            # Put everything back together
            newevents = [before_event]
            for day in sorted(perday_events.keys()):
                newevents.extend(perday_events[day])
            newevents.append(after_event)

            conference_schedules[conference][channel] = newevents

    # Fill in any gaps
    for conference in conference_schedules:
        for channel in conference_schedules[conference]:
            oldevents = conference_schedules[conference][channel]

            if len(oldevents) == 0:
                # No events on day
                continue
            newevents = [oldevents.pop(0)]
            conference_schedules[conference][channel] = newevents

            while len(oldevents) > 0:
                delta = oldevents[0]['start'] - newevents[-1]['end']

                if delta.seconds > (5*60):
                    unknown_event = {
                        'start': newevents[-1]['end'],
                        'end': oldevents[0]['start'],
                        'abstract': '',
                        'generated': True,
                        }
                    unknown_event['title'] = '%i minute break' % ((unknown_event['end'] - unknown_event['start']).seconds/60)
                    newevents.append(unknown_event)
                newevents.append(oldevents.pop(0))

    # Add guid to each event
    for conference in conference_schedules:
        for channel in conference_schedules[conference]:
            for item in conference_schedules[conference][channel]:
                if 'guid' not in item:
                    item['guid'] = hashlib.md5(str(item['start'])+channel).hexdigest()

    print_schedule(conference_schedules)

    output_data = {}
    for conference in conference_schedules:
        for channel in conference_schedules[conference]:
            output_data[channel] = conference_schedules[conference][channel]

    out = StringIO.StringIO()
    pprint.pprint(output_data, stream=out)
    print """\
from datetime_tz import datetime_tz
import pytz

data = \\"""
    print out.getvalue()
Пример #3
0
def main(argv):

    conference_schedules = defaultdict(dict)

    # Download the schedule details for each channel and group into
    # conferences.
    for channel in CONFIG.groups():
        if channel == 'example':
            continue

        config = CONFIG.config(channel)

        if 'schedule' not in config or not config['schedule']:
            sys.stderr.write("Channel %s doesn't have a schedule.\n" % channel)
            continue

        tzinfo = None
        if config['schedule-timezone']:
            tzinfo = pytz.timezone(config['schedule-timezone'])

        channel_schedule = get_schedule_json(config['schedule'], channel,
                                             tzinfo)
        channel_schedule_list = []
        for e in channel_schedule:
            channel_schedule_list.append(e['fields'])

        conference = config['group']
        if config['conference']:
            conference = config['conference']

        schedule = []
        for item in channel_schedule_list:
            if item['name'] in ("miniconf schedules to be determined", ):
                continue

            data = {
                'start': item['start'],
                'end': item['end'],
                'title': item['name'].strip(),
                'abstract': item['description'],
                'url': item['public_url'],
            }

            if not data['title']:
                continue

            schedule.append(data)

        schedule.sort(key=lambda i: i['start'])
        conference_schedules[conference][channel] = schedule

    # Fill in day start / day end events for each conference day.
    # (We need to work in the schedule's timezone for this to work properly.)
    for conference in conference_schedules:
        # First earliest and latest event in a conference.
        all_events = []
        for channel_schedule in conference_schedules[conference].values():
            all_events.extend(channel_schedule)
        all_events.sort(key=lambda i: i['start'])

        starting_event = all_events[0]
        ending_event = all_events[-1]

        for channel in conference_schedules[conference]:
            oldevents = conference_schedules[conference][channel]

            config = CONFIG.config(channel)
            if not config['schedule-timezone']:
                sys.stderr.write(
                    "%s has not timezone, can't add conference day events\n" %
                    channel)
                continue
            tzinfo = pytz.timezone(config['schedule-timezone'])

            # Group events onto days
            perday_events = defaultdict(list)
            for event in oldevents:
                perday_events[event['end'].astimezone(tzinfo).date()].append(
                    event)

            # Remove any days which are 100% via another schedule.
            for day in list(perday_events.keys()):
                for event in perday_events[day]:
                    if not event.get('via', False):
                        break
                else:
                    # All generated
                    del perday_events[day]

            # Add in any missing days
            startdate = datetime_tz.combine(
                starting_event['start'].astimezone(tzinfo).date(),
                datetime_tz.min.time(), tzinfo)
            enddate = datetime_tz.combine(
                ending_event['start'].astimezone(tzinfo).date(),
                datetime_tz.min.time(), tzinfo)
            for day in dt_iterate.days(startdate, enddate):
                if day.date() not in perday_events:
                    day_skipped_event = {
                        'start':
                        datetime_tz.combine(day, datetime_tz.min.time(),
                                            tzinfo).astimezone(pytz.utc),
                        'end':
                        datetime_tz.combine(day, datetime_tz.max.time(),
                                            tzinfo).astimezone(pytz.utc),
                        'title':
                        'Nothing in %s today' % config['title'],
                        'abstract':
                        '',
                        'generated':
                        True,
                    }

                    perday_events[day.date()].append(day_skipped_event)

            # Add start of day / end of day events
            for day, events in perday_events.items():
                if day > startdate.date() and events[0]['start'].astimezone(
                        tzinfo).time() != datetime_tz.min.time():
                    events.insert(
                        0, {
                            'start':
                            datetime_tz.combine(day, datetime_tz.min.time(),
                                                tzinfo).astimezone(pytz.utc),
                            'end':
                            events[0]['start'],
                            'title':
                            'Not yet started in %s' % config['title'],
                            'abstract':
                            '',
                            'generated':
                            True,
                        })

                if day < enddate.date() and events[-1]['end'].astimezone(
                        tzinfo).time() != datetime_tz.max.time():
                    events.append({
                        'start':
                        events[-1]['end'],
                        'end':
                        datetime_tz.combine(day, datetime_tz.max.time(),
                                            tzinfo).astimezone(pytz.utc),
                        'title':
                        'Finished for the day in %s' % config['title'],
                        'abstract':
                        '',
                        'generated':
                        True,
                    })

            # Create a before conference start event.
            before_event = {
                'start':
                datetime_tz(datetime_tz.min.asdatetime(naive=True),
                            tzinfo).astimezone(pytz.utc),
                'end':
                starting_event['start'],
                'title':
                '%s not yet started' % conference,
                'abstract':
                '',
                'generated':
                True,
            }
            # Create an after conference end event.
            after_event = {
                'start':
                ending_event['end'],
                'end':
                datetime_tz(datetime_tz.max.asdatetime(naive=True),
                            tzinfo).astimezone(pytz.utc),
                'title':
                '%s finished :(' % conference,
                'abstract':
                '',
                'generated':
                True,
            }

            # Put everything back together
            newevents = [before_event]
            for day in sorted(perday_events.keys()):
                newevents.extend(perday_events[day])
            newevents.append(after_event)

            conference_schedules[conference][channel] = newevents

    # Fill in any gaps
    for conference in conference_schedules:
        for channel in conference_schedules[conference]:
            oldevents = conference_schedules[conference][channel]

            newevents = [oldevents.pop(0)]
            conference_schedules[conference][channel] = newevents

            while len(oldevents) > 0:
                delta = oldevents[0]['start'] - newevents[-1]['end']

                if delta.seconds > (5 * 60):
                    unknown_event = {
                        'start': newevents[-1]['end'],
                        'end': oldevents[0]['start'],
                        'abstract': '',
                        'generated': True,
                    }
                    unknown_event['title'] = '%i minute break' % (
                        (unknown_event['end'] - unknown_event['start']).seconds
                        / 60)
                    newevents.append(unknown_event)
                newevents.append(oldevents.pop(0))

    # Add guid to each event
    for conference in conference_schedules:
        for channel in conference_schedules[conference]:
            for item in conference_schedules[conference][channel]:
                if 'guid' not in item:
                    item['guid'] = hashlib.md5(str(item['start']) +
                                               channel).hexdigest()

    print_schedule(conference_schedules)

    output_data = {}
    for conference in conference_schedules:
        for channel in conference_schedules[conference]:
            output_data[channel] = conference_schedules[conference][channel]

    out = StringIO.StringIO()
    pprint.pprint(output_data, stream=out)
    print """\
from datetime_tz import datetime_tz
import pytz

data = \\"""
    print out.getvalue()
Пример #4
0
def main(argv):
    if CONFIG['config']['schedule-format']:
        if CONFIG['config']['schedule-format'] == 'pycon':
            return os.system('python pycon2internal.py')
        if CONFIG['config']['schedule-format'] == 'veyepar':
            return os.system('python veyepar2internal.py')
        if CONFIG['config']['schedule-format'] == 'symposion':
            return os.system('python symposion2internal.py')

    conference_schedules = defaultdict(dict)

    # Download the schedule details for each channel and group into
    # conferences.
    for channel in CONFIG.groups():
        config = CONFIG.config(channel)

        if 'schedule' not in config or not config['schedule']:
            sys.stderr.write("Channel %s doesn't have a schedule.\n" % channel)
            continue

        tzinfo = None
        if config['schedule-timezone']:
            tzinfo = pytz.timezone(config['schedule-timezone'])

        channel_schedule = get_schedule_json(config['schedule'], tzinfo)

        conference = config['group']
        if config['conference']:
            conference = config['conference']

        schedule = []
        for item in channel_schedule:
            if 'Title' not in item or not item['Title'] or item[
                    'Title'] in BLACKLISTED_EVENTS:
                continue

            if item['Room Name'] != config['schedule-key'] and item[
                    'Room Name'] != config['schedule-see-also']:
                # Event is not in this room
                continue

            data = {
                'start': item['Start'],
                'title': item['Title'].strip(),
                'abstract': item['Description'],
                'url': None,
            }

            if 'End' in item:
                data['end'] = item['End']
            elif 'Duration' in item:
                data['end'] = data['start'] + parse_pytimedelta(
                    item['Duration'])
            else:
                sys.stderr.write(
                    'Event %r does not have a End time or Duration, dropped.\n'
                    % item['Title'])
                continue
            if 'URL' in item:
                data['url'] = item['URL']

            schedule.append(data)

        schedule.sort(key=lambda i: i['start'])
        conference_schedules[conference][channel] = schedule

    # Fill in day start / day end events for each conference day.
    # (We need to work in the schedule's timezone for this to work properly.)
    for conference in conference_schedules:
        # First earliest and latest event in a conference.
        all_events = []
        for channel_schedule in conference_schedules[conference].values():
            all_events.extend(channel_schedule)
        all_events.sort(key=lambda i: i['start'])

        if len(all_events) == 0:
            # No events this day
            sys.stderr.write("There are no events in %r\n" % (conference, ))
            continue
        starting_event = all_events[0]
        ending_event = all_events[-1]

        for channel in conference_schedules[conference]:
            oldevents = conference_schedules[conference][channel]

            config = CONFIG.config(channel)
            if not config['schedule-timezone']:
                sys.stderr.write(
                    "%s has not timezone, can't add conference day events\n" %
                    channel)
                continue
            tzinfo = pytz.timezone(config['schedule-timezone'])

            # Group events onto days
            perday_events = defaultdict(list)
            for event in oldevents:
                perday_events[event['end'].astimezone(tzinfo).date()].append(
                    event)

            # Remove any days which are 100% via another schedule.
            for day in list(perday_events.keys()):
                for event in perday_events[day]:
                    if not event.get('via', False):
                        break
                else:
                    # All generated
                    del perday_events[day]

            # Add in any missing days
            startdate = datetime_tz.combine(
                starting_event['start'].astimezone(tzinfo).date(),
                datetime_tz.min.time(), tzinfo)
            enddate = datetime_tz.combine(
                ending_event['start'].astimezone(tzinfo).date(),
                datetime_tz.min.time(), tzinfo)
            for day in dt_iterate.days(startdate, enddate):
                if day.date() not in perday_events:
                    day_skipped_event = {
                        'start':
                        datetime_tz.combine(day, datetime_tz.min.time(),
                                            tzinfo).astimezone(pytz.utc),
                        'end':
                        datetime_tz.combine(day, datetime_tz.max.time(),
                                            tzinfo).astimezone(pytz.utc),
                        'title':
                        'Nothing in %s today' % config['title'],
                        'abstract':
                        '',
                        'generated':
                        True,
                    }

                    perday_events[day.date()].append(day_skipped_event)

            # Add start of day / end of day events
            for day, events in perday_events.items():
                if day > startdate.date() and events[0]['start'].astimezone(
                        tzinfo).time() != datetime_tz.min.time():
                    events.insert(
                        0, {
                            'start':
                            datetime_tz.combine(day, datetime_tz.min.time(),
                                                tzinfo).astimezone(pytz.utc),
                            'end':
                            events[0]['start'],
                            'title':
                            'Not yet started in %s' % config['title'],
                            'abstract':
                            '',
                            'generated':
                            True,
                        })

                if day < enddate.date() and events[-1]['end'].astimezone(
                        tzinfo).time() != datetime_tz.max.time():
                    events.append({
                        'start':
                        events[-1]['end'],
                        'end':
                        datetime_tz.combine(day, datetime_tz.max.time(),
                                            tzinfo).astimezone(pytz.utc),
                        'title':
                        'Finished for the day in %s' % config['title'],
                        'abstract':
                        '',
                        'generated':
                        True,
                    })

            # Create a before conference start event.
            before_event = {
                'start':
                datetime_tz(datetime_tz.min.asdatetime(naive=True),
                            tzinfo).astimezone(pytz.utc),
                'end':
                starting_event['start'],
                'title':
                '%s not yet started' % conference,
                'abstract':
                '',
                'generated':
                True,
            }
            # Create an after conference end event.
            after_event = {
                'start':
                ending_event['end'],
                'end':
                datetime_tz(datetime_tz.max.asdatetime(naive=True),
                            tzinfo).astimezone(pytz.utc),
                'title':
                '%s finished :(' % conference,
                'abstract':
                '',
                'generated':
                True,
            }

            # Put everything back together
            newevents = [before_event]
            for day in sorted(perday_events.keys()):
                newevents.extend(perday_events[day])
            newevents.append(after_event)

            conference_schedules[conference][channel] = newevents

    # Fill in any gaps
    for conference in conference_schedules:
        for channel in conference_schedules[conference]:
            oldevents = conference_schedules[conference][channel]

            if len(oldevents) == 0:
                # No events on day
                continue
            newevents = [oldevents.pop(0)]
            conference_schedules[conference][channel] = newevents

            while len(oldevents) > 0:
                delta = oldevents[0]['start'] - newevents[-1]['end']

                if delta.seconds > (5 * 60):
                    unknown_event = {
                        'start': newevents[-1]['end'],
                        'end': oldevents[0]['start'],
                        'abstract': '',
                        'generated': True,
                    }
                    unknown_event['title'] = '%i minute break' % (
                        (unknown_event['end'] - unknown_event['start']).seconds
                        / 60)
                    newevents.append(unknown_event)
                newevents.append(oldevents.pop(0))

    # Add guid to each event
    for conference in conference_schedules:
        for channel in conference_schedules[conference]:
            for item in conference_schedules[conference][channel]:
                if 'guid' not in item:
                    item['guid'] = hashlib.md5(str(item['start']) +
                                               channel).hexdigest()

    print_schedule(conference_schedules)

    output_data = {}
    for conference in conference_schedules:
        for channel in conference_schedules[conference]:
            output_data[channel] = conference_schedules[conference][channel]

    out = StringIO.StringIO()
    pprint.pprint(output_data, stream=out)
    print """\
from datetime_tz import datetime_tz
import pytz

data = \\"""
    print out.getvalue()