Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

is Date.new() ... DateTime.new() a valid syntax?

When I use two DateTime objects on both sides of the sequence operator (...), Raku reports that No such method 'succ' for invocant of type 'DateTime'. Did you mean any of these: 'sum', 'utc'?

DateTime.new("2022-03-26") ...  DateTime.new("2022-03-28")

However, when the left side of the ... operator is a Date object, and the right side is a DateTime object, it leads to an infinite loop:

.say for Date.new("2022-03-26") ... DateTime.new("2022-03-28");
.say for Date.new("2022-03-26") ... DateTime.new("2022-03-18");

Is the above syntax valid? Should it report an error?

For comparison, the following code works fine:

.say for Date.new("2022-03-26") .. DateTime.new("2022-03-28")
.say for Date.new("2022-03-26") .. Date.new("2022-03-28")

Output:

2022-03-26
2022-03-27
2022-03-28
like image 218
ohmycloudy Avatar asked Apr 28 '26 17:04

ohmycloudy


1 Answers

Infinite loop

when the left side of ... operator is a Date object, and the right side is a DateTime object, it will lead to an infinite loop

Yes. Here's what I believe to be the underlying bug:

say Date('2023-03-17') ~~ DateTime('2023-03-17') # False

Given that a ... sequence iterates until a value (generated from the startpoint/generator on the LHS of the ...) smartmatches the endpoint (on the RHS of the ...), then switching from an infix ~~ to ... currently guarantees an infinite loop.

I've filed an issue.

Rule of thumb about .. vs ...

For increment-by-1 semantics, from a start value to an end value, I recommend defaulting to using the range operator (..) which creates a Range. If you iterate that then the generated sequence ends when the incremented LHS compares greater than the endpoint RHS. Assuming the RHS is not Inf (or *), then the range can only "infinitely loop" (actually just take too long) if there are too many steps before spanning the gap from start to endpoint.

Only use the sequence operator (...) when you need something other than increment-by-1 semantics.

No such method 'succ' (a DateTime is a timestamp)

A DateTime is a time, not a date. (It perhaps ought have been named Timestamp, and I can imagine it maybe being renamed to that next decade, but we've got bigger fish to fry for now.) Quoting the doc:

For handling points in civil time ... stores year, month, day, hour, minute (all Int), second (potentially fractional) and a time zone.

As such, if it did work to put a DateTime on the left hand side of a range (..) or sequence (...), i.e. if there were a .succ method for DateTimes, then it should presumably step by some unit of time -- presumably one second, minute, or hour. (And I presume that's why there's no succ. Which would it be?)

Perhaps these two rules of thumb are appropriate:

  1. If what you really mean is a date without regard for timezones, then use Date, don't use DateTime.

  2. If what you really mean is a date within some timezone, then consider using a DateTime but make sure to explicitly specify the time component. (This will irritate you enough that you'll just use Date if that's all you really mean.)

Then again, using a DateTime may still be inadequate if you're stepping through or comparing some range/sequence because civil time and timezones are a whole complex thing in their own right and seconds don't always match up:

In 1972, the leap-second system was introduced ... By then, the UTC clock was already 10 seconds behind TAI, which had been synchronized with UT1 in 1958, but had been counting true SI seconds since then. ... the difference between their displays at any time is 10 seconds plus the total number of leap seconds that have been applied to UTC as of that time; as of June 2020, 27 leap seconds have been applied to UTC...

(No, I'm not going to explain UTC, TAI, UT1, SI, and leap seconds.)

Put another way, consider using, or converting to, Instants, especially if you wish to use .. or ... operators, but don't forget to take leap seconds into account.

(I think you can safely ignore the difference between civil time, which is by agreement, and the actual passing of time, which is ultimately unknowable with absolute precision according to current laws/theories of physics, presuming you're not reading this after we've reached the heat death of the universe.)

like image 106
raiph Avatar answered May 02 '26 04:05

raiph