Hacking a Google Calendar CLI Tool

I wrote earlier of the very useful command line utility called gcalcli (short for GoogleCALendarCommandLineInterface). Click here to read that post. One of the options is called “agenda” which spits out, by default, the next five days of calendar entries. If you would prefer a different range of time than five days, then you can specify two dates and the utility will give you that set of entries.

But I find that to be a bit of a pain, typing in the dates to start and end the list, when I generally want a quick and dirty “next several days.” That, I suppose, is why there is a default of five days. But five days is not a good default. If it is Wednesday, I want to see what I’ve got on my calendar for the rest of the current week, as well as what is on my calendar for ALL of next week. For me, a better default would be 14 days. With 14 days, you always get a full look at the present week and the next week, plus, sometimes, a bit after that.

One can imagine writing a bash script that figures out what day it is, and then adds enough days that you get an agenda for the remainder of the present week plus all of the next week, but no more days than that. Such a script could make use of bash’s ability to manage and manipulate dates as they occur in our periodic system, with 24 hours in a day, 7 days in a week, work days being a subset of five of those days, etc. etc.

One could also imagine writing a bash script to poke one’s eyes out with hot soldering irons.

A simpler solution is this:

Pick a number of days that you like, and add that to the current day, and use those two parameters to invoke the agenda command, and put all that in a script. The problem with this is still figuring out the second day. How do you add, say, 14 days to the present day? If the date utility in bash gives us something like 10/19/10, how do you add 14 to that? 19 plus 14 is 33. There is no day 33. So you’d have to increment the month. So the month would become 11. One could use a modulo function if available, but some months are 30 days long, some 31 days long, and one is sometimes 28 days long but sometimes 29 days long. And then, what if you wanted fourteen days starting on December 20th? Then, the month goes back to 1, and the year is incremented. Holy crap!

Software like spreadsheets and other financial applications do date math. It is interesting to note that such applications didn’t originally do date math, and when they first did it, they did it poorly, and for years (and as far as I know this is ongoing) major screw ups in spreadsheet code often have to do with date math. Date math, as a matter of fact, is the bane of computers and those who work with them. (Remember the year 2000 fiasco?)

But there is a way to do this easily, and this is in fact the way that most date math is probably done at some level in spreadsheets and other apps. Convert everything into the number of seconds since some arbitrary historical moment in time. This is a bit like how radiocarbon dating works. When you see a date like “1,000 years before present” that year is 950 AD, because “Present” = 1950.

For this purpose, Linux uses Unix Time, also known as Posix time. In this system, time started at midnight ZULU time in the morning of January 1st, 1970. Everything before that is prehistory. Approximately one and a quarter billion seconds have passed since then.

So the solution is easy: Convert the present time to Unix time. Then, add the number of seconds that is 14 days into the future (1209600 seconds) to that number to obtain the second time. Then, since gcalcli does not read Linux time (shame on the coders! shame on the coders!) convert the Unix time back to esoteric time (with the slashes) and feed that to the gcalcli command. I originally did this as a one liner but I’ve since parsed it out into individual lines and put it in a bash script I call “agenda.” Here it is:


#/bin/bash

nownum=`date +%s`
thennum=$((nownum+1209600))
now=`date --date=@$nownum +%D`
then=`date --date=@$thennum +%D`
echo Agenda for $now through $then
gcalcli --nc agenda $now $then

Let’s break it down.

First, the shebang line, and this may vary across systems:

#/bin/bash

Then we make some numbers. nownum is the current date in Unix format, using the “date” command and specifying a “format” code of %s, which is seconds since the start of the Unixverse. Then, 14 days of seconds are added to this to make a second Unix time number:

nownum=`date +%s`
thennum=$((nownum+1209600))

Then, these two values, “nownum” and “thennum” are converted, using the esoteric –date switch of the date command, into strings “now” and “then” which are in standard date format:

now=`date --date=@$nownum +%D`
then=`date --date=@$thennum +%D`

These two numbers are then printed out as part of a sentence reminding the user what today’s date is and what the end of the 14 day period is:

echo Agenda for $now through $then

And finally, gcalcli is invoked using $now and $then as parameters to the agenda subcommand. I also threw in –nc which suppresses color coding.

gcalcli --nc agenda $now $then

The reason I suppress color coding is so I can do this at the command line

agenda > ~/agenda.txt
alpine-> (c)ompose -> amanda -> ctrl-r -> ~/Desktop/agenda.txt -> ctrl-X -> Y

that slams the current agenda into a text file, opens a mail program, composes a message to Amanda, slams the contents of the agenda file into the email and sends it off.

Hey, wait, what am I doing? I should add a line that creates agenda.txt every time I request the agenda from Google.

tapity-tap-tap tappity-tap

Done.

#/bin/bash

nownum=`date +%s`
thennum=$((nownum+1209600))
now=`date --date=@$nownum +%D`
then=`date --date=@$thennum +%D`
echo Agenda for $now through $then
gcalcli --nc agenda $now $then > ~/Desktop/agenda.txt
cat ~/Desktop/agenda.txt

