Last active
October 4, 2017 22:21
-
-
Save benmmurphy/e3d6ef6f4545683132ae2eb23c3840cb to your computer and use it in GitHub Desktop.
time ambiguity
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# frozen_string_literal: true | |
begin | |
require "bundler/inline" | |
rescue LoadError => e | |
$stderr.puts "Bundler version 1.10 or later is required. Please update your Bundler" | |
raise e | |
end | |
gemfile(true) do | |
source "https://rubygems.org" | |
git_source(:github) { |repo| "https://github.com/#{repo}.git" } | |
gem "rails", "5.1.4" | |
gem "activerecord", "5.1.4" | |
gem "sqlite3" | |
end | |
require "active_support/railtie" | |
require "action_controller/railtie" | |
require "active_record" | |
ActiveRecord::Base.establish_connection(adapter: "sqlite3", database: ":memory:") | |
ActiveRecord::Base.logger = Logger.new(STDOUT) | |
ActiveRecord::Schema.define do | |
create_table :events, force: true do |t| | |
t.timestamp :start_datetime | |
end | |
end | |
class Event < ActiveRecord::Base | |
end | |
class TestApp < Rails::Application | |
config.root = __dir__ | |
secrets.secret_key_base = "secret_key_base" | |
config.logger = Logger.new($stdout) | |
Rails.logger = config.logger | |
config.time_zone = "Europe/London" | |
routes.draw do | |
put "/events/:id" => "events#update" | |
end | |
end | |
class EventsController < ActionController::Base | |
include Rails.application.routes.url_helpers | |
def update | |
@event = Event.find(params[:id]) | |
if @event.update(params.require(:event).permit(:start_datetime)) | |
render plain: "Event was successfully updated." | |
else | |
render plain: "Event was failed to update." | |
end | |
end | |
end | |
require "minitest/autorun" | |
require "rack/test" | |
Time.zone_default = Time.find_zone!("Europe/London") | |
ActiveRecord::Base.time_zone_aware_attributes = true | |
class BugTest < Minitest::Test | |
include Rack::Test::Methods | |
def test_update_at_ambiguous_time | |
# this date is 2017/10/29 1:00 Europe/London | |
# however, 2017/10/29 1:00 Europe/London happens at two times | |
# 2017/10/29 1:00 UTC | |
# 2017/10/29 0:00 UTC | |
# When rails converts back from local->UTC it always chooses | |
# the first one | |
time = ActiveSupport::TimeZone["UTC"].parse("2017/10/29 1:00") | |
event = Event.new(start_datetime: time) | |
event.save(validate: false) | |
event.reload | |
year = event.start_datetime.year | |
assert_equal(2017, year) | |
month = event.start_datetime.month | |
assert_equal(10, month) | |
day = event.start_datetime.day | |
assert_equal(29, day) | |
hour = event.start_datetime.hour | |
assert_equal(1, hour) | |
minute = event.start_datetime.min | |
assert_equal(0, minute) | |
put "/events/#{event.id}", | |
"event"=>{"start_datetime(1i)"=> year.to_s, | |
"start_datetime(2i)"=> month.to_s, | |
"start_datetime(3i)"=>day.to_s, | |
"start_datetime(4i)"=>hour.to_s, | |
"start_datetime(5i)"=>minute.to_s} | |
assert last_response.ok? | |
event.reload | |
assert_equal(time, event.start_datetime) | |
end | |
def test_update_in_ambiguous_time_zone | |
time = ActiveSupport::TimeZone["UTC"].parse("2017/10/29 3:00") | |
event = Event.new(start_datetime: time) | |
event.save(validate: false) | |
year = event.start_datetime.year | |
assert_equal(2017, year) | |
month = event.start_datetime.month | |
assert_equal(10, month) | |
day = event.start_datetime.day | |
assert_equal(29, day) | |
hour = event.start_datetime.hour | |
assert_equal(3, hour) | |
minute = event.start_datetime.min | |
assert_equal(0, minute) | |
put "/events/#{event.id}", | |
"event"=>{"start_datetime(1i)"=> year.to_s, | |
"start_datetime(2i)"=> month.to_s, | |
"start_datetime(3i)"=>day.to_s, | |
"start_datetime(4i)"=>hour.to_s, | |
"start_datetime(5i)"=>minute.to_s} | |
assert last_response.ok? | |
event.reload | |
assert_equal(time, event.start_datetime) | |
end | |
private | |
def app | |
Rails.application | |
end | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment