Perl Weekly Challenge #237 - Carpe Diem

Hello everybody! Welcome back to the Weekly Challenge series, where today we're working on dates again. I like these challenges in particular, for some reason. In this case, we have a rather simple challenge except that it gives us less common date formats than usual.

The challenge gives us a year, month, week(day) of the month, and day of week. Now DateTime provides us with get operations to find WoM and DoW info, but it doesn't provide set operations. For that we need to do a little math. Here's the code below:

#!/usr/bin/perl
use v5.36;
use DateTime;

my ($year, $month, $wom, $dow) = @ARGV;
my $obj = DateTime->new(year => $year, month => $month, day => 1);
if($obj->dow() <= $dow) {
    $obj->add(days => (($dow - $obj->dow()) + (($wom - 1) * 7)));
} else {
    $obj->add(days => ((7 - ($obj->dow() - $dow)) + (($wom - 1) * 7)));
}
say 0 and exit if $obj->month() != $month;
say $obj->day();

We only really have to handle wrapping and assessing whether that day is possible within the month. We use DateTime because it just makes sense, and we create an object with the first day of the month that we're using. If the day is the same or earlier in the week (to save code complexity) than the day we're looking for, we shift the difference and add that to the number of weeks later that the target day is on. If the 1st of the month is later in the week than our target day, we wrap and still shift $wom-1 weeks later.

If our addition to the date means we're now in a different month from the intended one we print out 0 and exit, otherwise we say what the date is now.

It's that simple! Just 12 lines including file header and boilerplate. Hope to see you next week!

Leave a comment

About oldtechaa

user-pic Just getting back into Perl programming. I have a personal project, SeekMIDI, a small graphical MIDI sequencer.