Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add option to store datetimes as ISO-8601 formatted strings #223

Conversation

william101
Copy link
Contributor

Currently datetimes are stored in DynamoDB as :number (UNIX timestamps)

This pr add the option to store these timestamps as :string (ISO 8601)

Reference:

https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/DynamoDBMapper.DataTypes.html
Date (as ISO_8601 millisecond-precision string, shifted to UTC)

README.md Outdated
@@ -598,6 +598,7 @@ Listed below are all configuration options.
* `sync_retry_max_times` - when Dynamoid creates or deletes table synchronously it checks for completion specified times. Default is 60 (times). It's a bit over 2 minutes by default
* `sync_retry_wait_seconds` - time to wait between retries. Default is 2 (seconds)
* `convert_big_decimal` - if `true` then Dynamoid converts numbers stored in `Hash` in `raw` field to float. Default is `false`
* `convert_date_to_string` - if `true`, datetimes will be stores as ISO-8601 formatted strings. When `false`, datetimes will be stores as UNIX timestamps with milisecond precission. Defaule is `false`
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Typo, default

@@ -208,7 +197,7 @@ def dynamo_type(type)
:string
else
raise 'unknown type'
end
end
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this intentional?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just my editor formatting the code. I'll update.

@coveralls
Copy link

coveralls commented Jan 11, 2018

Coverage Status

Coverage decreased (-0.01%) to 97.316% when pulling c54c259 on pratik60:william/add_option_to_store_datetimes_as_strings into fb9db64 on Dynamoid:master.

1 similar comment
@coveralls
Copy link

Coverage Status

Coverage decreased (-0.01%) to 97.316% when pulling c54c259 on pratik60:william/add_option_to_store_datetimes_as_strings into fb9db64 on Dynamoid:master.

@coveralls
Copy link

coveralls commented Jan 11, 2018

Coverage Status

Coverage decreased (-0.01%) to 97.316% when pulling 21376c9 on pratik60:william/add_option_to_store_datetimes_as_strings into fb9db64 on Dynamoid:master.

when :utc
time_for_timezone(value, 'UTC')
when :local
time_for_timezone(value, Time.now.getlocal.zone)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ActiveSupport::TimeZone works badly with decree time and may loose 1 hour. That's why we used Time.at(value).to_datetime to convert time.

ActiveSupport::TimeZone[Dynamoid::Config.application_timezone].at(value).to_datetime
end
end
parse_datetime(value)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's a good refactoring. The feature could be done just with one additional line

value = DateTime.iso8601(value).to_time.to_i if Dynamoid::Config.convert_date_to_string

@@ -26,6 +26,7 @@ module Config
option :sync_retry_max_times, default: 60 # a bit over 2 minutes
option :sync_retry_wait_seconds, default: 2
option :convert_big_decimal, default: false
option :convert_date_to_string, default: false
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

To support existed projects and data we may need to specify this format not globally but for specific model and field (as well as allow to set it globally)

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@andrykonchin wouldn't the default value of false make it backwards compatible with any existing implementation?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@pboling It would, sure.
But you could want to keep old format for existing tables and new format for new ones. You couldn't use new format if already have data in old one in any table.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh, I see. Agreed, this has to be model-specific per field.

end
end

include_examples 'dump_datetime_attributes'
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would wrap it with context context 'when convert_date_to_string == false' do

user = User.create(last_logged_in_at: time)
user = User.find(user.id)
expect(user.dump[:last_logged_in_at]).to be_a(String)
expect(user.dump[:last_logged_in_at]).to eq '2017-06-20T05:00:00+00:00'
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The test passes only because it runs in UTC timezone and it fails when local time zone isn't UTC.
You should set application_timezone='UTC' for this test case. It's local by default

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ideally we would have tests for multiple time zones for any feature based on parsing time.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@pboling Agree, but I didn't find a way to change timezone in tests. We can travel in time with Timecop but we cannot change timezone.

Copy link
Member

@pboling pboling left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

New option option :convert_date_to_string, default: false must be model specific per field, not global.

@william101 william101 force-pushed the william/add_option_to_store_datetimes_as_strings branch from d1d558d to 7963591 Compare January 12, 2018 10:42
@william101 william101 force-pushed the william/add_option_to_store_datetimes_as_strings branch from 7963591 to a85fc93 Compare January 12, 2018 10:43
@coveralls
Copy link

coveralls commented Jan 12, 2018

Coverage Status

Coverage increased (+0.02%) to 97.346% when pulling a85fc93 on pratik60:william/add_option_to_store_datetimes_as_strings into fb9db64 on Dynamoid:master.

README.md Outdated
class Document
include DynamoId::Document

field :sent_at, :datetime, convert_date_to_string: true
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We already have similar option for boolean field store_as_native_boolean

field :active, :boolean, store_as_native_boolean: true

It makes sense to name new option in similar way

@pboling What do you think?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Again, it may be useful to apply this new option globally and override it for specific field

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should follow existing naming patterns. 👍

@coveralls
Copy link

coveralls commented Jan 12, 2018

Coverage Status

Coverage increased (+0.02%) to 97.346% when pulling a85fc93 on pratik60:william/add_option_to_store_datetimes_as_strings into fb9db64 on Dynamoid:master.

@coveralls
Copy link

Coverage Status

Coverage increased (+0.03%) to 97.356% when pulling f5282a6 on pratik60:william/add_option_to_store_datetimes_as_strings into fb9db64 on Dynamoid:master.

2 similar comments
@coveralls
Copy link

Coverage Status

Coverage increased (+0.03%) to 97.356% when pulling f5282a6 on pratik60:william/add_option_to_store_datetimes_as_strings into fb9db64 on Dynamoid:master.

@coveralls
Copy link

coveralls commented Jan 15, 2018

Coverage Status

Coverage increased (+0.03%) to 97.356% when pulling f5282a6 on pratik60:william/add_option_to_store_datetimes_as_strings into fb9db64 on Dynamoid:master.

Copy link
Member

@pboling pboling left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This now addresses everything except @andrykonchin 's suggestion to make the setting an optional global setting with a per model override.

Copy link
Member

@andrykonchin andrykonchin left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Other improvements like global option or support string format for date fields can be done in separate PRs

@pboling pboling merged commit 451ff9a into Dynamoid:master Jan 16, 2018
@william101 william101 deleted the william/add_option_to_store_datetimes_as_strings branch January 17, 2018 10:44
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

5 participants