Flex Pasta » How to Avoid Timezone Headaches

How to Avoid Timezone Headaches

I wake up to the phone ringing.  I check the clock: 2:30 A.M on January 5th.  Groggy and dizzy I answer the phone.  It is my brother.  I am in Cincinnati(Eastern Time) and he lives in San Fransisco(Pacific Time).  “Why are you calling me at 2:30 in the morning”, I ask him.  “It’s only 11:30 P.M. here”, he says,  “and I am calling to tell you that I am father to a baby boy named Johnny!”.  “Congratulations!!”, I tell him.  We chat a bit more and then hang up.  The whole family is excited.  We had all placed bets on which day little Johnny would be born.  I had picked January 5th.  “Yes!!!”, I say.  I have won.  Or have I??  Johnny is born on January 5th eastern time, but January 4th pacific time.  So who wins?  Johnny’s birth date of record is January 4th.  But when was he born?  The answer to that depends on where I am.

Flex and Timezones

Assume now the nurse is entering the date and time of birth(when the baby is born) in the Flex baby tracker application: Jan. 4, 11:30 PM Pacific.  Also assume that the developer has coded the app to use a Date object in Flex, and java.util.Date in the Java remote class and that the application servers sits in Cincinnati(eastern time).  When the nurse saves the record, AMF will transfer over the date object as milliseconds since 1970.  When it hits the server in eastern time, the date is now stored as 2:30 AM January 5th.  If the nurse wanted to record the birth date, then as a developer, I would not want to use a date. In this instance, the date should be January 4th, globally, regardless of location or timezone.  A string or integer value should be used.  A Flex mx:DateChooser component is dangerous.  If the nurse picks a birthdate in a mx:DateChooser, the date would be created locally on the client pc as Jan 4th, 2010 at midnight(00:00:00).  When transferred to a server in eastern time, this date would become Jan 4th, 2010 at 3AM.  This is not what we want.  Someone in Hawaii viewing this baby record would get the date Jan 3rd, 2010 at 10PM.  The birth date January 4th should appear globally to anyone the same way.

Solution:

Option 1 - Have the date chooser covert the value to a string like 01-04-2010 and then transfer the value to the server and store it as a string.  This would ensure it globally being January 4th.

Option 2 - Option 1 has a problem: How do I do a query for all birthdays in January?  A little tricky with a string variable.  Option 2 is to covert the date chooser value to an integer in the form yyyymmdd(20100104). The date is transferred and stored in the database as an integer.  Doing this makes it easier to query.  For example, select * from baby where birthdate > 20100101 and birthdate < 20100131.  The data still keeps the integrity for greater than and less than operations.

Have a headache yet?  Go take some Tylenol:)

