Time::HiRes is not really helping me. I checked the CPAN for time packages many hours and found nothing.
Believe me I am using google, super search and cpan a lot before asking here. And I really want to learn from you and not that you provide me a full solution.
My goal was it to use a common module. But because I do not find one, I've written my own class.
Here you can see the code.
EDIT: Updated code and rewrote some paragraphs which described the code.
EDIT: Now I found a package which has milli and nanoseconds and has math and duration stuff: DateTime. I'll look deeper into it. Perhaps I can replace my own class by using this module. But it was cool to try overloading and writing an own module.
package My::TimeCalc;
use strict;
use overload ('""' => 'asString',
'+' => 'add',
'-' => 'subtract',
'*' => 'mult',
'/' => 'divide',
'<=>' => 'compare');
sub new
{
my ($class, $time_str) = @_;
my $seconds;
my $self = \$seconds;
bless($self, $class);
$time_str = defined($time_str) ? $time_str : "0";
return( $self->fromString($time_str) );
}
sub sec
{
my ($self) = @_;
return $$self;
}
sub asString
{
my ($self, $precision) = @_;
$precision = defined($precision)?$precision:2;
my $min = int(abs($$self) / 60.0);
my $sec = abs($$self) % 60.0;
my $frac = sprintf("%.${precision}f", abs($$self - int($$self))) *
+ 10**$precision;
my $time_str = "";
if( $$self < 0 ) { $time_str = "-"; }
$time_str .= "$min:" if( $min != 0 );
$time_str .= sprintf("%02d", $sec) if ( ($min != 0) || ($sec != 0)
+ );
$time_str .= "," . sprintf("%0${precision}d", $frac) if ( $frac !=
+ 0 );
if( ($min == 0) && ($sec == 0) && ($frac == 0) ) { $time_str = "0"
+; }
return( $time_str );
}
sub fromString
{
my ($self, $time_str) = @_;
# 1) min:sec,frac e.g. "5:29,11"
# 2) sec,frac e.g. "29,11"
# 3) sec e.g. "29"
# 4) ,frac e.g. ",11"
# 5) min:sec e.g. "5:29"
# Note: instead of "," you can also take "."!
# remove leading and trailing whitespace characters
$time_str =~ s/^\s+|\s+$//g;
# valid time string
if( ($time_str =~ m/^(?<min>\d+):(?<sec>\d+)(,|\.)(?<frac>\d+)$/)
+||
($time_str =~ m/^(?<sec>\d+)(,|\.)(?<frac>\d+)$/) ||
($time_str =~ m/^(?<sec>\d+)$/) ||
($time_str =~ m/^(,|\.)(?<frac>\d+)$/) ||
($time_str =~ m/^(?<min>\d+):(?<sec>\d+)$/) )
{
no warnings 'uninitialized'; # intention: undef treated as zer
+o
$$self = ($+{'min'} * 60.0) + $+{'sec'} + ($+{'frac'}/(10**len
+gth($+{'frac'})));
return( $self );
}
return( undef );
}
sub add
{
my ($self, $another) = @_;
my $result;
if( ref($another) eq "My::TimeCalc" )
{
$result = $self->sec() + $another->sec();
}
else
{
$result = $self->sec() + $another;
}
return( new My::TimeCalc($result) );
}
sub subtract
{
my ($self, $another) = @_;
my $result;
if( ref($another) eq "My::TimeCalc" )
{
$result = $self->sec() - $another->sec();
}
else
{
$result = $self->sec() - $another;
}
return( new My::TimeCalc($result) );
}
sub mult
{
my ($self, $another) = @_;
my $result;
if( ref($another) eq "My::TimeCalc" )
{
$result = $self->sec() * $another->sec();
}
else
{
$result = $self->sec() * $another;
}
return( new My::TimeCalc($result) );
}
sub divide
{
my ($self, $another) = @_;
my $result;
if( ref($another) eq "My::TimeCalc" )
{
$result = $self->sec() / $another->sec();
}
else
{
$result = $self->sec() / $another;
}
return( new My::TimeCalc($result) );
}
sub compare
{
my ($self, $another) = @_;
if( ref($another) eq "My::TimeCalc" )
{
return( $self->sec() <=> $another->sec() );
}
else
{
return( $self->sec() <=> $another );
}
}
1;
And now I come back to the example ($t1 * 4) + $t2.
use strict;
use warnings;
use My::TimeCalc;
my $t1 = new My::TimeCalc("16:51,12");
my $t2 = new My::TimeCalc("34:48,14");
my $t = ($t1 * 4) + $t2;
print($t,"\n"); # 102:12,62
It's the first time I used perl in an object oriented way and my first test with this new class were successful.
I'm sure that it is not good code. I want to change the parse and print function to common time formats. Perhaps here I can use an official module.
Would be great if you can give me feedback. What could I do better?
Thank you
Dirk
|