Module: DecisionAgent::Dsl::Helpers::DateHelpers

Defined in:
lib/decision_agent/dsl/helpers/date_helpers.rb

Overview

Date/time helper methods for ConditionEvaluator

Constant Summary collapse

ALLOWED_COMPARISON_OPERATORS =
i[< > <= >= ==].freeze

Class Method Summary collapse

Class Method Details

.compare_dates(actual_value, expected_value, operator, parse_date:) ⇒ Object

Raises:

  • (ArgumentError)


51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
# File 'lib/decision_agent/dsl/helpers/date_helpers.rb', line 51

def self.compare_dates(actual_value, expected_value, operator, parse_date:)
  return false unless actual_value && expected_value

  op = operator.to_sym
  raise ArgumentError, "Unsupported comparison operator: #{operator}" unless ALLOWED_COMPARISON_OPERATORS.include?(op)

  # Fast path: Both are already Time/Date objects (no parsing needed)
  actual_is_date = actual_value.is_a?(Time) || actual_value.is_a?(Date) || actual_value.is_a?(DateTime)
  expected_is_date = expected_value.is_a?(Time) || expected_value.is_a?(Date) || expected_value.is_a?(DateTime)
  return actual_value.public_send(op, expected_value) if actual_is_date && expected_is_date

  # Slow path: Parse dates (with caching)
  actual_date = parse_date.call(actual_value)
  expected_date = parse_date.call(expected_value)

  return false unless actual_date && expected_date

  actual_date.public_send(op, expected_date)
end

.normalize_day_of_week(value) ⇒ Object



71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
# File 'lib/decision_agent/dsl/helpers/date_helpers.rb', line 71

def self.normalize_day_of_week(value)
  case value
  when Numeric
    value.to_i % 7
  when String
    day_map = {
      "sunday" => 0, "sun" => 0,
      "monday" => 1, "mon" => 1,
      "tuesday" => 2, "tue" => 2,
      "wednesday" => 3, "wed" => 3,
      "thursday" => 4, "thu" => 4,
      "friday" => 5, "fri" => 5,
      "saturday" => 6, "sat" => 6
    }
    day_map[value.downcase]
  end
end

.parse_date(value, get_cached_date:) ⇒ Object



38
39
40
41
42
43
44
45
46
47
# File 'lib/decision_agent/dsl/helpers/date_helpers.rb', line 38

def self.parse_date(value, get_cached_date:)
  case value
  when Time, Date, DateTime
    value
  when String
    get_cached_date.call(value)
  end
rescue ArgumentError
  nil
end

.parse_date_fast(date_string) ⇒ Object



8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
# File 'lib/decision_agent/dsl/helpers/date_helpers.rb', line 8

def self.parse_date_fast(date_string)
  return nil unless date_string.is_a?(String)

  # Fast-path: ISO8601 date format (YYYY-MM-DD)
  if date_string.match?(/^\d{4}-\d{2}-\d{2}$/)
    year, month, day = date_string.split("-").map(&:to_i)
    begin
      return Time.new(year, month, day)
    rescue StandardError => e
      warn "[DecisionAgent] Failed to parse date '#{date_string}': #{e.message}"
      nil
    end
  end

  # Fast-path: ISO8601 datetime format (YYYY-MM-DDTHH:MM:SS or YYYY-MM-DDTHH:MM:SSZ)
  if date_string.match?(/^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}/)
    begin
      # Try ISO8601 parsing first (faster than Time.parse for this format)
      return Time.iso8601(date_string)
    rescue ArgumentError
      # Fall through to Time.parse
    end
  end

  # Fallback to Time.parse for other formats
  Time.parse(date_string)
rescue ArgumentError, TypeError
  nil
end