module Sequel::Postgres::ExtendedDateSupport

Constants

CONVERT_TYPES

:nocov:

DATETIME_YEAR_1
INFINITE_DATETIME_VALUES
INFINITE_TIMESTAMP_STRINGS
MINUS_DATE_INFINITY
PLUS_DATE_INFINITY
RATIONAL_60
TIME_CAN_PARSE_BC
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)
  if ocps = db.instance_variable_get(:@oid_convertor_map)
    # Clear the oid convertor map entries for timestamps if they
    # exist, so it will regenerate new ones that use this extension.
    # This is only taken when using the jdbc adapter.
    Sequel.synchronize do
      ocps.delete(1184)
      ocps.delete(1114)
    end
  end
end

Public Instance Methods

bound_variable_arg(arg, conn) click to toggle source

Handle BC dates and times in bound variables. This is necessary for Date values when using both the postgres and jdbc adapters, but also necessary for Time values on jdbc.

Calls superclass method
# File lib/sequel/extensions/pg_extended_date_support.rb, line 53
def bound_variable_arg(arg, conn)
  case arg
  when Time, Date
    @default_dataset.literal_date_or_time(arg)
  else
    super
  end
end
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 70
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 106
def to_application_timestamp(value)
  if value.is_a?(String) && (m = /((?:[-+]\d\d:\d\d)(:\d\d)?)?( BC)?\z/.match(value)) && (m[2] || m[3])
    if m[3]
      value = value.sub(' BC', '').sub(' ', ' BC ')
    end
    if m[2]
      dt = if Sequel.datetime_class == DateTime
        DateTime.parse(value)
      elsif TIME_CAN_PARSE_BC
        Time.parse(value)
      # :nocov:
      else
        DateTime.parse(value).to_time
      # :nocov:
      end

      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 141
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 157
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 173
def typecast_value_datetime(value)
  if convert_infinite_timestamps
    case value
    when *INFINITE_DATETIME_VALUES
      value
    else
      super
    end
  else
    super
  end
end