Permalink
Browse files

Customize subsecond digits when encoding DateWithTime

The subsecond fraction digits had been hardcoded to 3. This forced all
timestamps to include the subsecond digits with no way to customize the
value. While the subsecond format is part of the ISO8601 spec, it is not
adhered to by all parsers (notably mobile clients). This adds the
ability to customize the number of digits used, optionally setting them
to 0 in order to eliminate the subsecond fraction entirely:

ActiveSupport::JSON::Encoding.subsecond_fraction_digits = 0
  • Loading branch information...
1 parent e1e17a5 commit 4cfc467594da86090efa63f1852fb82df9458c2b @sorentwo sorentwo committed with pixeltrix Jul 16, 2013
@@ -4,6 +4,7 @@
module ActiveSupport
class << self
delegate :use_standard_json_time_format, :use_standard_json_time_format=,
+ :subsecond_fraction_digits, :subsecond_fraction_digits=,
:escape_html_entities_in_json, :escape_html_entities_in_json=,
:encode_big_decimal_as_string, :encode_big_decimal_as_string=,
:json_encoder, :json_encoder=,
@@ -60,7 +61,7 @@ def to_json(*)
end
# Mark these as private so we don't leak encoding-specific constructs
- private_constant :ESCAPED_CHARS, :ESCAPE_REGEX_WITH_HTML_ENTITIES,
+ private_constant :ESCAPED_CHARS, :ESCAPE_REGEX_WITH_HTML_ENTITIES,
:ESCAPE_REGEX_WITHOUT_HTML_ENTITIES, :EscapedString
# Convert an object into a "JSON-ready" representation composed of
@@ -105,6 +106,10 @@ class << self
# as a safety measure.
attr_accessor :escape_html_entities_in_json
+ # Configures the inclusion of subsecond resolution when serializing instances
+ # of ActiveSupport::TimeWithZone.
+ attr_accessor :subsecond_fraction_digits
+
# Sets the encoder used by Rails to encode Ruby objects into JSON strings
# in +Object#to_json+ and +ActiveSupport::JSON.encode+.
attr_accessor :json_encoder
@@ -154,7 +154,8 @@ def xmlschema(fraction_digits = 0)
# # => "2005/02/01 05:15:10 -1000"
def as_json(options = nil)
if ActiveSupport::JSON::Encoding.use_standard_json_time_format
- xmlschema(3)
+ digits = ActiveSupport::JSON::Encoding.subsecond_fraction_digits || 3
+ xmlschema(digits)
else
%(#{time.strftime("%Y/%m/%d %H:%M:%S")} #{formatted_offset(false)})
end
@@ -67,17 +67,25 @@ def test_zone
end
def test_to_json_with_use_standard_json_time_format_config_set_to_false
- old, ActiveSupport.use_standard_json_time_format = ActiveSupport.use_standard_json_time_format, false
- assert_equal "\"1999/12/31 19:00:00 -0500\"", ActiveSupport::JSON.encode(@twz)
- ensure
- ActiveSupport.use_standard_json_time_format = old
+ with_standard_json_time_format(false) do
+ assert_equal "\"1999/12/31 19:00:00 -0500\"", ActiveSupport::JSON.encode(@twz)
+ end
end
def test_to_json_with_use_standard_json_time_format_config_set_to_true
- old, ActiveSupport.use_standard_json_time_format = ActiveSupport.use_standard_json_time_format, true
- assert_equal "\"1999-12-31T19:00:00.000-05:00\"", ActiveSupport::JSON.encode(@twz)
+ with_standard_json_time_format(true) do
+ assert_equal "\"1999-12-31T19:00:00.000-05:00\"", ActiveSupport::JSON.encode(@twz)
+ end
+ end
+
+ def test_to_json_with_custom_subsecond_resolution
+ with_standard_json_time_format(true) do
+ ActiveSupport::JSON::Encoding.subsecond_fraction_digits = 0
+
+ assert_equal "\"1999-12-31T19:00:00-05:00\"", ActiveSupport::JSON.encode(@twz)
+ end
ensure
- ActiveSupport.use_standard_json_time_format = old
+ ActiveSupport::JSON::Encoding.subsecond_fraction_digits = nil
end
def test_to_json_when_wrapping_a_date_time
@@ -814,6 +822,13 @@ def with_env_tz(new_tz = 'US/Eastern')
ensure
old_tz ? ENV['TZ'] = old_tz : ENV.delete('TZ')
end
+
+ def with_standard_json_time_format(boolean = true)
+ old, ActiveSupport.use_standard_json_time_format = ActiveSupport.use_standard_json_time_format, boolean
+ yield
+ ensure
+ ActiveSupport.use_standard_json_time_format = old
+ end
end
class TimeWithZoneMethodsForTimeAndDateTimeTest < ActiveSupport::TestCase

0 comments on commit 4cfc467

Please sign in to comment.