Unique arrays and
differing dates
Weekly challenge 183 — 19 September 2022
Week 183: 19 Sep 2022
You are given two dates, $date1
and $date2
in the format YYYY-MM-DD
.
Write a script to find the difference between the given dates in terms of years and days only.
Example 1 Input: $date1 = '2019-02-10' $date2 = '2022-11-01' Output: 3 years 264 days Example 2 Input: $date1 = '2020-09-15' $date2 = '2022-03-29' Output: 1 year 195 days Example 3 Input: $date1 = '2019-12-31' $date2 = '2020-01-01' Output: 1 day Example 4 Input: $date1 = '2019-12-01' $date2 = '2019-12-31' Output: 30 days Example 5 Input: $date1 = '2019-12-31' $date2 = '2020-12-31' Output: 1 year Example 6 Input: $date1 = '2019-12-31' $date2 = '2021-12-31' Output: 2 years Example 7 Input: $date1 = '2020-09-15' $date2 = '2021-09-16' Output: 1 year 1 day Example 8 Input: $date1 = '2019-09-15' $date2 = '2021-09-16' Output: 2 years 1 day
Date and time calculations are always complicated by leap years, and if time of day is included, by daylight saving time and in the extreme by leap seconds. Thankfully we only have leap years to consider in this task.
From the examples given we may deduce that a 'year' means the period between a 'date' (month and day) in
one year until the same date in the following year, which could be 365 or 366 days. So what we are looking for
is the number of 'years' from $date1
until the last 'date' preceding $date2
, and then the number of days
between that 'date' and $date2
.
Let's start with $date1
. Make a note of its month and day - call that $anniversary
.
Step forward day by day until you get to $date2
, incrementing $days
by one each day, or
if the date matches $anniversary
, increment $years
and set $days
to zero.
The only slightly messy bit is incrementing the date, but timelocal/localtime make that easy enough. Note that the Posix version of timelocal can handle signed 64 bit second values, so that covers any sensible dates.
If you're looking at really long gaps between $date1 and $date2 of course this method is relatively slow. But on my machine it comes up with the late Queen Elizabeth's lifespan as 96 years 140 days in just a few seconds.
#!/usr/bin/perl # Peter Campbell Smith - 2022-09-20 # PWC 183 task 2 use v5.28; use utf8; use warnings; use Time::Local qw(timelocal_posix); my (@tests, $test, $date1, $date2, $days, $years, $anniversary, $month_day); @tests = ( ['2019-02-10', '2022-11-01'], ['2020-09-15', '2022-03-29'], ['2019-12-31', '2020-01-01'], ['2019-12-01', '2019-12-31'], ['2019-12-31', '2020-12-31'], ['2019-12-31', '2021-12-31'], ['2020-09-15', '2021-09-16'], ['2019-09-15', '2021-09-16'], ['1926-04-21', '2022-09-08'], ['2022-09-20', '2022-09-19']); # loop over input tests for $test (@tests) { ($date1, $date2) = @$test; # output input say qq[\nInput: \$date1 = $date1\n \$date2 = $date2]; if ($date2 lt $date1) { say qq[\$date2 = $date2 precedes \$date1 = $date1]; next; } # initialise $years = 0; $days = 0; $anniversary = substr($date1, 5, 5); # month and day of date1 # increment date1 until it reaches date2 while ($date1 lt $date2) { $date1 = date_add($date1, 1); $month_day = substr($date1, 5, 5); # if month and day match date1, increment years and reset days to 0 if ($month_day eq $anniversary) { $years ++; $days = 0; # otherwise just increment days } else { $days ++; } } # format per Mohammad say qq[Output: ] . ($years == 0 ? '' : ($years == 1 ? '1 year ' : qq[$years years ])) . ($days == 0 ? '' : ($days == 1 ? '1 day' : qq[$days days])) } sub date_add { # (date, days) # adds days to date my (@tt); if ($_[0] =~ m|^(....)-(..)-(..)|) { @tt = localtime(timelocal_posix(0, 0, 12, $3, $2 - 1, $1 - 1900) + $_[1] * 86400); return sprintf('%04d-%02d-%02d', $tt[5] + 1900, $tt[4] + 1, $tt[3]); } else { return 0; } }
Input: $date1 = 2019-02-10 $date2 = 2022-11-01 Output: 3 years 264 days Input: $date1 = 2020-09-15 $date2 = 2022-03-29 Output: 1 year 195 days Input: $date1 = 2019-12-31 $date2 = 2020-01-01 Output: 1 day Input: $date1 = 2019-12-01 $date2 = 2019-12-31 Output: 30 days Input: $date1 = 2019-12-31 $date2 = 2020-12-31 Output: 1 year Input: $date1 = 2019-12-31 $date2 = 2021-12-31 Output: 2 years Input: $date1 = 2020-09-15 $date2 = 2021-09-16 Output: 1 year 1 day Input: $date1 = 2019-09-15 $date2 = 2021-09-16 Output: 2 years 1 day Input: $date1 = 1926-04-21 $date2 = 2022-09-08 Output: 96 years 140 days Input: $date1 = 2022-09-20 $date2 = 2022-09-19 $date2 = 2022-09-19 precedes $date1 = 2022-09-20
Any content of this website which has been created by Peter Campbell Smith is in the public domain