Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

improve date/time parsing and arithmetic #306

Closed
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
4 changes: 3 additions & 1 deletion lib/dentaku/date_arithmetic.rb
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ def add(duration)

def sub(duration)
case duration
when DateTime, Numeric
when Date, DateTime, Numeric
@base - duration
when Dentaku::AST::Duration::Value
case duration.unit
Expand All @@ -40,6 +40,8 @@ def sub(duration)
when :day
@base - duration.value
end
when Dentaku::TokenScanner::DATE_TIME_REGEXP
@base - Time.parse(duration).to_datetime
else
raise Dentaku::ArgumentError.for(:incompatible_type, value: duration, for: Numeric),
"'#{duration || duration.class}' is not coercible for date arithmetic"
Expand Down
2 changes: 1 addition & 1 deletion lib/dentaku/token_scanner.rb
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ module Dentaku
class TokenScanner
extend StringCasing

DATE_TIME_REGEXP = /\d{2}\d{2}?-\d{1,2}-\d{1,2}( \d{1,2}:\d{1,2}:\d{1,2})? ?(Z|((\+|\-)\d{2}\:?\d{2}))?(?!\d)/.freeze
DATE_TIME_REGEXP = /\d{2}\d{2}?-\d{1,2}-\d{1,2}([ |T]\d{1,2}:\d{1,2}:\d{1,2}(\.\d*)?)? ?(Z|((\+|\-)\d{2}\:?\d{2}))?(?!\d)/.freeze

def initialize(category, regexp, converter = nil, condition = nil)
@category = category
Expand Down
12 changes: 8 additions & 4 deletions spec/calculator_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -471,16 +471,20 @@

it 'from string variable' do
value = '2023-01-01'
value2 = '2022-12-31'

expect(calculator.evaluate!('value + duration(1, month)', { value: value }).to_date).to eql(Date.parse('2023-02-01'))
expect(calculator.evaluate!('value - duration(1, month)', { value: value }).to_date).to eql(Date.parse('2022-12-01'))
expect(calculator.evaluate!('value + duration(1, month)', { value: value }).to_date).to eq(Date.parse('2023-02-01'))
expect(calculator.evaluate!('value - duration(1, month)', { value: value }).to_date).to eq(Date.parse('2022-12-01'))
expect(calculator.evaluate!('value - value2', { value: value, value2: value2 })).to eq(1)
end

it 'from date object' do
value = Date.parse('2023-01-01').to_date
value2 = Date.parse('2022-12-31').to_date

expect(calculator.evaluate!('value + duration(1, month)', { value: value }).to_date).to eql(Date.parse('2023-02-01'))
expect(calculator.evaluate!('value - duration(1, month)', { value: value }).to_date).to eql(Date.parse('2022-12-01'))
expect(calculator.evaluate!('value + duration(1, month)', { value: value }).to_date).to eq(Date.parse('2023-02-01'))
expect(calculator.evaluate!('value - duration(1, month)', { value: value }).to_date).to eq(Date.parse('2022-12-01'))
expect(calculator.evaluate!('value - value2', { value: value, value2: value2 })).to eq(1)
end
end

Expand Down
10 changes: 6 additions & 4 deletions spec/tokenizer_spec.rb
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
require 'dentaku/exceptions'
require 'dentaku/tokenizer'

describe Dentaku::Tokenizer do
Expand Down Expand Up @@ -234,9 +235,9 @@
end

it 'tokenizes Time literals' do
tokens = tokenizer.tokenize('2017-01-01 2017-01-2 2017-1-03 2017-01-04 12:23:42 2017-1-5 1:2:3 2017-1-06 1:02:30 2017-01-07 12:34:56 Z 2017-01-08 1:2:3 +0800')
expect(tokens.length).to eq(8)
expect(tokens.map(&:category)).to eq([:datetime, :datetime, :datetime, :datetime, :datetime, :datetime, :datetime, :datetime])
tokens = tokenizer.tokenize('2017-01-01 2017-01-2 2017-1-03 2017-01-04 12:23:42 2017-1-5 1:2:3 2017-1-06 1:02:30 2017-01-07 12:34:56 Z 2017-01-08 1:2:3 +0800 2017-01-08T01:02:03.456Z')
expect(tokens.length).to eq(9)
expect(tokens.map(&:category)).to eq([:datetime, :datetime, :datetime, :datetime, :datetime, :datetime, :datetime, :datetime, :datetime])
expect(tokens.map(&:value)).to eq([
Time.local(2017, 1, 1).to_datetime,
Time.local(2017, 1, 2).to_datetime,
Expand All @@ -245,7 +246,8 @@
Time.local(2017, 1, 5, 1, 2, 3).to_datetime,
Time.local(2017, 1, 6, 1, 2, 30).to_datetime,
Time.utc(2017, 1, 7, 12, 34, 56).to_datetime,
Time.new(2017, 1, 8, 1, 2, 3, "+08:00").to_datetime
Time.new(2017, 1, 8, 1, 2, 3, "+08:00").to_datetime,
Time.utc(2017, 1, 8, 1, 2, 3, 456000).to_datetime
])
end

Expand Down