# ETOOBUSY ðŸš€ minimal blogging for the impatient

# PWC138 - Workdays

**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, Twitter, GitHub, Reddit, or drop me a line!*