Good times

People sometimes say “morning” or “evening” on IRC for a time zone unlike my own. Here’s a bash one-liner that emits the correct time-of-day generalization based on the datetime settings of the machine you run it on.

case $(($(date +%H)/6)) in 0|1)m="morning";;2)m="afternoon";;3)m="night";;esac; echo good $m

How?

First, check if the feature is already implemented. man date and try not to giggle. Search for morning. It’s not there.

So we need a switch/case:

case EXPRESSION in CASE1) COMMAND-LIST;; CASE2) COMMAND-LIST;; ... CASEN) COMMAND-LIST;; esac

And the expression we’re switching on will be the current hour:

date +%H

My first attempt does not work because I expect too much of Bash:

case $(date +%H) in [0-12]) m="morning";;[13-18]) m="afternoon";;[19-21])m="evening";;*)m="night";;esac; echo $m

It fails because the “ranges” are actually just shell patterns.

I could either expand my script to handle all hours, or compress ranges of hours down into something that can be expressed by patterns. The latter sounds shorter and easier. I want to divide the current hour by 6, to tell which quarter of the day I’m in.

A bit of trial and error reveals that a syntax that allows me to do math on the result of date is:

$(( $(date +%H)/6 ))

because it’s shorthand for assigning the result of the math into a variable and using it immediately. This only adds a few characters to the one-liner:

case $(($(date +%H)/6)) in 0|1)m="morning";;2)m="afternoon";;3)m="night";;esac; echo $m

That’s it!