Creating iCalendar file

Hello.

I find that comforting, as I couldn’t find any reference to the X-WR-TIMEZONE format when I glanced through the rfc. Well, I know I have to figure out the naming convention/transitioninging scheme.

I think it is somehow linked to the same scheme as is used for the vcf format (contact - info files).

Well, all in all, this is very interesting, and I hope to have time in the near future to follow up on the matter, as lots of the stuff I write will benefit from being put into calendar files, as do a lot of other stuff too, that is of general interest.

I wonder first of all, what happens if the calender is already there, does the events getting added once more, or are the former, totally removed, or are just unique elements added. That is things I want to investigate.

Better get back to the planetary motions for now. :slight_smile:

Anyways: is there any information you lack, then I’d suggest you’d have a look at Calendar and Contacts for Mac Os X server, as there you’ll find information for the Server side of those Applications.

Edit

There is also a program named iCal buddy, that is a command -line tool for interacting with iCal at least, that is made by hhas among others. The source code should be available.

Good Luck with your endeavours and efforts kel! :slight_smile:

Hi.

I think that properties beginning with “X-” are defined by an application for its own use, but I’m not sure. It wouldn’t hurt to include the ones that iCal/Calendar uses if you intend to import the calendar to it.

In my Calendar files, GMT/UTC dates and times (those followed by “Z”) are used only for administrative details such as creation and modification dates. Event dates and times are stored as per the time zone in which they were created. If the calendar’s opened on a computer set to a different time zone, iCal/Calendar will display the events at the local times corresponding to those instants. (This may depend on whether or not time zone support is turned on in the application’s preferences, but I can’t test it at the moment.)

Event dates which don’t have times or time zones are all-day events and are taken as lasting all day in whichever time zone they’re viewed.

Hi everybody,

The rfc page lists the definition as ‘x-name’, but doesn’t give examples of these experimental properties.

I think I’ve found how Calendar uses the X-WR-TIMEZONE property. Need to do more tests later, but here’s the scenario on my simple calendar file. Firstly, here’s the simple file which I changed a little:

When this is imported into Calendar, it is split into two calendar files. Note that in the second event Calendar DTStart is in utc. To every event an invisible alarm is added probably for Notification Center and the utc time remains. Here’s the newly created calendar file:

Note that DTStart is still in utc. So Calendar must change that time at run time for display.

Now for the good part. I created a new event in calendar “OurMeetings”. It seems that Calendar uses the timezone name to create the new event. Here’s the new event:

Calendar seems to use the ‘X-WR-TIMEZONE:Pacific/Honolulu’ in DTSTART for the new event. I was thinking that Calendar might want to know this information, if the user changes timezones. I still need to check if Calendar is really using theX-WR-TIMEZONE information or getting it from the system as some people do. :slight_smile:

I think I should import the simple calendar file with all the information that is need from the file. It would probably take too long to script Calendar to create 730 individual calendar file events, than to have it import the whole simple calendar.

Hope I’m not too far off. :smiley: Getting there.

Thanks a lot,
kel

I edited the time zone in the simple file to “X-WR-TIMEZONE:US/Pacific” and reimported it. Creating the new event shows that Calendar gets the timezone name from the system.

So, it still seems that the X-WR-TIMEZONE is not used. Think it’s best to write the times in this form as Calendar did.

It’s getting close to 1:00 PM. Need to check out what will happen in Notification Center.

Later,
kel

Here’s the basic simple file I ended up with:

If the time is in utc, then use the form of the second event. Otherwise, add the timezone name as in the first event. I left the X-WR-TIMEZONE just in case Calendar uses it for some reason.

Edited: one more thing. Linefeeds must be changed to returns in the ics file or else Calendar can’t read it.

Thanks a lot,
kel

Hi kel.

I imported your calendar into Calendar here, choosing the “New calendar” option. A new calendar was created with the name specified in the file and with events at 18:10 and 19:01 BST on 10th of this month ” so it works OK. I got exactly the same event times when I did it again with time zone support turned off.

Linefeeds in the file are fine on my machine.

Edit: Addendum. When I actually open the events, the times shown inside are BST when time zone support’s turned off and the originals ” along with notes of the times zones ” when it’s turned on.

Hi Nigel,

So, Calendar adjusts for the timezone change. Great!

Thanks for testing that,
kel

Hi Nigel,

What you’re saying is that the notes are added to the Calendar ics files noting changes in the timezone?

Here’s a short script to create the file from text if anyone is interested:

