#!/usr/bin/perl -w # # $Id: sumtime,v 1.9 2003/08/01 02:10:57 jmates Exp $ # # The author disclaims all copyrights and releases this script into the # public domain. # # Totals up short-hand time durations such as 3h20m. # # Run perldoc(1) on this file for additional documentation. require 5; use strict; my $VERSION; ($VERSION = '$Revision: 1.9 $ ') =~ s/[^0-9.]//g; my $duration; # how to convert various time units to seconds my %factor = ( y => 31536000, M => 2592000, w => 604800, d => 86400, h => 3600, m => 60, s => 1, ); # tie y, M to current year and month if possible eval { require Date::Calc; }; unless ($@) { my ($month, $year) = (localtime)[4, 5]; $year += 1900; $month++; $factor{y} = Date::Calc::Days_in_Year($year, 12) * $factor{d} or die "error: could not calculate days in year\n"; $factor{M} = Date::Calc::Days_in_Month($year, $month) * $factor{d} or die "error: could not calculate days in month\n"; } my $factors = join '', keys %factor; # parse command-line options use Getopt::Std; my %opts; getopts('h?', \%opts); help() if exists $opts{'h'} or exists $opts{'?'}; if (@ARGV) { $_ = "@ARGV"; parse_line(); } else { while () { parse_line(); } } sub parse_line { LOOP: { # match "3h" or "45 m" $duration += $1 * $factor{$2}, redo LOOP if /\G(\d+) ?([$factors])(?=\b|\d)/gco; # treat unmatched numbers as seconds $duration += $1, redo LOOP if /\G(\d+)/gc; # or skip to next interesting bit redo LOOP if /\G\D+/gc; } } die "error: no parseable duration found\n" unless defined $duration and $duration =~ /^\d+$/; print deltatimefmt($duration), "\n"; exit; sub deltatimefmt { my $difference = int(shift); return "0s" if $difference == 0; my $seconds = $difference % 60; $difference = ($difference - $seconds) / 60; my $minutes = $difference % 60; $difference = ($difference - $minutes) / 60; # my $hours = $difference; my $hours = $difference % 24; $difference = ($difference - $hours) / 24; my $days = $difference % 7; my $weeks = ($difference - $days) / 7; # better way to do this? my $temp = ($weeks) ? "${weeks}w " : ''; $temp .= ($days) ? "${days}d " : ''; $temp .= ($hours) ? "${hours}h " : ''; $temp .= ($minutes) ? "${minutes}m " : ''; $temp .= ($seconds) ? "${seconds}s" : ''; return $temp; } # a generic help blarb sub help { print <<"HELP"; Usage: $0 [opts] [time specifications] Totals up short hand time durations. Options for version $VERSION: -h/-? Display this message Run perldoc(1) on this script for additional documentation. HELP exit; } __END__ =head1 NAME sumtime - totals up short-hand time durations =head1 SYNOPSIS $ sumtime 27h 71s 1d 3h 1m 11s $ (echo 1m 2m; echo 3m 4m) | sumtime 10m =head1 DESCRIPTION =head2 Overview Short description of what script is intended to do. =head2 Normal Usage $ sumtime [options] [time specifications] Input is either taken from the data on the command line, or failing that, from STDIN. See L<"OPTIONS"> for details on the command line switches supported. =head1 OPTIONS This script currently supports the following command line switches: =over 4 =item B<-h>, B<-?> Prints a brief usage note. =back =head1 BUGS =head2 Reporting Bugs Newer versions of this script may be available from: http://sial.org/code/perl/ If the bug is in the latest version, send a report to the author. Patches that fix problems or add new features are welcome. =head2 Known Issues No known bugs. =head1 TODO Output formatting, e.g. raw seconds, or ability to select output time format (e.g. hours only, and so forth). Ability to set a default input factor, e.g. when passing in unadorned hours or minutes. =head1 SEE ALSO perl(1) =head1 AUTHOR Jeremy Mates, http://sial.org/contact/ =head1 COPYRIGHT The author disclaims all copyrights and releases this script into the public domain. =head1 VERSION $Id: sumtime,v 1.9 2003/08/01 02:10:57 jmates Exp $ =head1 SCRIPT CATEGORIES Utilities =cut