We woke up one saturday morning to find that one of our Flex application screens quit working. On further analysis, it unravelled that the problem would occur only on Saturdays. Good luck selling the product to a customer with that bug
We deal with time ranges in our application. An instance of our Period class represents a time continuum between a start and an end. Something like below
public class Period {
private var _start:Date;
private var _end:Date;
public function get start():Date {
return _start;
}
public function set start(dt:Date):void {
_start = dt;
}
...
}
One special block of code tries to go through our known periods and tries to determine which period the today’s date falls in. And it didn’t find any when today happened to be a Saturday, because all periods ending on saturdays were being translated to Fridays thanks to timezone conversion
A couple things were contributing to the problem
1. Lack of date-only abstraction in Java (time has to be there always)
2. Flex, BlazeDs dutiful timezone translation when a date is sent from Java to ActionScript
In normal applications wherein we want time component represented in a timezone dependent manner, all these are just what the doctor ordered. For ex, in a trading application if a trade was submitted at 15:00 EST, then a user in CST timezone should see that as 14:00 CST. The above 2 will make it partially possible (partial because there’s more to accurately storing a timezone dependent time than just these). But in our application we did not want the time component, period. Our date was a pure date. Java does not have this concept, so a pure date is a date with 12:00 AM as the time (and a default timezone of the OS). Even that is fine with us. But when that date is received in Flex for a user in CST, Jan 1 12:00 AM EST becomes Dec 31 11:00 PM CST. And the only thing that mattered got altered, i mean the date.
The following were the solutions we could think of
1. Use a custom type to store timeless dates (timeless
). There would be one custom type in Java and a mirror in Flex. But then we lose all the date API support (or whatever silly support) that is available. We can’t extend the Date class in Flex, its final. And we do not have control over serialization of the primitives and default types, one of which is Date.
2. Manipulate the date’s time component in the Flex remoting layer to account for the difference between the client and server GMT offsets. This is a cool solution but is a bit hacky. For ex, we would add 1 hr in the above case to Dec 31 11:00 PM CST to get Jan 1 12:00 AM CST. We have to do this on the way in and the way out.
3. Use a custom type, but use it just for transmission: This works when we have an abstraction on top of dates, like our Period which had a startDate and endDate. The rest of the application depended on these startDate and endDate attributes. For transmission, we added 2 parallel attributes, transStartDate and transEndDate, which use the custom type. The accessors were intelligent enough to convert between transmission date and the regular date.
We went with #3. If we had to transmit a date by itself we could use the TransmissionDate custom type to do that. #2 was a strong favorite, but then #3 was cleaner, way simpler and all in one class; basically had the symptoms of a better solution.
So on Flex side our Period class now looked like this
public class Period {
private var _start:Date;
private var _end:Date;
public function get start():Date {
return _start;
}
public function set start(dt:Date):void {
_start = dt;
}
public function set transStartDate(dt:TransmissionDate):void {
_start = new Date(dt.getYear, dt.getMonth, dt.getDate());
}
public function get transStartDate():TransmissionDate {
return ...
}
All existing code was safe and didn’t need to change. This solution also helps highlight the importance of proper abstractions. A couple of getters, setters and two new classes and the problem was behind us.
There are quite a few blogs that talk about this issue. For ex this one
Inspite of their massive relevance to our everyday lives, Dates and times are some of the poorly understood concepts when it comes to programming and APIs. In every application that we build that deals with time, we will find something quirky, guaranteed. Its fun.