Skip to content

Instantly share code, notes, and snippets.

@shinenelson
Last active April 6, 2021 21:42
Show Gist options
  • Save shinenelson/40fd12e046f1d79dfc0890b17fde7f74 to your computer and use it in GitHub Desktop.
Save shinenelson/40fd12e046f1d79dfc0890b17fde7f74 to your computer and use it in GitHub Desktop.
Calculate duration between 2 epoch timestamps passed as arguments
#!/bin/bash
# This script calculates the duration between
# 2 epoch timestamps passed as arguments to it
# This script accepts only epoch timestamps
# because only the epoch timestamps are complete.
# Other timestamps may cause confusions.
# However, support for formats supported by `date'
# can be added in the future.
# Source liberated by @shinenelson at gist.github.com/shinenelson
# Read arguments
lt=$1
gt=$2
# Argument Validation
if [ $# -lt 2 ]; then
echo "That's not enough arguments."
echo "Please provide exactly 2 epoch timestamps"
exit 1
fi
if [ $# -gt 2 ]; then
echo "That's too many arguments."
echo "Please provide exactly 2 epoch timestamps"
exit $#
fi
if [ $1 -eq $2 ]; then
echo "That's the same timestamp repeated twice"
echo "The duration between them is 0 Millennia, 0 Centuries, 0 Years, 0 Days, 0 Hours, 0 Minutes, 0 Seconds, 0 Milliseconds, 0 Nanoseconds, ..."
echo "I could just keep going on and on, but I'd rather save my computational power for something productive."
echo "Do you see that the difference is zero?"
echo "If you wish to see me productive, give me some timestamps that has a difference of at least 1 second"
exit 255
fi
# Swap arguments if $1 is greater than $2
if [ $lt -gt $gt ]; then
tmp=$lt
lt=$gt
gt=$tmp
fi
diff=$(expr $gt - $lt) # Compute difference of timestamps
sec=$(expr $diff % 60) # % 60 % 24 % 365 % 100 % 1000) # Seconds
min=$(expr $diff / 60 % 60) # % 24 % 365 % 100 % 1000) # Minutes
hrs=$(expr $diff / 60 / 60 % 24) # % 365 % 100 % 1000) # Hours
days=$(expr $diff / 60 / 60 / 24 % 365) # % 100 % 1000) # Days
yrs=$(expr $diff / 60 / 60 / 24 / 365) # % 100 % 1000) # Years
# This script computes the centuries and millenia passed too.
# Because it can... arithmetically
# But then `date' doesn't support it, neither does digital time.
cen=$(expr $diff / 60 / 60 / 24 / 365 / 100 % 1000) # Centuries
mil=$(expr $diff / 60 / 60 / 24 / 365 / 100 / 1000) # Millenia
vars=(yrs days hrs min sec) # Array variable to iterate over each computed value
# Strings to be printed along with values
yrs_str="Year"
days_str="Day"
hrs_str="Hour"
min_str="Minute"
sec_str="Second"
for var in ${vars[@]}; do
var_str=$var"_str" # Compute variable string to be printed
[ $((${!var} / 10)) -eq 0 ] && eval $var="0${!var}" # Append 0 to single digit values
if [ ${!var} -gt 0 ]; then
if [ ${!var} -eq 1 ]; then
echo -n " ${!var} ${!var_str} " # Print value with singular value string
else
echo -n " ${!var} ${!var_str}s " # Print value with plural value string
fi
fi
done
echo # add newline after output
#!/usr/bin/env sh
# This script calculates the duration between 2 epoch timestamps
# passed as arguments to it
# This script accepts only epoch timestamps because only the epoch
# timestamps are complete. Other timestamps may cause confusions.
# It is a similar script to [epoch-duration.bash](epoch-duration.bash)
# but it borrows the logic from the `uptime` command from the `procps`
# package.
# https://gitlab.com/procps-ng/procps/-/blob/00ab5f0b/proc/whattime.c
# Why? Because the script needed a POSIX-compliant revamp
# But why re-invent? Because then it would be a refactor and would
# change pretty much the entire script. Then why not create a new
# script and retain the legacy?
# Read arguments
lt=${1}
gt=${2}
# Argument Validation
if [ $# -ne 2 ] || [ ${1} -eq ${2} ]; then
echo "Please provide exactly 2 epoch timestamps"
echo "with a difference of at least 1 second"
exit 1
fi
# Swap arguments if $1 is greater than $2
if [ ${lt} -gt ${gt} ]; then
tmp=${lt}
lt=${gt}
gt=${tmp}
fi
diff=$((${gt} - ${lt})) # Compute difference of timestamps)
# https://gitlab.com/procps-ng/procps/-/blob/00ab5f0b/proc/whattime.c#L71-74
dec=$((${diff} / (60 * 60 * 24 * 365 * 10)))
yrs=$((${diff} / (60 * 60 * 24 * 365) % 10))
wks=$((${diff} / (60 * 60 * 24 * 7) % 52))
days=$((${diff} / (60 * 60 * 24) % 7))
# https://gitlab.com/procps-ng/procps/-/blob/00ab5f0b/proc/whattime.c#L87-90
min=$((${diff} / 60))
hrs=$((${min} / 60))
hrs=$((${hrs} % 24))
min=$((${min} % 60))
# https://gitlab.com/procps-ng/procps/-/blob/00ab5f0b/proc/whattime.c#L118-154
comma_count=0
if [ ${dec} -ne 0 ]; then
if [ ${dec} -gt 1 ]; then
var_str="decades"
else
var_str="decade"
fi
printf "%d %s" "${dec}" "${var_str}"
comma_count=$(( ${comma_count} + 1 ))
fi
if [ ${yrs} -ne 0 ]; then
if [ ${yrs} -gt 1 ]; then
var_str="years"
else
var_str="year"
fi
if [ ${comma_count} -gt 0 ]; then
comma_print=", "
else
comma_print=""
fi
printf "%s%d %s" "${comma_print}" "${yrs}" "${var_str}"
comma_count=$(( ${comma_count} + 1 ))
fi
if [ ${wks} -ne 0 ]; then
if [ ${wks} -gt 1 ]; then
var_str="weeks"
else
var_str="week"
fi
if [ ${comma_count} -gt 0 ]; then
comma_print=", "
else
comma_print=""
fi
printf "%s%d %s" "${comma_print}" "${wks}" "${var_str}"
comma_count=$(( ${comma_count} + 1 ))
fi
if [ ${days} -ne 0 ]; then
if [ ${days} -gt 1 ]; then
var_str="days"
else
var_str="day"
fi
if [ ${comma_count} -gt 0 ]; then
comma_print=", "
else
comma_print=""
fi
printf "%s%d %s" "${comma_print}" "${days}" "${var_str}"
comma_count=$(( ${comma_count} + 1 ))
fi
if [ ${hrs} -ne 0 ]; then
if [ ${hrs} -gt 1 ]; then
var_str="hours"
else
var_str="hour"
fi
if [ ${comma_count} -gt 0 ]; then
comma_print=", "
else
comma_print=""
fi
printf "%s%d %s" "${comma_print}" "${hrs}" "${var_str}"
comma_count=$(( ${comma_count} + 1 ))
fi
if [ ${min} -ne 0 ] || [ ${min} -eq 0 -a ${diff} -lt 60 ]; then
if [ ${min} -ne 1 ]; then
var_str="minutes"
else
var_str="minute"
fi
if [ ${comma_count} -gt 0 ]; then
comma_print=", "
else
comma_print=""
fi
printf "%s%d %s" "${comma_print}" "${min}" "${var_str}"
comma_count=$(( ${comma_count} + 1 ))
fi
echo # add newline after output
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment