Module: DateParser

Defined in:
lib/date_parser.rb

Class Method Summary collapse

Class Method Details

.parse_date_string(date_str, from_beginning = true) ⇒ Date?

Best effort date parsing from multiple formats.

Parameters:

  • date_str (String)

    The date string to parse.

  • from_beginning (Boolean) (defaults to: true)

    If true, returns the beginning of the date (e.g., first day of month or year).

Returns:

  • (Date, nil)

    Returns a Date object if parsing is successful, or nil if parsing fails.



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
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
# File 'lib/date_parser.rb', line 11

def self.parse_date_string(date_str, from_beginning = true)
  return nil if date_str.nil?
  return nil if date_str.empty?
  return nil if date_str.length > 10

  # Try to parse basic format YYYY-MM-DD
  begin
    return Date.strptime(date_str, '%Y-%m-%d') if date_str.match(/^\d{4}-\d{1,2}-\d{1,2}$/)
  rescue Date::Error
    # puts "Date not in format YYYY-MM-DD."
  end

  # Try to parse format YYYY-MM
  begin
    if date_str.match(/^\d{4}-\d{1,2}$/)
      d = Date.strptime(date_str, '%Y-%m')
      return d if from_beginning

      return Date.new(d.year, d.month, -1)

    end
  rescue Date::Error
    # puts "Date not in format YYYY-MM."
  end

  # Try to parse format YYYY (without Q1234)
  if date_str.match(/^\d{4}$/)
    d = Date.strptime(date_str, '%Y')
    return d if from_beginning

    return Date.new(d.year, -1, -1)

  end

  # Long form quarter (2024-Q1, etc.)
  match = date_str.match(/(\d{4})-[qQ]([1234])/)
  if match
    year, quarter = match.captures.map(&:to_i)
    d = Date.new(year, ((quarter - 1) * 3) + 1, 1)
    return d if from_beginning

    return Date.new(d.year, d.month + 2, -1)

  end

  # Short form quarter
  match = date_str.match(/[qQ]([1234])/)
  return unless match

  quarter = match.captures.first.to_i
  d = Date.new(Date.today.year, ((quarter - 1) * 3) + 1, 1)
  return d if from_beginning

  Date.new(d.year, d.month + 2, -1)
end

.parse_date_string!(date_str, from_beginning = true) ⇒ Object

Similar to parse_date_string, but raises an error if parsing fails.

Raises:

  • (ArgumentError)


68
69
70
71
72
73
# File 'lib/date_parser.rb', line 68

def self.parse_date_string!(date_str, from_beginning = true)
  date = parse_date_string(date_str, from_beginning)
  raise ArgumentError, "Could not parse date string: \"#{date_str}\"" if date.nil?

  date
end