Yes, but I can detect possible border cases, as they can only start to arise when the amount of minutes goes above 22 or 23 hours + n*24 hours, and the amount of days is n days. Otherwise, the problem is clear or rather, is left to the application (legal issues like TZ changes).after some thinking about how to compare the "inconvertible" units, I came up with an ugly hack that will work for "most" cases - the border cases where it fails, are not yet detected, but I'm working on that. The patch passes all my ad-hoc tests, I'll run it later against the DateTime test suite.You can't possibly detect the border cases because they only exist in the context of a "base" datetime to which the durations are added. That's the fundamental problem of trying to compare durations.
I would leave the legal tz changes to the calling application.sub _normalize_sign { my $self = shift; my $minutes = $self->{minutes};
# A day is longer than (or equal to) 23 hours, # a month is longer than (or equal to) 28 days a 24 hours, as DST is never in february:
DST changes may not occur in February, but time zone offset changes can, because these can occur due to legislation.
$minutes += $self->{days} * 23 * 60; $minutes += $self->{months} * 24 * 60 * 28;
$self->{sign} = 0 <=> $minutes; };
I would explain that the comparision of ::Durations only works for mixed durations that are far enough apart (e.g. 1 day less 10 minutes is shorter than 3 days). For the adventurous, I would explain the method how I arrive at the number used for comparision.This is a vague approximation that won't work in all cases. How would we document this? It's incredibly complicated to explain.
I did think a bit more about the comparision, and I think there will be four numbers needed for comparision of two ::Durations, both the maximum number of minutes and the minimum number of minutes for each ::Duration. If we have both these numbers, we can safely tell whether one is larger or smaller, and we can die if it is undecidable. The undecidable cases are thus left to the application, which is fine by me.
I'm not interested in the 100% solution, as I think that accumulating 28 days (or 22 hours) worth of minutes means that there is some other flaw in the application design and that the application/business process itself must already have a way of converting that amount into days if a mix of days and minutes is needed.
But if you don't want to put the comparisions into ::Duration objects, maybe this additional behaviour could be made available through a mixin that stomps over the ::Duration namespace and implements the comparision operators and is_* methods needed for it. I dabbled with this shortly but stumbled across some weird behaviour when trying to overload stuff that had already been loaded. But I attribute that to my stupidity and not the general infeasibleness...
-max