set t to quoted form of "summary1
time1
summary2
time2"
set cmd to "sed -e '
1 {
i\\
BEGIN:VCALENDAR\\
VERSION:2.0\\
X-WR-CALNAME;VALUE=TEXT:OurMeetings\\
X-WR-TIMEZONE:Pacific/Honolulu\\
PRODID:-//Kel.Meetings//MeetingsCal 1.0//EN\\
CALSCALE:GREGORIAN
}
i\\
BEGIN:VEVENT
s/.*/SUMMARY: &/
n
s/.*/DTSTART;TZID=Pacific\\/Honolulu:&/
a\\
END:VEVENT
$ a\\
END:VCALENDAR
'"
do shell script "echo " & t & " | " & cmd -- & " >~/Desktop/TestCal.ics" -- write to file

Uncomment the last line to write to file. I haven’t tested the resulting ics file yet with actual times. Need to take a nap. I’ll fix it up tomorrow.

Edited: the script. fixed the comment for writing to file.

Edited: this script doesn’t work for me. I think I need another way to write the text to file. Not sure.

gl,
kel

No. I’m saying that if I double-click the events in Calendar while time zone support is off, the inspector windows simply show the start and end times transposed to my time zone .

. whereas if I do the same with time zone support on, the inspector windows show the times as for the original zone, with a “time zone” property underneath:

In both cases, the events are shown transposed to my local time in the calendar display.

However, the “time zone” entry in an inspector window is a pop-up menu which allows other zones to be selected. Selecting another zone here causes the times to be reinterpreted as if they were from that zone. So if I change the time zone of your Hawaiian event to UTC, 07:10 Hawaii-Aleutian Standard Time becomes 07:10 UTC and the event shifts in the calendar display from 18:10 to 08:10 United Kingdom Time. Clicking “Apply” in the inspector window makes the change permanent and edits the start and end time entries in the event’s calendar file.

If I return the event to Hawaii-Aleutian Standard Time and export the calendar from Calendar, the exported file’s X-WR-TIMEZONE has my time zone. There’s also a VTIMEZONE object with details of how to interpret yours. :slight_smile:

Hi Nigel,

That’s interesting!

I tried changing the time zone in the VEVENT last night and didn’t notice the time zone in the inspector window. I’ll check out your observations. Thanks for the in-depth explanation. Now I think I understand.

Later,
kel

I think I’ve found what is wrong with my script that writes to file. There are carriage returns! Just thought of something. Maybe I copied an pasted the returns into some text. So what I need to do is check the script’s text.

Hello Kel.

One of the nice things with BBEdit and TextWrangler, is that it is so easy to see invisbles. Especially when it comes to hard spaces in a shell script, but it should work for you as well, when you look for carriage returns. No need for hexedit, od -cb, or xxd. :slight_smile:

Hi McUsr,

I tried Text Wrangler but didn’t get anything. But with this script, I found something strange:

set t to quoted form of "summary1
time1
summary2
time2"
set cmd to "sed -e '
1 {
i\\
BEGIN:VCALENDAR\\
VERSION:2.0\\
X-WR-CALNAME;VALUE=TEXT:OurMeetings\\
X-WR-TIMEZONE:Pacific/Honolulu\\
PRODID:-//Kel.Meetings//MeetingsCal 1.0//EN\\
CALSCALE:GREGORIAN
}
i\\
BEGIN:VEVENT
s/.*/SUMMARY: &/
n
s/.*/DTSTART;TZID=Pacific\\/Honolulu:&/
a\\
END:VEVENT
$ a\\
END:VCALENDAR
'"
set r to do shell script "echo " & t & " | " & cmd -- & " >~/Desktop/TestCal.ics" -- write to file
offset of return in r

→ 16
So, I have a carriage return at the end of the first line. I can’t figure out why so far. I think this is the script where I searched the script for Returns and didn’t find any. I don’t think Sed would return Returns.

Edited: I think I’ve found what’s wrong in the script. The text I used had "return & linefeed’. Probably got that from downloading the basic calendar file text.

I might retype it.

Oh I got it! It’s the backslash at end of line. Something to do with that.

The returns are probably from ‘do shell script’. Try it this way:

set r to do shell script "echo " & t & " | " & cmd without altering line endings
offset of return in r

Hi Nigel,

That worked! Now I need to make a new plan.

Thanks a lot,
kel

I was making some stupid mistakes. Finally, got the script working up to making the file.

