Module: GovCodes::Dafecd::Text

Defined in:
lib/gov_codes/dafecd/text.rb

Overview

Shared text utilities for the DAFECD extractor: normalization of pdf-reader glue artifacts and date parsing. Used by RecordSplitter, SpecialtyParser, and the extractor CLI so the behavior stays consistent.

Constant Summary collapse

MONTHS =
%w[jan feb mar apr may jun jul aug sep oct nov dec]
.each_with_index.to_h { |m, i| [m, i + 1] }.freeze
DEFAULT_GLUED_AFSC =

Default (enlisted) glue boundary: a letter immediately followed by an "AFSC <5-char enlisted code>".

/(?<=[A-Za-z])(?=AFSC \d[A-Z]\d\d\d)/

Class Method Summary collapse

Class Method Details

.parse_date(raw) ⇒ Object

Normalize a directory date such as "31 Oct 25", "31 Oct 2024", or the officer directory's glued "30Apr 25" to ISO 8601 ("2025-10-31" / "2024-10-31"). The day/month gap is optional (\s*) to absorb pdf-reader's glued day/month; the enlisted (always-spaced) dates are unaffected. Returns nil when unparseable.



37
38
39
40
41
42
43
44
45
# File 'lib/gov_codes/dafecd/text.rb', line 37

def parse_date(raw)
  return nil unless raw =~ /(\d{1,2})\s*(\w{3,9})\s+(\d{2,4})/
  day = $1.to_i
  month = MONTHS[$2[0, 3].downcase]
  year = $3.to_i
  year += 2000 if year < 100
  return nil unless month
  format("%04d-%02d-%02d", year, month, day)
end

.split_glued_afsc(text, pattern = DEFAULT_GLUED_AFSC) ⇒ Object

pdf-reader frequently glues the word "AFSC" to a preceding word when a ladder line wraps, e.g. "LeaderAFSC 1A178*, Craftsman". Insert a newline before an "AFSC " that is glued to a letter so the ladder line is detectable at line start. This is safe for prose mentions such as "possession ofAFSC 1A132" because ladder detection additionally requires a skill-level word at end of line, which prose lines do not satisfy.

The glue boundary is publication-specific (the enlisted and officer AFSC code shapes differ); pass the publication's pattern to override the enlisted default.



28
29
30
# File 'lib/gov_codes/dafecd/text.rb', line 28

def split_glued_afsc(text, pattern = DEFAULT_GLUED_AFSC)
  text.gsub(pattern, "\n")
end