From e0d8bc56235f8bf5e1653db0d3da17e5fa3a3043 Mon Sep 17 00:00:00 2001 From: Alex 'AdUser' Z Date: Mon, 23 Jul 2018 23:15:41 +1000 Subject: [PATCH] + Subtitle::Utils : parse_timeshift() --- lib/Subtitle/Utils.pm | 33 +++++++++++++++++++++++++++++---- t/utils-timing.t | 15 ++++++++++++++- 2 files changed, 43 insertions(+), 5 deletions(-) diff --git a/lib/Subtitle/Utils.pm b/lib/Subtitle/Utils.pm index 991bc64..562addc 100644 --- a/lib/Subtitle/Utils.pm +++ b/lib/Subtitle/Utils.pm @@ -7,13 +7,13 @@ use base 'Exporter'; our @EXPORT_OK = qw( chomp_all strip_bom trim - make_timing parse_timing + make_timing parse_timeshift parse_timing round ); our %EXPORT_TAGS = ( string => [qw(chomp_all strip_bom trim)], - timing => [qw(make_timing parse_timing)], + timing => [qw(make_timing parse_timeshift parse_timing)], ); ## string functions @@ -47,11 +47,36 @@ sub make_timing { return ($hrs, $min, $sec, $msec); } +# recognized format [+-][[hh:]mm:]ss[.ms] +sub parse_timeshift { + my ($str) = @_; + my $ts = { sign => '+', hrs => 0, min => 0, sec => 0 }; + + return unless defined $str; + + while(1) { + if ($str =~ s<^([+-])><>o) { $ts->{sign} = $1; } + if ($str =~ s<^([0-9](?:\.\d{1,3})?)$><>o) { $ts->{sec} = $1; } + if ($str =~ s<([0-5][0-9](?:\.\d{1,3})?)$><>o) { $ts->{sec} = $1; } + if ($str =~ s<^([0-9]):$><>o) { $ts->{min} = $1; } + if ($str =~ s<([0-5][0-9]):$><>o) { $ts->{min} = $1; } + if ($str =~ s<^(\d+):$><>o) { $ts->{hrs} = $1; } + last; + }; + + if ($str or $ts->{min} >= 60 or $ts->{sec} >= 60.0) { + return; # wrong time format + } + my $time = $ts->{sec} + $ts->{min} * 60 + $ts->{hrs} * 3600; + $time *= -1 if $ts->{sign} eq '-'; + return $time; +} + 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); + return unless $str =~ m/(\d+):(\d+):(\d+)[.,](\d+)/o; + my ($hrs, $min, $sec, $msec) = ($1, $2, $3, $4); if ($msec < 0 or $msec > 999) { return -1; # wrong mseconds part of timing } diff --git a/t/utils-timing.t b/t/utils-timing.t index 7f8a33b..46a5f6d 100644 --- a/t/utils-timing.t +++ b/t/utils-timing.t @@ -1,7 +1,7 @@ use strict; use warnings; -use Test::More tests => 11; +use Test::More tests => 21; use Subtitle::Utils qw(:timing); @@ -16,6 +16,19 @@ is(parse_timing('123:60:15.45'), -1); is(parse_timing('123:11:65.45'), -1); is(parse_timing('123:11:15.4500'), -1); +## parse_timeshift() +is(parse_timeshift('1'), +1.0); +is(parse_timeshift('-1.2'), -1.2); +is(parse_timeshift('+2:15'), +135.0); +is(parse_timeshift('+03:07.35'), +187.35); +is(parse_timeshift('4:05:17.312'), 14717.312); +# invalid timecodes +is(parse_timeshift('o.17'), undef); +is(parse_timeshift('-.05'), undef); +is(parse_timeshift('1:60'), undef); +is(parse_timeshift('57.4321'), undef); +is(parse_timeshift('1:62:03'), undef); + ## make_timing() my @ts = make_timing(8*3600 + 11*60 + 15 + 0.46); is($ts[0], 8);