Camel
Peter
Peter Campbell Smith

Days to decompress

Weekly challenge 326 — 16 June 2025

Week 326: 16 Jun 2025

Task 1

Task — Day of the year

You are given a date in the format YYYY-MM-DD. Write a script to find the day number of the year that the given date represents.

Examples


Example 1
Input: $date = '2025-02-02'
Output: 33
The 2nd Feb, 2025 is the 33rd day of the year.

Example 2
Input: $date = '2025-04-10'
Output: 100

Example 3
Input: $date = '2025-09-07'
Output: 250

Analysis

There are many ways to meet this challenge, and they fall into two categories: use a module or do it entirely in Perl. Which is better? I would say that in almost any imaginable real-life use case, it doesn't matter - the time taken for that calculation will be insignificant in the scale of whatever else you are doing with the data.

Also, if you are handling dates in bulk, they are very probably held in a database, from which you can probably extract them in the day-of-year format using SQL fuctions. For example, MariaDB and MySQL have a DAYOFYEAR() function and Oracle has YearDay().

Nevertheless, my solution offers two results, one using Date::Calc 'Day_of_Year' and the other using simple Perl.

Both of these assume the Gregorian calendar and will require changes if you are handling dates prior to the date that was adopted in your jurisdiction. However, with that proviso, both work from
0001-01-01 to 9999-12-31.

Try it 

Try running the script with any input:



example: 2025-12-25

Script


#!/usr/bin/perl

# Blog: http://ccgi.campbellsmiths.force9.co.uk/challenge

use v5.26;    # The Weekly Challenge - 2025-06-16
use utf8;     # Week 326 - task 1 - Day of the year
use warnings; # Peter Campbell Smith
binmode STDOUT, ':utf8';
use Encode;

day_of_the_year('2025-02-02');
day_of_the_year('2025-04-10');
day_of_the_year('2025-09-07');
day_of_the_year('1900-12-31');  # not a leap year
day_of_the_year('2000-12-31');  # was a leap year
day_of_the_year('1819-05-24');  # Queeen Victoria born
day_of_the_year('2047-11-09');  # my 100th birthday
day_of_the_year('1752-12-31');
day_of_the_year('0001-01-01');
day_of_the_year('9999-12-31');

# today
my @t = localtime;
day_of_the_year(sprintf('%04d-%02d-%02d', $t[5] + 1900, $t[4] + 1, $t[3]));

sub day_of_the_year {
    
    my($y, $m, $d, $day_of_year, @days_in_month);
    
    # initialise
    say qq[\nInput:    \$date = '$_[0]'];
    ($y, $m, $d) = $_[0] =~ m|(\d\d\d\d)\-(\d\d)\-(\d\d)|;
    
    # method 1 - use a module
    use Date::Calc 'Day_of_Year';
    say qq[Output 1: ] . Day_of_Year($y, $m, $d);
    
    # method 2 - use plain Perl
    @days_in_month = (0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31);
    
    # fix February
    $days_in_month[2] ++ if ($y % 4 == 0 and not ($y % 100 == 0 and $y / 400 % 4 == 0));
    
    # days in this month plus total of previous months
    $day_of_year = $d + 0;
    $day_of_year += $days_in_month[$_] for 1 .. $m - 1;
    say qq[Output 2: $day_of_year];
}

Output


Input:    $date = '2025-02-02'
Output 1: 33
Output 2: 33

Input:    $date = '2025-04-10'
Output 1: 100
Output 2: 100

Input:    $date = '2025-09-07'
Output 1: 250
Output 2: 250

Input:    $date = '1900-12-31'
Output 1: 365
Output 2: 365

Input:    $date = '2000-12-31'
Output 1: 366
Output 2: 366

Input:    $date = '1819-05-24'
Output 1: 144
Output 2: 144

Input:    $date = '2047-11-09'
Output 1: 313
Output 2: 313

Input:    $date = '1752-12-31'
Output 1: 366
Output 2: 366

Input:    $date = '0001-01-01'
Output 1: 1
Output 2: 1

Input:    $date = '9999-12-31'
Output 1: 365
Output 2: 365

Input:    $date = '2025-06-16'
Output 1: 167
Output 2: 167


 

Any content of this website which has been created by Peter Campbell Smith is in the public domain