def ical_init(): cal = Calendar() cal.add('prodid', '-//CSPay calendar//EN/') cal.add('version', '2.0') TZ = Timezone() TZ.add('tzid','Europe/Bucharest') TZS = StandardT() TZS.add('TZOFFSETFROM',timedelta(hours=3)) TZS.add('TZOFFSETTO',timedelta(hours=2)) TZS.add('TZNAME','EET') TZS.add('DTSTART',datetime(1997,10,26)) TZS.add('rrule',vRecur.from_ical('FREQ=YEARLY;BYMONTH=10;BYDAY=-1SU')) TZ.add_component(TZS) TZS = DaylightT() TZS.add('TZOFFSETFROM',timedelta(hours=2)) TZS.add('TZOFFSETTO',timedelta(hours=3)) TZS.add('TZNAME','EEST') TZS.add('DTSTART',datetime(1997,03,30)) TZS.add('rrule',vRecur.from_ical('FREQ=YEARLY;BYMONTH=3;BYDAY=-1SU')) TZ.add_component(TZS) cal.add_component(TZ) return cal
def set_calendar_metadata(ics_calendar, panchaanga, set_sequence): timezone = Timezone() timezone.add('TZID', panchaanga.city.timezone) ics_calendar.add_component(timezone) if set_sequence: # Calendar programs such as Google Calendar might not update events if they don't recognize that the ics data has changed. https://support.google.com/calendar/thread/17012350?hl=en # https://icalendar.org/iCalendar-RFC-5545/3-8-7-4-sequence-number.html ics_calendar.add("SEQUENCE", ist_timezone.current_time_as_int())
def _create_timezone(): tz = Timezone() tz.add("TZID", "Asia/Shanghai") tz_standard = TimezoneStandard() tz_standard.add("DTSTART", datetime.datetime(1970, 1, 1)) tz_standard.add("TZOFFSETFROM", datetime.timedelta(hours=8)) tz_standard.add("TZOFFSETTO", datetime.timedelta(hours=8)) tz.add_component(tz_standard) return tz
def make_icalendar_data(uid, summary, current, end, begin, account_id, create_flag=False): """ Generate iCalendar data format message body. reference - https://developers.worksmobile.com/jp/document/1007011?lang=en """ cal = Calendar() cal.add('PRODID', 'Works sample bot Calendar') cal.add('VERSION', '2.0') standard = TimezoneStandard() standard.add('DTSTART', datetime(1970, 1, 1, 0, 0, 0, tzinfo=pytz.timezone(TZone))) standard.add('TZOFFSETFROM', current.utcoffset()) standard.add('TZOFFSETTO', current.utcoffset()) standard.add('TZNAME', current.tzname()) tz = Timezone() tz.add_component(standard) tz.add('TZID', tz) event = Event() event.add('UID', uid) if create_flag: event.add('CREATED', current) event.add('DESCRIPTION', account_id) event.add('SUMMARY', summary) event.add('DTSTART', begin) event.add('DTEND', end) event.add('LAST-MODIFIED', current) event.add('DTSTAMP', current) cal.add_component(event) cal.add_component(tz) schedule_local_string = bytes.decode(cal.to_ical()) LOGGER.info("schedule:%s", schedule_local_string) return schedule_local_string
def create_timezone(): central = Timezone() central.add("tzid", CLASS_TIMEZONE) central.add("x-lic-location", CLASS_TIMEZONE) tzs = TimezoneStandard() tzs.add("tzname", "CST") tzs.add("dtstart", datetime(1970, 10, 25, 3, 0, 0)) tzs.add("rrule", {"freq": "yearly", "bymonth": 10, "byday": "-1su"}) tzs.add("TZOFFSETFROM", timedelta(hours=-5)) tzs.add("TZOFFSETTO", timedelta(hours=-6)) tzd = TimezoneDaylight() tzd.add("tzname", "CDT") tzd.add("dtstart", datetime(1970, 3, 29, 2, 0, 0)) tzd.add("rrule", {"freq": "yearly", "bymonth": 3, "byday": "-1su"}) tzd.add("TZOFFSETFROM", timedelta(hours=-6)) tzd.add("TZOFFSETTO", timedelta(hours=-5)) central.add_component(tzs) central.add_component(tzd) return central
def make_icalendar_data(uid, summary, current, end, begin, account_id, create_flag=False): cal = Calendar() cal.add('PRODID', 'Works sample bot Calendar') cal.add('VERSION', '2.0') tz = load_time_zone() standard = TimezoneStandard() standard.add('DTSTART', datetime(1970, 1, 1, 0, 0, 0, tzinfo=pytz.timezone(tz))) standard.add('TZOFFSETFROM', current.utcoffset()) standard.add('TZOFFSETTO', current.utcoffset()) standard.add('TZNAME', current.tzname()) tz = Timezone() tz.add_component(standard) tz.add('TZID', tz) event = Event() event.add('UID', uid) if create_flag: event.add('CREATED', current) event.add('DESCRIPTION', account_id) event.add('ATTENDEE', account_id) event.add('SUMMARY', summary) event.add('DTSTART', begin) event.add('DTEND', end) event.add('LAST-MODIFIED', current) event.add('DTSTAMP', current) cal.add_component(event) cal.add_component(tz) schedule_local_string = bytes.decode(cal.to_ical()) LOGGER.info("schedule:%s", schedule_local_string) return schedule_local_string
def ical_creat(filename): courselist = JsonLoadHandle(filename) cal = Calendar() cal.add('prodid', '-//My CourseTable//') cal.add('version', '2.0') cal.add('CALSCALE', 'GREGORIAN') cal.add('method', 'PUBLISH') tz = Timezone() tzst = TimezoneStandard() tzst.add('tzoffsetfrom', timedelta(hours=8)) tzst.add('tzoffsetto', timedelta(hours=8)) tzst.add('tzname', 'CST') tzst.add('dtstart', datetime(1970, 1, 1, 0, 0, 0)) tz.add('tzid', 'Asia/Shanghai') tz.add_component(tzst) cal.add_component(tz) for course in courselist: cal.add_component(course.getEvent()) f = open(os.path.abspath('cache/ics/' + filename + '.ics'), 'wb') f.write(cal.to_ical()) f.close()
def create_timezone(tz): # Function from https://github.com/pimutils/khal/blob/64d70e3eb59570cfd3af2e10dbbcf0a26bf89111/khal/khalendar/event.py#L287 first_date = datetime.today() last_date = datetime.today() timezone = Timezone() timezone.add('TZID', tz) dst = {one[2]: 'DST' in two.__repr__() for one, two in tz._tzinfos.items()} first_num, last_num = 0, len(tz._utc_transition_times) - 1 first_tt = tz._utc_transition_times[0] last_tt = tz._utc_transition_times[-1] for num, dt in enumerate(tz._utc_transition_times): if dt > first_tt and dt < first_date: first_num = num first_tt = dt if dt < last_tt and dt > last_date: last_num = num last_tt = dt for num in range(first_num, last_num + 1): name = tz._transition_info[num][2] if dst[name]: subcomp = TimezoneDaylight() rrule = {'freq': 'yearly', 'bymonth': 3, 'byday': '2su'} else: subcomp = TimezoneStandard() rrule = {'freq': 'yearly', 'bymonth': 11, 'byday': '1su'} subcomp.add('TZNAME', tz._transition_info[num][2]) subcomp.add( 'DTSTART', tz.fromutc(tz._utc_transition_times[num]).replace(tzinfo=None)) subcomp.add('TZOFFSETTO', tz._transition_info[num][0]) subcomp.add('TZOFFSETFROM', tz._transition_info[num - 1][0]) subcomp.add('RRULE', rrule) timezone.add_component(subcomp) return timezone
def add_vtimezone(cal): tzc = Timezone() tzc.add('tzid', 'Europe/Copenhagen') tzc.add('x-lic-location', 'Europe/Copenhagen') tzs = TimezoneStandard() tzs.add('tzname', 'CET') tzs.add('dtstart', datetime.datetime(1970, 10, 25, 3, 0, 0)) tzs.add('rrule', {'freq': 'yearly', 'bymonth': 10, 'byday': '-1su'}) tzs.add('TZOFFSETFROM', datetime.timedelta(hours=2)) tzs.add('TZOFFSETTO', datetime.timedelta(hours=1)) tzd = TimezoneDaylight() tzd.add('tzname', 'CEST') tzd.add('dtstart', datetime.datetime(1970, 3, 29, 2, 0, 0)) tzs.add('rrule', {'freq': 'yearly', 'bymonth': 3, 'byday': '-1su'}) tzd.add('TZOFFSETFROM', datetime.timedelta(hours=1)) tzd.add('TZOFFSETTO', datetime.timedelta(hours=2)) tzc.add_component(tzs) tzc.add_component(tzd) cal.add_component(tzc)
def writeIcs(): cal = Calendar() cal.add('PRODID', '-//Dayfacto Journal//dpd//') cal.add('VERSION', '1.0') cal.add('VERSION', 'GREGORIAN') timezone = Timezone() timezone.add('TZID', 'Europe/London') daylight = TimezoneDaylight() daylight.add('TZOFFSETFROM', datetime.timedelta(hours=0)) daylight.add('TZOFFSETTO', datetime.timedelta(hours=1)) daylight.add('TZNAME', 'BST') timezone.add_component(daylight) standard = TimezoneStandard() standard.add('TZNAME', 'GMT') standard.add('TZOFFSETFROM', datetime.timedelta(hours=1)) standard.add('TZOFFSETTO', datetime.timedelta(hours=0)) timezone.add_component(standard) cal.add_component(timezone) evtList = fetchAllEvents() count = 0 for evt in evtList: event = Event() event.add('SUMMARY', evt[0]) event.add('DTSTART', evt[2]) if evt[5] > 1: event.add('RRULE', {'freq': numPeriod[evt[4]], 'interval': evt[6], 'count': evt[5]}) event['uid'] = str(datetime.datetime.today().time()) + str(evt[8]) \ + '*****@*****.**' # event.add('DESCRIPTION', 'This is another description') # event.add('VJOURNAL', 'This is another journal entry') cal.add_component(event) # print(numPeriod[evt[4]]) count += 1 print(count) f = open('example.ics', 'wb') f.write(cal.to_ical()) f.close()
def add_timezone(cal): cal.add('x-wr-timezone', TZID) timezone = Timezone() timezone.add('tzid', TZID) tz_std = TimezoneStandard() tz_std.add('dtstart', vText(arrow.get('2006-11-06 02:00').format('YYYYMMDDTHHmmss'))) tz_std.add('rrule', vRecur(freq='YEARLY', bymonth='11', byday='+1SU')) tz_std.add('tzoffsetfrom', timedelta(hours=-4)) tz_std.add('tzoffsetto', timedelta(hours=-5)) tz_std.add('tzname', "EST") timezone.add_component(tz_std) tz_dst = TimezoneDaylight() tz_dst.add('dtstart', vText(arrow.get('2006-03-13 02:00').format('YYYYMMDDTHHmmss'))) tz_dst.add('rrule', vRecur(freq='YEARLY', bymonth='3', byday='+2SU')) tz_dst.add('tzoffsetfrom', timedelta(hours=-5)) tz_dst.add('tzoffsetto', timedelta(hours=-4)) tz_dst.add('tzname', "EDT") timezone.add_component(tz_dst) cal.add_component(timezone)
def generate(student_id: str, student_name: str, student_classes, semester_string: str, semester): """ 生成 ics 文件并保存到目录 :param student_id: 学号 :param student_name: 姓名 :param student_classes: classes student are taking :param semester_string: 学期字符串,显示在日历标题中,如 `17-18-1` :param semester: 当前导出的学期,三元组 :return: True """ # 创建 calender 对象 cal = Calendar() cal.add('prodid', '-//Admirable//EveryClass//EN') cal.add('version', '2.0') cal.add('calscale', 'GREGORIAN') cal.add('method', 'PUBLISH') cal.add('X-WR-CALNAME', student_name + '的' + semester_string + '学期课表') cal.add('X-WR-TIMEZONE', 'Asia/Shanghai') # 时区 tzc = Timezone() tzc.add('tzid', 'Asia/Shanghai') tzc.add('x-lic-location', 'Asia/Shanghai') tzs = TimezoneStandard() tzs.add('tzname', 'CST') tzs.add('dtstart', datetime(1970, 1, 1, 0, 0, 0)) tzs.add('TZOFFSETFROM', timedelta(hours=8)) tzs.add('TZOFFSETTO', timedelta(hours=8)) tzc.add_component(tzs) cal.add_component(tzc) # 创建 events for time in range(1, 7): for day in range(1, 8): if (day, time) in student_classes: for every_class in student_classes[(day, time)]: # 每一节课 durations = re.split(r',', every_class['duration']) for each_duration in durations: # 空区间 bug fix if not each_duration: continue # 每一段上课周 if len(re.findall(r'\d{1,2}', each_duration)) == 1: # 仅当周 dur_starting_week = dur_ending_week = re.findall( r'\d{1,2}', each_duration)[0] else: # X 到 X 周 dur_starting_week, dur_ending_week = re.findall( r'\d{1,2}', each_duration) if every_class['week'] == '周': interval = 1 else: interval = 2 if every_class['week'] == '双周' and int( dur_starting_week) % 2 != 0: dur_starting_week = str(int(dur_starting_week) + 1) if every_class['week'] == '单周' and int( dur_starting_week) % 2 == 0: dur_starting_week = str(int(dur_starting_week) + 1) dtstart = __get_datetime(dur_starting_week, day, get_time(time)[0], semester) dtend = __get_datetime(dur_starting_week, day, get_time(time)[1], semester) until = __get_datetime(dur_ending_week, day, get_time(time)[1], semester) + timedelta(days=1) # 参数:课程名称、初次时间[start、end、interval、until、duration]、循环规则、地点、老师、学生 ID cal.add_component( __add_event(name=every_class['name'], times=[ dtstart, dtend, interval, until, each_duration, every_class['week'] ], location=every_class['location'], teacher=every_class['teacher'], student_id=student_id, day=day, time=time)) # 写入文件 import os with open( os.path.join( os.path.dirname(__file__), '../../../calendar_files/%s-%s.ics' % (student_id, semester_string)), 'w') as f: f.write(cal.to_ical().decode(encoding='utf-8')) return True
tz = Timezone() #might need to accomodate for DSaveTime dlt = TimezoneDaylight() dlt.add('TZOFFSETFROM', timedelta(hours=-6)) dlt.add('RRULE', {'FREQ': 'YEARLY', 'BYMONTH': '3', 'BYDAY': '2SU'}) #very weird, python 3.5 requires 0o03 instead of 03 dlt['DTSTART'] = datetime(2007, 0o03, 11, 2, 0, 0) dlt.add('TZNAME', 'CDT') dlt.add('TZOFFSETTO', timedelta(hours=-5)) stnd = TimezoneStandard() stnd.add('TZOFFSETFROM', timedelta(hours=-5)) stnd.add('RRULE', {'FREQ': 'YEARLY', 'BYMONTH': '11', 'BYDAY': '1SU'}) stnd['DTSTART'] = datetime(2007, 11, 4, 2, 0, 0) stnd.add('TZNAME', 'CST') stnd.add('TZOFFSETTO', timedelta(hours=-6)) tz.add('TZID', 'America/Chicago') tz.add_component(dlt) tz.add_component(stnd) gcal.add_component(tz) #end setting up preamble stuff room = { ##'J205':' ##'J203' ##'J113' ##'J101' 'C161': 'CH157encoder161', 'C184': 'CH157encoder184', 'C179': 'CH157encoder179', 'C183': 'CH157encoder183' }
from icalendar import Calendar, Timezone, TimezoneStandard, Event from lxml import html group_id = sys.argv[1] schedule_url = f'http://www.1spbgmu.ru/ruz/?timetable&group={group_id}' html_source = requests.get(schedule_url).text schedule = html.fromstring(html_source) cal = Calendar() # timezone info tz = Timezone() tz.add('TZID', '(UTC+03:00) Moscow, St. Petersburg, Volgograd') tz_st = TimezoneStandard() tz_st.add('DTSTART', datetime(1601, 1, 1)) tz_st.add('TZOFFSETFROM', timedelta(hours=4)) tz_st.add('TZOFFSETTO', timedelta(hours=3)) tz.add_component(tz_st) cal.add_component(tz) h4 = schedule.xpath("//h4") group_name = h4[0].text if h4 else group_id p_status = schedule.xpath("//p[contains(@class, 'status')]") status = p_status[0].text if p_status else 'unknown status' for day_info in schedule.xpath("//div[contains(@class, 'list')]"): day_of_week_node = day_info.xpath("*[contains(@class, 'dayofweek')]") try:
def _main(osm, auth, sections, outdir): assert os.path.exists(outdir) and os.path.isdir(outdir) for section in sections: assert section in list(Group.SECTIONIDS.keys()) + ['Group'], \ "section must be in {!r}.".format(Group.SECTIONIDS.keys()) osm_sections = osm.OSM(auth, Group.SECTIONIDS.values()) tzc = Timezone() tzc.add('tzid', 'Europe/London') tzc.add('x-lic-location', 'Europe/London') tzs = TimezoneStandard() tzs.add('tzname', 'GMT') tzs.add('dtstart', datetime.datetime(1970, 10, 25, 2, 0, 0)) tzs.add('rrule', {'freq': 'yearly', 'bymonth': 10, 'byday': '-1su', 'interval': '1'}) tzd = TimezoneDaylight() tzd.add('tzname', 'BST') tzd.add('dtstart', datetime.datetime(1970, 3, 29, 1, 0, 0)) tzd.add('rrule', {'freq': 'yearly', 'bymonth': 3, 'byday': '-1su', 'interval': '1'}) tzd.add('TZOFFSETFROM', datetime.timedelta(hours=0)) tzd.add('TZOFFSETTO', datetime.timedelta(hours=1)) for section in sections: i = Calendar() tzc.add_component(tzs) tzc.add_component(tzd) i.add_component(tzc) if section == "Group": i['x-wr-calname'] = '7th Lichfield: Group Calendar' i['X-WR-CALDESC'] = 'Current Programme' i['calscale'] = 'GREGORIAN' i['X-WR-TIMEZONE'] = 'Europe/London' for s in Group.SECTIONIDS.keys(): section_obj = osm_sections.sections[Group.SECTIONIDS[s]] [meeting2ical(s, event, i) for event in section_obj.programme.events_by_date()] [event2ical(s, event, i) for event in section_obj.events] open(os.path.join(outdir, section + ".ical"), 'w').write(i.to_ical().decode()) else: section_obj = osm_sections.sections[Group.SECTIONIDS[section]] i['x-wr-calname'] = '7th Lichfield: {}'.format(section) i['X-WR-CALDESC'] = '{} Programme'.format(section_obj.term['name']) i['calscale'] = 'GREGORIAN' i['X-WR-TIMEZONE'] = 'Europe/London' [meeting2ical(section, event, i) for event in section_obj.programme.events_by_date()] [event2ical(section, event, i) for event in section_obj.events] open(os.path.join(outdir, section + ".ical"), 'w').write(i.to_ical().decode())
DEBUGMSG += '- ignore duplicated events\n' DEBUGMSG += 'init done\n' # We need the iCalendar package from http://codespeak.net/icalendar/ from icalendar import Calendar, Event, Timezone # Open the new calendarfile and adding the information about this script to it newcal = Calendar() newcal.add('prodid', '-//' + MY_NAME + '//' + MY_DOMAIN + '//') newcal.add('version', '2.0') newcal.add('x-wr-calname', CALENDARNAME) DEBUGMSG += 'new calendar ' + ICS_OUT + ' started\n' # we need to add a timezone, because some clients want it (e.g. sunbird 0.5) newtimezone = Timezone() newtimezone.add('tzid', OUR_TIMEZONE) newcal.add_component(newtimezone) # Looping through the existing calendarfiles for s in glob.glob(CALDIR + '*.ics'): try: # open the file and read it calfile = open(s, 'rb') cal = Calendar.from_string(calfile.read()) DEBUGMSG += 'reading file ' + s + '\n' # every part of the file... for component in cal.subcomponents: # ...which name is VEVENT will be added to the new file if component.name == 'VEVENT': try: if HISTORY_DAYS > 0:
def to_ical(event, include_sessions=False, my_schedule=False, user_id=None): cal = Calendar() cal.add('version', '2.0') cal.add('METHOD', 'PUBLISH') cal.add('X-WR-CALNAME', event.name) cal.add('X-WR-CALDESC', 'Event Calendar') event_component = Event() event_component.add('uid', event.identifier) event_component.add('summary', event.name) event_component.add('url', event.site_link) event_component.add('dtstart', event.starts_at_tz) event_component.add('dtend', event.ends_at_tz) event_component.add('location', event.normalized_location) event_component.add('description', remove_html_tags(event.description)) if event.has_coordinates: event_component.add('geo', (event.latitude, event.longitude)) if event.owner_description: event_component.add('organizer', remove_html_tags(event.owner_description)) cal.add_component(event_component) timezone = Timezone() timezone.add('TZID', event.timezone) cal.add_component(timezone) if include_sessions: sessions_query = (Session.query.filter_by(event_id=event.id).options( joinedload( Session.microlocation)).filter_by(deleted_at=None).filter( or_(Session.state == 'accepted', Session.state == 'confirmed')).order_by( Session.starts_at.asc())) if my_schedule: if not (current_user or user_id): return jsonify(error='Login or User ID required'), 401 user_id = user_id or current_user.id sessions_query = sessions_query.join( Session.favourites).filter_by(user_id=user_id) sessions = sessions_query.all() for session in sessions: if not (session and session.starts_at and session.ends_at): continue session_video_url = ( " " + event.site_link + '/video/' + quote(session.microlocation.video_stream.name) + "/" + str(session.microlocation.video_stream.id) if session.microlocation.video_stream else "") session_link_heading = (" Join using link: " + session_video_url + "<br/>" if session_video_url else "") session_description = (" " + "Room: " + session.microlocation.name + "<br/>" + session_link_heading + " <br/> " + session.short_abstract) session_component = Event() session_component.add('summary', session.title) session_component.add('uid', str(session.id) + "-" + event.identifier) session_component.add('geo', (event.latitude, event.longitude)) session_component.add( 'location', session_video_url or (session.microlocation and session.microlocation.name) or '' + " " + event.location_name, ) session_component.add( 'dtstart', session.starts_at.astimezone(pytz.timezone(event.timezone))) session_component.add( 'dtend', session.ends_at.astimezone(pytz.timezone(event.timezone))) session_component.add('description', remove_html_tags(session_description)) session_component.add( 'url', event.site_link + '/session/' + str(session.id)) cal.add_component(session_component) return cal.to_ical()
DEBUGMSG = DEBUGMSG + 'import of glob and sys done\n' # We need the iCalendar package from http://codespeak.net/icalendar/ from icalendar import Calendar, Event, Timezone DEBUGMSG = DEBUGMSG + 'inport of icalendar done\n' # Open the new calendarfile and adding the information about this script to it newcal = Calendar() newcal.add('prodid', '-//' + MY_NAME + '//' + MY_DOMAIN + '//') newcal.add('version', '2.0') newcal.add('x-wr-calname', CALENDARNAME) DEBUGMSG = DEBUGMSG + 'new calendar started\n' # we need to add a timezone, because some clients want it (e.g. sunbird 0.5) newtimezone = Timezone() newtimezone.add('tzid', OUR_TIMEZONE) newcal.add_component(newtimezone) # Looping through the existing calendarfiles for s in glob.glob(CALDIR + '*.ics'): try: # open the file and read it calfile = open(s,'rb') cal = Calendar.from_string(calfile.read()) # every part of the file... for component in cal.subcomponents: if component.name == 'VEVENT': # ...which name is VEVENT will be added to the new file newcal.add_component(component) # close the existing file DEBUGMSG = DEBUGMSG + 'done with file ' + s +'\n'
def parsePage(page, username): soup = BeautifulSoup(page) #print(soup.prettify()) geroosterd = soup.find('span', id="RoosterIngeroosterd0").find('table', "OraTableContent") ingeloggedstring = soup.find(text=re.compile("Laatst ingelogd")) m = re.search('(\d{4})',ingeloggedstring) jaar = int(m.group(0)) #print 'Niet geroosterd' #print soup('span', id="RoosterNietIngeroosterd0")[0].find('table', "x1h") #setup calendar cal = Calendar() cal.add('version', '2.0') cal.add('prodid', '-//Mijn Rooster//osiris.uu.nl//') cal.add('x-wr-calname', 'Rooster') cal.add('X-WR-TIMEZONE', 'Europe/Amsterdam') newtimezone = Timezone() newtimezone.add('tzid', "Europe/Amsterdam") cal.add_component(newtimezone) #get the data out and into the calendar maand = 0 dag = 0 for tr in geroosterd: if tr.contents[0].contents[0].name == 'table': #get the day dag = int(tr.contents[0].tr.contents[1].span.string) if len(tr.contents[0].tr.contents[1].span.string) > 1 else dag #get the time tijd = tr.contents[0].tr.contents[2].span.string startuur = int(tijd[1:3]) startmin = int(tijd[4:6]) enduur = int(tijd[10:12]) endmin = int(tijd[13:15]) #get the other data vakcode = tr.contents[1].span.string naam = tr.contents[3].span.string ctype = tr.contents[5].span.string groep = tr.contents[7].span.string if tr.contents[7].span != None else '' gebouw = tr.contents[9].a.string if tr.contents[9].a != None else '' ruimte = tr.contents[11].span.string if tr.contents[11].span != None else '' docent = tr.contents[13].span.string if tr.contents[13].span != None else '' description = groep + '\n' if groep != '' else '' description += 'docent: ' + docent if docent != '' else '' #make an event and add it event = Event() event.add('summary', ctype + ' ' + naam) event.add('location', gebouw + ' ' + ruimte) event.add('description', description) event.add('dtstart', datetime(jaar,maand,dag,startuur,startmin,0)) event.add('dtend', datetime(jaar,maand,dag,enduur,endmin,0)) event.add('dtstamp', datetime.now()) event['uid'] = str(jaar)+str(maand)+str(dag)+'T'+str(startuur)+str(startmin)+'00/'+username+vakcode+str(datetime.now().toordinal())+'*****@*****.**' cal.add_component(event) elif tr.contents[0].name == 'td': #record the new month and check if we are in the next year maand = monthnames.index(tr.contents[0].span.string) + 1 if maand == 1: jaar = jaar + 1 return cal
def import_calendars(user_dir, username, zadmin, zadmin_password): IGNORE_DUPLICATE = True url = "https://127.0.0.1:8443/ical/"+username merged_ical = os.path.join(user_dir, 'merged.ics') now = datetime.datetime.now() icals = get_files([user_dir], ['.ics']) # do nothing if no ics files found if not icals: return # this set will be used fo find duplicate events eventSet = set() if DEBUG: if IGNORE_DUPLICATE: print 'ignore duplicated events' # Open the new calendarfile and adding the information about this script to it newcal = Calendar() newcal.add('prodid', '-//py_zarafa_pst_importer//') newcal.add('version', '2.0') newcal.add('x-wr-calname', 'Default') if DEBUG: print 'new calendar ' + merged_ical + ' started' # we need to add a timezone, because some clients want it (e.g. sunbird 0.5) newtimezone = Timezone() newtimezone.add('tzid', OUR_TIMEZONE) newcal.add_component(newtimezone) # Looping through the existing calendarfiles for ical in icals: try: # open the file and read it with open(ical,'rb') as calfile: cal = Calendar.from_ical(calfile.read()) if DEBUG: print 'reading file ' + ical # every part of the file... for component in cal.subcomponents: # ...which name is VEVENT will be added to the new file if component.name == 'VEVENT': try: if IGNORE_DUPLICATE: eventId = str(component['dtstart']) + ' | ' + str(component['dtend']) + ' | ' + str(component['summary']) if eventId not in eventSet: eventSet.add(eventId) else: if DEBUG: print 'skipped duplicated event: ' + eventId continue except: # ignore events with missing dtstart, dtend or summary if DEBUG: print '! skipped an event with missing dtstart, dtend or summary. likely historic or duplicated event.' continue newcal.add_component(component) except: # if the file was not readable, we need a errormessage ;) print 'Merge iCals: Error: reading file:', sys.exc_info()[1] print ical # After the loop, we have all of our data and can write the file now try: with open(merged_ical, 'wb') as f: f.write(newcal.to_ical()) if DEBUG: print 'new calendar written' except: print 'Merge iCals: Error: ', sys.exc_info()[1] s = requests.Session() s.auth = (zadmin, zadmin_password) try: #print "Importing Calendar" with open(merged_ical, 'rb') as f: r = s.put(url, verify=False, data=f) if r.status_code == 200: print "Successfully imported calendar" else: print "Failed to import calendar" except: print "Failed to connect with server"
This is module to generate .ics file. Should follow RFC2445 standard. https://tools.ietf.org/html/rfc2445 """ import hashlib from datetime import datetime, timedelta from typing import Dict, List, Tuple import pytz from icalendar import Alarm, Calendar, Event, Timezone, TimezoneStandard from everyclass.server.config import get_config from everyclass.server.db.model import Semester from everyclass.server.utils import get_time tzc = Timezone() tzc.add('tzid', 'Asia/Shanghai') tzc.add('x-lic-location', 'Asia/Shanghai') tzs = TimezoneStandard() tzs.add('tzname', 'CST') tzs.add('dtstart', datetime(1970, 1, 1, 0, 0, 0)) tzs.add('TZOFFSETFROM', timedelta(hours=8)) tzs.add('TZOFFSETTO', timedelta(hours=8)) def generate(name: str, courses: Dict[Tuple[int, int], List[Dict]], semester: Semester, ics_token: str): """ 生成 ics 文件并保存到目录 :param name: 姓名 :param courses: 参与的课程
def make_calendar(parsed, pourProf=False, querry_name=None): """ création du calendrier a partir du parseur """ # Création de l'agenda cal = Calendar() # Etablissement du nom du Timezone calname = querry_name or u"ENSEA" caldesc = u""" Parseur de calendrier de %s a partir de webteam.ensea.fr realise par Webtim. \n AUCUNE GARANTIE DE LA FIABILITE DES INFORMATIONS N'EST DONNEE.\n Vous pouvez envoyer des suggestions, rapport de bug, insultes ou remerciments à <webteam at ensea.fr>\n """ % (calname) cal.add('x-wr-calname', calname) cal.add('x-wr-caldesc', caldesc) cal.add('x-wr-relcalid', u"12345") cal.add('x-wr-timezone', u"Europe/Paris") tzc = Timezone() tzc.add('tzid', 'Europe/Paris') tzc.add('x-lic-location', 'Europe/Paris') tzs = TimezoneStandard() tzs.add('tzname', 'CET') tzs.add('dtstart', datetime(1970, 10, 25, 3, 0, 0)) tzs.add('rrule', {'freq': 'yearly', 'bymonth': 10, 'byday': '-1su'}) tzs.add('TZOFFSETFROM', timedelta(hours=2)) tzs.add('TZOFFSETTO', timedelta(hours=1)) tzd = TimezoneDaylight() tzd.add('tzname', 'CEST') tzd.add('dtstart', datetime(1970, 3, 29, 2, 0, 0)) tzs.add('rrule', {'freq': 'yearly', 'bymonth': 3, 'byday': '-1su'}) tzd.add('TZOFFSETFROM', timedelta(hours=1)) tzd.add('TZOFFSETTO', timedelta(hours=2)) tzc.add_component(tzs) tzc.add_component(tzd) cal.add_component(tzc) for i in parsed: event = Event() if len(i) < 7: continue start = datetime.strptime("%s %s" % (i[0], i[1]), "%d/%m/%Y %H:%M") # Correction des horaires pour correspondre à l'ENSEA if start.hour == 10 and start.minute == 0: start = start + timedelta(minutes=10) elif start.hour == 13 and start.minute == 0: start = start + timedelta(minutes=15) elif start.hour == 15 and start.minute == 0: start = start + timedelta(minutes=25) if re.match("^\d{1,2}h$", i[2]): delta = datetime.strptime(i[2], "%Hh") elif re.match("^\d{1,2}min$", i[2]): # /30min/ delta = datetime.strptime(i[2], "%Mmin") else: delta = datetime.strptime(i[2], "%Hh%Mmin") if delta.hour == 2: # prise en compte des pauses pour les séquences de deux heures delta = delta - timedelta(minutes=10) end = start + timedelta(hours=delta.hour, minutes=delta.minute) groups = unicodedata.normalize('NFKD', i[5]).encode('ascii', 'ignore').replace(" ", '') prof = unicodedata.normalize('NFKD', i[6]).encode('ascii', 'ignore') # On inverse nom et prénom pour avoir {prenom nom} prof_lst = prof.split(" ") if len(prof_lst) < 3: prof = prof_lst[-1] + " " + " ".join(prof_lst[0:-1]) # Si le nom est trop long (comme pour les cours de langues), on le coupe et ajoute [...] if len(prof) > 40: prof = prof[:40] + '[...]' room = i[7][:5] name = unicodedata.normalize('NFKD', i[4]).encode('ascii', 'ignore') name = re.sub(u'ŕ', u"a", name) typeevent = re.sub(u'ŕ', u"à", i[3]) # typeevent = unicodedata.normalize('NFKD', i[3]).encode('Utf-8','ignore') if typeevent == "TP" and name.lower().find("projet") >= 0: typeevent = "" start_ical = dateICal(start) end_ical = dateICal(end) if pourProf: if len(typeevent) > 0: summary = "%s de %s avec %s en %s" % (typeevent, name, groups, room) else: summary = "%s avec %s en %s" % (name, groups, room) else: if len(typeevent) > 0: if len(typeevent) > 6: summary = "%s avec %s en %s" % (typeevent, prof, room) else: summary = "%s de %s avec %s en %s" % (typeevent, name, prof, room) else: summary = "%s avec %s en %s" % (name, prof, room) uid = "%s-%s@%s" % (dateICal(start), dateICal(end), room) # event_condensed_name[:10]) # Pour ajouter le timezone proprement à chaque heure d'événements (optionel) hour_start = [int(h) for h in str(start).split(" ")[1].split(':')] hour_end = [int(h) for h in str(end).split(" ")[1].split(':')] date_start = [int(d) for d in str(start).split(" ")[0].split('-')] date_end = [int(d) for d in str(end).split(" ")[0].split('-')] # Le fichier de sortie ne doit pas dépasser 75 caractères par ligne event = Event() event.add('summary', summary) event.add('location', room + ", ENSEA, Cergy") event.add('status', "confirmed") event.add('category', 'Event') event.add('dtstart', datetime(date_start[0], date_start[1], date_start[2], hour_start[0], hour_start[1], hour_start[2], tzinfo=pytz.timezone("Europe/Paris"))) event.add('dtend', datetime(date_end[0], date_end[1], date_end[2], hour_end[0], hour_end[1], hour_end[2], tzinfo=pytz.timezone("Europe/Paris"))) event["uid"] = uid event.add('priority', 0) cal.add_component(event) return cal