Module: USQualityCoreTestKit::DateSearchValidation

Included in:
SearchTest
Defined in:
lib/us_quality_core_test_kit/date_search_validation.rb

Instance Method Summary collapse

Instance Method Details

#date?(value) ⇒ Boolean

Returns:

  • (Boolean)


118
119
120
# File 'lib/us_quality_core_test_kit/date_search_validation.rb', line 118

def date?(value)
  /^\d{4}(-\d{2})?(-\d{2})?$/.match?(value) # YYYY or YYYY-MM or YYYY-MM-DD
end

#fhir_date_comparer(search_range, target_range, comparator, extend_start: false, extend_end: false) ⇒ Object



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
66
67
68
69
# File 'lib/us_quality_core_test_kit/date_search_validation.rb', line 41

def fhir_date_comparer(search_range, target_range, comparator, extend_start: false, extend_end: false)
  # Implicitly, a missing lower boundary is "less than" any actual date. A missing upper boundary is "greater than" any actual date.
  case comparator
  when 'eq' # the range of the search value fully contains the range of the target value
    !target_range[:start].nil? && !target_range[:end].nil? && search_range[:start] <= target_range[:start] && search_range[:end] >= target_range[:end]
  when 'ne' # the range of the search value does not fully contain the range of the target value
    target_range[:start].nil? || target_range[:end].nil? || search_range[:start] > target_range[:start] || search_range[:end] < target_range[:end]
  when 'gt' #  the range above the search value intersects (i.e. overlaps) with the range of the target value
    target_range[:end].nil? || search_range[:end] < target_range[:end] || (search_range[:end] < (target_range[:end] + 1) && extend_end)
  when 'lt' # the range below the search value intersects (i.e. overlaps) with the range of the target value
    target_range[:start].nil? || search_range[:start] > target_range[:start] || (search_range[:start] > (target_range[:start] - 1) && extend_start)
  when 'ge'
    fhir_date_comparer(search_range, target_range, 'gt', extend_start:, extend_end:) || fhir_date_comparer(search_range, target_range, 'eq')
  when 'le'
    fhir_date_comparer(search_range, target_range, 'lt', extend_start:, extend_end:) || fhir_date_comparer(search_range, target_range, 'eq')
  when 'sa' # the range above the search value contains the range of the target value
    !target_range[:start].nil? && search_range[:end] < target_range[:start]
  when 'eb' # the range below the search value contains the range of the target value
    !target_range[:end].nil? && search_range[:start] > target_range[:end]
  when 'ap' # the range of the search value overlaps with the range of the target value
    if target_range[:start].nil? || target_range[:end].nil?
      (target_range[:start].nil? && search_range[:start] < target_range[:end]) ||
        (target_range[:end].nil? && search_range[:end] > target_range[:start])
    else
      (search_range[:start] >= target_range[:start] && search_range[:start] <= target_range[:end]) ||
        (search_range[:end] >= target_range[:start] && search_range[:end] <= target_range[:end])
    end
  end
end

#get_fhir_datetime_range(datetime) ⇒ Object



5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
# File 'lib/us_quality_core_test_kit/date_search_validation.rb', line 5

def get_fhir_datetime_range(datetime)
  range = { start: DateTime.xmlschema(datetime), end: nil }
  range[:end] =
    case datetime
    when /^\d{4}$/ # YYYY
      range[:start].next_year - 1.seconds
    when /^\d{4}-\d{2}$/ # YYYY-MM
      range[:start].next_month - 1.seconds
    when /^\d{4}-\d{2}-\d{2}$/ # YYYY-MM-DD
      range[:start].next_day - 1.seconds
    else # YYYY-MM-DDThh:mm:ss+zz:zz
      range[:start]
    end
  range
end

#get_fhir_period_range(period) ⇒ Object



21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
# File 'lib/us_quality_core_test_kit/date_search_validation.rb', line 21

def get_fhir_period_range(period)
  range = { start: nil, end: nil }
  range[:start] = DateTime.xmlschema(period.start) unless period.start.nil?
  return range if period.end.nil?

  period_end_beginning = DateTime.xmlschema(period.end)
  range[:end] =
    case period.end
    when /^\d{4}$/ # YYYY
      period_end_beginning.next_year - 1.seconds
    when /^\d{4}-\d{2}$/ # YYYY-MM
      period_end_beginning.next_month - 1.seconds
    when /^\d{4}-\d{2}-\d{2}$/ # YYYY-MM-DD
      period_end_beginning.next_day - 1.seconds
    else # YYYY-MM-DDThh:mm:ss+zz:zz
      period_end_beginning
    end
  range
end

#validate_date_search(search_value, target_value) ⇒ Object



71
72
73
74
75
76
77
# File 'lib/us_quality_core_test_kit/date_search_validation.rb', line 71

def validate_date_search(search_value, target_value)
  if target_value.instance_of? FHIR::Period
    validate_period_search(search_value, target_value)
  else
    validate_datetime_search(search_value, target_value)
  end
end

#validate_datetime_search(search_value, target_value) ⇒ Object



79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
# File 'lib/us_quality_core_test_kit/date_search_validation.rb', line 79

def validate_datetime_search(search_value, target_value)
  comparator = search_value[0..1]
  if %w[eq ge gt le lt ne sa eb ap].include? comparator
    search_value = search_value[2..]
  else
    comparator = 'eq'
  end
  search_is_date = date?(search_value)
  target_is_date = date?(target_value)
  search_range = get_fhir_datetime_range(search_value)
  target_range = get_fhir_datetime_range(target_value)
  fhir_date_comparer(
    search_range,
    target_range,
    comparator,
    extend_start: !search_is_date && target_is_date,
    extend_end: !search_is_date && target_is_date
  )
end

#validate_period_search(search_value, target_value) ⇒ Object



99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
# File 'lib/us_quality_core_test_kit/date_search_validation.rb', line 99

def validate_period_search(search_value, target_value)
  comparator = search_value[0..1]
  if %w[eq ge gt le lt ne sa eb ap].include? comparator
    search_value = search_value[2..]
  else
    comparator = 'eq'
  end
  search_is_date = date?(search_value)
  search_range = get_fhir_datetime_range(search_value)
  target_range = get_fhir_period_range(target_value)
  fhir_date_comparer(
    search_range,
    target_range,
    comparator,
    extend_start: !search_is_date && date?(target_value.start),
    extend_end: !search_is_date && date?(target_value.end)
  )
end