This post is part of the cli series. The full list is here.

If you found this post useful, please consider using the social networking tools below to spread it around! Thank you

Comments

  1. #1 brand0con
    October 19, 2010

    The bashing up of this is interesting and all but seriously!? If the purpose is demonstrating bash principles in practice than kudos, but for practicality sake, just share your google calendar with your wife through the web gui. One should also consider how the recipient wants to view a calendar/agenda; in a slightly esoteric text file format or the familiar calendar graphical representation that they’ve looked at on paper for the greater share of their lives.

    Still, I’ll “like” the post out of overall appreciation.

  2. #2 Greg Laden
    October 19, 2010

    Brand0con, not really. I gave my wife access to the google calendar months ago. That has had no effect in our communication about scheduling. We converse about scheduling either while we are sitting in the same room, me with my laptop and her with her blue book (she does not use google calendar), or via email.

    Sharing the google calendar only works if both parties are using it. Making everybody use a particular resource so that the “obvious” or “simple” solution will work is not really a solution, except to a system administrator!

    Also, with a bit of editing that takes a few seconds, I can share blocks of this calendar with anyone with whom I’m negotiating a schedule. Sharing a google calendar is not going to work under those cases.

    Finally, do refer to the earlier post, where I demonstrate why a command line access to google calendar can be a good thing, and look at the first post in this series for the philosophy of having both the GUI and the cli methods available.

    I’m glad you think this is a good demonstration of bash. I assume there will be bash-trolls showing up to tell me that I’m using too many processes or something!

  3. #3 Nemo
    October 19, 2010

    Check it:

    date -d “+2 weeks”

  4. #4 Greg Laden
    October 19, 2010

    Brilliant! I knew someone would solve this more easily than I had. It would have to be:

    date -d “+2 weeks” +%D

    (we need 11/02/10 for the format)

    So, in the above, forget that math and substitute the above, or something like “+10 days” or whatever.

    Just out of curiosity, where did you find documentation of the date STRING codes? (Not in the man file. Maybe I should have looked in the info?)

  5. #5 RSG
    October 20, 2010

    The date string codes can be accessed by “date –help”.

  6. #6 Greg Laden
    October 20, 2010

    RSG, sorry, no. man date and date –help do not indicate the required information used by Nemo.

  7. #7 Garry Knight
    October 20, 2010

    “what if you wanted ten days starting on December 20th? Then, the month goes back to 1, and the year is incremented.” How so? Surely those days would be the 20th thru 29th.

  8. #8 Greg Laden
    October 20, 2010

    I meant 14 days.

  9. #9 Nemo
    October 20, 2010

    I just experimented. I knew that GNU date had some powerful parsing abilities, but I didn’t and still don’t know exactly what it will take. The first few things I tried, like “two weeks from now”, didn’t work. But the GNU stuff often saves its best documentation for the “info” system, so maybe it’s there?

    This only works with GNU date, not e.g. the “date” that comes with OS X.

  10. #10 travc
    October 21, 2010

    bash scripting is very very useful and all…

    But you could just modify the actual gcalcli program (it’s in python).

    Line 227 in version 1.4 is:
    agendaLength = 5

    I assume that is the default value you want to be different.

    If you wanted to be cool about it, you could change the way it parses the “end” argument for the “agenda” option. I’d suggest something simple like a string starting with ‘+’ is parsed as a number of days from the start value. While you’re at it, you could have it accept unix time for start and/or end… maybe if the string is prefixed with ‘@’, or again getting cool, if the string is just an integer value without any extra stuff.

    Oh, and share the patch of course ;)

  11. #11 travc
    October 21, 2010

    Nemo,
    You may already know this, but to get pedantic…
    OSX is based on BSD, so a lot of the standard utilities are bit different. Generally BSD is leaner than GNU stuff, so the GNU tools have extra options but almost always handles all the BSD options.

    Anyway, throwing in “OSX” or “BSD” into web-searches for documentation can be useful. I frequently write stuff on my desktop (Ubuntu) and get annoyed by it not working on my laptop (OSX).

  12. #12 Greg Laden
    October 21, 2010

    travc: I thought about that, but is beyond me. You should do it! Anyway, what you are suggesting is actually much preferable to a bash script, because, at least I’d argue, these small changes would enhance but not bloat the program. Just bringing existing functionality in line with existing usage. Otherwise, a bash (or other) script might be better because of the one well made tool per job thingie. But really, my script is a wrapper, not a tool.

    Regarding OSX, etc.: I’ll note that Dave Taylor now develops and tests on his Mac for his column in Linux Journal. Which makes me feel a little funny but I suppose it’s OK.

  13. #13 GrouchyGaijin
    Sweden
    March 11, 2014

    Thanks man,
    This is exactly what I set out to do when I found your post.

Current ye@r *