def _make_ics(event, etime): cal = Calendar() cal.add('prodid', 'N1-send-availability-package') cal.add('version', '1.0') evt = Event() evt.add('summary', event.title) evt.add('location', event.location) evt.add('description', event.description) evt.add('dtstart', etime.start) evt.add('dtend', etime.end) evt.add('dtstamp', datetime.now()) evt['uid'] = '{timestamp}/{email}'.format(timestamp=time.mktime( datetime.now().timetuple()), email=event.organizer.email) evt.add('priority', 5) organizer = vCalAddress('MAILTO:{}'.format(event.organizer.email)) organizer.params['cn'] = vText(event.organizer.name) organizer.params['role'] = vText('CHAIR') evt['organizer'] = organizer for attendee in event.attendees: atnd = vCalAddress('MAILTO:{}'.format(attendee.email)) atnd.params['cn'] = vText(attendee.name) atnd.params['ROLE'] = vText('REQ-PARTICIPANT') evt.add('attendee', atnd, encode=0) cal.add_component(evt) return cal.to_ical()
def property_items(self, recursive=True, sorted=True): """Returns properties in this component and subcomponents as: [(name, value), ...] """ vText = types_factory['text'] properties = [('BEGIN', vText(self.name).to_ical())] if sorted: property_names = self.sorted_keys() else: property_names = self.keys() for name in property_names: values = self[name] if isinstance(values, list): # normally one property is one line for value in values: properties.append((name, value)) else: properties.append((name, values)) if recursive: # recursion is fun! for subcomponent in self.subcomponents: properties += subcomponent.property_items(sorted=sorted) properties.append(('END', vText(self.name).to_ical())) return properties
def _make_ics(event, etime): cal = Calendar() cal.add('prodid', 'N1-send-availability-package') cal.add('version', '1.0') evt = Event() evt.add('summary', event.title) evt.add('location', event.location) evt.add('description', event.description) evt.add('dtstart', etime.start) evt.add('dtend', etime.end) evt.add('dtstamp', datetime.now()) evt['uid'] = '{timestamp}/{email}'.format( timestamp=time.mktime(datetime.now().timetuple()), email=event.organizer.email ) evt.add('priority', 5) organizer = vCalAddress('MAILTO:{}'.format(event.organizer.email)) organizer.params['cn'] = vText(event.organizer.name) organizer.params['role'] = vText('CHAIR') evt['organizer'] = organizer for attendee in event.attendees: atnd = vCalAddress('MAILTO:{}'.format(attendee.email)) atnd.params['cn'] = vText(attendee.name) atnd.params['ROLE'] = vText('REQ-PARTICIPANT') evt.add('attendee', atnd, encode=0) cal.add_component(evt) return cal.to_ical()
def _make_ics(event, etime): cal = Calendar() cal.add("prodid", "N1-send-availability-package") cal.add("version", "2.0") cal.add("method", "REQUEST") # also have PUBLISH or CANCEL evt = Event() evt.add("summary", event.title) evt.add("location", event.location) evt.add("description", event.description) evt.add("dtstart", etime.start.replace(tzinfo=pytz.UTC)) evt.add("dtend", etime.end.replace(tzinfo=pytz.UTC)) evt.add("dtstamp", datetime.now(pytz.UTC)) evt["uid"] = "{timestamp}/{email}".format( timestamp=time.mktime(datetime.now(pytz.UTC).timetuple()), email=event.organizer.email ) evt.add("priority", 5) organizer = vCalAddress("MAILTO:{}".format(event.organizer.email)) organizer.params["cn"] = vText(event.organizer.name) organizer.params["role"] = vText("CHAIR") evt["organizer"] = organizer for attendee in event.attendees: atnd = vCalAddress("MAILTO:{}".format(attendee.email)) atnd.params["cn"] = vText(attendee.name) atnd.params["ROLE"] = vText("REQ-PARTICIPANT") evt.add("attendee", atnd, encode=0) cal.add_component(evt) return cal.to_ical()
def uid(self, host_name='example.com', unique=''): """ Generates a unique id consisting of: datetime-uniquevalue@host. Like: [email protected] """ from icalendar.prop import vText, vDatetime unique = unique or self.rnd_string() return vText('%s-%s@%s' % (vDatetime(datetime.today()).to_ical(), unique, host_name))
def uid(self, host_name='example.com', unique=''): """Generates a unique id consisting of: datetime-uniquevalue@host. Like: [email protected] """ host_name = to_unicode(host_name) unique = unique or self.rnd_string() today = to_unicode(vDatetime(datetime.today()).to_ical()) return vText('%s-%s@%s' % (today, unique, host_name))
def uid(self, host_name='example.com', unique=''): """ Generates a unique id consisting of: datetime-uniquevalue@host. Like: [email protected] """ from icalendar.prop import vText, vDatetime unique = unique or self.rnd_string() return vText( '%s-%s@%s' % (vDatetime(datetime.today()).to_ical(), unique, host_name))
def property_items(self): """ Returns properties in this component and subcomponents as: [(name, value), ...] """ vText = types_factory["text"] properties = [("BEGIN", vText(self.name).ical())] property_names = self.sorted_keys() for name in property_names: values = self[name] if type(values) == ListType: # normally one property is one line for value in values: properties.append((name, value)) else: properties.append((name, values)) # recursion is fun! for subcomponent in self.subcomponents: properties += subcomponent.property_items() properties.append(("END", vText(self.name).ical())) return properties
def property_items(self): """ Returns properties in this component and subcomponents as: [(name, value), ...] """ vText = types_factory['text'] properties = [('BEGIN', vText(self.name).ical())] property_names = self.keys() property_names.sort() for name in property_names: values = self[name] if type(values) == ListType: # normally one property is one line for value in values: properties.append((name, value)) else: properties.append((name, values)) # recursion is fun! for subcomponent in self.subcomponents: properties += subcomponent.property_items() properties.append(('END', vText(self.name).ical())) return properties
def patched_categories(self): """ Patch categories to include our custom tags values """ ret = [] if self.context.tag: factory = getUtility(IVocabularyFactory, 'eionet.fullcalendar.categories') vocabulary = factory(self.context) ret.append(vText(vocabulary.getTerm(self.context.tag).title)) for cat in self.event.subjects or []: ret.append(cat) if ret: return {'value': ret} return None
def _make_ics(event, etime): cal = Calendar() cal.add('prodid', 'N1-quick-schedule-package') cal.add('version', '2.0') cal.add('method', 'REQUEST') # also have PUBLISH or CANCEL evt = Event() evt.add('summary', event.title) evt.add('location', event.location) evt.add('description', event.description) evt.add('dtstart', etime.start.replace(tzinfo=pytz.UTC)) evt.add('dtend', etime.end.replace(tzinfo=pytz.UTC)) evt.add('dtstamp', datetime.now(pytz.UTC)) evt['uid'] = '{timestamp}/{email}'.format( timestamp=time.mktime(datetime.now(pytz.UTC).timetuple()), email=event.organizer.email ) evt.add('priority', 5) organizer = vCalAddress('MAILTO:{}'.format(event.organizer.email)) organizer.params['cn'] = vText(event.organizer.name) organizer.params['role'] = vText('CHAIR') evt['organizer'] = organizer for attendee in event.attendees: atnd = vCalAddress('MAILTO:{}'.format(attendee.email)) atnd.params['cn'] = vText(attendee.name) atnd.params['ROLE'] = vText('REQ-PARTICIPANT') evt.add('attendee', atnd, encode=0) cal.add_component(evt) return cal.to_ical()
def test_multiple(self): directory = os.path.dirname(__file__) cals = Calendar.from_ical(open(os.path.join(directory, 'multiple.ics'), 'rb').read(), multiple=True) self.assertEqual(len(cals), 2) self.assertSequenceEqual([comp.name for comp in cals[0].walk()], ['VCALENDAR', 'VEVENT']) self.assertSequenceEqual([comp.name for comp in cals[1].walk()], ['VCALENDAR', 'VEVENT', 'VEVENT']) self.assertEqual( cals[0]['prodid'], vText('-//Mozilla.org/NONSGML Mozilla Calendar V1.0//EN'))
def test_multiple(self): directory = os.path.dirname(__file__) with open(os.path.join(directory, 'multiple.ics'), 'rb') as fp: data = fp.read() cals = Calendar.from_ical(data, multiple=True) self.assertEqual(len(cals), 2) self.assertSequenceEqual([comp.name for comp in cals[0].walk()], ['VCALENDAR', 'VEVENT']) self.assertSequenceEqual([comp.name for comp in cals[1].walk()], ['VCALENDAR', 'VEVENT', 'VEVENT']) self.assertEqual( cals[0]['prodid'], vText('-//Mozilla.org/NONSGML Mozilla Calendar V1.0//EN') )
def from_parts(parts): "Turns a tuple of parts into a content line" (name, params, values) = parts try: if hasattr(values, "to_ical"): values = values.to_ical() else: values = vText(values).to_ical() # elif isinstance(values, basestring): # values = escape_char(values) if params: return Contentline("%s;%s:%s" % (name, params.to_ical(), values)) return Contentline("%s:%s" % (name, values)) except Exception as exc: logger.error(str(exc)) raise ValueError(u'Property: %r Wrong values "%r" or "%r"' % (name, params, values))
def generate_calendar(request): """http://codespeak.net/icalendar/""" cal = Calendar() cal.add("prodid", "-//Club Connect//ericleong.me//") cal.add("version", "2.0") posts = Post.objects.order_by("-created") cal["X-WR-CALNAME"] = "Club Connect Events" cal["X-PUBLISH-TTL"] = "PT12H" cal["CALSCALE"] = "GREGORIAN" cal["METHOD"] = "PUBLISH" # TODO: separate out private events using a private URL? # TODO: switch to using EDT for post in posts: if post.start_time: # Make sure we have a time event = Event() event.add("summary", vText(post.title)) event.add("dtstart", post.start_time) event.add("dtend", post.end_time if post.end_time else post.start_time) # event.add('dtstamp', datetime(2005,4,4,0,10,0,tzinfo=UTC)) event["uid"] = vText(post.id) event["organizer"] = vText(post.author.username) event["description"] = vText(post.description) event["url"] = vUri(post.get_absolute_url()) if post.location: if post.location.room: event["location"] = vText("%s (%s)" % (post.location.name, post.location.room)) else: event["location"] = vText(post.location.name) for commit in post.committed.all(): attendee = vCalAddress("MAILTO:" + commit.email) name = ( ([commit.first_name, commit.last_name]) if (commit.first_name and commit.last_name) else commit.username ) attendee.params["cn"] = vText(name) event.add("attendee", attendee, encode=0) cal.add_component(event) return HttpResponse(cal.to_ical().replace("\n", "\r\n"), content_type="text/calendar")
def from_parts(parts): "Turns a tuple of parts into a content line" (name, params, values) = parts try: if hasattr(values, 'to_ical'): values = values.to_ical() else: values = vText(values).to_ical() #elif isinstance(values, basestring): # values = escape_char(values) if params: return Contentline('%s;%s:%s' % (name, params.to_ical(), values)) return Contentline('%s:%s' % (name, values)) except: raise ValueError( 'Property: %s Wrong values "%s" or "%s"' % (repr(name), repr(params), repr(values)))
def from_parts(cls, name, params, values, sorted=True): """Turn a parts into a content line. """ assert isinstance(params, Parameters) if hasattr(values, 'to_ical'): values = values.to_ical() else: values = vText(values).to_ical() # elif isinstance(values, basestring): # values = escape_char(values) # TODO: after unicode only, remove this # Convert back to unicode, after to_ical encoded it. name = to_unicode(name) values = to_unicode(values) if params: params = to_unicode(params.to_ical(sorted=sorted)) return cls(u'%s;%s:%s' % (name, params, values)) return cls(u'%s:%s' % (name, values))
def handle(self, *args, **options): URL = r'http://contests.acmicpc.info/contests.json' TZ = timezone('Asia/Shanghai') cal = Calendar() cal.add('prodid', '-//ACM EVENTS CALENDAR//WHUACM TEAM//') cal.add('version', '2.0') events = requests.get(URL).json() for item in events: event = Event() fmt = '%Y-%m-%d %H:%M:%S' time = datetime.strptime(item['start_time'], fmt).replace(tzinfo=TZ) event.add('dtstart', time) event.add('summary', item['name']) event['location'] = vText(item['oj']) event['uid'] = item['id'] + '@whuctf.org' cal.add_component(event) f = open(os.path.join(settings.MEDIA_ROOT, 'acmevents.ics'), 'wb') f.write(cal.to_ical()) f.close()
def test_cal_Component(self): from icalendar.cal import Component, Calendar, Event from icalendar import prop # A component is like a dictionary with extra methods and attributes. c = Component() c.name = 'VCALENDAR' # Every key defines a property.A property can consist of either a # single item. This can be set with a single value... c['prodid'] = '-//max m//icalendar.mxm.dk/' self.assertEqual( c, Calendar({'PRODID': '-//max m//icalendar.mxm.dk/'}) ) # or with a list c['ATTENDEE'] = ['Max M', 'Rasmussen'] self.assertEqual( c, Calendar({'ATTENDEE': ['Max M', 'Rasmussen'], 'PRODID': '-//max m//icalendar.mxm.dk/'}) ) ### ADD MULTIPLE VALUES TO A PROPERTY # if you use the add method you don't have to considder if a value is # a list or not. c = Component() c.name = 'VEVENT' # add multiple values at once c.add('attendee', ['*****@*****.**', '*****@*****.**']) # or add one per line c.add('attendee', '*****@*****.**') c.add('attendee', '*****@*****.**') # add again multiple values at once to very concatenaton of lists c.add('attendee', ['*****@*****.**', '*****@*****.**']) self.assertEqual( c, Event({'ATTENDEE': [ prop.vCalAddress('*****@*****.**'), prop.vCalAddress('*****@*****.**'), prop.vCalAddress('*****@*****.**'), prop.vCalAddress('*****@*****.**'), prop.vCalAddress('*****@*****.**'), prop.vCalAddress('*****@*****.**') ]}) ) ### # You can get the values back directly ... c.add('prodid', '-//my product//') self.assertEqual(c['prodid'], prop.vText(u'-//my product//')) # ... or decoded to a python type self.assertEqual(c.decoded('prodid'), b'-//my product//') # With default values for non existing properties self.assertEqual(c.decoded('version', 'No Version'), 'No Version') c.add('rdate', [datetime(2013, 3, 28), datetime(2013, 3, 27)]) self.assertTrue(isinstance(c.decoded('rdate'), prop.vDDDLists)) # The component can render itself in the RFC 2445 format. c = Component() c.name = 'VCALENDAR' c.add('attendee', 'Max M') self.assertEqual( c.to_ical(), b'BEGIN:VCALENDAR\r\nATTENDEE:Max M\r\nEND:VCALENDAR\r\n' ) # Components can be nested, so You can add a subcompont. Eg a calendar # holds events. e = Component(summary='A brief history of time') e.name = 'VEVENT' e.add('dtend', '20000102T000000', encode=0) e.add('dtstart', '20000101T000000', encode=0) self.assertEqual( e.to_ical(), b'BEGIN:VEVENT\r\nDTEND:20000102T000000\r\n' + b'DTSTART:20000101T000000\r\nSUMMARY:A brief history of time\r' + b'\nEND:VEVENT\r\n' ) c.add_component(e) self.assertEqual( c.subcomponents, [Event({'DTEND': '20000102T000000', 'DTSTART': '20000101T000000', 'SUMMARY': 'A brief history of time'})] ) # We can walk over nested componentes with the walk method. self.assertEqual([i.name for i in c.walk()], ['VCALENDAR', 'VEVENT']) # We can also just walk over specific component types, by filtering # them on their name. self.assertEqual([i.name for i in c.walk('VEVENT')], ['VEVENT']) self.assertEqual( [i['dtstart'] for i in c.walk('VEVENT')], ['20000101T000000'] ) # We can enumerate property items recursively with the property_items # method. self.assertEqual( c.property_items(), [('BEGIN', b'VCALENDAR'), ('ATTENDEE', prop.vCalAddress('Max M')), ('BEGIN', b'VEVENT'), ('DTEND', '20000102T000000'), ('DTSTART', '20000101T000000'), ('SUMMARY', 'A brief history of time'), ('END', b'VEVENT'), ('END', b'VCALENDAR')] ) # We can also enumerate property items just under the component. self.assertEqual( c.property_items(recursive=False), [('BEGIN', b'VCALENDAR'), ('ATTENDEE', prop.vCalAddress('Max M')), ('END', b'VCALENDAR')] ) sc = c.subcomponents[0] self.assertEqual( sc.property_items(recursive=False), [('BEGIN', b'VEVENT'), ('DTEND', '20000102T000000'), ('DTSTART', '20000101T000000'), ('SUMMARY', 'A brief history of time'), ('END', b'VEVENT')] ) # Text fields which span multiple mulitple lines require proper # indenting c = Calendar() c['description'] = u'Paragraph one\n\nParagraph two' self.assertEqual( c.to_ical(), b'BEGIN:VCALENDAR\r\nDESCRIPTION:Paragraph one\\n\\nParagraph two' + b'\r\nEND:VCALENDAR\r\n' ) # INLINE properties have their values on one property line. Note the # double quoting of the value with a colon in it. c = Calendar() c['resources'] = 'Chair, Table, "Room: 42"' self.assertEqual( c, Calendar({'RESOURCES': 'Chair, Table, "Room: 42"'}) ) self.assertEqual( c.to_ical(), b'BEGIN:VCALENDAR\r\nRESOURCES:Chair\\, Table\\, "Room: 42"\r\n' + b'END:VCALENDAR\r\n' ) # The inline values must be handled by the get_inline() and # set_inline() methods. self.assertEqual( c.get_inline('resources', decode=0), [u'Chair', u'Table', u'Room: 42'] ) # These can also be decoded self.assertEqual( c.get_inline('resources', decode=1), [b'Chair', b'Table', b'Room: 42'] ) # You can set them directly ... c.set_inline('resources', ['A', 'List', 'of', 'some, recources'], encode=1) self.assertEqual(c['resources'], 'A,List,of,"some, recources"') # ... and back again self.assertEqual( c.get_inline('resources', decode=0), ['A', 'List', 'of', 'some, recources'] ) c['freebusy'] = '19970308T160000Z/PT3H,19970308T200000Z/PT1H,'\ + '19970308T230000Z/19970309T000000Z' self.assertEqual( c.get_inline('freebusy', decode=0), ['19970308T160000Z/PT3H', '19970308T200000Z/PT1H', '19970308T230000Z/19970309T000000Z'] ) freebusy = c.get_inline('freebusy', decode=1) self.assertTrue(isinstance(freebusy[0][0], datetime)) self.assertTrue(isinstance(freebusy[0][1], timedelta))
datestr += time.strftime(' %Y') dtstart = datetime.datetime.strptime(datestr, "%d %b %Y") dtend = None duration = datetime.timedelta(1) props = { 'categories': opts.categories.split(','), 'dtstart': vDate(dtstart.date()), 'created': vDatetime(datetime.datetime.now()), 'class': 'PUBLIC', } if status is not None: props['status'] = status if location is not None: props['location'] = vText(location) if opts.event_url: props['url'] = vUri(opts.event_url) if description is not None: props['summary'] = vText(description) if dtend is not None: props['dtend'] = vDate(dtend.date()) if duration is not None: props['duration'] = vDuration(duration) uid = str(uuid.uuid1()) props['UID'] = uid ev = Event(**props) c = Calendar() c.add_component(ev)
def test_cal_Component(self): from icalendar.cal import Component, Calendar, Event from icalendar import prop # A component is like a dictionary with extra methods and attributes. c = Component() c.name = 'VCALENDAR' # Every key defines a property.A property can consist of either a # single item. This can be set with a single value... c['prodid'] = '-//max m//icalendar.mxm.dk/' self.assertEqual(c, Calendar({'PRODID': '-//max m//icalendar.mxm.dk/'})) # or with a list c['ATTENDEE'] = ['Max M', 'Rasmussen'] self.assertEqual( c, Calendar({ 'ATTENDEE': ['Max M', 'Rasmussen'], 'PRODID': '-//max m//icalendar.mxm.dk/' })) ### ADD MULTIPLE VALUES TO A PROPERTY # if you use the add method you don't have to considder if a value is # a list or not. c = Component() c.name = 'VEVENT' # add multiple values at once c.add('attendee', ['*****@*****.**', '*****@*****.**']) # or add one per line c.add('attendee', '*****@*****.**') c.add('attendee', '*****@*****.**') # add again multiple values at once to very concatenaton of lists c.add('attendee', ['*****@*****.**', '*****@*****.**']) self.assertEqual( c, Event({ 'ATTENDEE': [ prop.vCalAddress('*****@*****.**'), prop.vCalAddress('*****@*****.**'), prop.vCalAddress('*****@*****.**'), prop.vCalAddress('*****@*****.**'), prop.vCalAddress('*****@*****.**'), prop.vCalAddress('*****@*****.**') ] })) ### # You can get the values back directly ... c.add('prodid', '-//my product//') self.assertEqual(c['prodid'], prop.vText(u'-//my product//')) # ... or decoded to a python type self.assertEqual(c.decoded('prodid'), b'-//my product//') # With default values for non existing properties self.assertEqual(c.decoded('version', 'No Version'), 'No Version') c.add('rdate', [datetime(2013, 3, 28), datetime(2013, 3, 27)]) self.assertTrue(isinstance(c.decoded('rdate'), prop.vDDDLists)) # The component can render itself in the RFC 2445 format. c = Component() c.name = 'VCALENDAR' c.add('attendee', 'Max M') self.assertEqual( c.to_ical(), b'BEGIN:VCALENDAR\r\nATTENDEE:Max M\r\nEND:VCALENDAR\r\n') # Components can be nested, so You can add a subcompont. Eg a calendar # holds events. e = Component(summary='A brief history of time') e.name = 'VEVENT' e.add('dtend', '20000102T000000', encode=0) e.add('dtstart', '20000101T000000', encode=0) self.assertEqual( e.to_ical(), b'BEGIN:VEVENT\r\nDTEND:20000102T000000\r\n' + b'DTSTART:20000101T000000\r\nSUMMARY:A brief history of time\r' + b'\nEND:VEVENT\r\n') c.add_component(e) self.assertEqual(c.subcomponents, [ Event({ 'DTEND': '20000102T000000', 'DTSTART': '20000101T000000', 'SUMMARY': 'A brief history of time' }) ]) # We can walk over nested componentes with the walk method. self.assertEqual([i.name for i in c.walk()], ['VCALENDAR', 'VEVENT']) # We can also just walk over specific component types, by filtering # them on their name. self.assertEqual([i.name for i in c.walk('VEVENT')], ['VEVENT']) self.assertEqual([i['dtstart'] for i in c.walk('VEVENT')], ['20000101T000000']) # We can enumerate property items recursively with the property_items # method. self.assertEqual(c.property_items(), [('BEGIN', b'VCALENDAR'), ('ATTENDEE', prop.vCalAddress('Max M')), ('BEGIN', b'VEVENT'), ('DTEND', '20000102T000000'), ('DTSTART', '20000101T000000'), ('SUMMARY', 'A brief history of time'), ('END', b'VEVENT'), ('END', b'VCALENDAR')]) # We can also enumerate property items just under the component. self.assertEqual(c.property_items(recursive=False), [('BEGIN', b'VCALENDAR'), ('ATTENDEE', prop.vCalAddress('Max M')), ('END', b'VCALENDAR')]) sc = c.subcomponents[0] self.assertEqual(sc.property_items(recursive=False), [('BEGIN', b'VEVENT'), ('DTEND', '20000102T000000'), ('DTSTART', '20000101T000000'), ('SUMMARY', 'A brief history of time'), ('END', b'VEVENT')]) # Text fields which span multiple mulitple lines require proper # indenting c = Calendar() c['description'] = u'Paragraph one\n\nParagraph two' self.assertEqual( c.to_ical(), b'BEGIN:VCALENDAR\r\nDESCRIPTION:Paragraph one\\n\\nParagraph two' + b'\r\nEND:VCALENDAR\r\n') # INLINE properties have their values on one property line. Note the # double quoting of the value with a colon in it. c = Calendar() c['resources'] = 'Chair, Table, "Room: 42"' self.assertEqual(c, Calendar({'RESOURCES': 'Chair, Table, "Room: 42"'})) self.assertEqual( c.to_ical(), b'BEGIN:VCALENDAR\r\nRESOURCES:Chair\\, Table\\, "Room: 42"\r\n' + b'END:VCALENDAR\r\n') # The inline values must be handled by the get_inline() and # set_inline() methods. self.assertEqual(c.get_inline('resources', decode=0), [u'Chair', u'Table', u'Room: 42']) # These can also be decoded self.assertEqual(c.get_inline('resources', decode=1), [b'Chair', b'Table', b'Room: 42']) # You can set them directly ... c.set_inline('resources', ['A', 'List', 'of', 'some, recources'], encode=1) self.assertEqual(c['resources'], 'A,List,of,"some, recources"') # ... and back again self.assertEqual(c.get_inline('resources', decode=0), ['A', 'List', 'of', 'some, recources']) c['freebusy'] = '19970308T160000Z/PT3H,19970308T200000Z/PT1H,'\ + '19970308T230000Z/19970309T000000Z' self.assertEqual(c.get_inline('freebusy', decode=0), [ '19970308T160000Z/PT3H', '19970308T200000Z/PT1H', '19970308T230000Z/19970309T000000Z' ]) freebusy = c.get_inline('freebusy', decode=1) self.assertTrue(isinstance(freebusy[0][0], datetime)) self.assertTrue(isinstance(freebusy[0][1], timedelta))
elif cmd == 'S': sem = arg elif cmd == 'H': start, end = arg.split('-') shour, smin = start.split('.') ehour, emin = end.split('.') elif cmd == 'T': title = arg elif cmd == 'L': location = arg elif cmd == 'P': prof.append(arg) else: if title is not None and sem.startswith(chosen_sem): event = Event() event.add('summary', vText(title)) description = vText(" ".join(prof)) #event['description'] = description event.add('description', vText(description)) event.add( 'dtstart', datetime(year, month, daynum[day], int(shour), int(smin), 0)) event.add( 'dtend', datetime(year, month, daynum[day], int(ehour), int(emin), 0)) event.add('dtstamp', datetime.now()) event.add('location', vText(location)) event.add('rrule', { "FREQ": "WEEKLY",
def parse(html): """ htmlをパースする """ root = lxml.html.fromstring(html) ical = Calendar() yyyymm = root.xpath('//td[@class="dateCell"]/b')[0].text year = yyyymm.split(u'年')[0] for events in root.find_class('eventcell'): for event_date in events.find_class('date'): event_date = event_date.text for event in events.find_class('eventInner'): event_line = {'time': '', 'detail': ''} ical_event = Event() for item in event: if (item.tag == 'li'): event_line['time'] = '' event_line['detail'] = item.find_class('event')[0].text if (item.tag == 'span'): for time in item.find_class('eventDateTime'): event_line['time'] = time.text for detail in item.find_class('event'): event_line['detail'] = detail.text mmdd = event_date.split('/') if (event_line['time'] != ''): startend_time = event_line['time'].split('-') start_time = startend_time[0] start_hhmm = start_time.split(':') if (len(startend_time) == 1): event_line['time'] = event_line['time'].strip() + '-' + event_line['time'].strip() end_time = startend_time[0] else: end_time = startend_time[1] end_hhmm = end_time.split(':') ical_event.add('dtstart', datetime(int(year), int(mmdd[0]), int(mmdd[1]), int(start_hhmm[0]), int(start_hhmm[1]))) ical_event.add('dtend', datetime(int(year), int(mmdd[0]), int(mmdd[1]), int(end_hhmm[0]), int(end_hhmm[1]))) else: start_date = date(int(year), int(mmdd[0]), int(mmdd[1])) dtstart_prop = vDate(start_date) dtstart_prop.params['VALUE'] = vText('DATE') ical_event.add('dtstart',dtstart_prop) end_date = date(int(year), int(mmdd[0]), int(mmdd[1])) dtend_prop = vDate(end_date) dtend_prop.params['VALUE'] = vText('DATE') ical_event.add('dtend', dtend_prop) ical_event.add('summary', event_line['detail']) ical.add_component(ical_event) ical.add('version', '2.0') ical.add('prodid', '-//kuma//cycal.py//EN') return ical.to_ical()
seen += 1 (old, todo, new, href, etag, ev) = utils.create_or_update_calendar_item( target_collection_url, "VEVENT", uid) out = Calendar() if import_url is not None: out['X-IMPORTED-FROM-URL'] = vUri(import_url) # If this is not an iTIP request, then make it one. if "METHOD" not in out and opts.invite: out["METHOD"] = "REQUEST" out.update(list(orig.items())) for c in other: out.add_component(c) if opts.category: if isinstance(ev.get('CATEGORIES', ''), vText): ev['CATEGORIES'] = [ev['CATEGORIES']] ev.setdefault('categories', []).append(vText(opts.category)) if opts.status and 'STATUS' not in ev: ev['STATUS'] = opts.status.upper() out.add_component(ev) write = hasChanged(old, out) if write: if old is None: added += 1 utils.add_member(target_collection_url, 'text/calendar', out.to_ical()) else: changed += 1 utils.put(href, 'text/calendar', out.to_ical(), if_match=[etag]) logger.info('Processed %s. Seen %d, updated %d, new %d', opts.prefix, seen, changed, added)
def get_calendar_entry(self): """ Build the iCalendar string for the event iCal validator, useful for debugging: http://icalvalid.cloudapp.net/ """ event = self.event event_tz = event.timezone creation_time = django_timezone.now() # Generate some description strings title, desc_plain, _desc_html = self.get_invite_texts() # Generate the Calendar event cal = icalendar.Calendar() cal.add("prodid", "-//OneEvent event entry//onevent//EN") cal.add("version", "2.0") cal.add("calscale", "GREGORIAN") cal.add("method", "REQUEST") # Generate timezone infos relevant to the event tzmap = {} tzmap = add_to_zones_map(tzmap, event_tz.zone, event.start) tzmap = add_to_zones_map(tzmap, event_tz.zone, event.get_real_end()) tzmap = add_to_zones_map(tzmap, django_timezone.get_default_timezone_name(), creation_time) for tzid, transitions in tzmap.items(): cal_tz = icalendar.Timezone() cal_tz.add("tzid", tzid) cal_tz.add("x-lic-location", tzid) for transition, tzinfo in transitions.items(): if tzinfo["dst"]: cal_tz_sub = icalendar.TimezoneDaylight() else: cal_tz_sub = icalendar.TimezoneStandard() cal_tz_sub.add("tzname", tzinfo["name"]) cal_tz_sub.add("dtstart", transition) cal_tz_sub.add("tzoffsetfrom", tzinfo["tzoffsetfrom"]) cal_tz_sub.add("tzoffsetto", tzinfo["tzoffsetto"]) cal_tz.add_component(cal_tz_sub) cal.add_component(cal_tz) cal_evt = icalendar.Event() cal_evt.add("uid", "event{0}-booking{1}@oneevent".format(event.id, self.id)) cal_evt.add("dtstamp", creation_time) cal_evt.add("dtstart", event.start.astimezone(event_tz)) cal_evt.add("dtend", event.get_real_end().astimezone(event_tz)) cal_evt.add("created", creation_time) cal_evt.add("sequence", "1") cal_evt.add("summary", title) cal_evt.add("description", desc_plain) cal_evt.add("location", vText(event.location_name)) cal_evt.add("category", "Event") cal_evt.add("status", "CONFIRMED") cal_evt.add("transp", "OPAQUE") cal_evt.add("priority", "5") cal_evt.add("class", "PUBLIC") organiser = vCalAddress("mailto:{0}".format(event.owner.email)) organiser.params["cn"] = vText(event.owner.get_full_name()) organiser.params["role"] = vText("CHAIR") cal_evt.add("organizer", organiser, encode=0) attendee = vCalAddress("mailto:{0}".format(self.person.email)) attendee.params["cutype"] = vText("INDIVIDUAL") attendee.params["role"] = vText("REQ-PARTICIPANT") attendee.params["partstat"] = vText("NEEDS-ACTION") attendee.params["rsvp"] = vText("FALSE") attendee.params["cn"] = vText(self.person.get_full_name()) cal_evt.add("attendee", attendee, encode=0) cal.add_component(cal_evt) return cal.to_ical()
added = 0 seen = 0 for (uid, ev) in items.iteritems(): seen += 1 fname = "%s-%s.ics" % (opts.prefix, uid.replace("/", "")) path = os.path.join(opts.outdir, fname) out = Calendar() out['X-IMPORTED-FROM-URL'] = vUri(url) out.update(orig.items()) for c in other: out.add_component(c) if opts.category: if isinstance(ev.get('categories', ''), vText): ev['categories'] = [ev['categories']] ev.setdefault('categories', []).append(vText(opts.category)) if opts.status and not 'status' in ev: ev['status'] = opts.status.upper() out.add_component(ev) try: old = Calendar.from_ical(open(path, 'rb').read()) except IOError: old = None write = True else: write = hasChanged(old, out) if write: if not os.path.exists(path): added += 1 else: changed += 1
return True for item in curr.split (","): if item.upper () in filter: return True return False # generate importance filter string imp_list = [] for i in xrange(imp, 3): imp_list.append ("%d" % i) imp_filter = "(" + ",".join (imp_list) + ")" q = db.GqlQuery ("select * from News_Record_v2 where when > :1 and when < :2 and importance in %s order by when" % imp_filter, d_from, d_to) id = 0 for ev in q: if not check_filter (curr_filter, ev.curr): continue event = Event () event['uid'] = "*****@*****.**" % (id, time.mktime (ev.when.timetuple ())) event['summary'] = vText (u"%s, Imp: %s" % (norm_str (ev.title), news.val2imp (ev.importance))) event['description'] = vText ("Prev: %s\\, Fore: %s" % (norm_str (ev.pred), norm_str (ev.fore))) event['dtstamp'] = ev.when.strftime ("%Y%m%dT%H%M%SZ") event['dtstart'] = ev.when.strftime ("%Y%m%dT%H%M%SZ") event['dtend'] = (ev.when + datetime.timedelta (minutes = 10)).strftime ("%Y%m%dT%H%M%SZ") event['priority'] = 0 cal.add_component (event) id += 1 print cal.as_string (),
# generate importance filter string imp_list = [] for i in xrange(imp, 3): imp_list.append("%d" % i) imp_filter = "(" + ",".join(imp_list) + ")" q = db.GqlQuery( "select * from News_Record_v2 where when > :1 and when < :2 and importance in %s order by when" % imp_filter, d_from, d_to) id = 0 for ev in q: if not check_filter(curr_filter, ev.curr): continue event = Event() event['uid'] = "*****@*****.**" % ( id, time.mktime(ev.when.timetuple())) event['summary'] = vText(u"%s, Imp: %s" % (norm_str(ev.title), news.val2imp(ev.importance))) event['description'] = vText("Prev: %s\\, Fore: %s" % (norm_str(ev.pred), norm_str(ev.fore))) event['dtstamp'] = ev.when.strftime("%Y%m%dT%H%M%SZ") event['dtstart'] = ev.when.strftime("%Y%m%dT%H%M%SZ") event['dtend'] = ( ev.when + datetime.timedelta(minutes=10)).strftime("%Y%m%dT%H%M%SZ") event['priority'] = 0 cal.add_component(event) id += 1 print cal.as_string(),
datestr += time.strftime(' %Y') dtstart = datetime.datetime.strptime(datestr, "%d %b %Y") dtend = None duration = datetime.timedelta(1) props = { 'categories': opts.categories.split(','), 'dtstart': vDate(dtstart.date()), 'created': vDatetime(datetime.datetime.now()), 'class': 'PUBLIC', } if status is not None: props['status'] = status if location is not None: props['location'] = vText(location) if opts.url: props['url'] = vUri(opts.url) if description is not None: props['summary'] = vText(description) if dtend is not None: props['dtend'] = vDate(dtend.date()) if duration is not None: props['duration'] = vDuration(duration) ev = Event(**props) c = Calendar() c.add_component(ev) md5 = hashlib.md5()
def test_cal_Component(self): from icalendar.cal import Component, Calendar, Event from icalendar import prop # A component is like a dictionary with extra methods and attributes. c = Component() c.name = "VCALENDAR" # Every key defines a property.A property can consist of either a # single item. This can be set with a single value... c["prodid"] = "-//max m//icalendar.mxm.dk/" self.assertEqual(c, Calendar({"PRODID": "-//max m//icalendar.mxm.dk/"})) # or with a list c["ATTENDEE"] = ["Max M", "Rasmussen"] self.assertEqual(c, Calendar({"ATTENDEE": ["Max M", "Rasmussen"], "PRODID": "-//max m//icalendar.mxm.dk/"})) ### ADD MULTIPLE VALUES TO A PROPERTY # if you use the add method you don't have to considder if a value is # a list or not. c = Component() c.name = "VEVENT" # add multiple values at once c.add("attendee", ["*****@*****.**", "*****@*****.**"]) # or add one per line c.add("attendee", "*****@*****.**") c.add("attendee", "*****@*****.**") # add again multiple values at once to very concatenaton of lists c.add("attendee", ["*****@*****.**", "*****@*****.**"]) self.assertEqual( c, Event( { "ATTENDEE": [ prop.vCalAddress("*****@*****.**"), prop.vCalAddress("*****@*****.**"), prop.vCalAddress("*****@*****.**"), prop.vCalAddress("*****@*****.**"), prop.vCalAddress("*****@*****.**"), prop.vCalAddress("*****@*****.**"), ] } ), ) ### # You can get the values back directly ... c.add("prodid", "-//my product//") self.assertEqual(c["prodid"], prop.vText(u"-//my product//")) # ... or decoded to a python type self.assertEqual(c.decoded("prodid"), b"-//my product//") # With default values for non existing properties self.assertEqual(c.decoded("version", "No Version"), "No Version") c.add("rdate", [datetime(2013, 3, 28), datetime(2013, 3, 27)]) self.assertTrue(isinstance(c.decoded("rdate"), prop.vDDDLists)) # The component can render itself in the RFC 2445 format. c = Component() c.name = "VCALENDAR" c.add("attendee", "Max M") self.assertEqual(c.to_ical(), b"BEGIN:VCALENDAR\r\nATTENDEE:Max M\r\nEND:VCALENDAR\r\n") # Components can be nested, so You can add a subcompont. Eg a calendar # holds events. e = Component(summary="A brief history of time") e.name = "VEVENT" e.add("dtend", "20000102T000000", encode=0) e.add("dtstart", "20000101T000000", encode=0) self.assertEqual( e.to_ical(), b"BEGIN:VEVENT\r\nDTEND:20000102T000000\r\n" + b"DTSTART:20000101T000000\r\nSUMMARY:A brief history of time\r" + b"\nEND:VEVENT\r\n", ) c.add_component(e) self.assertEqual( c.subcomponents, [Event({"DTEND": "20000102T000000", "DTSTART": "20000101T000000", "SUMMARY": "A brief history of time"})], ) # We can walk over nested componentes with the walk method. self.assertEqual([i.name for i in c.walk()], ["VCALENDAR", "VEVENT"]) # We can also just walk over specific component types, by filtering # them on their name. self.assertEqual([i.name for i in c.walk("VEVENT")], ["VEVENT"]) self.assertEqual([i["dtstart"] for i in c.walk("VEVENT")], ["20000101T000000"]) # We can enumerate property items recursively with the property_items # method. self.assertEqual( c.property_items(), [ ("BEGIN", b"VCALENDAR"), ("ATTENDEE", prop.vCalAddress("Max M")), ("BEGIN", b"VEVENT"), ("DTEND", "20000102T000000"), ("DTSTART", "20000101T000000"), ("SUMMARY", "A brief history of time"), ("END", b"VEVENT"), ("END", b"VCALENDAR"), ], ) # We can also enumerate property items just under the component. self.assertEqual( c.property_items(recursive=False), [("BEGIN", b"VCALENDAR"), ("ATTENDEE", prop.vCalAddress("Max M")), ("END", b"VCALENDAR")], ) sc = c.subcomponents[0] self.assertEqual( sc.property_items(recursive=False), [ ("BEGIN", b"VEVENT"), ("DTEND", "20000102T000000"), ("DTSTART", "20000101T000000"), ("SUMMARY", "A brief history of time"), ("END", b"VEVENT"), ], ) # Text fields which span multiple mulitple lines require proper # indenting c = Calendar() c["description"] = u"Paragraph one\n\nParagraph two" self.assertEqual( c.to_ical(), b"BEGIN:VCALENDAR\r\nDESCRIPTION:Paragraph one\\n\\nParagraph two" + b"\r\nEND:VCALENDAR\r\n" ) # INLINE properties have their values on one property line. Note the # double quoting of the value with a colon in it. c = Calendar() c["resources"] = 'Chair, Table, "Room: 42"' self.assertEqual(c, Calendar({"RESOURCES": 'Chair, Table, "Room: 42"'})) self.assertEqual( c.to_ical(), b'BEGIN:VCALENDAR\r\nRESOURCES:Chair\\, Table\\, "Room: 42"\r\n' + b"END:VCALENDAR\r\n" ) # The inline values must be handled by the get_inline() and # set_inline() methods. self.assertEqual(c.get_inline("resources", decode=0), [u"Chair", u"Table", u"Room: 42"]) # These can also be decoded self.assertEqual(c.get_inline("resources", decode=1), [b"Chair", b"Table", b"Room: 42"]) # You can set them directly ... c.set_inline("resources", ["A", "List", "of", "some, recources"], encode=1) self.assertEqual(c["resources"], 'A,List,of,"some, recources"') # ... and back again self.assertEqual(c.get_inline("resources", decode=0), ["A", "List", "of", "some, recources"]) c["freebusy"] = "19970308T160000Z/PT3H,19970308T200000Z/PT1H," + "19970308T230000Z/19970309T000000Z" self.assertEqual( c.get_inline("freebusy", decode=0), ["19970308T160000Z/PT3H", "19970308T200000Z/PT1H", "19970308T230000Z/19970309T000000Z"], ) freebusy = c.get_inline("freebusy", decode=1) self.assertTrue(isinstance(freebusy[0][0], datetime)) self.assertTrue(isinstance(freebusy[0][1], timedelta))
def get_calendar(self): # Create calendar object cal = icalendar.Calendar() for j in self.jobs: e = icalendar.Event() # Add title and description e.add('summary', j.title.encode('utf-8')) e.add('description', j.event.get_description().encode('utf-8')) # Add place e.add('location', vText(j.event.place).encode('utf-8')) # Now, get start and end-time for info in job_list: if info.name == j.t: start_date = j.event.date # Look for fixed start if re.search('arb.*', j.event.time.additional, re.IGNORECASE): start = self.format_time(j.event.time.t_start) start_delta = 0 # Has introduction elif info.t_einf and j.event.time.t_einf: start = self.format_time(j.event.time.t_einf) start_delta = - info.t_einf # Has regular start elif (info.t_start and j.event.time.t_start): start = self.format_time(j.event.time.t_start) start_delta = - info.t_start # Has no start, no intro, but an end time! -> comp start time elif j.event.time.t_end: start_date = j.event.date_end # Use different date! start = self.format_time(j.event.time.t_end) start_delta = - info.t_duration else: print('time data insufficient for:\n%s!' % str(j)) exit e.add('dtstart', datetime.datetime.combine(start_date, start) + datetime.timedelta(minutes=start_delta)) # Compute ending time # # Case 1: there is a fixed ending if not j.event.time.t_end == "": end = self.format_time(j.event.time.t_end) end_delta = 0 # # Case 2: no fixed end else: end = self.format_time(j.event.time.t_start) end_delta = start_delta + info.t_duration e.add('dtend', datetime.datetime.combine(j.event.date_end, end) + datetime.timedelta(minutes=end_delta)) # timestamp e.add('dtstamp', datetime.datetime.now()) # Add to calendar cal.add_component(e) # give calendar return cal