Ruby on Rails | Screencasts | Download | Documentation | Weblog | Community | Source

Ticket #9750 (closed defect: fixed)

Opened 8 months ago

Last modified 4 months ago

[PATCH] Unambiguous Time, Date and DateTime #to_json format

Reported by: gbuesing Assigned to: core
Priority: normal Milestone: 1.x
Component: ActiveSupport Version: edge
Severity: normal Keywords:
Cc: chuyeow

Description

Currently, Time, Date and DateTime #to_json output dates in an ambiguous mm/dd/yyyy format:

>> Time.now.to_json
=> "\"10/01/2007 12:15:02 CDT\""

...which, depending upon the regional settings of the client, could be interpreted as Oct 1, 2007, or Jan 10, 2007.

This patch changes the format of the date to the unambiguous yyyy/mm/dd format:

>> Time.now.to_json
=> "\"2007/10/01 12:15:02 CDT\""

Existing tests have been revised.

Attachments

unambiguous_time_date_and_datetime_to_json.diff (2.1 kB) - added by gbuesing on 10/01/07 17:35:26.
unambiguous_time_date_and_datetime_to_json.unified.diff (2.3 kB) - added by chuyeow on 10/04/07 05:49:51.
Time#to_json and DateTime#to_json is encoded the same way

Change History

10/01/07 17:35:26 changed by gbuesing

  • attachment unambiguous_time_date_and_datetime_to_json.diff added.

(follow-up: ↓ 2 ) 10/02/07 01:43:56 changed by jaylev

