module Sequel::Timezones
def application_to_database_timestamp(v)
Convert the given +Time+/+DateTime+ object into the database timezone, used when
def application_to_database_timestamp(v) convert_output_timestamp(v, Sequel.database_timezone) end
def convert_input_datetime_no_offset(v, input_timezone)
Convert the given +DateTime+ to the given input_timezone, keeping the
def convert_input_datetime_no_offset(v, input_timezone) case input_timezone when :utc, nil v # DateTime assumes UTC if no offset is given when :local offset = local_offset_for_datetime(v) v.new_offset(offset) - offset else convert_input_datetime_other(v, input_timezone) end end
def convert_input_datetime_other(v, input_timezone)
by default (i.e. one other than +nil+, :local, or :utc). Raises an +InvalidValue+ by default.
Convert the given +DateTime+ to the given input_timezone that is not supported
def convert_input_datetime_other(v, input_timezone) raise InvalidValue, "Invalid input_timezone: #{input_timezone.inspect}" end
def convert_input_timestamp(v, input_timezone)
instance of Sequel.datetime_class. If given an array or a string that doesn't
Converts the object from a +String+, +Array+, +Date+, +DateTime+, or +Time+ into an
def convert_input_timestamp(v, input_timezone) case v when String v2 = Sequel.string_to_datetime(v) if !input_timezone || Date._parse(v).has_key?(:offset) v2 else # Correct for potentially wrong offset if string doesn't include offset if v2.is_a?(DateTime) v2 = convert_input_datetime_no_offset(v2, input_timezone) else # Time assumes local time if no offset is given v2 = v2.getutc + v2.utc_offset if input_timezone == :utc end v2 end when Array y, mo, d, h, mi, s, ns, off = v if datetime_class == DateTime s += (defined?(Rational) ? Rational(ns, 1000000000) : ns/1000000000.0) if ns if off DateTime.civil(y, mo, d, h, mi, s, off) else convert_input_datetime_no_offset(DateTime.civil(y, mo, d, h, mi, s), input_timezone) end else Time.send(input_timezone == :utc ? :utc : :local, y, mo, d, h, mi, s, (ns ? ns / 1000.0 : 0)) end when Hash ary = [:year, :month, :day, :hour, :minute, :second, :nanos].map{|x| (v[x] || v[x.to_s]).to_i} if (offset = (v[:offset] || v['offset'])) ary << offset end convert_input_timestamp(ary, input_timezone) convert_input_timestamp(ary, input_timezone) when Time if datetime_class == DateTime v.respond_to?(:to_datetime) ? v.to_datetime : string_to_datetime(v.iso8601) else v end when DateTime if datetime_class == DateTime v else v.respond_to?(:to_time) ? v.to_time : string_to_datetime(v.to_s) end else raise InvalidValue, "Invalid convert_input_timestamp type: #{v.inspect}" end end
def convert_output_datetime_other(v, output_timezone)
by default (i.e. one other than +nil+, :local, or :utc). Raises an +InvalidValue+ by default.
Convert the given +DateTime+ to the given output_timezone that is not supported
def convert_output_datetime_other(v, output_timezone) raise InvalidValue, "Invalid output_timezone: #{output_timezone.inspect}" end
def convert_output_timestamp(v, output_timezone)
def convert_output_timestamp(v, output_timezone) if output_timezone if v.is_a?(DateTime) case output_timezone when :utc v.new_offset(0) when :local v.new_offset(local_offset_for_datetime(v)) else convert_output_datetime_other(v, output_timezone) end else v.send(output_timezone == :utc ? :getutc : :getlocal) end else v end end
def convert_timestamp(v, input_timezone)
+application_timezone+ using +convert_input_timestamp+ and
Converts the given object from the given input timezone to the
def convert_timestamp(v, input_timezone) begin if v.is_a?(Date) && !v.is_a?(DateTime) # Dates handled specially as they are assumed to already be in the application_timezone if datetime_class == DateTime DateTime.civil(v.year, v.month, v.day, 0, 0, 0, application_timezone == :local ? (defined?(Rational) ? Rational(Time.local(v.year, v.month, v.day).utc_offset, 86400) : Time.local(v.year, v.month, v.day).utc_offset/86400.0) : 0) else Time.send(application_timezone == :utc ? :utc : :local, v.year, v.month, v.day) end else convert_output_timestamp(convert_input_timestamp(v, input_timezone), application_timezone) end rescue InvalidValue raise rescue => e raise convert_exception_class(e, InvalidValue) end end
def convert_timezone_setter_arg(tz)
Convert the timezone setter argument. Returns argument given by default,
def convert_timezone_setter_arg(tz) tz end
def database_to_application_timestamp(v)
+application_timezone+. Used when coverting datetime/timestamp columns
Convert the given object into an object of Sequel.datetime_class in the
def database_to_application_timestamp(v) convert_timestamp(v, Sequel.database_timezone) end
def default_timezone=(tz)
def default_timezone=(tz) self.database_timezone = tz self.application_timezone = tz self.typecast_timezone = tz end
def local_offset_for_datetime(dt)
def local_offset_for_datetime(dt) time_offset_to_datetime_offset Time.local(dt.year, dt.month, dt.day, dt.hour, dt.min, dt.sec).utc_offset end
def time_offset_to_datetime_offset(offset_secs)
def time_offset_to_datetime_offset(offset_secs) @local_offsets ||= {} @local_offsets[offset_secs] ||= respond_to?(:Rational, true) ? Rational(offset_secs, 60*60*24) : offset_secs/60/60/24.0 end
def typecast_to_application_timestamp(v)
+application_timezone+. Used when typecasting values when assigning them
Convert the given object into an object of Sequel.datetime_class in the
def typecast_to_application_timestamp(v) convert_timestamp(v, Sequel.typecast_timezone) end