I’ve been thinking of writing some CPAN API review blog posts. There’s a lot of bad APIs on CPAN. But before I pick on other people’s modules, I thought it would be good to start with something of my own.
The first release of DateTime was in early 2003. There’s 7+ years of mistakes to review, but I’ll just hit the highlights.
Duration and subtraction APIs
In my experience, the single most confusing part of the distribution is DateTime::Duration API. The original API exposed too much of the internals (via the
delta_* methods) and not enough of what people actually wanted. Since then, there’s been some band-aids, but the bleeding continues.
Ultimately, I’m not sure how fixable this is. One of the biggest API problems here is that users expect to be able to freely convert between any units in a duration. This isn’t possible, because there’s no fixed conversion between most units (how many days in 3 months?).
This confusion is compounded by the fact that there are several different methods for subtracting one DateTime from another, and the naming for these methods sucks. The
delta_md method gives you months and days,
delta_ms gives you minutes and seconds, and
subtract gives you all units. For extra fail, there is a
delta_days method in DateTime and DateTime::Duration, and they’re totally unrelated.
Finally, all of this is exacerbated by the fact that there is no date-only class. For any math where you just need to deal with dates, having a date-only class would obviously make your life easier. There’d simply be less API to understand, and the date-only class would be more likely to do what you mean.
Time Zones by Default
I think DateTime would be much better off if there was one class for floating datetimes, and another class for datetimes with time zones. Mixing the two together in one class makes the internals more complicated, and can lead to confusion when comparing two objects. If there were two classes, we could define explicit conversion methods, but otherwise make them unmixable.
Also, date math without time zones is a lot simpler to understand.
When I first created DateTime, I imitated parts of Time::Piece API, and I’ve since regretted that. Namely, a lot of the methods have multiple names, so we have
mday, all of which return the same thing. This is just clutter. Even worse, it means that two pieces of code using DateTime may use different methods to do exactly the same thing.
This is a global, and globals are bad.
Nowadays, the CLDR patterns are much more useful than strftime. If I were starting over I’d put strftime and strptime together in an external DateTime::Format::Strxtime library.
There’s probably other API problems, but I think these are some of the highlights. Feel free to complain in the comments, or more usefully, submit doc patches where appropriate.