module Sequel::Postgres::ExtendedDateSupport

Constants

CONVERT_TYPES

:nocov:

DATETIME_YEAR_1
DATE_YEAR_1
INFINITE_DATETIME_VALUES
INFINITE_TIMESTAMP_STRINGS
MINUS_DATE_INFINITY
PLUS_DATE_INFINITY
TIME_YEAR_1

Attributes

convert_infinite_timestamps[R]

Whether infinite timestamps/dates should be converted on retrieval. By default, no conversion is done, so an error is raised if you attempt to retrieve an infinite timestamp/date. You can set this to :nil to convert to nil, :string to leave as a string, or :float to convert to an infinite float.

Public Class Methods

extended(db) click to toggle source

Add dataset methods and update the conversion proces for dates and timestamps.

# File lib/sequel/extensions/pg_extended_date_support.rb, line 34
def self.extended(db)
  db.extend_datasets(DatasetMethods)
  procs = db.conversion_procs
  procs[1082] = ::Sequel.method(:string_to_date)
  procs[1184] = procs[1114] = db.method(:to_application_timestamp)
end

Public Instance Methods

convert_infinite_timestamps=(v) click to toggle source

Set whether to allow infinite timestamps/dates. Make sure the conversion proc for date reflects that setting.

# File lib/sequel/extensions/pg_extended_date_support.rb, line 49
def convert_infinite_timestamps=(v)
  @convert_infinite_timestamps = case v
  when Symbol
    v
  when 'nil'
    :nil
  when 'string'
    :string
  when 'date'
    :date
  when 'float'
    :float
  when String, true
    typecast_value_boolean(v)
  else
    false
  end

  pr = old_pr = Sequel.method(:string_to_date)
  if @convert_infinite_timestamps
    pr = lambda do |val|
      case val
      when *INFINITE_TIMESTAMP_STRINGS
        infinite_timestamp_value(val)
      else
        old_pr.call(val)
      end
    end
  end
  add_conversion_proc(1082, pr)
end
to_application_timestamp(value) click to toggle source

Handle BC dates in timestamps by moving the BC from after the time to after the date, to appease ruby's date parser. If #convert_infinite_timestamps is true and the value is infinite, return an appropriate value based on the #convert_infinite_timestamps setting.

Calls superclass method
# File lib/sequel/extensions/pg_extended_date_support.rb, line 85
def to_application_timestamp(value)
  if value.is_a?(String) && (m = value.match(/(?:(?:[-+]\d\d:\d\d)(:\d\d)?)?( BC)?\z/)) && (m[1] || m[2])
    if m[2]
      value = value.sub(' BC', '').sub(' ', ' BC ')
      conv = defined?(JRUBY_VERSION) && JRUBY_VERSION == '9.2.0.0'
    end
    if m[1] || conv
      dt = DateTime.parse(value)
      if conv
        # :nocov:
        if Sequel.datetime_class == DateTime
          dt >>= 12
        else
          dt >>= 24
        end
        # :nocov:
      end
      dt = dt.to_time unless Sequel.datetime_class == DateTime
      Sequel.convert_output_timestamp(dt, Sequel.application_timezone)
    else
      super(value)
    end
  elsif convert_infinite_timestamps
    case value
    when *INFINITE_TIMESTAMP_STRINGS
      infinite_timestamp_value(value)
    else
      super
    end
  else
    super
  end
end

Private Instance Methods

infinite_timestamp_value(value) click to toggle source

Return an appropriate value for the given infinite timestamp string.

# File lib/sequel/extensions/pg_extended_date_support.rb, line 122
def infinite_timestamp_value(value)
  case convert_infinite_timestamps
  when :nil
    nil
  when :string
    value
  when :date
    value == 'infinity' ? PLUS_DATE_INFINITY : MINUS_DATE_INFINITY
  else
    value == 'infinity' ? PLUS_INFINITY : MINUS_INFINITY
  end
end
typecast_value_date(value) click to toggle source

If the value is an infinite value (either an infinite float or a string returned by by PostgreSQL for an infinite date), return it without converting it if #convert_infinite_timestamps is set.

Calls superclass method
# File lib/sequel/extensions/pg_extended_date_support.rb, line 138
def typecast_value_date(value)
  if convert_infinite_timestamps
    case value
    when *INFINITE_DATETIME_VALUES
      value
    else
      super
    end
  else
    super
  end
end
typecast_value_datetime(value) click to toggle source

If the value is an infinite value (either an infinite float or a string returned by by PostgreSQL for an infinite timestamp), return it without converting it if #convert_infinite_timestamps is set.

Calls superclass method
# File lib/sequel/extensions/pg_extended_date_support.rb, line 154
def typecast_value_datetime(value)
  if convert_infinite_timestamps
    case value
    when *INFINITE_DATETIME_VALUES
      value
    else
      super
    end
  else
    super
  end
end