diff options
| author | Jörg Sommrey <28217714+jo-37@users.noreply.github.com> | 2021-11-08 21:54:58 +0100 |
|---|---|---|
| committer | Jörg Sommrey <28217714+jo-37@users.noreply.github.com> | 2021-11-12 16:04:12 +0100 |
| commit | d8369f7f6a48b89f150482a90531edbb67d3d490 (patch) | |
| tree | 1eeecbb2577f20b1ed531fe599834655aba70e5e | |
| parent | 8efdb41631ac61515e268960162a0e8c4066d41c (diff) | |
| download | perlweeklychallenge-club-d8369f7f6a48b89f150482a90531edbb67d3d490.tar.gz perlweeklychallenge-club-d8369f7f6a48b89f150482a90531edbb67d3d490.tar.bz2 perlweeklychallenge-club-d8369f7f6a48b89f150482a90531edbb67d3d490.zip | |
Solution to task 1
| -rwxr-xr-x | challenge-138/jo-37/perl/ch-1.pl | 91 |
1 files changed, 91 insertions, 0 deletions
diff --git a/challenge-138/jo-37/perl/ch-1.pl b/challenge-138/jo-37/perl/ch-1.pl new file mode 100755 index 0000000000..da396433b8 --- /dev/null +++ b/challenge-138/jo-37/perl/ch-1.pl @@ -0,0 +1,91 @@ +#!/usr/bin/perl -s + +use v5.16; +use Test2::V0; +use DateTime; +use experimental 'signatures'; +# For testing only: +use DateTime::Duration; + +our ($tests, $examples); + +run_tests() if $tests || $examples; # does not return + +die <<EOS unless @ARGV; +usage: $0 [-examples] [-tests] [Y] + +-examples + run the examples from the challenge + +-tests + run some tests + +Y + Count workday in year Y. + +EOS + + +### Input and Output + +# Count workdays between Jan 1 of the given year and the next. +say workdays_int(DateTime->new(year => $ARGV[0]), + DateTime->new(year => $ARGV[0] + 1)); + + +### Implementation + +# Find the number of workdays in the interval from $start to (not +# including) $end. Expecting DateTime arguments. +sub workdays_int ($start, $end) { + return 0 if $start >= $end; + my $days = $end->delta_days($start)->in_units('days'); + # Sat is 5, Sun is 6. + my $dow = $start->day_of_week_0; + + # Every full week has 5 workdays. From the remaining days count + # working days only. + 5 * int($days / 7) + grep abs($dow + $_ - 5.5) > 1, 0 .. $days % 7 - 1; +} + + +### Examples and tests + +sub run_tests { + SKIP: { + skip "examples" unless $examples; + + is workdays_int(DateTime->new(year => 2021), + DateTime->new(year => 2022)), 261, 'example 1'; + is workdays_int(DateTime->new(year => 2020), + DateTime->new(year => 2021)), 262, 'example 2'; + } + + SKIP: { + skip "tests" unless $tests; + + my $m = DateTime->new( + year => 2021, + month => 11, + day => 8); # Challenge 138 published on Mon + my $d = DateTime::Duration->new(days => 1); + is workdays_int($m, $m), 0, 'same day'; + is workdays_int($m, $m + 4*$d), 4, 'Mon to Fri'; + is workdays_int($m, $m + 5*$d), 5, 'Mon to Sat'; + is workdays_int($m, $m + 6*$d), 5, 'Mon to Sun'; + is workdays_int($m + 3*$d, $m + 17*$d), 10, 'two full weeks'; + is workdays_int($m + 3*$d, $m + 5*$d), 2, 'Thu to Sat'; + is workdays_int($m + 3*$d, $m + 6*$d), 2, 'Thu to Sun'; + is workdays_int($m + 3*$d, $m + 7*$d), 2, 'Thu to Mon'; + is workdays_int($m + 4*$d, $m + 5*$d), 1, 'Fri to Sat'; + is workdays_int($m + 4*$d, $m + 6*$d), 1, 'Fri to Sun'; + is workdays_int($m + 4*$d, $m + 7*$d), 1, 'Fri to Mon'; + is workdays_int($m + 5*$d, $m + 7*$d), 0, 'Sat to Mon'; + is workdays_int($m + 6*$d, $m + 7*$d), 0, 'Sun to Mon'; + is workdays_int($m + 6*$d, $m + 12*$d), 5, 'Sun to Sat'; + is workdays_int($m + $d, $m), 0, 'end before start'; + } + + done_testing; + exit; +} |
