#!/usr/bin/env perl
# elapsed --- print elapsed time
# Author: Noah Friedman <friedman@splode.com>
# Created: 2003-08-08
# Public domain.

# $Id: elapsed,v 1.3 2018/11/19 01:47:46 friedman Exp $

# Commentary:

#     $ elapsed 1713607
#     19 days, 20 hours, 7 seconds
#
#     $ elapsed 106037343 1060388175
#     30 years, 3 months, 5 days, 17 hours, 27 minutes, 12 seconds

# Code:

use strict;

# One month is considered 30 days.
# One year is considered 365 days.
my @time_mult = (31536000, 2592000, 86400, 3600,   60,       1);
my @time_name = ("year",   "month", "day", "hour", "minute", "second");

my %timespec_unit = ( 'y' => 365 * 24 * 60 * 60,
                      'm' =>  30 * 24 * 60 * 60,
                      'w' =>   7 * 24 * 60 * 60,
                      'd' =>       24 * 60 * 60,
                      'h' =>            60 * 60,
                      'M' =>                 60,
                      's' =>                  1,
                      ''  =>                  1, );

sub to_sec
{
  local $_ = shift;
  my $sec = 0;

  while (m/\G\s*(\d+)\s*(\D)?\D*/g)
    {
      my $unit = $timespec_unit{$2} or die "$_: invalid unit specifier \"$2\"";
      $sec += $1 * $unit;
    }
  return $sec;
}

sub duration
{
  my $sec = shift;

  my $output = "";
  for (my $i = 0; $i < @time_mult; $i++)
    {
      my $val = int ($sec / $time_mult[$i]);
      $sec -= $val * $time_mult[$i];
      if ($val || ($output eq "" && $i == $#time_mult))
        {
          $output .= ", " unless $output eq "";
          $output .= "$val $time_name[$i]";
          $output .= "s" if ($val != 1);
        }
    }
  return $output;
}

sub main
{
  if (@ARGV == 2)
    {
      print duration( to_sec( $ARGV[1] ) - to_sec( $ARGV[0] ) ), "\n";
    }
  elsif (@ARGV == 1)
    {
      print duration( to_sec( $ARGV[0] ) ), "\n";
    }
  else
    {
      print STDERR "Usage: elapsed [s1] [s2] where t2 > t1\n";
      print STDERR "       elapsed [seconds]\n";
      exit (1);
    }
}

main ();

# eof
