Skip to content

Commit

Permalink
Implements timestamp with time zone ranges
Browse files Browse the repository at this point in the history
  • Loading branch information
danmcclain committed Jun 14, 2013
1 parent 69a5d04 commit 992550f
Show file tree
Hide file tree
Showing 3 changed files with 97 additions and 6 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ def type_cast_with_extended_types(value)
when :inet, :cidr then klass.string_to_cidr_address(value)
when :numrange,:int4range,:int8range then klass.string_to_numeric_range(value,type)
when :daterange then klass.string_to_date_range(value)
when :tsrange then klass.string_to_datetime_range(value)
when :tsrange,:tstzrange then klass.string_to_datetime_range(value)
else
type_cast_without_extended_types(value)
end
Expand Down Expand Up @@ -87,7 +87,7 @@ def type_cast_code_with_extended_types(var_name)
when :inet, :cidr then "#{klass}.string_to_cidr_address(#{var_name})"
when :numrange,:int4range,:int8range then "#{klass}.string_to_numeric_range(#{var_name},#{type.inspect})"
when :daterange then "#{klass}.string_to_date_range(#{var_name})"
when :tsrange then "#{klass}.string_to_datetime_range(#{var_name})"
when :tsrange,:tstzrange then "#{klass}.string_to_datetime_range(#{var_name})"
else
type_cast_code_without_extended_types(var_name)
end
Expand All @@ -98,7 +98,7 @@ def type_cast_code_with_extended_types(var_name)
if RUBY_PLATFORM =~ /java/
def default_value_with_extended_types(default)
case default
when /\A'(.*)'::(?:(num|int[48]|date|ts)range)\z/
when /\A'(.*)'::(?:(num|int[48]|date|ts(tz)?)range)\z/
$1
else
default_value_without_extended_types(default)
Expand All @@ -112,7 +112,7 @@ class << self
unless RUBY_PLATFORM =~ /java/
def extract_value_from_default_with_extended_types(default)
case default
when /\A'(.*)'::(?:(num|int[48]|date|ts)range)\z/
when /\A'(.*)'::(?:(num|int[48]|date|ts(tz)?)range)\z/
$1
else
extract_value_from_default_without_extended_types(default)
Expand Down Expand Up @@ -378,7 +378,9 @@ def type_cast_extended(value, column, part_array = false)
type_cast_without_extended_types(value, column)
end
when Date, DateTime, Time
if [:tsrange].include?(column.type)
if column.type == :tstzrange
quoted_date(value)
elsif column.type == :tsrange
value.to_s(:db)
else
type_cast_without_extended_types(value, column)
Expand Down
2 changes: 1 addition & 1 deletion spec/dummy/config/application.rb
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ class Application < Rails::Application

# Set Time.zone default to the specified zone and make Active Record auto-convert to this zone.
# Run "rake -D time" for a list of tasks for finding time zone names. Default is UTC.
# config.time_zone = 'Central Time (US & Canada)'
config.time_zone = 'Eastern Time (US & Canada)'

# The default locale is :en and all translations from config/locales/*.rb,yml are auto loaded.
# config.i18n.load_path += Dir[Rails.root.join('my', 'locales', '*.{rb,yml}').to_s]
Expand Down
89 changes: 89 additions & 0 deletions spec/models/ranges/tstzrange_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
require 'spec_helper'

describe 'Models with tstzrange columns' do
let!(:adapter) { ActiveRecord::Base.connection }

context 'no default value, range' do
before do
adapter.create_table :tstz_rangers, :force => true do |t|
t.tstzrange :best_estimate
end
class TstzRanger < ActiveRecord::Base
attr_accessible :best_estimate
end
end

after do
adapter.drop_table :tstz_rangers
Object.send(:remove_const, :TstzRanger)
end

describe '#create' do
it 'creates an record when there is no assignment' do
range = TstzRanger.create()
range.reload
range.best_estimate.should eq nil
end

it 'creates an record with a range' do
ts_range = Time.new(2011, 01, 01, 12, 34)..Time.new(2012, 01, 31, 8, 0, 1)
range = TstzRanger.create( :best_estimate => ts_range)
range.reload
range.best_estimate.should eq ts_range
end
end

describe 'range assignment' do
it 'updates an record with an range string' do
ts_range = Time.new(2011, 01, 01, 12, 34)..Time.new(2012, 01, 31, 8, 0, 1)
new_ts_range = Time.new(2012, 01, 01, 11, 0, 0)..Time.new(2012, 02, 01, 13, 0, 0)
range = TstzRanger.create( :best_estimate => ts_range)
range.best_estimate = new_ts_range
range.save

range.reload
range.best_estimate.should eq new_ts_range
end

it 'converdate empty strings to nil' do
range = TstzRanger.create
range.best_estimate = ''
range.save

range.reload
range.best_estimate.should eq nil
end
end
end

context 'default value, ts range' do
before do
adapter.create_table :tstz_default_rangers, :force => true do |t|
t.tstzrange :best_estimate, :default => Time.new(2011, 01, 01, 12, 34, 0, '-07:00')..Time.new(2011, 01, 31, 1, 0, 0, '-07:00')
end
class TstzDefaultRanger < ActiveRecord::Base
attr_accessible :best_estimate
end
end

after do
adapter.drop_table :tstz_default_rangers
Object.send(:remove_const, :TstzDefaultRanger)
end

describe '#create' do
it 'creates an record when there is no assignment' do
range = TstzDefaultRanger.create()
range.reload
range.best_estimate.should eq Time.new(2011, 01, 01, 12, 34,0, '-07:00')..Time.new(2011, 01, 31, 1, 0, 0, '-07:00')
end

it 'creates an record with a range' do
new_ts_range = Time.new(2012, 01, 01, 9, 0, 0, '-05:00')..Time.new(2012, 12, 31, 9, 0, 0, '-05:00')
range = TstzDefaultRanger.create(:best_estimate => new_ts_range)
range.reload
range.best_estimate.should eq new_ts_range
end
end
end
end

0 comments on commit 992550f

Please sign in to comment.