I loved Time::Piece (formerly Time::Object) with a passion. After Y2K I sketched out a plan for two Perl libraries that would perform date functions. It sat on my whiteboard for several months, and then suddenly Matt Sergeant released a module that implemented it almost exactly. It worked exactly the way I wanted to think. There was a class to represent moments in time, there was a class to represent intervals of time, and every operator possible was overloaded in meaningful ways. If you subtracted two points in time you got an interval, if you added an interval to a point in time you got a point in time, if you performed multiplication or division on an interval it just worked, and on and on. Intervals were real objects, not just integers representing some unit of time like in Oracle or other systems I've seen.
DateTime came out, and I knew it was the next best thing, and in fact Time::Object was reimplemented to use it internally. But the learning curve was steep. I slowly picked up a bit here and there, wrote myself some utility programs, and then when I got interested in other calendars and some of the more esoteric things that happened to have DateTime-related modules on CPAN I converted and started writing with it.
But DateTime's two classes did not work the way I expected. I tried to perform division on a time interval and got something that was not a time interval. DateTime refused to perform all sorts of conversions because of exception cases that meant that certain things were not always true. Every time I touched it I found myself looking things up
... and looking things up didn't help. Time interval objects didn't stringify. They appeared to have redundant methods. There weren't ways to say "Look, don't give me the seconds component of the interval, tell me how many seconds long the interval really is, and since I computed it from two moments in time this is not a meaningless question that can't be answered; tell me, and tell me in a way that I can perform math on." And the documentation had an oh-so-helpful section on "How Datetime Math is done" that really didn't help at all, because it dealt with all sorts of exceptions I didn't care about and didn't actually tell me how to do what I used to just do with Time::Object.
Of course, I couldn't go back for a host of reasons. So I'd puzzle something out, and then when I needed it again I'd hope I'd find it lying around in one of my programs somewhere so I could refer to it again.
So it's time to start recording some of this knowledge here. IMO, DateTime long since should've had a date math section in the documentation that actually shows how to do these things.
So, today's puzzle is: given two DateTimes, divide the interval between them into N equal parts and give me back a series of N + 1 DateTimes, from $start to $end, all evenly spaced:
my($start, $end, $n) = @_;
my $int = $end - $start;
for my $i (0
push @a, $start + $int->clone->multiply($i / $n);
Of course, I'm scared to death this somehow doesn't really work right because DateTime is so pathological about saying, "I can't really tell if this interval divides like this or like that because sometimes days have extra hours or seconds or something." Even though I'm doing it all in UTC.
Update: No, it doesn't work. If I divide into too many partitions, DateTime can't handle adding fractional days, hours, minutes, seconds, etc. Look, the interval is three days long. Divide it into 250 equal portions and let me know where those breaks are. I could do it in a snap with Time::Object.