aboutsummaryrefslogtreecommitdiffstats
path: root/perllib/FixMyStreet/WorkingDays.pm
diff options
context:
space:
mode:
authorMarius Halden <marius.h@lden.org>2021-10-07 13:32:40 +0200
committerMarius Halden <marius.h@lden.org>2021-10-07 13:32:40 +0200
commit09dacfc6b8bf62addeee16c20b1d90c2a256da96 (patch)
tree7caa2bf9e92227ab74448f9b746dd28bbcb81b2a /perllib/FixMyStreet/WorkingDays.pm
parent585e57484f9c6332668bf1ac0a6a3b39dbe32223 (diff)
parentcea89fb87a96943708a1db0f646492fbfaaf000f (diff)
Merge tag 'v3.1' into fiksgatami-devfiksgatami-dev
Diffstat (limited to 'perllib/FixMyStreet/WorkingDays.pm')
-rw-r--r--perllib/FixMyStreet/WorkingDays.pm78
1 files changed, 78 insertions, 0 deletions
diff --git a/perllib/FixMyStreet/WorkingDays.pm b/perllib/FixMyStreet/WorkingDays.pm
new file mode 100644
index 000000000..615b226c6
--- /dev/null
+++ b/perllib/FixMyStreet/WorkingDays.pm
@@ -0,0 +1,78 @@
+package FixMyStreet::WorkingDays;
+
+use Moo;
+
+=head1 FixMyStreet::WorkingDays
+
+Given a list of public holiday dates, creates an object that can be used to
+add/subtract days from a date, only counting working days (excluding public
+holidays and weekends).
+
+=over
+
+=cut
+
+has public_holidays => (
+ is => 'ro',
+ coerce => sub {
+ return { map { $_ => 1 } @{$_[0]} };
+ },
+);
+
+=item add_days
+
+Given a DateTime object and a number of days, returns a new DateTime object
+that many working days (excluding public holidays and weekends) later.
+
+=cut
+
+sub add_days {
+ my ( $self, $dt, $days, $subtract ) = @_;
+ $dt = $dt->clone;
+ while ( $days > 0 ) {
+ $dt->add ( days => $subtract ? -1 : 1 );
+ next if $self->is_public_holiday($dt);
+ next if $self->is_weekend($dt);
+ $days--;
+ }
+ return $dt;
+}
+
+=item sub_days
+
+Given a DateTime object and a number of days, returns a new DateTime object
+that many working days (excluding public holidays and weekends) earlier.
+
+=cut
+
+sub sub_days {
+ my $self = shift;
+ return $self->add_days(@_, 1);
+}
+
+=item is_public_holiday
+
+Given a DateTime object, return true if it is a public holiday.
+
+=cut
+
+sub is_public_holiday {
+ my ($self, $dt) = @_;
+ return $self->public_holidays->{$dt->ymd};
+}
+
+=item is_weekend
+
+Given a DateTime object, return true if it is a weekend.
+
+=cut
+
+sub is_weekend {
+ my ($self, $dt) = @_;
+ return $dt->dow > 5;
+}
+
+1;
+
+=back
+