Counting down to the holidays Unix-style

countdown steven depolo
Credit: flickr / Steven Depolo

Counting down the days until Christmas or the beginning of Kwanzaa? Your Unix system can help with that. Let's look at the commands that you would use to get a talking cow reminding you about an upcoming holiday or an important event.

$ countdown
 ___________________
< 3 days until Xmas >
 -------------------
        \   ^__^
         \  (oo)\_______
            (__)\       )\/\
                ||----w |
                ||     ||

And, for the technique we're going to be looking at, your choice of holiday or special event is up to you.

$ countdown2
 ______________________
< 4 days until Kwanzaa >
 ----------------------
        \   ^__^
         \  (oo)\_______
            (__)\       )\/\
                ||----w |
                ||     ||

The first thing you need is a very unusual Unix tool that allows you to, well, put words into a cow's mouth. That tool is called "cowsay" and it's one that you can install on many Linux systems with this yum command:

$ sudo yum install cowsay

Once cowsay is installed on your system, you can have the cow say things to you in much the same way as you would use the echo command.

$ cowsay What am I thinking?
 _____________________
< What am I thinking? >
 ---------------------
        \   ^__^
         \  (oo)\_______
            (__)\       )\/\
                ||----w |
                ||     ||

OK, so this isn't going to be your favorite Unix tool, but it might break the monotony on some days when you're working on a pile of very tedious tasks.

Next comes the counting down part. For that, we're going to use a special function of the date command that allows you to represent a date in the "day of year" format. For example, in this format, January 1st would be day 001.

$ date -d 1-Jan +%j
001

Today's date would be translated to this format using this command:

$ date +%j
356

By specifying our date of interest in the "day of year" format, we can easily calculate the number of days we have left to go before the special day that we're so busy anticipating and have the reminder spring forth from the mouth of our little cow.

$ alias countdown='cowsay $(($(date -d 25-Dec +%j) - $(date +%j))) days until Xmas'
$ countdown
 ___________________
< 3 days until Xmas >
 -------------------
        \   ^__^
         \  (oo)\_______
            (__)\       )\/\
                ||----w |
                ||     ||

Doing the same thing for the start of Kwanzaa requires only a tiny change in our alias.

$ alias countdown2='cowsay $(($(date -d 26-Dec +%j) - $(date +%j))) days until Kwanzaa'

Using this little calculation won't work for just any holiday or special event, however, and the reason for this requires a little more insight into how the calculation is being performed. Say what you really want to know is how many days until April Fools Day. Using the same sort of command, we run into two issues. First, April Fools Day isn't until next year. So we have to make sure we don't compute the difference between 091 and today (356). That would give us a fairly large negative number!

$ date +%j
356
$ date -d 1-Apr +%j
091

That's not too hard to fix. We add 365 to our calculation -- 366 if our target date is after April 29th on any year that, like 2016, is leap year.

$ alias countdown3='cowsay $(($(date -d 1-Apr +%j) + 365 - $(date +%j))) days until April Fools Day'

But, depending on the target date you're working with, you might just see something like this:

$ countdown3
-bash: 091: value too great for base (error token is "091")

"What's going on here?" you may ask. And, after a little experimentation, you might notice that you get the same error when you do this:

$ echo $((091))
-bash: 091: value too great for base (error token is "091")

As it turns out, the 0 at the beginning of the number 091 is interpreted as meaning that the number is octal. Do the same thing for a number like 77 and you'll see how the number is converted to decimal.

$ echo $((077))
63

So, to ensure that our calculation is going to work for April Fools Day or any arbitrary day, we need to make sure that our "day of year" date doesn't begin with a 0. If we add a sed command to strip off any leading zeroes, we should be able to count down to any special day next year.

$ alias countdown3='cowsay $(($(date -d 1-Apr +%j | sed "s/^0*//" ) + 365 - $(date +%j))) days until April Fools Day'
$ countdown3
 ________________________________
< 100 days until April Fools Day >
 --------------------------------
        \   ^__^
         \  (oo)\_______
            (__)\       )\/\
                ||----w |
                ||     ||

Using a tool like this, you won't be likely to forget Talk Like a Pirate Day, Pi Day, Sysadmin Day, or your wedding anniversary. And, hey, we only have 100 days until April Fools Day. It's time to start planning your Unix pranks!

This article is published as part of the IDG Contributor Network. Want to Join?

The brave new world of Windows 10 license activation
View Comments
Join the discussion
Be the first to comment on this article. Our Commenting Policies