Browse Source

* Subtitle::Utils : add *_timing() functions

master
Alex 'AdUser' Z 8 years ago
parent
commit
a955cc8173
  1. 50
      lib/Subtitle/BASE.pm
  2. 61
      lib/Subtitle/Utils.pm
  3. 44
      t/utils-timing.t

50
lib/Subtitle/BASE.pm

@ -19,56 +19,6 @@ sub log {
return 1;
}
sub parse_timing {
my ($self, $str) = @_;
my $time = 0.0;
return unless $str =~ m/(\d+):(\d+):(\d+)([.,])(\d+)/oi;
my ($hrs, $min, $sec, $delim, $msec) = ($1, $2, $3, $4, $5);
if ($msec < 0 or $msec > 999) {
$self->log(warn => "wrong mseconds part of timing: $msec");
return;
}
if ($sec < 0 or $sec > 59) {
$self->log(warn => "wrong seconds part of timing: $sec");
return;
}
if ($min < 0 or $min > 59) {
$self->log(warn => "wrong minutes part of timing: $sec");
return;
}
if ($hrs < 0) {
$self->log(warn => "wrong minutes part of timing: $sec");
return;
}
given (length("$msec")) {
when ("3") { $time += $msec * 0.001; }
when ("2") { $time += $msec * 0.01; }
when ("1") { $time += $msec * 0.1; }
default {
$self->log(error => "abnormal length of mseconds part");
return;
}
}
$time += $sec;
$time += $min * 60;
$time += $hrs * 60 * 60;
return $time;
}
sub build_timing {
my ($self, $time, $prec) = @_;
$prec //= 2;
my ($hrs, $min, $sec, $msec, $rest);
$hrs = int($time / 3600);
$rest = $time - ($hrs * 3600);
$min = int($rest / 60);
$rest = $rest - ($min * 60);
$sec = int($rest / 1);
$msec = sprintf "%.${prec}f", ($rest - ($sec * 1));
$msec =~ s/^0\.//o;
return sprintf($self->{timing_fmt}, $hrs, $min, $sec, $msec);
}
sub events {
my ($self) = @_;

61
lib/Subtitle/Utils.pm

@ -7,10 +7,12 @@ use base 'Exporter';
our @EXPORT_OK = qw(
chomp_all strip_bom trim
make_timing parse_timing
);
our %EXPORT_TAGS = (
string => [qw(chomp_all strip_bom trim)],
timing => [qw(make_timing parse_timing)],
);
@ -31,6 +33,48 @@ sub trim {
$_ =~ s/(^\s+|\s+$)//go for @_;
}
## timing functions
sub make_timing {
my ($time) = @_;
my ($hrs, $min, $sec, $msec, $rest);
$hrs = int($time / 3600);
$rest = $time - ($hrs * 3600);
$min = int($rest / 60);
$rest = $rest - ($min * 60);
$sec = int($rest / 1);
$msec = sprintf "%.0f", (($rest - $sec) * 1000);
return ($hrs, $min, $sec, $msec);
}
sub parse_timing {
my ($str) = @_;
my $time = 0.0;
return unless $str =~ m/(\d+):(\d+):(\d+)([.,])(\d+)/oi;
my ($hrs, $min, $sec, $delim, $msec) = ($1, $2, $3, $4, $5);
if ($msec < 0 or $msec > 999) {
return -1; # wrong mseconds part of timing
}
if ($sec < 0 or $sec > 59) {
return -1; # wrong seconds part of timing
}
if ($min < 0 or $min > 59) {
return -1; # wrong minutes part of timing
}
if ($hrs < 0) {
return -1; # wrong minutes part of timing
}
my $msec_len = length $msec;
if ($msec_len == 3) { $time += $msec * 0.001; }
elsif ($msec_len == 2) { $time += $msec * 0.01; }
elsif ($msec_len == 1) { $time += $msec * 0.1; }
else { return -1; } # abnormal length of mseconds part
$time += $sec;
$time += $min * 60;
$time += $hrs * 60 * 60;
return $time;
}
1;
=pod
@ -66,4 +110,21 @@ In-place strips Unicode's BOM (Byte Order Mark) from line.
In-place strips leading and trailing spaces from the given string
=head1 FUNCTIONS / TIMING
=head2 C<make_timing>
my ($hrs, $min, $sec, $msec) = make_timing($time);
printf "%d:%02d:02d.%s", $hrs, $min, $sec, $msec;
Takes float number of seconds and returns array with components of timing split by units.
=head2 C<parse_timing>
my $time = parse_timing($string);
Takes string like "HH:MM:SS.MSEC" and returns float number of seconds
On parse error returns -1
=cut

44
t/utils-timing.t

@ -0,0 +1,44 @@
use strict;
use warnings;
use Test::More tests => 11;
use Subtitle::Utils qw(:timing);
my ($timing, $time);
$timing = "123:11:15.459";
$time = parse_timing($timing);
is($time, (123 * 3600 + 11 * 60 + 15 + 0.459));
$timing = "123:11:15.45";
$time = parse_timing($timing);
is($time, (123 * 3600 + 11 * 60 + 15 + 0.450));
$timing = "123:11:15.4";
$time = parse_timing($timing);
is($time, (123 * 3600 + 11 * 60 + 15 + 0.400));
$timing = "123:11:15,4";
$time = parse_timing($timing);
is($time, (123 * 3600 + 11 * 60 + 15 + 0.400));
$timing = "123:60:15.45";
$time = parse_timing($timing);
is($time, -1);
$timing = "123:11:65.45";
$time = parse_timing($timing);
is($time, -1);
$timing = "123:11:15.4500";
$time = parse_timing($timing);
is($time, -1);
my ($hrs, $min, $sec, $msec);
($hrs, $min, $sec, $msec) = make_timing(8 * 3600 + 11 * 60 + 15 + 0.46);
is($hrs, 8);
is($min, 11);
is($sec, 15);
is($msec, 460);
Loading…
Cancel
Save