def test_issue_188_timezone_dropped(): assert "DTSTART;TZID={tzid}:20200121T070000".format(tzid=Timezone.from_tzid("Europe/Berlin").tzid) in Calendar(fixture1).serialize() assert "DTSTART;TZID={tzid}:20200121T070000".format(tzid="W. Europe Standard Time") in Calendar(fixture2).serialize() assert "DTSTART;TZID={tzid}:20200121T070000".format(tzid="Europe/Berlin") in Calendar(fixture3).serialize() pacific = Timezone.from_tzid("US/Pacific") assert pacific.tzid.endswith("America/Los_Angeles") event1 = Event(begin=datetime(2014, 1, 1, 0, 0, 0, tzinfo=gettz("US/Pacific"))) event1.dtstamp = event1.dtstamp.replace(microsecond=0) ser1 = Calendar(events=[event1]).serialize() assert "DTSTART:20140101T000000Z" not in ser1 assert "DTSTART;TZID=%s:20140101T000000" % pacific.tzid in ser1 event2 = event1.clone() event2.begin = datetime(2014, 1, 1, 0, 0, 0, tzinfo=pacific) ser2 = Calendar(events=[event1]).serialize() assert "DTSTART:20140101T000000Z" not in ser2 assert "DTSTART;TZID=%s:20140101T000000" % pacific.tzid in ser2 assert event1 == event2 assert event1.begin == event2.begin assert event1.begin.tzinfo != event2.begin.tzinfo assert ser1 == ser2 deser1 = Calendar(ser1).events[0] deser2 = Calendar(ser2).events[0] assert deser1 == deser2 assert deser1 == event2
def main(): """ :return: None :rtype: None """ ics_url, file, wiki, debug = get_args() event_strings = [] past_events = [] if file: calendar = Calendar(deradicalise_ical(open(file).read())) else: ics_result = requests.get(ics_url) ics_result.encoding = 'utf-8' calendar = Calendar(deradicalise_ical(ics_result.text)) for event in sorted(calendar.events, key=lambda ev: ev.begin): event = EntropiaEvent(event) if not event.is_past_event: event_strings.append("\n" + LINE_SEPARATOR + str(event)) else: past_events.append(event) append_past_events(past_events, wiki['user'], wiki['pass'], wiki['archive']) termine = BOTWARNING + "\n" + TABLE_HEADER + "\n" + "".join( event_strings) + "\n" + "".join(TABLE_FOOTER) if debug: print(termine) site = Site('entropia.de', path='/') site.login(wiki['user'], wiki['pass']) page = site.pages[wiki['page']] if termine: page.save(termine, "Terminbot was here") page.purge()
def merge_calendars(filenames, output='all.ics'): """ Given a list of ics filenames, merge calendars together into combined cal. Arguments: filenames -- A list of .ics files in current working directory to merge (list) output -- Name of ICS file to output (str) (optional) """ new_cal = Calendar() new_cal.extra.append(ContentLine(name='X-WR-CALNAME', value='KQB All')) new_cal.extra.append( ContentLine( name='X-WR-CALDESC', value='All matches and events in the Killer Queen Black community.' )) new_cal.extra.append(ContentLine(name='X-PUBLISHED-TTL', value='PT15M')) new_cal.extra.append(ContentLine(name='TZNAME', value='UTC')) existing_calendars = [] for file in filenames: with open(file) as f: existing_calendars.append(Calendar(f.read())) for calendar in existing_calendars: for event in calendar.events: new_cal.events.add(event) with open(output, 'w') as cal_file: cal_file.writelines(new_cal)
def read_google_ics(ics_url): """ Fetch events directly from Google calendar ICS file """ events = [] try: calendar = Calendar(unidecode(requests.get(ics_url).text)) except: calendar = Calendar( unidecode(urlopen(ics_url).read().decode('iso-8859-1'))) for event in calendar.events: if event.begin.year >= datetime.today().year: date = event.begin.strftime('%d-%m-%Y') starttime = event.begin.strftime("%I:%M %p") endtime = event.end.strftime("%I:%M %p") description = event.description description = BeautifulSoup(description, 'html.parser').get_text( '\n') if description is not None else '' title = event.name events.append({ 'title': title, #Speaker set later 'date': date, #Location set later 'description': description, 'starttime': starttime, 'endtime': endtime, #Owner and URL set later }) return events
def get_difference_in_calendars(old, new): """Get the dates in which an old and new Calendar differ. An Event differs if it is not included in the other calendar Arguments: old {str} -- The old calendar new {str} -- The new calendar Returns: list(str) -- A list of unique dates in DD.MM.YYYY format """ changed_dates = [] old_cal = Calendar(old) new_cal = Calendar(new) old_events = old_cal.events new_events = new_cal.events for event in old_events: if event not in new_events: changed_dates.append(event.begin.format("DD.MM.YYYY")) for event in new_events: if event not in old_events: changed_dates.append(event.begin.format("DD.MM.YYYY")) changed_dates = list(set(changed_dates)) changed_dates.sort(key=lambda date: datetime.strptime(date, '%d.%m.%Y')) print(changed_dates) return changed_dates
def test_issue_181_timezone_ignored(): cal1 = Calendar(fixture1) cal2 = Calendar(fixture2) cal3 = Calendar(fixture3) begin1 = cal1.events[0].begin begin2 = cal2.events[0].begin begin3 = cal3.events[0].begin tzinfo1 = begin1.tzinfo tzinfo2 = begin2.tzinfo tzinfo3 = begin3.tzinfo assert isinstance(tzinfo1, Timezone) assert tzinfo1 == Timezone.from_tzid("Europe/Berlin") assert tzinfo1.tzid.endswith("Europe/Berlin") assert tzinfo1.tzname(begin1) == "CET" assert tzinfo1.utcoffset(begin1) == timedelta(hours=1) assert isinstance(tzinfo2, Timezone) assert tzinfo2 == Timezone.from_container(lines_to_container(fixture2_tz)) assert tzinfo2.tzid == "W. Europe Standard Time" assert tzinfo2.tzname(begin2) == "MEZ" assert tzinfo2.utcoffset(begin2) == timedelta(hours=1) assert isinstance(tzinfo3, Timezone) assert tzinfo3 == Timezone.from_container(lines_to_container(fixture3_tz)) assert tzinfo3.tzid == "Europe/Berlin" assert tzinfo3.tzname(begin3) == "MEZ" assert tzinfo3.utcoffset(begin3) == timedelta(hours=8)
def index(self, calendar=None, filter=None, find="", replacement=None, t=0): """ Retrieve calendar, reduce to events matching filter and apply find/replace """ if calendar: if t == 0: cherrypy.response.headers['Content-Type'] = 'text/calendar' else: cherrypy.response.headers['Content-Type'] = 'text/plain' # Create new calendar to copy events into new_cal = Calendar() calendar = calendar.replace('webcal', 'http') c = Calendar(urlopen(calendar).read().decode('iso-8859-1')) if "," in filter: keywords = filter.split(',') else: keywords = [filter] print keywords for event in c.events: for keyword in keywords: if keyword.lower() in event.name.lower(): if replacement: event.name = event.name.replace(find, replacement) new_cal.events.append(event) return new_cal else: return """
def load_cal(entry: dict) -> Calendar: """Load the calendar from the cache or from remote according to the entry. If the calendar is supposed to be in cached but could not be found in cache, an error is thrown :param entry: representation of the entry to cache. This is the Python representation of the corresponding entry in the config file :type entry: dict :return: the calendar corresponding to the entry :rtype: Calendar :raises FileNotfoundError: if the entry was supposed to be cached but has not been cached before """ if "cache" in entry and entry["cache"]: print("Getting", entry["name"], "from cache") try: return get_from_cache(entry) except FileNotFoundError: return Calendar() else: print("Getting", entry["name"], "from remote") r = requests.get(entry["url"], allow_redirects=True) if "encoding" in entry: cal = Calendar(imports=r.content.decode( encoding=entry["encoding"])) else: cal = Calendar(imports=r.content.decode()) cal = horodate(cal, 'Downloaded at') return cal
def create_calendar(token, enrollment_id, options): file_list = [] if options['academicCal'] or options['careerCal']: academic_calendar = Calendar() career_calendar = Calendar() for sess in get_sessions(token, enrollment_id)['calendarSessions']: e = Event() if (sess['context']['id'] == 1) and options['academicCal']: start_time = datetime.strptime(sess['session']['startTime'], '%Y-%m-%dT%H:%M:%SZ') end_time = datetime.strptime(sess['session']['endTime'], '%Y-%m-%dT%H:%M:%SZ') e.name = str(sess['session']['chapter']) + ': ' + sess['session']['name'] e.transparent = True if options['academicIsTrans'] else False if options['officeHours']: e.begin = start_time - timedelta(minutes=45) e.end = end_time + timedelta(minutes=30) else: e.begin = start_time e.end = end_time academic_calendar.events.add(e) elif (sess['context']['id'] == 2) and options['careerCal']: e.name = sess['session']['name'] e.begin = sess['session']['startTime'] e.end = sess['session']['endTime'] e.transparent = True if options['careerIsTrans'] else False career_calendar.events.add(e) if len(academic_calendar.events) > 0: academic_file_name = str(enrollment_id) + '-academic-calendar' academic_file_name = academic_file_name + '-oh.ics' if options['officeHours'] else academic_file_name + '.ics' file_list.append(academic_file_name) with open('files/' + academic_file_name, 'w') as f: f.writelines(academic_calendar) if len(career_calendar.events) > 0: career_file_name = str(enrollment_id) + '-career-calendar.ics' file_list.append(career_file_name) with open('files/' + career_file_name, 'w') as f: f.writelines(career_calendar) if options['assignmentCal']: assignment_calendar = Calendar() for assignment in get_assignments(token, enrollment_id)['calendarAssignments']: e = Event() if assignment['context']['id'] == 1: e.name = assignment['title'] e.begin = datetime.strptime(assignment['effectiveDueDate'], '%Y-%m-%dT%H:%M:%SZ') - timedelta(days=1) e.end = datetime.strptime(assignment['effectiveDueDate'], '%Y-%m-%dT%H:%M:%SZ') - timedelta(days=1) e.make_all_day() e.transparent = True if options['assignmentsIsTrans'] else False assignment_calendar.events.add(e) assignment_file_name = str(enrollment_id) + '-assignment-calendar.ics' file_list.append(assignment_file_name) with open('files/' + assignment_file_name, 'w') as f: f.writelines(assignment_calendar) return file_list
def generate_ics(event_sources, future_only=True): calendar = Calendar() all_events = list(itertools.chain(*event_sources)) if future_only: all_events = [ event for event in all_events if event.begin.date() >= datetime.date.today() ] calendar = Calendar() for event in all_events: calendar.events.add(event) return calendar
def main(): with open(SOURCES_PATH) as f: content = list(filter(lambda z: len(z) > 0, map(lambda x: x.split('#')[0].strip(), f.readlines()))) new_c = Calendar() for source in content: cal_text = requests.get(source).text c = Calendar(cal_text) new_c.events.update(c.events) with open(OUT_PATH, "w") as f: f.write(str(new_c)) print(f"Saved new calendar to `{OUT_PATH}``")
def main(): with open(SOURCES_PATH) as f: content = f.readlines() content = [x.strip() for x in content] new_c = Calendar() for source in content: c = Calendar(requests.get(source).text) new_c.events.update(c.events) with open("out.ics", "w") as f: f.write(str(c)) print(f"Saved new calendar to `{OUT_PATH}``")
def create_ics(sender, instance, **kwargs): c = Calendar() alarm = [DisplayAlarm(trigger=timedelta(minutes=30))] e = Event() e.name = instance.title e.begin = instance.date e.end = instance.dateend e.alarms = alarm if instance.duration != None: e.duration = instance.duration if (instance.cost == 0 or instance.cost == None): cost = 'Бесплатно' e.description = str(instance.intro) + ' Стоимость: ' + str(cost) else: e.description = str(instance.intro) + ' Стоимость: ' + str(instance.cost)+ 'р.' e.location = instance.location if instance.timepad != None: e.url = instance.timepad c.events.add(e) instance.ics.delete(save=False) instance.ics.save(instance.title +'.ics', ContentFile(str(c)), save=True) #Формирование глобального файла со всеми мероприятиями global_ics = EventIndex.objects.all()[0] events = global_ics.get_children() c = Calendar() for event in events: if (event.specific.date < timezone.now()): pass else: e = Event() e.name = event.title e.begin = event.specific.date e.end = event.specific.dateend e.alarms = alarm if event.specific.duration != None: e.duration = event.specific.duration if (event.specific.cost == 0 or event.specific.cost == None): cost = 'Бесплатно' e.description = str(event.specific.intro.strip("<p>*</p>")) + ' Стоимость: ' + str(cost) else: e.description = str(event.specific.intro.strip("<p>*</p>")) + ' Стоимость: ' + str(event.specific.cost)+ 'р.' e.location = event.specific.location if event.specific.timepad != None: e.url = event.specific.timepad c.events.add(e) global_ics.calenadar_file.delete(save=False) global_ics.calenadar_file.save('global.ics', ContentFile(str(c)), save=True)
def cache(entry: dict, scheduler: sched.scheduler = None) -> None: """Cache an .ics feed in the app/cache directory. Different entries with the same URL will be cached in the same file. The cached calendar contains a new line in the description with the current time when cached prefixed by the 'Cached at' mention :param entry: representation of the entry to cache. This is the Python representation of the corresponding entry in the config file :type entry: dict :param scheduler: scheduler used to relaunch the caching task in the future. If not scheduler is specified, the task will not be relaunched :type scheduler: sched.scheduler """ try: if not os.path.isdir('app/cache'): os.mkdir('app/cache') url = entry['url'] path = "app/cache/" + sha256(url.encode()).hexdigest() + ".ics" r = requests.get(entry["url"], allow_redirects=True) if "encoding" in entry: cal = Calendar(imports=r.content.decode(encoding=entry["encoding"])) else: cal = Calendar(imports=r.content.decode()) cal = horodate(cal, 'Cached at') open(path, 'w').writelines(cal) print(arrow.now().format("YYYY-MM-DD HH:mm:ss"), "Cached", entry['name']) except FailedParse: print("Could not parse", entry['name']) # Save stack trace when an unknown error occurs except Exception as e: with open("error " + arrow.now().format("YYYY-MM-DD HH:mm:ss")+".txt", 'w') as file: file.write(arrow.now().format("YYYY-MM-DD HH:mm:ss") + "\nCould not cache : " + str(entry)) file.write(str(e)) file.write(str(traceback.format_exc())) finally: if scheduler is not None: delay = entry['cache'] if entry['cache'] > 0 else 10 delay *= 60 scheduler.enter(delay=delay, priority=1, action=cache, argument=(entry, scheduler))
def handle_sncf_message(self, message): payload = list(message.walk())[1].get_payload() payload = payload.replace("\r", "").replace("\n", "").replace("=20", "") root = fromstring( quopri.decodestring(payload).decode("latin1").replace( "\t", "").replace("\n", "").replace('\\xa0', ' ')) departure_city, _, arrival_city, _, seat_info, duration, _ = [ r.replace("\xa0", " ") for r in root.xpath( "//table/tr/td/table/tr/td/table/tr/td/span/text()") ] departure_time, train_id, ticket_id, arrival_time = [ r.replace("\xa0", " ") for r in root.xpath( "//table/tr/td/table/tr/td/table/tr/td/span/b/text()") ] departure_date = [ r.replace("\xa0", " ") for r in root.xpath( "//html/body/table/tr/td/table/tr/td/span/text()") ] c = None target_file = os.path.join(self.output_dir, "calendar.ics") if os.path.isfile(target_file): with open(target_file, "r") as f: c = Calendar(f.read()) if c is None: c = Calendar() e = Event() e.name = "%s: %s -> %s [%s]" % (train_id, departure_city, arrival_city, ticket_id) e.begin = dateparser.parse("%s %s CEST" % (departure_date, departure_time), languages=["fr"]) e.end = dateparser.parse("%s %s CEST " % (departure_date, arrival_time), languages=["fr"]) e.location = departure_city e.description = "%s" % seat_info #weird. sometimes it's list, sometime it's set... if type(c.events) is list: c.events.append(e) else: c.events.add(e) with open(target_file, 'w') as f: f.writelines(c)
def handler(event, context): try: opener = urllib2.build_opener() opener.addheaders = [('User-agent', 'Mozilla/5.0')] ics = opener.open(iCalURL).read().decode('iso-8859-1') c = Calendar(ics) lock_code_updated = False delete_code = False print "Server Local Time: {0}".format(arrow.now()) print "Server UTC Time: {0}".format(arrow.utcnow()) now = arrow.utcnow().to('US/Eastern') print "Server UTC Converted to Eastern time: {0}".format(now) print "Starting compare of events" for event in c.events: eventTitle = event.name if not lock_code_updated and eventTitle != "Not available": begin = event.begin.replace(hour=CheckinHour, minute=0, second=0, tzinfo='US/Eastern') end = event.end.replace(hour=CheckOutHour, minute=30, second=0, tzinfo='US/Eastern') description = event.description print "Comparing Title:{} - Now:{} to EventBegin:{} with EventEnd:{}".format(eventTitle, now, begin, end) if now.date() == begin.date(): phone = get_phone(description) lock_code = phone[-4:] print "Setting lock code to {0} for {1}".format(lock_code, eventTitle) set_lock_code(lock_code, eventTitle) lock_code_updated = True elif now > end and end.date() == now.date(): delete_code=True if delete_code and not lock_code_updated: print "Guest's stay ended today. Deleting Lock Code" delete_lock_code() return {'Lock Code Updated': lock_code_updated} except Exception as ex: print ex return False
def getAvailableBlocks(ical_links, date_range, time_range): # Build list of calendars of events cals = [] # list of calendars from iCal links # Iterative through each user's ical link for link in ical_links: # Append calendar, extracting only dates within given date_range cals.append( Calendar(requests.get(link).text).timeline.included( arrow.get(date_range[0]), arrow.get(date_range[1]))) # Build list of datetime tuples from calendar events dt_blocks = [] # convert each ical link into calendar for i, cal in enumerate(cals): dt_blocks.append([]) for event in cal: begin = datetime.fromtimestamp(event.begin.timestamp) end = datetime.fromtimestamp(event.end.timestamp) dt_blocks[i].append((begin, end)) final = set(fillDuration(date_range, time_range)) # subtract each user's calendar from the filled timeline for blocks in dt_blocks: final = subtract(final, blocks) # for f in sorted(final): # print(f) return list(final)
def get_current_event(content: str, include_all_day: bool): calendar = Calendar(content) if calendar is None: return None temp_event = None for event in calendar.timeline.at(utcnow()): if event.all_day and not include_all_day: continue if temp_event is None: temp_event = event elif temp_event.end > event.end: temp_event = event if temp_event is None: return None return { "summary": temp_event.name, "start": parser_ics.get_hass_date(temp_event.begin, temp_event.all_day), "end": parser_ics.get_hass_date(temp_event.end, temp_event.all_day), "location": temp_event.location, "description": temp_event.description, }
def get_event_list(content: str, start, end, include_all_day: bool): event_list = [] calendar = Calendar(re.sub(parser_ics.re_method, "", content)) if calendar is not None: ar_start = arrowget(start) ar_end = arrowget(end) for event in calendar.timeline.included(ar_start, ar_end): if event.all_day and not include_all_day: continue uid = None if hasattr(event, "uid"): uid = event.uid data = { "uid": uid, "summary": event.name, "start": parser_ics.get_date_formatted(event.begin, event.all_day), "end": parser_ics.get_date_formatted(event.end, event.all_day), "location": event.location, "description": event.description, } # Note that we return a formatted date for start and end here, # but a different format for get_current_event! event_list.append(data) return event_list