I recently turned on Google Sync for the iPhone to enable wireless syncing of my Google calendar and contacts with my iPhone. A limitation of the current version of Google Sync for the iPhone is that it only supports 5 Calendars. I've got more than 5 Calendars in Google Calendar so that's a problem. Fortunately, many of these Calendars are read only (e.g. public/school holidays, your favorite teams game schedule, etc.) and by combining multiple read-only calendars into 1 read-only calendar it is possible to get them all sync-ed between Google Calendar and you're iPhone.

Now all we need is a utility that merges the calendars. Enter merge-ics, a Python script that reads all .ics files in a file system directory and merges them into one new .ics file which you can then import into Google Calendar. Instead of syncing the individual calendars to you iPhone, you now simply sync the combined one. You loose the per calendar color for the merged calendars, but that's acceptable for me.

Of course you can manually download the .ics files of the individual calendars and then import the combined .ics file into Google Calendar, but wouldn't it be nice is this is automated? Do do that I created a shell script that:

  1. downloads individual calendar .ics files. The URLs of these calendars are stored in a text file.
  2. kicks of the merge-ics python script to combine the .ics files

In addition I'm hosting that combined .ics file on my webserver, subscribed to it from Google Calendar and scheduled the script to run on a daily basis. So now I'm able to sync these read only calendars to my iPhone without further manual intervention.

Below are the shell script and an example text file contains the calendars to be merged. If you'd want to use it, make sure you update the variables at the beginning of the script and also update the variables in the merge-ics.py Python script. Needless to say that you'll need to download and install that script form the merge-ics site.

# Script takes one argument: filename containing the URLs of the
# Calendar .ics files to be downloaded.



# Get new copies of the ICAL files
for url in `cat ${ICALSFILE}` ; do

# Only successfuly downloaded files are copied to
# ${TARGET_ICS_DIR} to be able to deal with temporarily
# unavailability of a calendar.
rm -f ${TEMP_ICS_FILE}
wget -q -O ${TEMP_ICS_FILE} ${url}
if [ $? -eq 0 ]; then
cp ${TEMP_ICS_FILE} ${TARGET_ICS_DIR}/`basename ${url}`
echo "Calendar ${url} could not be retrieved"


# Run the merge_ics script

Example text file with input:


After moving my mail en calendar to the cloud I decided to also to stop hosting my own blog. I've been using Pebble for well over 5 years and have mostly been pretty happy with it. Why?

  • Running you own does consume some maintenance time (do upgrades, etc). Especially re-doing the tweaks to templates etc became a hassle.
  • I had occasional problems doing posts (typed in a full post, hit the button and ooops... post gone. May well be caused by local set up but even in that case it's even better to move it out).
  • It blocked me from doing major OS updates since I wanted to prevent downtime (and I finally want to upgrade my Mac Mini to Leopard).
  • It's dependent on the availability of my server and network connection. Both are pretty reliable but still...
  • Using Cloud services is this years hype ;-)

Getting a blog setup with Google Blogger is easy, but of course you also want to migrate the old blog posts and not break the links from other sources to you blog. I digged around hoping to find an easy way to migrate the blog posts to Google Blogger and somehow redirects visitors from the old to the new location... no luck. Google Blogger does have an import option, but it only imports it's own exports and the only tool I found migrates from Wordpress to Google Blogger. So I had to scratch my own itch and created a simple command line utility that:

  • Reads the original Pebble posts and posts them to Blogger. This includes comments but due to limitations in the Google Blogger API the details of the original poster of the comment had to be included in the comment text and I show up as the poster. (Google does not allow to specify another author as poster of a comment though the API to prevent spam.)
  • Validates links in blogs posts and attempts to fix them where possible (for example links between blog posts that would break when moving to new location). If it can't fix a link, it reports this in the log file.
  • Generate a redirects file that you can include in your Apache httpd.conf to redirect visitors that access the old location to the new location of a post.

You can find the utility here: Blogger Importer. Feel free to use or extend it. I did the trick for me, but maybe you need some additional features. The current version only works for Pebble but it is set up such that you can easily plug in other sources and migrate these to Blogger.

A limitation of hosting my blog at Blogger is that it's less easy to create plugins. For Pebble I created my own plugin that would post a message on Twitter each time I created/updated a blog post. There's no such plugin for Blogger (yet) and I don't think Google provides hooks in their Blogger Dashboard where I could stick that functionality in. There is a service (TwitterFeed) that does this, but then you'd have to provide your Twitter credentials to that site... not sure if I'd want to do that.

Another point I have to fix are the Google Maps integrations that I did for showing Skeeler routes. For Pebble I created a 'decorator' plugin that would do some tweaks to the blog post contents which caused it to show the skeeler route on a Google Map. This is now broken and I have to find a solution for that (worst case I'd have to 'hardcode' it into the blog posts themselves, would be nice if it's a more elegant solution though).

As a heads up...

I'm migrating my blog from self-hosted Pebble to Google Blogger. I'll be doing this in the coming days so you may want to update your feed settings:

New blog location: http://blog.vermaas.net
New feed: http://blog.vermaas.net/feeds/posts/default