Skip to content

Commit f1e286d

Browse files
cyclotron3kaidan-sh
authored andcommitted
Fixes #6 - Parsing of timestamps with microsecond precision (without require 'time')
1 parent 600c1c4 commit f1e286d

File tree

2 files changed

+54
-5
lines changed

2 files changed

+54
-5
lines changed

lib/db/postgres/native/types.rb

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -99,12 +99,16 @@ def initialize(name = "TIMESTAMP")
9999
attr :name
100100

101101
def parse(string)
102-
if match = string.match(/(\d+)-(\d+)-(\d+) (\d+):(\d+):(\d+)([\+\-].*)?/)
103-
parts = match.captures
104-
parts[6] ||= "UTC"
105-
106-
return Time.new(*parts)
102+
return nil unless match = string.match(/\A(\d+)-(\d+)-(\d+) (\d+):(\d+):(\d+(?:\.\d+)?)([-+].*)?\z/)
103+
parts = match.captures
104+
parts[5] = BigDecimal(parts[5])
105+
if parts[6].nil?
106+
parts[6] = '+00:00'
107+
elsif /^[-+]\d\d$/ === parts[6]
108+
parts[6] += ':00'
107109
end
110+
111+
Time.new(*parts)
108112
end
109113
end
110114

spec/db/postgres/connection_spec.rb

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,51 @@
6666
ensure
6767
connection.close
6868
end
69+
70+
it "can get timestamps with microseconds and tz" do
71+
[{
72+
# PG produces: "2022-11-11 12:38:59.123456+00"
73+
zone: 'UTC',
74+
time: '2022-11-11 23:38:59.123456+11',
75+
result: Time.new(2022, 11, 11, 23, 38, BigDecimal('59.123456'), '+11:00'),
76+
}, {
77+
# PG produces: "2022-11-11 12:38:59+00"
78+
zone: 'UTC',
79+
time: '2022-11-11 23:38:59+11',
80+
result: Time.new(2022, 11, 11, 23, 38, BigDecimal('59'), '+11:00'),
81+
}, {
82+
# PG produces: "2022-11-11 23:38:59.123456+00"
83+
zone: 'UTC',
84+
time: '2022-11-11 23:38:59.123456',
85+
result: Time.new(2022, 11, 11, 23, 38, BigDecimal('59.123456'), '+00:00'),
86+
}, {
87+
# PG produces: "2022-11-11 23:38:59+11"
88+
zone: 'Australia/Sydney',
89+
time: '2022-11-11 23:38:59',
90+
result: Time.new(2022, 11, 11, 23, 38, BigDecimal('59'), '+11:00'),
91+
}, {
92+
# PG produces: "2022-11-12 06:08:59.123456+11"
93+
zone: 'Australia/Sydney',
94+
time: '2022-11-11 23:38:59.123456+04:30',
95+
result: Time.new(2022, 11, 11, 23, 38, BigDecimal('59.123456'), '+04:30'),
96+
}, {
97+
# PG produces: "2000-01-01 05:30:00+05:30"
98+
zone: 'Asia/Kolkata',
99+
time: '2000-01-01 00:00:00+00',
100+
result: Time.new(2000, 1, 1, 5, 30, 0, '+05:30'),
101+
}].each do |spec|
102+
103+
connection.send_query("SET TIME ZONE '#{spec[:zone]}'");
104+
connection.send_query("SELECT '#{spec[:time]}'::TIMESTAMPTZ AS TS")
105+
106+
result = connection.next_result
107+
row = result.to_a.first
108+
109+
expect(row.first).to be == spec[:result]
110+
end
111+
ensure
112+
connection.close
113+
end
69114

70115
describe '#append_string' do
71116
it "should escape string" do

0 commit comments

Comments
 (0)