Over on Twitter Joelle Maslak (Twitter handle @jmaslak) asked a question about a date and time problem I honestly had never thought about.

How to calculate the number of seconds in a day on dates starting or ending DST? I’ve always just assumed that 86.400 is the correct answer. It makes sense, doesn’t it? 24 hours * 60 minutes * 60 seconds = 86.400.

Joelle reminded me that these two days a year — at least here in Norway — are either more or less than 86.400. This year (2018) we switched to DST March 25. So I thought that, surely, that had to be something Perl’s Datetime object could figure out? To be honest I thought Joelle had misunderstood something. As it turned out, she hadn’t:

my $d1 = Date.new("2018-03-25").DateTime.posix;

my $d2 = Date.new("2018-03-26").DateTime.posix;

say $d2 - $d1; Output:

86400

Stubborn as I am I double checked what’d happen if I checked October 28, 2018 (the day Norway switches from DST to winter time).

my $d1 = Date.new("2018-10-28").DateTime.posix;

my $d2 = Date.new("2018-10-29").DateTime.posix;

say $d2 - $d1; Output:

86400

It seems that DateTime ignores daylight savings time here, and counts 1 day from the first to the latter. I guess there are good reasons for this — without having checked the underlying code; perhaps it is based on UTC which is without all that DST nonsense?

No matter what the reason is: Those of us with locales and time zones that suffer DST changes twice yearly, and who experience that days sometimes are longer, sometimes shorter, knows that the reality feels and is different. What to do?

Well, sometimes it helps to have lived for a while, because I vaguely remembered that Perl 5’s localtime function returned an array with an element that flagged whether that particular time was DST or not (the Perl 5 localtime documentation calls this flag $isdst). Alas, it seemed that Perl 6 didn’t have the similar built-in.

Researching this I found Liz’s module Time::localtime. It basically ports Perl 5’s localtime functions to Perl 6 [1]. Using zef to install it, I had what it took to write a code snippet that answered Joelle’s original question:

#!/usr/bin/env perl6 use Time::localtime; sub seconds-in-a-day($start-date) {

my $d1 = Date.new($start-date).DateTime.posix;

my $d2 = Date.new($start-date).DateTime.later(days => 1).posix;

my $l1 = localtime($d1);

my $l2 = localtime($d2);

return ($l2.isdst ?? $d2 - 3600 !! $d2)

- ($l1.isdst ?? $d1 - 3600 !! $d1);

} say seconds-in-a-day("2018-03-25");

say seconds-in-a-day("2018-05-17");

say seconds-in-a-day("2018-10-28"); Output:

82800

86400

90000

So now we’ve solved Joelle’s problem. The number of seconds in a day is 86.400 and 82.800 and 90.000. Case closed…