diff options
author | Matthew Somerville <matthew@mysociety.org> | 2020-06-16 16:04:21 +0100 |
---|---|---|
committer | M Somerville <matthew-github@dracos.co.uk> | 2020-09-02 14:56:41 +0100 |
commit | 32c80504c0f4aad36f7d9eaef5ff3f2f6d851b77 (patch) | |
tree | 2b13714b6419d58ee9025e831fbc02f657e4cfc8 /perllib/FixMyStreet/WorkingDays.pm | |
parent | 764a6b7f8056d55aeba4656cba279b27a60d6b1a (diff) |
[Zurich] Factor out working days calculator.
Diffstat (limited to 'perllib/FixMyStreet/WorkingDays.pm')
-rw-r--r-- | perllib/FixMyStreet/WorkingDays.pm | 78 |
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 + |