omz:forum

    • Register
    • Login
    • Search
    • Recent
    • Popular

    Welcome!

    This is the community forum for my apps Pythonista and Editorial.

    For individual support questions, you can also send an email. If you have a very short question or just want to say hello — I'm @olemoritz on Twitter.


    How to remove or change a calendar event?

    Pythonista
    5
    23
    9043
    Loading More Posts
    • Oldest to Newest
    • Newest to Oldest
    • Most Votes
    Reply
    • Reply as topic
    Log in to reply
    This topic has been deleted. Only users with topic management privileges can see it.
    • cvp
      cvp @brumm last edited by cvp

      @brumm to remove, use this

      from  objc_util import *
      #from ctypes import POINTER
      #import threading
      import calendar, time
      
      store = ObjCClass('EKEventStore').alloc().init()
      
      # this code is only needed once
      #access_granted = threading.Event()
      #def completion(_self, granted, _error):
      #    access_granted.set()
      #completion_block = ObjCBlock(completion, argtypes=[c_void_p, c_bool, c_void_p])
      #store.requestAccessToEntityType_completion_(0, completion_block)
      #access_granted.wait()
      
      startDate = ObjCClass('NSDate').dateWithTimeIntervalSince1970_(time.mktime(time.strptime('2018-12-30 00:00:00', '%Y-%m-%d %H:%M:%S')))
      endDate = ObjCClass('NSDate').dateWithTimeIntervalSince1970_(time.mktime(time.strptime('2018-12-30 23:59:59', '%Y-%m-%d %H:%M:%S')))
      
      predicate = store.predicateForEventsWithStartDate_endDate_calendars_(startDate, endDate, None)
      
      events = store.eventsMatchingPredicate_(predicate) # array of events
      
      for event in events:
      	print(event.title())
      	if str(event.title()) == 'Test':
      		span = 0 # only this instance
      		store.removeEvent_span_error_(event,span,None)
      

      You can see that predicate returns an array of events, even if only one.

      M calendar has several events at this date, I only remove this one with title = Test

      1 Reply Last reply Reply Quote 2
      • cvp
        cvp @brumm last edited by

        @brumm to update the event, for instance it's title:

        for event in events:
        	print(event.title())
        	if str(event.title()) == 'Test':
        		span = 0 # only this instance
        		#store.removeEvent_span_error_(event,span,None)
        		event.title = 'ttt'
        		store.saveEvent_span_error_(event,span,None) 
        
        1 Reply Last reply Reply Quote 2
        • brumm
          brumm last edited by

          @cvp: Great, you made my day.

          1 Reply Last reply Reply Quote 1
          • AA737
            AA737 last edited by

            Hello!

            Brand new to python, and programming as a whole. I used this template successfully, thank you, but I was wondering how to specify a specific calendar? I assume it would be in the “predicate,” after the start and end time, the “none?”

            Thanks!

            cvp 2 Replies Last reply Reply Quote 0
            • ccc
              ccc last edited by

              how to specify a specific calendar

              What exactly does that mean? Can you provides some sample code of what you have working so far with a description of how you want to change it?

              The Apple docs for this function call are at https://developer.apple.com/documentation/eventkit/ekeventstore/1507479-predicateforeventswithstartdate?language=objc

              1 Reply Last reply Reply Quote 1
              • cvp
                cvp @AA737 last edited by

                @AA737 said:

                I assume it would be in the “predicate,”

                Yes, the third parameter is None (all calendars) or an array of EKCalendar objects.

                1 Reply Last reply Reply Quote 1
                • cvp
                  cvp @AA737 last edited by cvp

                  @AA737 try this

                  import datetime
                  from objc_util import *
                  
                  # EKEventStore = calendar database
                  store = ObjCClass('EKEventStore').alloc().init()
                  	
                  # Convert string yyyymmdd to NSdate
                  dateFormat = ObjCClass('NSDateFormatter').alloc().init()
                  dateFormat.setDateFormat_('yyyyMMdd HH:mm')
                  
                  for calendar in store.calendars():
                  	print(calendar.title())
                  	if str(calendar.title()) == 'your calendar' :
                  		print('here')
                  		date1 = dateFormat.dateFromString_('20200101 00:01') 
                  		date2 = dateFormat.dateFromString_('20201231 23:59')  
                  		predicate = store.predicateForEventsWithStartDate_endDate_calendars_(date1, date2, [calendar])
                  		events = store.eventsMatchingPredicate_(predicate)
                  		for event in events:
                  			print(event.title())
                  		break
                  
                  1 Reply Last reply Reply Quote 1
                  • AA737
                    AA737 last edited by AA737

                    @ccc sorry, I didn’t word that very clearly. Right now, I have a parameter to return all events that occur in the next 2 days, from all calendars. I would like to return events from only one calendar. I have reviewed the Apple documentation, but I have to admit I don’t understand it

                    @cvp thank you, that works well, however, instead of doing an If statement, what would be the format to replace the “None” with a calendar name in the predicate?

                    I tried a few things, but I really can’t figure out the format.
                    Thanks for the help

                     store = ObjCClass('EKEventStore').alloc().init()
                     now = datetime.now()
                    
                    start_date = now.strftime('%Y-%m-%d %H:%M:%S')
                    
                    start_date = datetime.now() + timedelta(hours=0)
                    tomorrow = datetime.now() + timedelta(days=2)
                    
                    start_date = start_date.strftime('%Y-%m-%d %H:%M:%S')
                    tomorrow_formatted = tomorrow.strftime('%Y-%m-%d %H:%M:%S')
                    
                    startDate = ObjCClass('NSDate').dateWithTimeIntervalSince1970_(time.mktime(time.strptime(start_date, '%Y-%m-%d %H:%M:%S')))
                    
                    endDate = 	ObjCClass('NSDate').dateWithTimeIntervalSince1970_(time.mktime(time.strptime(tomorrow_formatted, '%Y-%m-%d %H:%M:%S')))
                    
                    predicate = store.predicateForEventsWithStartDate_endDate_calendars_(startDate, endDate, None)
                    
                    events = store.eventsMatchingPredicate_(predicate)’ ‘ ‘
                    
                    cvp 2 Replies Last reply Reply Quote 0
                    • cvp
                      cvp @AA737 last edited by cvp

                      @AA737 said:

                      what would be the format to replace the “None” with a calendar name in the predicate?

                      The third parameter of the predicate is not a calendar name but an array of calendars EKCalendar objects.

                      1 Reply Last reply Reply Quote 1
                      • cvp
                        cvp @AA737 last edited by cvp

                        @AA737 try this

                        calendars_array = [calendar for calendar in store.calendars() if str(calendar.title()) == 'your calendar']
                        predicate = store.predicateForEventsWithStartDate_endDate_calendars_(date1, date2, calendars_array)
                        events = store.eventsMatchingPredicate_(predicate) 
                        
                        1 Reply Last reply Reply Quote 1
                        • AA737
                          AA737 last edited by

                          @cvp that worked great, thank you! I have a lot to learn...

                          cvp 1 Reply Last reply Reply Quote 0
                          • cvp
                            cvp @AA737 last edited by

                            @AA737 Believe me, you don't begin with the easiest project 😀

                            1 Reply Last reply Reply Quote 1
                            • AA737
                              AA737 last edited by

                              @cvp Have you noticed you can only run your calendar script about 8 times in a row, and then it stops working and Pythonista has to be reset? Any idea why, or a fix for it?

                              cvp 2 Replies Last reply Reply Quote 0
                              • cvp
                                cvp @AA737 last edited by

                                @AA737 said:

                                run your calendar script about 8 times in a row, and then it stops working

                                You're right and I did never see that. I'll check. Perhaps an Apple limitation

                                1 Reply Last reply Reply Quote 1
                                • cvp
                                  cvp @AA737 last edited by

                                  @AA737 After testing, I've remarked that after 10 runs (always), there is no crash at all but the returned calendars list of EKEventStore is empty and sincerely, I didn't find anything similar in Google nor any explanation.

                                  AA737 1 Reply Last reply Reply Quote 1
                                  • AA737
                                    AA737 @cvp last edited by

                                    @cvp said:

                                    @AA737 After testing, I've remarked that after 10 runs (always), there is no crash at all but the returned calendars list of EKEventStore is empty and sincerely, I didn't find anything similar in Google nor any explanation.

                                    Interesting, thank you for looking into it, and all your help!

                                    cvp 1 Reply Last reply Reply Quote 0
                                    • JonB
                                      JonB last edited by

                                      @cvp maybe try an autoreleasepool context handler around the code of interest, and then autorelease() and delete the python objects for objc objects you don't need anymore, like the predicate, and maybe the store, calendar arrays, etc. it sounds like ekeventstore gets pissed if you are not releasing its objects.

                                      1 Reply Last reply Reply Quote 1
                                      • cvp
                                        cvp @AA737 last edited by

                                        @AA737 Thanks to @JonB , this works

                                        import datetime
                                        import objc_util
                                        
                                        with objc_util.autoreleasepool():
                                        	
                                        	# EKEventStore = calendar database
                                        	store = objc_util.ObjCClass('EKEventStore').alloc().init()
                                        	
                                        	# Convert string yyyymmdd to NSdate
                                        	dateFormat = objc_util.ObjCClass('NSDateFormatter').alloc().init()
                                        	dateFormat.setDateFormat_('yyyyMMdd HH:mm')
                                        
                                        	date1 = dateFormat.dateFromString_('20200101 00:01') 
                                        	date2 = dateFormat.dateFromString_('20201231 23:59')  
                                        
                                        	calendars_array = [calendar for calendar in store.calendars() if str(calendar.title()) == 'Sorties']
                                        	predicate = store.predicateForEventsWithStartDate_endDate_calendars_(date1, date2, calendars_array)
                                        	events = store.eventsMatchingPredicate_(predicate)
                                        	for event in events:
                                        		print(event.title())
                                        		
                                        	store.autorelease()
                                        	
                                        del events, predicate, store, calendars_array 
                                        
                                        AA737 1 Reply Last reply Reply Quote 1
                                        • ccc
                                          ccc last edited by

                                          To convert from Python datetimes...

                                          from datetime import datetime
                                          print(f'{datetime.now():%Y%m%d %H:%M}')
                                          
                                          cvp 1 Reply Last reply Reply Quote 1
                                          • cvp
                                            cvp @ccc last edited by cvp

                                            @ccc I know, but here we need Objectivec NSDateFormatter objects

                                            1 Reply Last reply Reply Quote 1
                                            • First post
                                              Last post
                                            Powered by NodeBB Forums | Contributors