From 888feb7f717063d9b14224f3a779402ee963bfb7 Mon Sep 17 00:00:00 2001 From: Matt Miller Date: Fri, 7 Jun 2024 00:10:20 +0200 Subject: [PATCH 1/8] Move heavily used regexps to constants. We lose the ability to interpolate sub-expressions, but this avoids a recompilation on each evalulation which is approximatiely as expensive as doing the match itself. --- lib/Date/Utility.pm | 56 +++++++++++++++++++-------------------------- 1 file changed, 24 insertions(+), 32 deletions(-) diff --git a/lib/Date/Utility.pm b/lib/Date/Utility.pm index 90585c7..90bd4e0 100644 --- a/lib/Date/Utility.pm +++ b/lib/Date/Utility.pm @@ -407,7 +407,8 @@ sub _build_is_a_weekday { return ($self->is_a_weekend) ? 0 : 1; } -my $EPOCH_RE = qr/^-?[0-9]{1,13}$/; +use constant EPOCH_RE => qr/^-?[0-9]{1,13}$/o; +use constant EPOCH_MAYBE_FRAC => qr/^-?[0-9]{1,13}(?:\.[0-9]+)?$/o; =head2 new @@ -437,21 +438,14 @@ sub new { #strip other potential parameters $new_params = _parse_datetime_param($params_ref->{'datetime'}); } - } elsif ($params_ref =~ $EPOCH_RE) { - $new_params->{epoch} = $params_ref; + } elsif ($params_ref =~ EPOCH_MAYBE_FRAC) { + # We cannot handle fractional seconds, so truncated if necessary + $new_params->{epoch} = int($params_ref); } else { $new_params = _parse_datetime_param($params_ref); } - my $obj = $popular{$new_params->{epoch}}; - - if (not $obj) { - $obj = $self->_new($new_params); - $popular{$new_params->{epoch}} = $obj; - } - - return $obj; - + return $popular{$new_params->{epoch}} //= $self->_new($new_params); } =head2 _parse_datetime_param @@ -462,16 +456,17 @@ dd-mmm-yy ddhddGMT, dd-mmm-yy, dd-mmm-yyyy, dd-Mmm-yy hh:mm:ssGMT, YYYY-MM-DD, Y =cut -my $mon_re = qr/j(?:an|u[nl])|feb|ma[ry]|a(?:pr|ug)|sep|oct|nov|dec/i; -my $sub_second = qr/^[0-9]+\.[0-9]+$/; -my $date_only = qr/^([0-3]?[0-9])-($mon_re)-([0-9]{2}|[0-9]{4})$/; -my $time_only_tz = qr/([0-2]?[0-9])[h:]([0-5][0-9])(?::)?([0-5][0-9])?(?:GMT)?/; -my $date_with_time = qr /^([0-3]?[0-9])-($mon_re)-([0-9]{2}) $time_only_tz$/; -my $numeric_date_regex = qr/([12][0-9]{3})-?([01]?[0-9])-?([0-3]?[0-9])/; -my $numeric_date_only = qr/^$numeric_date_regex$/; -my $fully_specced = qr/^([12][0-9]{3})-?([01]?[0-9])-?([0-3]?[0-9])(?:T|\s)?([0-2]?[0-9]):?([0-5]?[0-9]):?([0-5]?[0-9])(\.[0-9]+)?(?:Z)?$/; -my $numeric_date_only_dd_mm_yyyy = qr/^([0-3]?[0-9])-([01]?[0-9])-([12][0-9]{3})$/; -my $datetime_yyyymmdd_hhmmss_TZ = qr/^$numeric_date_regex $time_only_tz$/; +# The below are for debugging interest, since `use constant` is a source pragma +# my $mon_re = qr/j(?:an|u[nl])|feb|ma[ry]|a(?:pr|ug)|sep|oct|nov|dec/i; +# my $time_only_tz = qr/([0-2]?[0-9])[h:]([0-5][0-9])(?::)?([0-5][0-9])?(?:GMT)?/; +# my $numeric_date_regex = qr/([12][0-9]{3})-?([01]?[0-9])-?([0-3]?[0-9])/; +use constant TEXT_DATE_ONLY => qr/^([0-3]?[0-9])-(j(?:an|u[nl])|feb|ma[ry]|a(?:pr|ug)|sep|oct|nov|dec)-([0-9]{2}|[0-9]{4})$/io; +use constant TEXT_DATE_TIME => + qr /^([0-3]?[0-9])-(j(?:an|u[nl])|feb|ma[ry]|a(?:pr|ug)|sep|oct|nov|dec)-([0-9]{2}) ([0-2]?[0-9])[h:]([0-5][0-9])(?::)?([0-5][0-9])?(?:GMT)?/io; +use constant NUMERIC_DATE_ONLY => qr/^([12][0-9]{3})-?([01]?[0-9])-?([0-3]?[0-9])$/o; +use constant NUMERIC_DATE_REV => qr/^([0-3]?[0-9])-([01]?[0-9])-([12][0-9]{3})$/o; +use constant NUMERIC_DATE_TIME => qr/^([12][0-9]{3})-?([01]?[0-9])-?([0-3]?[0-9]) ([0-2]?[0-9])[h:]([0-5][0-9])(?::)?([0-5][0-9])?(?:GMT)?$/o; +use constant FULLY_SPECCED => qr/^([12][0-9]{3})-?([01]?[0-9])-?([0-3]?[0-9])(?:T|\s)?([0-2]?[0-9]):?([0-5]?[0-9]):?([0-5]?[0-9])(\.[0-9]+)?(?:Z)?$/o; sub _parse_datetime_param { my $datetime = shift; @@ -483,14 +478,11 @@ sub _parse_datetime_param { # The ordering of these regexes is an attempt to match early # to avoid extra comparisons. If our mix of supplied datetimes changes # it might be worth revisiting this. - if ($datetime =~ $sub_second) { - # We have an epoch with sub second precision which we can't handle - return {epoch => int($datetime)}; - } elsif ($datetime =~ $date_only) { + if ($datetime =~ TEXT_DATE_ONLY) { $day = $1; $month = month_abbrev_to_number($2); $year = $3; - } elsif ($datetime =~ $date_with_time) { + } elsif ($datetime =~ TEXT_DATE_TIME) { $day = $1; $month = month_abbrev_to_number($2); $year = $3; @@ -499,22 +491,22 @@ sub _parse_datetime_param { if (defined $6) { $second = $6; } - } elsif ($datetime =~ $numeric_date_only) { + } elsif ($datetime =~ NUMERIC_DATE_ONLY) { $day = $3; $month = $2; $year = $1; - } elsif ($datetime =~ $numeric_date_only_dd_mm_yyyy) { + } elsif ($datetime =~ NUMERIC_DATE_REV) { $day = $1; $month = $2; $year = $3; - } elsif ($datetime =~ $fully_specced) { + } elsif ($datetime =~ FULLY_SPECCED) { $day = $3; $month = $2; $year = $1; $hour = $4; $minute = $5; $second = $6; - } elsif ($datetime =~ $datetime_yyyymmdd_hhmmss_TZ) { + } elsif ($datetime =~ NUMERIC_DATE_TIME) { $year = $1; $month = $2; $day = $3; @@ -1075,7 +1067,7 @@ Check if a given datetime is an epoch timestemp, i.e. an integer of under 14 dig =cut sub is_epoch_timestamp { - return (shift // '') =~ $EPOCH_RE; + return (shift // '') =~ EPOCH_RE; } =head2 is_ddmmmyy From e6c89a79e17a43bae1d40eb64ce709f24a08afe7 Mon Sep 17 00:00:00 2001 From: Matt Miller Date: Fri, 7 Jun 2024 10:23:34 +0200 Subject: [PATCH 2/8] Drop LRU cache FETCH and STORE operations can be surprisingly expensive with at tied LRU cache. In fact, they are slower than just building a new object. On the other hand, there may be cached attribute build which would also improve things for using those objects. I cannot believe that the hit rate for those will be able to dominate this storage and retrieval problem. --- Makefile.PL | 147 +++++++++++++++++++++----------------------- README.md | 1 - cpanfile | 1 - lib/Date/Utility.pm | 8 +-- 4 files changed, 73 insertions(+), 84 deletions(-) diff --git a/Makefile.PL b/Makefile.PL index 43656ad..04b388c 100644 --- a/Makefile.PL +++ b/Makefile.PL @@ -1,4 +1,4 @@ -# This file was automatically generated by Dist::Zilla::Plugin::MakeMaker v6.024. +# This file was automatically generated by Dist::Zilla::Plugin::MakeMaker v6.032. use strict; use warnings; @@ -7,87 +7,82 @@ use 5.010000; use ExtUtils::MakeMaker 7.64; my %WriteMakefileArgs = ( - "ABSTRACT" => "A class that represents a datetime in various format", - "AUTHOR" => "DERIV ", - "CONFIGURE_REQUIRES" => { - "ExtUtils::MakeMaker" => "7.64" - }, - "DISTNAME" => "Date-Utility", - "LICENSE" => "perl", - "MIN_PERL_VERSION" => "5.010000", - "NAME" => "Date::Utility", - "PREREQ_PM" => { - "Carp" => 0, - "DateTime" => 0, - "DateTime::TimeZone" => 0, - "Moose" => 0, - "POSIX" => 0, - "Scalar::Util" => 0, - "Syntax::Keyword::Try" => 0, - "Tie::Hash::LRU" => 0, - "Time::Duration::Concise::Localize" => "2.5", - "Time::Local" => 0, - "Time::Piece" => 0, - "feature" => 0, - "strict" => 0, - "warnings" => 0 - }, - "TEST_REQUIRES" => { - "ExtUtils::MakeMaker" => 0, - "File::Spec" => 0, - "IO::Handle" => 0, - "IPC::Open3" => 0, - "Test::CheckDeps" => "0.010", - "Test::Exception" => 0, - "Test::MockTime" => "0.15", - "Test::More" => "0.98", - "Test::Most" => "0.22", - "Test::NoWarnings" => 0, - "charnames" => 0 - }, - "VERSION" => "1.12", - "test" => { - "TESTS" => "t/*.t" - } -); - + "ABSTRACT" => "A class that represents a datetime in various format", + "AUTHOR" => "binary.com ", + "CONFIGURE_REQUIRES" => {"ExtUtils::MakeMaker" => "7.64"}, + "DISTNAME" => "Date-Utility", + "LICENSE" => "perl", + "MIN_PERL_VERSION" => "5.010000", + "NAME" => "Date::Utility", + "PREREQ_PM" => { + "Carp" => 0, + "DateTime" => 0, + "DateTime::TimeZone" => 0, + "Moo" => 0, + "Moose" => 0, + "POSIX" => 0, + "Scalar::Util" => 0, + "Syntax::Keyword::Try" => 0, + "Time::Duration::Concise::Localize" => "2.5", + "Time::Local" => 0, + "Time::Piece" => 0, + "constant" => 0, + "feature" => 0, + "strict" => 0, + "warnings" => 0 + }, + "TEST_REQUIRES" => { + "ExtUtils::MakeMaker" => 0, + "File::Spec" => 0, + "IO::Handle" => 0, + "IPC::Open3" => 0, + "Test::CheckDeps" => "0.010", + "Test::Exception" => 0, + "Test::MockTime" => "0.15", + "Test::More" => "0.98", + "Test::Most" => "0.22", + "Test::NoWarnings" => 0, + "charnames" => 0 + }, + "VERSION" => "1.12", + "test" => {"TESTS" => "t/*.t"}); my %FallbackPrereqs = ( - "Carp" => 0, - "DateTime" => 0, - "DateTime::TimeZone" => 0, - "ExtUtils::MakeMaker" => 0, - "File::Spec" => 0, - "IO::Handle" => 0, - "IPC::Open3" => 0, - "Moose" => 0, - "POSIX" => 0, - "Scalar::Util" => 0, - "Syntax::Keyword::Try" => 0, - "Test::CheckDeps" => "0.010", - "Test::Exception" => 0, - "Test::MockTime" => "0.15", - "Test::More" => "0.98", - "Test::Most" => "0.22", - "Test::NoWarnings" => 0, - "Tie::Hash::LRU" => 0, - "Time::Duration::Concise::Localize" => "2.5", - "Time::Local" => 0, - "Time::Piece" => 0, - "charnames" => 0, - "feature" => 0, - "strict" => 0, - "warnings" => 0 + "Carp" => 0, + "DateTime" => 0, + "DateTime::TimeZone" => 0, + "ExtUtils::MakeMaker" => 0, + "File::Spec" => 0, + "IO::Handle" => 0, + "IPC::Open3" => 0, + "Moo" => 0, + "Moose" => 0, + "POSIX" => 0, + "Scalar::Util" => 0, + "Syntax::Keyword::Try" => 0, + "Test::CheckDeps" => "0.010", + "Test::Exception" => 0, + "Test::MockTime" => "0.15", + "Test::More" => "0.98", + "Test::Most" => "0.22", + "Test::NoWarnings" => 0, + "Time::Duration::Concise::Localize" => "2.5", + "Time::Local" => 0, + "Time::Piece" => 0, + "charnames" => 0, + "constant" => 0, + "feature" => 0, + "strict" => 0, + "warnings" => 0 ); - -unless ( eval { ExtUtils::MakeMaker->VERSION(6.63_03) } ) { - delete $WriteMakefileArgs{TEST_REQUIRES}; - delete $WriteMakefileArgs{BUILD_REQUIRES}; - $WriteMakefileArgs{PREREQ_PM} = \%FallbackPrereqs; +unless (eval { ExtUtils::MakeMaker->VERSION(6.63_03) }) { + delete $WriteMakefileArgs{TEST_REQUIRES}; + delete $WriteMakefileArgs{BUILD_REQUIRES}; + $WriteMakefileArgs{PREREQ_PM} = \%FallbackPrereqs; } delete $WriteMakefileArgs{CONFIGURE_REQUIRES} - unless eval { ExtUtils::MakeMaker->VERSION(6.52) }; + unless eval { ExtUtils::MakeMaker->VERSION(6.52) }; WriteMakefile(%WriteMakefileArgs); diff --git a/README.md b/README.md index a1cca7c..f9dbef2 100644 --- a/README.md +++ b/README.md @@ -333,7 +333,6 @@ Returns a valid [Date::Utility](https://metacpan.org/pod/Date%3A%3AUtility) obje - [DateTime](https://metacpan.org/pod/DateTime) - [POSIX](https://metacpan.org/pod/POSIX) - [Scalar::Util](https://metacpan.org/pod/Scalar%3A%3AUtil) -- [Tie::Hash::LRU](https://metacpan.org/pod/Tie%3A%3AHash%3A%3ALRU) - [Time::Local](https://metacpan.org/pod/Time%3A%3ALocal) - [Syntax::Keyword::Try](https://metacpan.org/pod/Syntax%3A%3AKeyword%3A%3ATry) diff --git a/cpanfile b/cpanfile index 1e1f73b..c879546 100644 --- a/cpanfile +++ b/cpanfile @@ -3,7 +3,6 @@ requires 'DateTime'; requires 'Moose'; requires 'POSIX'; requires 'Scalar::Util'; -requires 'Tie::Hash::LRU'; requires 'Time::Duration::Concise::Localize', '2.5'; requires 'Time::Local'; requires 'Time::Piece'; diff --git a/lib/Date/Utility.pm b/lib/Date/Utility.pm index 90bd4e0..192504d 100644 --- a/lib/Date/Utility.pm +++ b/lib/Date/Utility.pm @@ -39,15 +39,11 @@ use Moose; use Carp qw( confess croak ); use POSIX qw( floor ); use Scalar::Util qw(looks_like_number); -use Tie::Hash::LRU; -use Time::Local qw(timegm); +use Time::Local qw(timegm); use Syntax::Keyword::Try; use Time::Duration::Concise::Localize; use POSIX qw(floor); -my %popular; -my $lru = tie %popular, 'Tie::Hash::LRU', 300; - has epoch => ( is => 'ro', isa => 'Int', @@ -445,7 +441,7 @@ sub new { $new_params = _parse_datetime_param($params_ref); } - return $popular{$new_params->{epoch}} //= $self->_new($new_params); + return $self->_new($new_params); } =head2 _parse_datetime_param From 338251f89d7dcd3ec0c778a7059a905bc7f1e246 Mon Sep 17 00:00:00 2001 From: Matt Miller Date: Fri, 7 Jun 2024 11:37:48 +0200 Subject: [PATCH 3/8] Move from Moose to Moo The major differences from a consumer perspective are: - `epoch` is no longer checked for proper type - Attempting to build an object from another object actually returns a new object, not the same one These are consequences of te diffeence between Moo and Moose. But they seem, to me, inconsequential. --- lib/Date/Utility.pm | 33 +++++++++++---------------------- 1 file changed, 11 insertions(+), 22 deletions(-) diff --git a/lib/Date/Utility.pm b/lib/Date/Utility.pm index 192504d..2cbd510 100644 --- a/lib/Date/Utility.pm +++ b/lib/Date/Utility.pm @@ -35,7 +35,7 @@ A class that represents a datetime in various format =cut -use Moose; +use Moo; use Carp qw( confess croak ); use POSIX qw( floor ); use Scalar::Util qw(looks_like_number); @@ -46,7 +46,6 @@ use POSIX qw(floor); has epoch => ( is => 'ro', - isa => 'Int', required => 1, ); @@ -94,8 +93,7 @@ has [qw( is_a_weekday ) ] => ( - is => 'ro', - lazy_build => 1, + is => 'lazy', ); sub _build__gmtime_attrs { @@ -403,24 +401,23 @@ sub _build_is_a_weekday { return ($self->is_a_weekend) ? 0 : 1; } -use constant EPOCH_RE => qr/^-?[0-9]{1,13}$/o; -use constant EPOCH_MAYBE_FRAC => qr/^-?[0-9]{1,13}(?:\.[0-9]+)?$/o; - =head2 new Returns a Date::Utility object. =cut -## no critic (ProhibitNewMethod) -sub new { - my ($self, $params_ref) = @_; +use constant EPOCH_RE => qr/^-?[0-9]{1,13}$/o; +use constant EPOCH_MAYBE_FRAC => qr/^-?[0-9]{1,13}(?:\.[0-9]+)?$/o; + +sub BUILDARGS { + my ($class, $params_ref) = @_; my $new_params = {}; if (not defined $params_ref) { $new_params->{epoch} = time; - } elsif (ref $params_ref eq 'Date::Utility') { - return $params_ref; + } elsif (ref $params_ref eq $class) { + $new_params->{epoch} = $params_ref->epoch; } elsif (ref $params_ref eq 'HASH') { if (not($params_ref->{'datetime'} or $params_ref->{epoch})) { confess 'Must pass either datetime or epoch to the Date object constructor'; @@ -441,7 +438,7 @@ sub new { $new_params = _parse_datetime_param($params_ref); } - return $self->_new($new_params); + return $new_params; } =head2 _parse_datetime_param @@ -1289,12 +1286,6 @@ sub create_trimmed_date { *_create_trimmed_date = \&create_trimmed_date; -no Moose; - -__PACKAGE__->meta->make_immutable( - constructor_name => '_new', - replace_constructor => 1 -); 1; __END__ @@ -1302,7 +1293,7 @@ __END__ =over 4 -=item L +=item L =item L @@ -1310,8 +1301,6 @@ __END__ =item L -=item L - =item L =item L From 6758a56481ba4d68c3dd8830d60320532036dbb0 Mon Sep 17 00:00:00 2001 From: Matt Miller Date: Tue, 11 Jun 2024 10:56:39 +0200 Subject: [PATCH 4/8] Improve BUILDARGS flow - Use early returns to make it obvious what we are doing - Don't preallocate a hashref which is directly returned - Reorder based on expected usage - Reduce checks inside a provided hashref --- lib/Date/Utility.pm | 42 ++++++++++++++++-------------------------- t/constructor.t | 4 ++-- 2 files changed, 18 insertions(+), 28 deletions(-) diff --git a/lib/Date/Utility.pm b/lib/Date/Utility.pm index 2cbd510..2519084 100644 --- a/lib/Date/Utility.pm +++ b/lib/Date/Utility.pm @@ -412,33 +412,23 @@ use constant EPOCH_MAYBE_FRAC => qr/^-?[0-9]{1,13}(?:\.[0-9]+)?$/o; sub BUILDARGS { my ($class, $params_ref) = @_; - my $new_params = {}; - - if (not defined $params_ref) { - $new_params->{epoch} = time; - } elsif (ref $params_ref eq $class) { - $new_params->{epoch} = $params_ref->epoch; - } elsif (ref $params_ref eq 'HASH') { - if (not($params_ref->{'datetime'} or $params_ref->{epoch})) { - confess 'Must pass either datetime or epoch to the Date object constructor'; - } elsif ($params_ref->{'datetime'} and $params_ref->{epoch}) { - confess 'Must pass only one of datetime or epoch to the Date object constructor'; - } elsif ($params_ref->{epoch}) { - #strip other potential parameters - $new_params->{epoch} = $params_ref->{epoch}; - - } else { - #strip other potential parameters - $new_params = _parse_datetime_param($params_ref->{'datetime'}); - } - } elsif ($params_ref =~ EPOCH_MAYBE_FRAC) { - # We cannot handle fractional seconds, so truncated if necessary - $new_params->{epoch} = int($params_ref); - } else { - $new_params = _parse_datetime_param($params_ref); - } - return $new_params; + # Bare `->new` + return +{epoch => time} unless $params_ref; + # Provided epoch + # We cannot handle fractional seconds, so truncated if necessary + return +{epoch => int($params_ref)} if ($params_ref =~ EPOCH_MAYBE_FRAC); + # Specified with hashref + if (ref $params_ref eq 'HASH') { + my $in_epoch = $params_ref->{epoch}; + my $in_dt = $params_ref->{datetime}; + + confess 'Must pass exactly one of datetime or epoch to the hashref Date object constructor' unless $in_dt xor $in_epoch; + #strip other potential parameters + return ($in_epoch) ? +{epoch => $in_epoch} : _parse_datetime_param($in_dt); + } + return +{epoch => $params_ref->epoch} if ref $params_ref eq $class; + return _parse_datetime_param($params_ref); } =head2 _parse_datetime_param diff --git a/t/constructor.t b/t/constructor.t index aec4555..02ee04b 100755 --- a/t/constructor.t +++ b/t/constructor.t @@ -7,9 +7,9 @@ require Test::NoWarnings; use Date::Utility; use charnames qw(:full); -throws_ok { Date::Utility->new({}) } qr/Must pass either datetime or epoch/, 'empty parameters, no object'; +throws_ok { Date::Utility->new({}) } qr/Must pass exactly one of datetime or epoch/, 'empty parameters, no object'; # Faily stuff -throws_ok { Date::Utility->new({datetime => 'fake', epoch => 1}) } qr/Must pass only one of datetime or epoch/, 'both epoch and datetime'; +throws_ok { Date::Utility->new({datetime => 'fake', epoch => 1}) } qr/Must pass exactly one of datetime or epoch/, 'both epoch and datetime'; throws_ok { Date::Utility->new(datetime => 'fake', epoch => 1); } qr/Invalid datetime format/, 'params not in a hash ref'; throws_ok { Date::Utility->new({datetime => '991111'}); } qr/Invalid datetime format/, 'numeric string as supplied date time is neither 8 nor 14 chars long'; From 27eb7b4050500cc2badb5adcbd7d0e089cd3be0d Mon Sep 17 00:00:00 2001 From: Matt Miller Date: Tue, 11 Jun 2024 11:49:45 +0200 Subject: [PATCH 5/8] Alter match order This organization reflects ease of matching (shorter is better) and liklelihood of match (more often is better) --- lib/Date/Utility.pm | 20 +++++++++----------- 1 file changed, 9 insertions(+), 11 deletions(-) diff --git a/lib/Date/Utility.pm b/lib/Date/Utility.pm index 2519084..38abbc2 100644 --- a/lib/Date/Utility.pm +++ b/lib/Date/Utility.pm @@ -465,6 +465,14 @@ sub _parse_datetime_param { $day = $1; $month = month_abbrev_to_number($2); $year = $3; + } elsif ($datetime =~ NUMERIC_DATE_ONLY) { + $day = $3; + $month = $2; + $year = $1; + } elsif ($datetime =~ NUMERIC_DATE_REV) { + $day = $1; + $month = $2; + $year = $3; } elsif ($datetime =~ TEXT_DATE_TIME) { $day = $1; $month = month_abbrev_to_number($2); @@ -474,14 +482,6 @@ sub _parse_datetime_param { if (defined $6) { $second = $6; } - } elsif ($datetime =~ NUMERIC_DATE_ONLY) { - $day = $3; - $month = $2; - $year = $1; - } elsif ($datetime =~ NUMERIC_DATE_REV) { - $day = $1; - $month = $2; - $year = $3; } elsif ($datetime =~ FULLY_SPECCED) { $day = $3; $month = $2; @@ -496,9 +496,7 @@ sub _parse_datetime_param { $hour = $4; $minute = $5; $second = $6; - } - # Type constraints mean we can't ever end up in here. - else { + } else { confess "Invalid datetime format: $datetime"; } From be8e0ef038e1f965d48a428ef9fced4c2d21a23d Mon Sep 17 00:00:00 2001 From: Matt Miller Date: Thu, 13 Jun 2024 07:20:25 +0200 Subject: [PATCH 6/8] Update for CPAN release - Changes file updated - Makefile.PL updated by dzil --- Changes | 3 ++ Makefile.PL | 147 +++++++++++++++++++++++++++------------------------- 2 files changed, 80 insertions(+), 70 deletions(-) diff --git a/Changes b/Changes index fab6a91..33c6406 100644 --- a/Changes +++ b/Changes @@ -1,6 +1,9 @@ Revision history for Date-Utility {{$NEXT}} + Remove dependency on Tie::Hash::LRU + Switch dependency from Moose to Moo + Improve datatime parsing performance 1.11 2022-10-17 14:32:15+00:00 UTC - Replace Try::Tiny with Syntax::Keyword::Try diff --git a/Makefile.PL b/Makefile.PL index 04b388c..23f0fef 100644 --- a/Makefile.PL +++ b/Makefile.PL @@ -7,82 +7,89 @@ use 5.010000; use ExtUtils::MakeMaker 7.64; my %WriteMakefileArgs = ( - "ABSTRACT" => "A class that represents a datetime in various format", - "AUTHOR" => "binary.com ", - "CONFIGURE_REQUIRES" => {"ExtUtils::MakeMaker" => "7.64"}, - "DISTNAME" => "Date-Utility", - "LICENSE" => "perl", - "MIN_PERL_VERSION" => "5.010000", - "NAME" => "Date::Utility", - "PREREQ_PM" => { - "Carp" => 0, - "DateTime" => 0, - "DateTime::TimeZone" => 0, - "Moo" => 0, - "Moose" => 0, - "POSIX" => 0, - "Scalar::Util" => 0, - "Syntax::Keyword::Try" => 0, - "Time::Duration::Concise::Localize" => "2.5", - "Time::Local" => 0, - "Time::Piece" => 0, - "constant" => 0, - "feature" => 0, - "strict" => 0, - "warnings" => 0 - }, - "TEST_REQUIRES" => { - "ExtUtils::MakeMaker" => 0, - "File::Spec" => 0, - "IO::Handle" => 0, - "IPC::Open3" => 0, - "Test::CheckDeps" => "0.010", - "Test::Exception" => 0, - "Test::MockTime" => "0.15", - "Test::More" => "0.98", - "Test::Most" => "0.22", - "Test::NoWarnings" => 0, - "charnames" => 0 - }, - "VERSION" => "1.12", - "test" => {"TESTS" => "t/*.t"}); + "ABSTRACT" => "A class that represents a datetime in various format", + "AUTHOR" => "binary.com ", + "CONFIGURE_REQUIRES" => { + "ExtUtils::MakeMaker" => "7.64" + }, + "DISTNAME" => "Date-Utility", + "LICENSE" => "perl", + "MIN_PERL_VERSION" => "5.010000", + "NAME" => "Date::Utility", + "PREREQ_PM" => { + "Carp" => 0, + "DateTime" => 0, + "DateTime::TimeZone" => 0, + "Moo" => 0, + "Moose" => 0, + "POSIX" => 0, + "Scalar::Util" => 0, + "Syntax::Keyword::Try" => 0, + "Time::Duration::Concise::Localize" => "2.5", + "Time::Local" => 0, + "Time::Piece" => 0, + "constant" => 0, + "feature" => 0, + "strict" => 0, + "warnings" => 0 + }, + "TEST_REQUIRES" => { + "ExtUtils::MakeMaker" => 0, + "File::Spec" => 0, + "IO::Handle" => 0, + "IPC::Open3" => 0, + "Test::CheckDeps" => "0.010", + "Test::Exception" => 0, + "Test::MockTime" => "0.15", + "Test::More" => "0.98", + "Test::Most" => "0.22", + "Test::NoWarnings" => 0, + "charnames" => 0 + }, + "VERSION" => "1.12", + "test" => { + "TESTS" => "t/*.t" + } +); + my %FallbackPrereqs = ( - "Carp" => 0, - "DateTime" => 0, - "DateTime::TimeZone" => 0, - "ExtUtils::MakeMaker" => 0, - "File::Spec" => 0, - "IO::Handle" => 0, - "IPC::Open3" => 0, - "Moo" => 0, - "Moose" => 0, - "POSIX" => 0, - "Scalar::Util" => 0, - "Syntax::Keyword::Try" => 0, - "Test::CheckDeps" => "0.010", - "Test::Exception" => 0, - "Test::MockTime" => "0.15", - "Test::More" => "0.98", - "Test::Most" => "0.22", - "Test::NoWarnings" => 0, - "Time::Duration::Concise::Localize" => "2.5", - "Time::Local" => 0, - "Time::Piece" => 0, - "charnames" => 0, - "constant" => 0, - "feature" => 0, - "strict" => 0, - "warnings" => 0 + "Carp" => 0, + "DateTime" => 0, + "DateTime::TimeZone" => 0, + "ExtUtils::MakeMaker" => 0, + "File::Spec" => 0, + "IO::Handle" => 0, + "IPC::Open3" => 0, + "Moo" => 0, + "Moose" => 0, + "POSIX" => 0, + "Scalar::Util" => 0, + "Syntax::Keyword::Try" => 0, + "Test::CheckDeps" => "0.010", + "Test::Exception" => 0, + "Test::MockTime" => "0.15", + "Test::More" => "0.98", + "Test::Most" => "0.22", + "Test::NoWarnings" => 0, + "Time::Duration::Concise::Localize" => "2.5", + "Time::Local" => 0, + "Time::Piece" => 0, + "charnames" => 0, + "constant" => 0, + "feature" => 0, + "strict" => 0, + "warnings" => 0 ); -unless (eval { ExtUtils::MakeMaker->VERSION(6.63_03) }) { - delete $WriteMakefileArgs{TEST_REQUIRES}; - delete $WriteMakefileArgs{BUILD_REQUIRES}; - $WriteMakefileArgs{PREREQ_PM} = \%FallbackPrereqs; + +unless ( eval { ExtUtils::MakeMaker->VERSION(6.63_03) } ) { + delete $WriteMakefileArgs{TEST_REQUIRES}; + delete $WriteMakefileArgs{BUILD_REQUIRES}; + $WriteMakefileArgs{PREREQ_PM} = \%FallbackPrereqs; } delete $WriteMakefileArgs{CONFIGURE_REQUIRES} - unless eval { ExtUtils::MakeMaker->VERSION(6.52) }; + unless eval { ExtUtils::MakeMaker->VERSION(6.52) }; WriteMakefile(%WriteMakefileArgs); From 478ac6191c6dcba79b1032fc73e1a2d938ce5539 Mon Sep 17 00:00:00 2001 From: Matt Miller Date: Fri, 14 Jun 2024 08:28:39 +0200 Subject: [PATCH 7/8] Update dist.ini for DERIV --- dist.ini | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/dist.ini b/dist.ini index 5a891ee..045382f 100644 --- a/dist.ini +++ b/dist.ini @@ -1,8 +1,8 @@ name = Date-Utility -author = binary.com +author = deriv.com license = Perl_5 -copyright_holder = Binary Services Ltd -copyright_year = 2022 +copyright_holder = Deriv Services Ltd. +copyright_year = 2024 [@Author::DERIV] allow_dirty = lib/Date/Utility.pm From bd59a81062ee5fce178474a3a10f3045f719811a Mon Sep 17 00:00:00 2001 From: Matt Miller Date: Fri, 14 Jun 2024 08:31:38 +0200 Subject: [PATCH 8/8] Release Date-Utility 1.12 Remove dependency on Tie::Hash::LRU Switch dependency from Moose to Moo Improve datatime parsing performance --- Changes | 2 ++ Makefile.PL | 4 ++-- README.md | 2 +- lib/Date/Utility.pm | 2 +- 4 files changed, 6 insertions(+), 4 deletions(-) diff --git a/Changes b/Changes index 33c6406..95877a5 100644 --- a/Changes +++ b/Changes @@ -1,6 +1,8 @@ Revision history for Date-Utility {{$NEXT}} + +1.12 2024-06-14 08:30:42+02:00 Africa/Maputo Remove dependency on Tie::Hash::LRU Switch dependency from Moose to Moo Improve datatime parsing performance diff --git a/Makefile.PL b/Makefile.PL index 23f0fef..7efb7a0 100644 --- a/Makefile.PL +++ b/Makefile.PL @@ -8,7 +8,7 @@ use ExtUtils::MakeMaker 7.64; my %WriteMakefileArgs = ( "ABSTRACT" => "A class that represents a datetime in various format", - "AUTHOR" => "binary.com ", + "AUTHOR" => "deriv.com ", "CONFIGURE_REQUIRES" => { "ExtUtils::MakeMaker" => "7.64" }, @@ -46,7 +46,7 @@ my %WriteMakefileArgs = ( "Test::NoWarnings" => 0, "charnames" => 0 }, - "VERSION" => "1.12", + "VERSION" => "1.13", "test" => { "TESTS" => "t/*.t" } diff --git a/README.md b/README.md index f9dbef2..c3bb068 100644 --- a/README.md +++ b/README.md @@ -329,7 +329,7 @@ Returns a valid [Date::Utility](https://metacpan.org/pod/Date%3A%3AUtility) obje # DEPENDENCIES -- [Moose](https://metacpan.org/pod/Moose) +- [Moo](https://metacpan.org/pod/Moo) - [DateTime](https://metacpan.org/pod/DateTime) - [POSIX](https://metacpan.org/pod/POSIX) - [Scalar::Util](https://metacpan.org/pod/Scalar%3A%3AUtil) diff --git a/lib/Date/Utility.pm b/lib/Date/Utility.pm index 38abbc2..ad4f3df 100644 --- a/lib/Date/Utility.pm +++ b/lib/Date/Utility.pm @@ -11,7 +11,7 @@ Date::Utility - A class that represents a datetime in various format =cut -our $VERSION = '1.12'; +our $VERSION = '1.13'; =head1 SYNOPSIS