Mimsy Were the Borogoves

Hacks: Articles about programming in Python, Perl, PHP, and whatever else I happen to feel like hacking at.

Put a relative clock on your Desktop with GeekTool

Jerry Stratton, April 1, 2011

Today on the Desktop

In this example, the current time is today.

Most clocks show time in a complicated display of day, month, year, hours, minutes, and seconds. But how often have you just wanted to know whether the time is today, yesterday, or last week? This Python-based GeekTool geeklet will display the relative date on your desktop.

[toggle code]

  • #!/usr/bin/python
  • # -*- coding: utf-8 -*-
  • import optparse, datetime
  • days = ('yesterday', 'today', 'tomorrow')
  • parser = optparse.OptionParser('%prog')
  • parser.add_option('-d', '--day', type='choice', choices=days, default='today')
  • (options, slugs) = parser.parse_args()
  • today = datetime.datetime.fromordinal(datetime.date.today().toordinal())
  • future20 = datetime.datetime.now() + datetime.timedelta(minutes=20)
  • oneDay = datetime.timedelta(days=1)
  • oneWeek = datetime.timedelta(days=7)
  • if options.day == 'today':
    • date = today
  • elif options.day == 'tomorrow':
    • date = today + datetime.timedelta(days=1)
  • elif options.day == 'yesterday':
    • date = today - datetime.timedelta(days=1)
  • else:
    • date = future20
  • #the future
  • if date >= today:
    • if date == future20:
      • print "20 minutes into the future"
    • elif date == today:
      • print "Today"
    • elif date <= today + oneDay:
      • print "Tomorrow"
    • elif date <= today + oneWeek:
      • print "Next", date.strftime('%A')
    • elif (date.year == today.year and date.month != today.month) or (date.year == today.year+1 and date.month <= today.month):
      • print "Next", date.strftime('%B')
    • else:
      • timeToFuture = date - today
      • print "In", timeToFuture.days, "Days"
  • #the past
  • elif date >= today - oneDay:
    • print "Yesterday"
  • elif date >= today - oneWeek:
    • print "Last", date.strftime('%A')
  • elif (date.year == today.year and date.month != today.month) or (date.year == today.year-1 and date.month >= today.month):
    • print "Last", date.strftime('%B')
  • else:
    • timeToPast = today - date
    • print timeToPast.days, "Days Ago"
GeekTool Shell Options

I set the geeklet to refresh every 60 seconds to ensure that the relative clock is always correct.

If the current time is today, the script displays “today”. If it’s yesterday or tomorrow, then it displays that. If it’s within one week in either direction, it displays “next” or “last” and then the weekday name. And if it’s within the last or next twelve months, it does the same for the month name. Otherwise, it just says how many days to or since the current date.

The script uses Python’s datetime and timedelta classes to make these checks. I would have liked to use datetimes, dates, and timedeltas, but dates and datetimes are very different classes; there’s a datetime.date() method, for example, but no date.datetime(), and the datetime.today() method is really just datetime.now().

The timedelta class is used to create, basically, a time range to subtract from or add to a datetime; and when you subtract one datetime from another datetime, the result is a timedelta of the difference.

If you’d rather see how tomorrow relates to the current time, or how yesterday relates to the current time, specify “tomorrow” or “yesterday” to the --day option on the command line.

I haven’t had any need to display times, so I haven’t programmed it. If you end up needing times, however, it shouldn’t be difficult to extend the pattern I’ve started here to go down to hours or even minutes or seconds.

Keep this on your Desktop and you’ll never forget what today is!

  1. <- Auto-closing HTML
  2. fix_ampersands & abbreviations ->