-- make some dates
set cd to current date
set d1 to cd + 1 * hours
set d2 to cd + 2 * hours
set summary1 to "Meeting at " & (time string of d1)
set summary2 to "Meeting at " & (time string of d2)
set date1 to MakeCalDate(d1)
set date2 to MakeCalDate(d2)
set t to quoted form of (summary1 & linefeed & date1 & linefeed & summary2 & linefeed & date2)
set cmd to "sed -e '
1 {
i\\
BEGIN:VCALENDAR\\
VERSION:2.0\\
X-WR-CALNAME;VALUE=TEXT:OurMeetings\\
X-WR-TIMEZONE:Pacific/Honolulu\\
PRODID:-//Kel.Meetings//MeetingsCal 1.0//EN\\
CALSCALE:GREGORIAN
}
i\\
BEGIN:VEVENT
s/.*/SUMMARY: &/
n
s/.*/DTSTART;TZID=Pacific\\/Honolulu:&/
a\\
END:VEVENT
$ a\\
END:VCALENDAR
'"
set r to do shell script ("echo " & t & " | " & cmd) without altering line endings
set f to choose file name
set ref_num to open for access f with write permission
write r to ref_num
close access ref_num

on MakeCalDate(d)
	set time1 to d as «class isot» as string
	set AppleScript's text item delimiters to {"-", ":"}
	set temp_list to text items of time1
	set AppleScript's text item delimiters to {""}
	set time1 to temp_list as string
	return time1
end MakeCalDate

Retyping it really helped in finding the mistakes. :slight_smile:

Thanks for all the help Nigel and Mcusr,
kel

Here’s the final script for now. Now I can test and modify.

-- Makes new calendar with events or adds to existing calendar.

-- get Calendar folder
set docs_path to (path to documents folder) as string
set cal_folder to docs_path & "Calendars:"
tell application "System Events"
	if not (exists folder cal_folder) then
		make new folder at folder docs_path with properties {name:"Calendars"}
	end if
end tell
set file_spec to cal_folder & "Meetings1.ics"
set file_spec_pp to POSIX path of file_spec

-- get user timezone name
set userTZ to (do shell script ("readlink '/etc/localtime' | sed 's|/usr/share/zoneinfo/||'"))

-- make some dates
set cd to current date
set d1 to cd + 1 * hours
set d2 to cd + 2 * hours
set summary1 to "Meeting at " & (time string of d1)
set summary2 to "Meeting at " & (time string of d2)
set dt1 to d1 as «class isot» as string
set dt2 to d2 as «class isot» as string
set t to quoted form of (summary1 & linefeed & dt1 & linefeed & summary2 & linefeed & dt2)

-- Sed make calender file text and save to file command
set cmd to "sed -e '
1 {
i\\
BEGIN:VCALENDAR\\
VERSION:2.0\\
X-WR-CALNAME;VALUE=TEXT:OurMeetings\\
X-WR-TIMEZONE:" & userTZ & "\\
PRODID:-//Kel.Meetings//MeetingsCal 1.0//EN\\
CALSCALE:GREGORIAN
}
i\\
BEGIN:VEVENT
s/.*/SUMMARY: &/
n
s/[-:]*//g
s_.*_DTSTART;TZID=" & userTZ & ":&_
a\\
END:VEVENT
$ {
a\\
END:VCALENDAR
}
'"
-- run sed command with input text (events' summaries and dates)
set r to do shell script ("echo " & t & " | " & cmd & " >" & file_spec_pp)

set file_ref to (file_spec) as alias
say "[[slnc 1000]] Select \"New Calendar\" from the popup menu to create a new calendar. [[slnc 500]] Or, [[slnc 400]] select an existing calendar to add events." without waiting until completion
-- open the file in Calendar
tell application "Calendar"
	launch
	activate
	open {file_ref}
end tell

I still need to check on the timezone changes. Got sidetracked.

Edited: changed the script a little.

Edited: the script.

Edited: had to edit the script one last time. Exchanged Finder for System Events.

Thanks,
kel

This thread was fascinating. Since the Apple Calendar app and Microsoft Outlook seem to be unable to add excluded dates, my next project is to write a script to batch process a folder with a bunch of ICS files in it and add excluded dates to each event.

The excluded dates field in ICS files look something like:

EXDATE:20210402T010000Z,20210403T010000Z,20210404T010000Z

The above line should exclude three specific dates in repeating events.

I think I can try to have the script search for:

END:VEVENT

And replace it with:

EXDATE:20210402T010000Z,20210403T010000Z,20210404T010000Z
END:VEVENT

I’m assuming I have to use the Finder dictionary to accomplish this.