Any reason not to go all the way to RFC-3339? A lot of people spent a lot of, um, time thinking about these issues. And the -00:00 offset (which I hadn't heard of till now) could prove useful, given Rails' out-of-the-box time-zone-agnosticism.

(in reply to: ↑ 1 ) 10/02/07 02:54:29 changed by gbuesing

Replying to jaylev:

Any reason not to go all the way to RFC-3339? A lot of people spent a lot of, um, time thinking about these issues. And the -00:00 offset (which I hadn't heard of till now) could prove useful, given Rails' out-of-the-box time-zone-agnosticism.

This standard won't work, unfortunately, if we wish to output dates that are compatible with the peculiarities of Javascript's Date.parse() function, which can't parse dates separated by '-' (you need to use '/').

When Time, Date and DateTime #to_json were first added, Date.parse compatibility was considered, see #8399 for the discussion.

10/02/07 04:32:42 changed by chuyeow

  • cc set to chuyeow.

I'd like to see this as well and checked that Firefox does parse the date string in "2007/10/01 12:15:02 CDT" format correctly (using new Date("2007/10/01 12:15:02 CDT")).

We will need to look around to see whether the "2007/10/01 12:15:02 CDT" is a universally parseable date string in the different browsers (or whether there is any "standard" format). I dug around and can't find much yet but I'll report back when I do.

(follow-up: ↓ 5 ) 10/02/07 06:26:19 changed by chuyeow

Setup a test page here. Basically just runs new Date(date_string_from_rails) with the date string format that this patch would output.

Works for me in Firefox 2 (Windows and Mac), Safari 2 and 3 (Mac), IE6, IE7, Firefox 3.0a9pre (Mac), and Opera 9.50. I believe it's a good format that new Date(date_string) and Date.parse() would parse correctly. If someone has some older or more obscure browsers please help verify the times are parsed correct!

(in reply to: ↑ 4 ) 10/02/07 17:06:51 changed by gbuesing

Replying to chuyeow:

Setup a test page here. Basically just runs new Date(date_string_from_rails) with the date string format that this patch would output.

Thanks for putting this test page up -- very helpful. Works for me in all the browsers I have access to (nothing outside of the ones you listed.)

I suppose to be thorough, we should also test the format outputted by DateTime.to_json, which displays the zone as "+00:00" instead of "UTC".

Regarding if there's a standard format -- the ECMA-262 spec isn't specific on which formats Date.parse should recognize:

"...in general, the value produced by Date.parse is implementation-dependent when given any string value that could not be produced in that implementation by the toString or toUTCString method." (15.9.4.2)

The output of toString is "implementation-dependent" as well:

"The contents of the string are implementation-dependent, but are intended to represent the Date in the current time zone in a convenient , human-readable form." (15.9.5.2).

10/04/07 03:03:48 changed by bitsweat

  1) Failure:
test_datetime(TestJSONEncoding)
    [./test/json/encoding_test.rb:39:in `test_datetime'
     ./test/json/encoding_test.rb:38:in `each'
     ./test/json/encoding_test.rb:38:in `test_datetime'
     /usr/local/lib/ruby/gems/1.8/gems/mocha-0.5.5/lib/mocha/test_case_adapter.rb:19:in `__send__'
     /usr/local/lib/ruby/gems/1.8/gems/mocha-0.5.5/lib/mocha/test_case_adapter.rb:19:in `run']:
<"\"2005/02/01 15:15:10 +00:00\""> expected but was
<"\"2005/02/01 15:15:10 Z\"">.

(follow-up: ↓ 8 ) 10/04/07 03:04:32 changed by bitsweat

(see %z vs %Z format strings)

(in reply to: ↑ 7 ) 10/04/07 05:30:46 changed by chuyeow

Replying to bitsweat:

(see %z vs %Z format strings)

Hmm this actually works for me (can't get that test to fail).

But I'm aware of the tricky platform-specific issues regarding the %z and %Z format string.

Time#strftime and DateTime#strftime produce different outputs for %Z. Time tries to give it a timezone (e.g. UTC, CDT), whereas DateTime outputs it in +00:00 or +0000.

Using %z is slightly better since both Time and DateTime gives +0000 (no colons). But I've read that it is platform-dependent.

I think the most ideal way for to_json output is to be consistent for Time and DateTime (same format), and they should be of the form:

2007/10/01 12:15:02 +0800

I've tested this form in the same browsers listed above and new Date(date_string) parses correctly (take note the lack of a colon). 3-letter TZ codes don't work in Opera but this +HHMM format does.

Anyway, if anyone has any suggestions on how to approach this please do. I'm leaning towards forcibly outputting +HHMM instead of using the platform-dependent strftime.

10/04/07 05:49:51 changed by chuyeow

  • attachment unambiguous_time_date_and_datetime_to_json.unified.diff added.

Time#to_json and DateTime#to_json is encoded the same way

(follow-up: ↓ 10 ) 10/04/07 05:54:15 changed by chuyeow

I've added another patch (keeping to gbuesing's YYYY/mm/dd format) that makes Time#to_json and DateTime#to_json consistent (basically, Times are first converted to DateTimes).

Changed strftime format string to

"%Y/%m/%d %H:%M:%S %z"

I've found that this converts on Mac OS X and Windows XP to +HHMM format (e.g. +0000, +0800). I've tested this format using JavaScript's new Date(date_string) in: Firefox 2 (Windows and Mac), Safari 2 and 3 (Mac), IE6, IE7, Firefox 3.0a9pre (Mac), and Opera 9.50 using this test page.

Needs more testing across different platforms (esp. Linux) and browsers.

(in reply to: ↑ 9 ) 10/05/07 02:56:54 changed by gbuesing

I've added another patch (keeping to gbuesing's YYYY/mm/dd format) that makes Time#to_json and DateTime#to_json consistent (basically, Times are first converted to DateTimes).

Good idea, that will ensure consistency between Times and DateTimes, and hopefully across platforms.

On Debian Etch:

>> DateTime.civil(2000).strftime("%Y/%m/%d %H:%M:%S %z")
=> "2000/01/01 00:00:00 +0000"

10/05/07 05:59:41 changed by eggie5

  • type changed from defect to task.

+! Tests confirmed...

10/05/07 06:00:16 changed by eggie5

  • type changed from task to defect.

+1

10/05/07 09:43:28 changed by bitsweat

  • status changed from new to closed.
  • resolution set to fixed.

(In [7746]) Disambiguate Time, Date, and DateTime#to_json formatting. Closes #9750.

01/12/08 21:02:49 changed by gbuesing

(In [8636]) Time#to_json uses Numeric#to_utc_offset_s to output cross-platform-consistent representation without having to convert to DateTime. References #9750