As I was looking at the Python Calendar implementation last night, I realised how rare it is for a programming language to get dates right.
PHP is the only language I can think of that really does it well. In fact, PHP date kindof amazes me in how it manages to completely transparantly deal with all the crap I give it when it comes to dates, and still gives me the output I expect. Lovely.
But this now got me thinking… why do I still suffer with Java Calendar at work? We would have been better storing dates and times as Strings at work than Calendars. No, really! But by far the best would be if you would let me write my own Date and Time object we could use in our work. Lets call it DateTime. It only needs a bit of thought.
Here in the travel reservation industry, what do we use dates for? Lets see:
- The departure and arrival time of a travel product. It might have a year, it will certainly have months, days. It might have an hour and a minute, but hotels really don’t care about those kinds of things. It will need a time zone too. (yyyy)/mm/dd (HH:MM) (z)
- The duration of a travel product. For things like hotels, this is going to be in nights, for things like flights you will need hours and minutes. (dd) (HH:MM)
- Processing payments. You’re going to get a credit card date to process, it’s going to come in the form mm/yy
- File creation and deadline dates. Travel agents are going to want to know when a reservation was made, and things like payment deadlines. (yyyy)/mm/dd (HH:MM)
Great, so calendar’s definitely way too complex for all this. We don’t give a crap about milliseconds. And none of these dates ever need to change. So my new DateTime class is clearly immutable.
Andwhat’s really important here isn’t time, it’s parsing. If I get any of these dates as in input string, I need to be able to store it in my date-time without ever having a problem. What’s more, when I toString() my DateTime, I want the output format to be the same as the input format.
There’s absolutely no point in me storing a credit card payment date, and when then I toString() my DateTime I get 2009/10/00 00:00 GMT. How do you know my card expires on the 0th of October in midnight in London? Even if you give me a real date here, it’s still not valid data because you’re just guessing! If I put in 10/09 as a Credit Card expiry date, I want to get 10/09 back.
Secondly, I want to be able to produce Durations from DateTimes. We have a great Duration object in Dossier, and DateTime should be able to generate it. It’s made up of a value and an enum.
Duration(DateTime start, DateTime end)
And there’s no reason this can’t be clever too. Flying Dublin -> New York, I might have input like
start = 2010/03/15 11:40 GMT
end = 2010/03/15 14:10 GMT-5
What do I want to see in Duration.toString() here? Clearly 8:30 – because my flight takes 8h, 30 mins. The internal representation would be: BigDecimal = 8.5, Enum=HOURS
How about if I make a hotel reservation?
start = 2010/03/15
end = 2010/03/19
Duration.toString() should now give me 4. Because I am staying for 4 nights. And based on my output can be input, if I initialize Duration with a string containing just the number 4, it will know that want 4 days. Internal representation? BigDecimal = 4, Enum = DAYS
Now we have something that makes manipulating your reservations incredibly not difficult at all. There’s no need for complexity, because all we really ever needed from a Date was
- Immutability, so that you know what you get
- Input = Output = Input, with intelligent, domain-specific string parsing, so that what you give is what you get
- The ability to find out the duration between two dates, and print it sensibly
So, why not use a String, and a DurationHelper to find the duration between two strings? Well, if my input is 31SEP2009, I want an Exception 🙂