date helper bug?

I've found an issue when trying to use the time_ago_in_words and distance_of_time_in_words from action view's date_helper.rb

Using SQL Server, I have a datetime column that gets returned as: "2007/02/21 09:54:00". When I pass this to time_ago_in_words (which just passes on to distance_of_time_in_words) it miscalculates the difference as "9 hours" (...um yeah, it was 10:54 when I tested this), when the difference should have been "1 hour". So I fired up script/ console to see what was going on...

# setting up to use the date_helpers...

helper.extend ApplicationHelper

=> #<Object:0x391bfd8>

# my record from SQL server returns time like this...

t.updated_on

=> "\"2007/02/20 15:09:04\""

t.updated_on.class

=> String

# so make a string in same format that represents ~1 hour ago...

nine_54 = "2007/02/21 09:54:00"

=> "2007/02/21 09:54:00"

# see what the helper gives me... (about 1 hour difference from Time.now)

helper.time_ago_in_words(nine_54)

=> "about 9 hours"

# looking at date_helper.rb I see that parameters passed in are called with to_time method...

nine_54.to_time

=> Wed Feb 21 09:54:00 UTC 2007

Time.now.to_time

=> Wed Feb 21 11:04:34 Pacific Standard Time 2007

# A ha! So we're off by the difference in time zones between PST and UTC (GMT?). So poking around a bit more...

Time.parse(nine_54)

=> Wed Feb 21 09:54:00 Pacific Standard Time 2007

Success!

So in my view, all I have to do to get the correct time is use time_ago_in_words(Time.parse(updated_on)) for it to work.

So is this a bug? It is correctly parsing the difference in the times when considering the time zone differences, but what about the difference between Time.parse and to_time? Shouldn't these return the same answer?

What about the datetime from SQL server? Is the value in the db stored with tzone info, or is to_time just assuming a defualt tzone of UTC?

Welcome to the club!

This is one of the most controversial arrays that I stumble upon - what is the correct time.

It all begin with some misunderstanding from guys that build first computer in believe that we all look in a same watch. Than for some unknown reason when the time zone information is introduced it was make in such way that the users should not be bothered with it. So, by default you will get the local time and the input is translated as it is entered in local time. The funny part is that the time is usually stored as number of quanta (seconds) from some arbitrary zero time and in UTC.

The time zone information that is used for calculations is present in two forms. On Windows it is one current value for daylight savings (DLS) time per geographical place (Town). It is stored somewhere in the system, and WIN API can get you the value for predefined set of geographical places. On Linux it is stored in a configuration file, as usually, and the good part is that you can extend the info in it, but still just the current DLS values.

The most interesting part is that this current DLS values for transforming local to and from UTC time is used for any time, even historical ones.

DLS values are not that universal and have been changed in a past. In some regions quite often. You do not what to know what some African rulers have done with it. Even in USA some parts use DLS and some parts not.

To kip this story short, it is of very importance to know exactly how the time methods work, what expect as input (local or UTC) and what output they produce.

My advice to you is to make every time value UTC specially ones that are stored in DB or used for calculations. It is always far more easy to format UTC value to user local time on demand - to display to the user on the page. Take good care on user input.

If you need more info on the subject do not hesitate to ask.

dima

My advice to you is to make every time value UTC specially ones that are stored in DB or used for calculations. It is always far more easy to format UTC value to user local time on demand - to display to the user on the page. Take good care on user input.

Well, I have no control over what goes into this database. I only have read access to it, and if I did have any control over it the first thing I'd do is throw it out :-/

Either way.. the tzone info is incorrect. A value of 9:00 PST going into this database comes out as 9:00 UTC -- so it jumps time/timezones in this process. When I pull it from the database I have to do tricks to get it to parse correctly:

nine_54.to_time

=> Wed Feb 21 09:54:00 UTC 2007

Time.parse(nine_54)

=> Wed Feb 21 09:54:00 Pacific Standard Time 2007

Time.parse(nine_54) == nine_54.to_time

false

Is there another way to coerce the timezone? i.e. force the UTC value to PST?

I've found an issue when trying to use the time_ago_in_words and distance_of_time_in_words from action view's date_helper.rb

Using SQL Server, I have a datetime column that gets returned as: "2007/02/21 09:54:00". When I pass this to time_ago_in_words (which just passes on to distance_of_time_in_words) it miscalculates the difference as "9 hours" (...um yeah, it was 10:54 when I tested this), when the difference should have been "1 hour". So I fired up script/ console to see what was going on...

<snip/>

# A ha! So we're off by the difference in time zones between PST and UTC (GMT?). So poking around a bit more...

Time.parse(nine_54)

=> Wed Feb 21 09:54:00 Pacific Standard Time 2007

Success!

So in my view, all I have to do to get the correct time is use time_ago_in_words(Time.parse(updated_on)) for it to work.

So is this a bug? It is correctly parsing the difference in the times when considering the time zone differences, but what about the difference between Time.parse and to_time? Shouldn't these return the same answer?

What about the datetime from SQL server? Is the value in the db stored with tzone info, or is to_time just assuming a defualt tzone of UTC?

In your config/environment.rb, find and uncomment:

   # Make Active Record use UTC-base instead of local time    config.active_record.default_timezone = :utc

So your database times will be UTC.

-Rob

Rob Biedenharn http://agileconsultingllc.com Rob@AgileConsultingLLC.com

In your config/environment.rb, find and uncomment:

   # Make Active Record use UTC-base instead of local time    config.active_record.default_timezone = :utc

So your database times will be UTC.

The times coming out of the database are already coming out as UTC when they're really PST times... i.e. PST time input -> stored in db -

rails retrieves a UTC time, all along the only thing that changes in

this is the tzone (0900 Feb 21 2007 PST -> database -> 0900 Feb 21 2007 UTC).

I don't have control of the data in the database. All I can do is read the data. Can I force the dates to come out as PST?