9 Comments

  • 1. PaulH replies at 20th January 2010, 9:53 pm :

    why not store with java epoch offsets?

  • 2. philip andrew replies at 23rd August 2010, 11:31 pm :

    I had this problem, at first I used the string method. Then I now use Joda Time on GraniteDS server and set the timezone correctly on the server as the local timezone of the browser.
    This works.

    Actually, this was all a very serious problem and took a lot of time and effort to fix.

  • 3. StephenM replies at 1st September 2010, 10:18 am :

    Encountered this problem and we are trying to solve without changing the date fields to String or numeric.
    Philip, would you elaborate on your solution a bit? Does it require that the browser’s timezone is always the same?

  • 4. Colin C replies at 11th October 2010, 12:16 am :

    This is such a pain in the backside. They should allow an option to save the date/time as recorded by the user without having to covert the date/time between timezones. 99% of the time when dealing with dates I want want the db value without having to convert the data. Try having a client give you a million plus stock records with the date/time fixed as a data type with no option to change it. Converting dates to strings is great for a small number of records but in reality is a very poor solution for large datasets. Eventually we moved the db to a local time zone for the client.

    I’ve also had issues where data which is supplied from other db’s (identical time zones) will be exclued in filters because the raw data might have been recorded at 11pm on a daylight savings crossover, though when converted to a flex date/time moves the date forward to the next day.

    After developing many applications that involve date/time requirements this has been a big issue for our company. We deal with many customers and databases and alot of our customers want extracts to excel, reporting services etc and its a big issue when the browser can exclude data that other applications will not.

  • 5. philip andrew replies at 11th January 2011, 9:42 am :

    Sorry I took a long time to reply, I use GraniteDS on server side. Joda Time on server side for storing and processing times.

    @Entity
    @Audited
    @Table(name = “booking”)
    @EntityListeners({Booking.BookingEntityListener.class})
    public class Booking extends AbstractEntity {
    @Index(name = “bookingStartDateIndex”)
    @Columns(columns={@Column(name=”start_date”),@Column(name=”start_date_timezone”)})
    @Type(type=”org.joda.time.contrib.hibernate.PersistentDateTimeTZ”)
    private DateTime startDate;

    @Column(name = “start_time”)
    @Type(type=”org.joda.time.contrib.hibernate.PersistentLocalTimeAsTime”)
    private LocalTime startTime;

    Look at the examples in GraniteDS code, also at:
    http://www.graniteds.org/confluence/display/DOC/8.+Type+Conversions+(Java+~+ActionScript3)

    This solves the timezone problem, I have a server in USA and a client Flex in Hong Kong. Works fine.

  • 6. DataNotion replies at 28th January 2011, 7:12 pm :

    @StephenM: You don’t have to alter your database, or even your application model. Just change the points to where the data changes hands. For example, I just given an app last week that had this problem. The application’s data model stored the data as Dates, and the database stored them as Dates, and I couldn’t change that because it would break other apps.

    So, this is how I solved it:

    1) Looked for the WRITE code on the ColdFusion side, and made it accept a string instead of a date. When I store the date, I tell the database to store (cast) it as a date.

    2) Looked for the READ code on the ColdFusion side, and changed the query to cast the date to a string, so when I send it back to Flex it’s already a string.

    3) Looked for the WRITE code on the Flex side and casted the date to a string before I sent it to CF.

    4) Looked for the READ code on the Flex side, looped through all of the received data and created a native date property for every record.

    Done. Now the app still uses a native date, and the sql server still uses a native date. All I’ve changed are a few functions that casted the data before I continued with the existing code.

    NOW if you want to live on the edge — there is also a monkey patch out there I saw that alters how Blaze works and handles the timezone thing for you….I wasn’t brave enough.

    I really wish Adobe would come up with a patch where we could flag gateways as timezone independent….

  • 7. Prabhat Ranjan replies at 20th February 2011, 1:42 am :

    Hi,

    I also faced the Similar problem in flex & java application, US users faced a date lagging of 1 day , so i changed the date data Type in flex to String and now it is working fine.

    1)Is there any impact of doing String instead of Date.
    2) others solution is to use timezone offset.

    how to use in please explore with simple application.

    send date from flex to java to database.

  • 8. Gerard replies at 1st July 2011, 12:23 am :

    Its all due to the poor naming in Java and Actionscript (and probably many other languages as well).

    When you and I think of “date”, we think of a year, a month and a date (and sometimes the day of the week as well).

    When Java and Actionscript say “Date”, they really mean “Timestamp”. They really mean, a point in time, which is timezone agnostic; a point in time in Japan, is the same point in time in Seattle. Humans just call that point in time different things depending on where they are.

    The principle is: Never send Date objects across timezones. Send a string, or send a custom object. I used the latter.

    I think the next Java (Java 7?) will have better (and no doubt more complicated) Dates.

  • 9. resume replies at 3rd August 2011, 1:17 pm :

    Thanks for the useful steps)

Leave a comment

XHTML: You can use these tags: <a href="" title=""> <abbr title=""> <acronym title=""> <blockquote cite=""> <code> <em> <strong>