Skip to content

Commit

Permalink
Add support for fractional timestamps (#127)
Browse files Browse the repository at this point in the history
  • Loading branch information
alextwoods authored Apr 12, 2023
1 parent e105257 commit 66a4156
Show file tree
Hide file tree
Showing 5 changed files with 151 additions and 3 deletions.
84 changes: 84 additions & 0 deletions codegen/projections/rails_json/spec/protocol_spec.rb

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
Expand Up @@ -196,7 +196,7 @@ public String timestampShape(TimestampShape shape) {
// rounding of floats cause an issue in the precision of fractional seconds
Double n = node.expectNumberNode().getValue().doubleValue();
long seconds = (long) Math.floor(n);
long ms = (long) ((n - Math.floor(n)) * 1000);
long ms = Math.round((n - Math.floor(n)) * 1000);
return "Time.at(" + seconds + ", " + ms + ", :millisecond)";
} else {
return "Time.at(" + node.expectNumberNode().getValue().toString() + ")";
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -168,6 +168,22 @@ use smithy.test#httpResponseTests
method: "POST",
uri: "/",
},
{
id: "rails_json_serializes_fractional_timestamp_shapes",
protocol: railsJson,
documentation: "Serializes fractional timestamp shapes",
body: "{\"timestamp\":\"2000-01-02T20:34:56.123Z\"}",
bodyMediaType: "application/json",
headers: {"Content-Type": "application/json"},
requireHeaders: [
"Content-Length"
],
params: {
Timestamp: 946845296.123,
},
method: "POST",
uri: "/",
},
{
id: "rails_json_serializes_timestamp_shapes_with_iso8601_timestampformat",
protocol: railsJson,
Expand Down Expand Up @@ -664,6 +680,18 @@ use smithy.test#httpResponseTests
},
code: 200,
},
{
id: "rails_json_parses_fractional_timestamp_shapes",
protocol: railsJson,
documentation: "Parses fractional timestamp shapes",
body: "{\"timestamp\":\"2000-01-02T20:34:56.123Z\"}",
bodyMediaType: "application/json",
headers: {"Content-Type": "application/json"},
params: {
Timestamp: 946845296.123,
},
code: 200,
},
{
id: "rails_json_parses_iso8601_timestamps",
protocol: railsJson,
Expand All @@ -688,6 +716,18 @@ use smithy.test#httpResponseTests
},
code: 200,
},
{
id: "rails_json_parses_fractional_httpdate_timestamps",
protocol: railsJson,
documentation: "Parses fractional httpdate timestamps",
body: "{\"httpdate_timestamp\":\"Sun, 02 Jan 2000 20:34:56.123 GMT\"}",
bodyMediaType: "application/json",
headers: {"Content-Type": "application/json"},
params: {
HttpdateTimestamp: 946845296.123,
},
code: 200,
},
{
id: "rails_json_parses_list_shapes",
protocol: railsJson,
Expand Down
6 changes: 4 additions & 2 deletions hearth/lib/hearth/time_helper.rb
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,8 @@ class << self
# @param [Time] time
# @return [String<Date Time>] The time as an ISO8601 string.
def to_date_time(time)
time.utc.strftime('%Y-%m-%dT%H:%M:%SZ')
optional_ms_digits = time.subsec.zero? ? nil : 3
time.utc.iso8601(optional_ms_digits)
end

# @param [Time] time
Expand All @@ -28,7 +29,8 @@ def to_epoch_seconds(time)
# @return [String<Http Date>] Returns the time formatted
# as an HTTP header date.
def to_http_date(time)
time.utc.httpdate
fractional = '.%L' unless time.subsec.zero?
time.utc.strftime("%a, %d %b %Y %H:%M:%S#{fractional} GMT")
end
end
end
Expand Down
22 changes: 22 additions & 0 deletions hearth/spec/hearth/time_helper_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -8,18 +8,40 @@ module Hearth
it 'converts a time object to date time format' do
expect(subject.to_date_time(time)).to eq '1970-01-01T00:00:00Z'
end

context 'fractional seconds' do
let(:time) { Time.at(946_845_296, 123, :millisecond) }
it 'converts to date time format with milliseconds' do
expect(subject.to_date_time(time)).to eq '2000-01-02T20:34:56.123Z'
end
end
end

describe '.to_epoch_seconds' do
it 'converts a time object to epoch seconds format' do
expect(subject.to_epoch_seconds(time)).to eq 0.0
end

context 'fractional seconds' do
let(:time) { Time.at(946_845_296, 123, :millisecond) }
it 'converts to date time format with milliseconds' do
expect(subject.to_epoch_seconds(time)).to eq 946_845_296.123
end
end
end

describe '.to_http_date' do
it 'converts a time object to http date format' do
expect(subject.to_http_date(time)).to eq 'Thu, 01 Jan 1970 00:00:00 GMT'
end

context 'fractional seconds' do
let(:time) { Time.at(946_845_296, 123, :millisecond) }
it 'converts to http date format with milliseconds' do
expect(subject.to_http_date(time))
.to eq 'Sun, 02 Jan 2000 20:34:56.123 GMT'
end
end
end
end
end

0 comments on commit 66a4156

Please sign in to comment.