TL;DR

Here we are with TASK #1 from The Weekly Challenge #138. Enjoy!

The challenge

You are given a year, $year in 4-digits form. Write a script to calculate the total number of workdays in the given year. For the task, we consider, Monday - Friday as workdays. Example 1 Input:$year = 2021
Output: 261


Example 2

Input: $year = 2020 Output: 262  The questions I guess that the laconic assertion about what workdays are put an end to all questions: thereâ€™s no holidays, vacations, or other fancy stuff. Just plain weeks with 5 workdays each. Right?!? Iâ€™d probably ask if we can stick to dates in the Gregorian Calendar but I wonâ€™t wait for the answer and assume itâ€™s a yes. The solution I already said that Mohammad Sajid Anwar is amazing and this challenge shows how kind he is: we can reuse a lot from the previous week! We can look at the year by taking into consideration three parts: • the first week, considering it from the first day of the year up to and including the first Sunday; • the last week, considering it from the last Monday up to the end of the year • the rest of the year, which will by definition be composed by complete weeks only. We will stick to the convention that Monday is 1 up to Sunday that is 7. If the first day of the week is$m$, then the first week: • will contain$n = 8 - m$days, and • will contain$max(0, n - 2)$work days. Not convinced about that weird$max(\cdot)$? The first week wil always contain a Sunday, and possibly a Saturday, so whatever number of workdays will always have to exclude these two days. When we calculate$n - 2$, if we get a negative number then there are surely no workdays, so we use$max(\cdot)$to clamp the value to$0$. Itâ€™s a math trick. Similarly, the last week will have a number of days corresponding to the number of the last day. In this case, though, it will always start from Monday and increase with workdays up to a maximum of$5$. So, if the number of days in the week is$k$, the number of workdays in that week will be$min(k, 5)$, underlining that thereâ€™s a cap to 5 workdays in the week. Last, the core of the year will have a number$d$of says that is a multiple of$7$. Out of them, exactly$5$are workdaysâ€¦ so the computation is easy:$\frac{7}{5}d$. Enough talking, letâ€™s get to the Raku code: #!/usr/bin/env raku use v6; subset FullyGregorianYear of Int where * > 1582; sub workdays (FullyGregorianYear$y) {
my $bdow = Date.new($y, 1, 1).day-of-week;
my $edow = Date.new($y, 12, 31).day-of-week;
my $bdays = 8 -$bdow; # 1 - 7
my $ydays = 365 + ($bdow == $edow ?? 0 !! 1) -$bdays - $edow; return max($bdays - 2, 0) + ($ydays / 7 * 5).Int + min($edow, 5);
}

sub MAIN (FullyGregorianYear $y = 2021) { workdays($y).put }


Time for Perl now:

#!/usr/bin/env perl
use v5.24;
use warnings;
use experimental 'signatures';
no warnings 'experimental::signatures';
use Time::Local 'timegm';
use List::Util qw< min max >;

sub dow ($y,$m, $d) { (gmtime(timegm(1, 1, 1,$d, --$m,$y)))[6] }
sub workdays ($y) { my$bdow = dow($y, 1, 1); my$edow = dow($y, 12, 31); my$bdays = 8 - $bdow; # 1 - 7 my$ydays = 365 + ($bdow ==$edow ? 0 : 1) - $bdays -$edow;
return max($bdays - 2, 0) + ($ydays / 7 * 5) + min(\$edow, 5);
}

say workdays(shift // 2021);


I know, I knowâ€¦ Iâ€™m always translating stuff, but it works!!!

Comments? Octodon, , GitHub, Reddit, or drop me a line!