Date/Time operations

Since I am not very fanatic of software homogeneity, when I write perl scripts and I need some function that performs certain task I use commands from console whenever it’s available even knowing that could be an equivalent Perl module available out there.

When your main goal is to get things done in the least amount of time, you cannot afford the time wasted in searching a library/module when the tools are just as far as calling a external program. This doesn’t mean that your code has to look horrible, it means that there’s no need to search for a (long) piece of code to attach it to yours in order to make your program homogeneous. After all, if you know how to write clean code, you will do it even if you mix 2323423423 languages inside your perl script.

Date/Time arithmetic using Perl.

I am aware of the existence of DateTime.pm but I have no experience using it. This was not the case with date command which finally led me to skip the learning curve and pass directly to the coding job.

The problem.

From a CDR entry containing end-datetime and duration, calculate the start-time, and transform the output using the YYMMDD/HHMMSS format.

[perl]

use strict;
use warnings;

sub main()
{
my $startTime = “02/01/2011 12:02:00”;
my $secs = 3650;

print “$startTime – $secs secs (YYMMDD HHMMSS) = @{ [ CalculateDate(“$startTime”, $secs) ] }”;
print “$secs secs in HHMMSS format is = @{ [ FormatTime($secs) ] } n”;
}

sub CalculateDate($$)
{
my ($date, $secs) = @_;

$date = FormatDateTime(`date –date “$date $secs seconds ago”`);

return $date;
}

sub FormatDateTime($)
{
return `date –date “$_[0]” +”%y%m%d %H%M%S”`;
}

sub FormatTime($)
{
my ($seconds, $hours, $mins, $secs) = shift;

$hours = padLeft(int($seconds / 3600));

$mins = padLeft($hours == 0 ? int($seconds / 60) : int(($seconds – ($hours * 3600)) / 60));

$secs = padLeft($hours == 0 && $mins == 0 ? $seconds : $seconds % 60);

return “$hours$mins$secs”;
}

sub padLeft($)
{
my $value = shift;
return (length “$value” == 1) ? “0$value” : $value;
}

main();
[/perl]

And the output is

[bash]
$ perl convert.pl
02/01/2011 12:02:00 – 3650 secs (YYMMDD HHMMSS) = 110201 110110
3650 secs in HHMMSS format is = 010050
[/bash]

Now, what I did not found searching the web was an easy method to convert seconds to a hour:minute:second format. This forced me to write my own algorithm which, hopefully, is bug free 😀
[perl]
sub FormatTime($)
{
my ($seconds, $hours, $mins, $secs) = shift;

$hours = padLeft(int($seconds / 3600));
$mins = padLeft($hours == 0 ? int($seconds / 60) : int(($seconds – ($hours * 3600)) / 60));
$secs = padLeft($hours == 0 && $mins == 0 ? $seconds : $seconds % 60);
return “$hours$mins$secs”;
}
[/perl]

What would a portability freak say?

It would probably say that my solution ignores the portability features of Perl. Yes, it is true but I don’t really care since my target is, and will always be, Unix based machines.