Skip to content

Instantly share code, notes, and snippets.

@mjf
Created July 12, 2011 23:31
Show Gist options
  • Save mjf/1079421 to your computer and use it in GitHub Desktop.
Save mjf/1079421 to your computer and use it in GitHub Desktop.
Posix shell script to convert between time in human form and seconds
#! /bin/sh
# Posix shell script to convert between time in human form and date
# Copyright (C) 2011 Matous J. Fialka, <http://mjf.cz/>
# Released under the terms of The MIT License
if humantime=`humantime -f $@`
then
date -d "$humantime seconds" '+%F %T'
fi
#! /bin/sh
# Posix shell script to convert between time in human form and seconds
# Copyright (C) 2011 Matous J. Fialka, <http://mjf.cz/>
# Released under the terms of The MIT License
is_number()
{
[ -n "$1" -a $1 -eq $1 ] 2>/dev/null
}
human_time_to_seconds()
{
local arg1
local arg2
local ago
local result
ago=0
while [ -n "$1" ]
do
local saved="$1"
if is_number "$1"
then
if [ $1 -lt 0 ]
then
printf -- "use 'ago' for past\n" 1>&2
exit 1
fi
arg1=$1
shift
else
arg1=1
fi
arg2="$1"
if [ -n "$1" ]
then
shift
fi
case "$arg2" in
s|sec|secs|second|seconds)
result=$(( result + arg1 ))
;;
m|min|mins|minute|minutes)
result=$(( result + 60 * arg1 ))
;;
h|hr|hrs|hour|hours)
result=$(( result + 3600 * arg1 ))
;;
d|day|days)
result=$(( result + 86400 * arg1 ))
;;
w|week|weeks)
result=$(( result + 604800 * arg1 ))
;;
a|ago)
if is_number "$saved"
then
printf -- 'bad syntax\n' 1>&2
exit 1
fi
if [ $ago -eq 0 ]
then
ago=1
fi
;;
*)
printf -- 'bad syntax\n' 1>&2
exit 1
esac
unset saved
done
unset arg1
unset arg2
if [ $ago -eq 1 ]
then
result=$(( -result ))
fi
unset ago
printf -- '%d\n' $result
unset result
return 0
}
seconds_to_human_time()
{
if ! is_number "$1"
then
printf -- 'seconds expected\n' 1>&2
exit 1
fi
if [ $1 -eq 0 ]
then
printf -- '0 seconds\n'
return 0
fi
local ago=0
local arg=$1
if [ $arg -lt 0 ]
then
ago=1
arg=$(( -arg ))
fi
local field_order='week day hour minute second'
local first_field_passed=0
local result=0
for field in $field_order
do
if [ $first_field_passed -ne 0 ]
then
if [ $result -ne 0 ]
then
printf -- ' '
fi
else
first_field_passed=1
fi
case $field in
second)
result=$(( arg % 60 ))
;;
minute)
result=$(( arg / 60 % 60 ))
;;
hour)
result=$(( arg / 3600 % 24 ))
;;
day)
result=$(( arg / 86400 % 7 ))
;;
week)
result=$(( arg / 604800 ))
esac
if [ $result -ne 0 ]
then
printf -- '%d %s' $result $field
if [ $result -ne 1 -a $result -ne -1 ]
then
printf -- 's'
fi
fi
done
if [ $ago -eq 1 ]
then
printf -- ' ago'
fi
unset ago
unset field_order
unset first_field_passed
unset result
printf -- '\n'
return 0
}
case "$1" in
-h)
printf -- 'usage: humantime [-hf] <time>\n'
;;
-f)
shift
if [ $# -eq 0 ]
then
printf -- 'human form expected\n' 1>&2
exit 1
fi
human_time_to_seconds $@
;;
*)
while :
do
seconds_to_human_time "$1"
if [ -z "$2" ]
then
break
fi
shift
done
esac
exit 0
@mjf
Copy link
Author

mjf commented Jul 12, 2011

If only Gauss had had it!

$ humantime `seq 1 100` |xargs humantime -f
5050

OK, let's be more serious about it.

Example usage:

$ humantime 10 -100 1000 -10000 100000 -6478000
10 seconds
1 minute 40 seconds ago
16 minutes 40 seconds
2 hours 46 minutes 40 seconds ago
1 day 3 hours 46 minutes 40 seconds
10 weeks 4 days 23 hours 26 minutes 40 seconds ago

Well, do some more tests...

$ humantime -f 10 weeks 100 hours 1000 minutes 10000 seconds ago
-6478000

$ humantime -6478000
10 weeks 4 days 23 hours 26 minutes 40 seconds ago

Confused? Test it more further!

$ humantime -f 10 weeks 4 days 23 hours 26 minutes 40 seconds ago
-6478000

Everything looks just fine. Love it or hate it...

The other, simple, script called "humandate" works as follows.

Example usage:

$ humandate 10 weeks 5 hours 2 seconds ago
2011-05-06 03:43:08

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment