Ruby Sequel gem允许在不进行时区转换、转换为本地时区或转换为时区的情况下检索日期时间。在这三种情况下,当windows客户端操作系统上的时区设置与Ruby中的时区设置冲突时,我们在转换为日光节约时都会得到不可用的结果。例如:
require 'sequel'
require_relative './ojdbc8.jar'
username = 'username'
password = 'password'
host = 'host'
port = 1521
sid = 'ORCL'
connection_string = "jdbc:oracle:thin:#{username}/#{password}@#{host}:#{port}:#{sid}"
puts "connection_string: #{connection_string}"
ENV['TZ'] = 'Etc/GMT-10'
# ENV['TZ'] = '+10:00'
db = Sequel.connect(connection_string)
db.drop_table :d
db.create_table :d do
primary_key :id
DateTime :DATETIME, unique: true, null: false
Integer :HOUR, null: false
end
# Using Time with TZ set to GMT+10
d = db[:d]
(1..4).each do|hour|
t = Time.new(2022, 10, 2, hour, 0, 0)
puts "time: #{t}"
d.insert(DATETIME: t, HOUR: hour)
end
sql = "SELECT * FROM d"
Sequel.default_timezone = :utc
dataset = db[sql]
puts "UTC timezone"
dataset.each do |row|
puts "row: #{row}"
end
Sequel.default_timezone = :local
dataset = db[sql]
puts "Local timezone..."
dataset.each do |row|
puts "row: #{row}"
end
Sequel.default_timezone = nil
dataset = db[sql]
puts "nil timezone (no conversion)..."
dataset.each do |row|
puts "row: #{row}"
end
使用Windows时区运行上述操作
(UTC+10) Canberra, Melbourne, Sydney
和
Adjust for Daylights Savings
设置为true将导致以下结果:
time: 2022-10-02 01:00:00 +1000
time: 2022-10-02 02:00:00 +1000
time: 2022-10-02 03:00:00 +1000
time: 2022-10-02 04:00:00 +1000
UTC timezone
row: {:id=>1, :datetime=>2022-10-02 01:00:00 UTC, :hour=>1}
row: {:id=>2, :datetime=>2022-10-02 03:00:00 UTC, :hour=>2}
row: {:id=>3, :datetime=>2022-10-02 03:00:00 UTC, :hour=>3}
row: {:id=>4, :datetime=>2022-10-02 04:00:00 UTC, :hour=>4}
Local timezone...
row: {:id=>1, :datetime=>2022-10-02 01:00:00 +1000, :hour=>1}
row: {:id=>2, :datetime=>2022-10-02 03:00:00 +1000, :hour=>2}
row: {:id=>3, :datetime=>2022-10-02 03:00:00 +1000, :hour=>3}
row: {:id=>4, :datetime=>2022-10-02 04:00:00 +1000, :hour=>4}
nil timezone (no conversion)...
row: {:id=>1, :datetime=>2022-10-02 01:00:00 +1000, :hour=>1}
row: {:id=>2, :datetime=>2022-10-02 03:00:00 +1000, :hour=>2}
row: {:id=>3, :datetime=>2022-10-02 03:00:00 +1000, :hour=>3}
row: {:id=>4, :datetime=>2022-10-02 04:00:00 +1000, :hour=>4}
请注意,在所有情况下,小时2和3返回的Time对象都是相同的。小时2不正确。鉴于TZ环境变量在代码中明确设置,如果
:local
选项为
Sequel.default_timezone = :local
使用TZ时区,而不是使用windows中的其他信息。请注意,如果TZ变量设置为非空值,则
Time
它本身将尊重这一设置,超越Windows设置。
数据库中的实际DATETIME列没有时区信息。
我还尝试了使用
named_timezones
扩展,但存在与上述相同的问题。这包括使用DateTime类而不是Time类。
我们发现的唯一解决方案是使用
TO_CHAR()
函数将DATETIME列转换为字符串。
还有其他人解决了这个问题吗?
当使用JRuby 9.4.0.0和与Oracle的JDBC连接时,会出现上述问题。我在MRI和SQLite中使用了非常相似的代码,并且没有出现所描述的问题。使用MRI时,default_timezone=nil或:utc可以正常工作,如果:local和named_timezone与Datetime和Time类都可以正常工作。