Linux – How to output a date/time as “20 minutes ago” or “9 days ago”, etc

conkydatelinux

I run rsync as a cron job and display the last backup via conky (i.e. "Last backup 2017 05 12 14:22:20"). I would like to display my last backup as "2 days ago" or "4 hours ago", rather than just displaying a static datestamp.

Is there any way to display a date/time using this sort of user-friendly output format? I've looked at man date, but cannot find anything about outputting a date in this sort of format. I see how to query a relative time or date with the -d flag, but cannot see how to get the output of date to include words like "yesterday", "3 days ago" etc.

Thanks!

Best Answer

Here's an extension of the_velour_fog's answer, adapted to use second/minute/day/month/year.

#!/usr/bin/env bash

last_run="2018-06-21T21:10:18-06:00"


function rel_fmt_low_precision() {
    local SEC_PER_MINUTE=$((60))
    local   SEC_PER_HOUR=$((60*60))
    local    SEC_PER_DAY=$((60*60*24))
    local  SEC_PER_MONTH=$((60*60*24*30))
    local   SEC_PER_YEAR=$((60*60*24*365))

    local last_unix="$(date --date="$1" +%s)"    # convert date to unix timestamp
    local now_unix="$(date +'%s')"

    local delta_s=$(( now_unix - last_unix ))

    if (( delta_s <  SEC_PER_MINUTE * 2))
    then
        echo "last run "$((delta_s))" seconds ago"
        return 
    elif (( delta_s <  SEC_PER_HOUR * 2))
    then
        echo "last run "$((delta_s / SEC_PER_MINUTE))" minutes ago"
        return 
    elif (( delta_s <  SEC_PER_DAY * 2))
    then
        echo "last run "$((delta_s / SEC_PER_HOUR))" hours ago"
        return 
    elif (( delta_s <  SEC_PER_MONTH * 2))
    then
        echo "last run "$((delta_s / SEC_PER_DAY))" days ago"
        return 
    elif (( delta_s <  SEC_PER_YEAR * 2))
    then
        echo "last run "$((delta_s / SEC_PER_MONTH))" months ago"
        return 
    else
        echo "last run "$((delta_s / SEC_PER_YEAR))" years ago"
        return 
    fi
}

rel_fmt_low_precision "`date`"
rel_fmt_low_precision "2018-06-21 21:10:18"
rel_fmt_low_precision "2018-06-21 20:10:18"
rel_fmt_low_precision "2018-05-21 21:10:18"
rel_fmt_low_precision "2017-06-21 20:10:18"
rel_fmt_low_precision "2016-06-21 20:10:18"

Here's how it decides which unit to use: it uses the largest unit that gives a number of at least two.

Example: If something happened 72 hours ago, it will output in days. If something happened exactly an hour ago, it will use minutes.

Related Question