Class: Mods::Date

Inherits:
Object
  • Object
show all
Defined in:
lib/mods/date.rb

Defined Under Namespace

Classes: CenturyFormat, DecadeAsYearDashFormat, DecadeStringFormat, EdtfFormat, EmbeddedBCYearFormat, EmbeddedThreeDigitYearFormat, EmbeddedYearFormat, EmbeddedYearWithBracketsFormat, ExtractorDateFormat, Iso8601Format, MMDDYYFormat, MMDDYYYYFormat, MarcFormat, MysteryCenturyFormat, OneOrTwoDigitYearFormat, RomanNumeralCenturyFormat, RomanNumeralYearFormat, UnparseableDate, W3cdtfFormat, YearRangeFormat

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(xml) ⇒ Date

Returns a new instance of Date.



315
316
317
318
# File 'lib/mods/date.rb', line 315

def initialize(xml)
  @xml = xml
  @date = self.class.parse_date(xml.text.strip)
end

Instance Attribute Details

#dateObject (readonly)

Returns the value of attribute date.



292
293
294
# File 'lib/mods/date.rb', line 292

def date
  @date
end

#xmlObject (readonly)

Returns the value of attribute xml.



5
6
7
# File 'lib/mods/date.rb', line 5

def xml
  @xml
end

Class Method Details

.from_element(xml) ⇒ Mods::Date

Ugly date factory that tries to pick an appropriate parser for the type of data.

Parameters:

  • xml (Nokogiri::XML::Element)

    A date-flavored MODS field from the XML

Returns:



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
# File 'lib/mods/date.rb', line 13

def self.from_element(xml)
  case xml.attr(:encoding)&.downcase
  when 'w3cdtf'
    Mods::Date::W3cdtfFormat.new(xml)
  when 'iso8601'
    Mods::Date::Iso8601Format.new(xml)
  when 'marc'
    Mods::Date::MarcFormat.new(xml)
  when 'edtf'
    Mods::Date::EdtfFormat.new(xml)
  # when 'temper'
  #   Mods::Date::TemperFormat.new(xml)
  else
    date_class = UnparseableDate if xml.text =~ /\p{Hebrew}/ || xml.text =~ /^-/
    date_class ||= [
      MMDDYYYYFormat,
      MMDDYYFormat,
      YearRangeFormat,
      DecadeAsYearDashFormat,
      DecadeStringFormat,
      EmbeddedBCYearFormat,
      EmbeddedYearFormat,
      EmbeddedThreeDigitYearFormat,
      EmbeddedYearWithBracketsFormat,
      MysteryCenturyFormat,
      CenturyFormat,
      RomanNumeralCenturyFormat,
      RomanNumeralYearFormat,
      OneOrTwoDigitYearFormat
    ].select { |klass| klass.supports? xml.text }.first

    (date_class || Mods::Date).new(xml)
  end
rescue
  Mods::Date.new(xml)
end

.normalize_to_edtf(text) ⇒ String

Apply any encoding-specific munging or text extraction logic

Parameters:

  • text (String)

Returns:

  • (String)


308
309
310
311
312
313
# File 'lib/mods/date.rb', line 308

def self.normalize_to_edtf(text)
  sanitized = text.gsub(/^[\[]+/, '').gsub(/[\.\]]+$/, '')
  sanitized = text.rjust(4, "0") if text =~ /^\d{3}$/

  sanitized
end

.parse_date(text) ⇒ Date

Parse a string to a Date or EDTF::Date using rules appropriate to the given encoding

Parameters:

  • text (String)

Returns:



299
300
301
302
# File 'lib/mods/date.rb', line 299

def self.parse_date(text)
  return nil if text == '0000-00-00'
  ::Date.edtf(normalize_to_edtf(text))
end

Instance Method Details

#approximate?Boolean

Is the date declared as an approximate date?

Returns:

  • (Boolean)


436
437
438
# File 'lib/mods/date.rb', line 436

def approximate?
  qualifier == 'approximate'
end

#as_rangeObject

Return a range, with the min point as the earliest possible date and the max as the latest possible date (useful particularly for ranges and uncertainty)

Parameters:

  • (Range)


325
326
327
328
329
# File 'lib/mods/date.rb', line 325

def as_range
  return unless earliest_date && latest_date

  earliest_date..latest_date
end

#encodingString

The declared encoding of date (from the MODS @encoding attribute)

Returns:

  • (String)


368
369
370
371
372
# File 'lib/mods/date.rb', line 368

def encoding
  return if xml.attr(:encoding)&.empty?

  xml.attr(:encoding)&.downcase
end

#encoding?Boolean

Was an encoding provided?

Returns:

  • (Boolean)


386
387
388
# File 'lib/mods/date.rb', line 386

def encoding?
  !encoding.nil?
end

#end?Boolean

Is this date the end point of a MODS-encoded range?

Returns:

  • (Boolean)


420
421
422
# File 'lib/mods/date.rb', line 420

def end?
  point == 'end'
end

#inferred?Boolean

Is the date declared as an inferred date?

Returns:

  • (Boolean)


444
445
446
# File 'lib/mods/date.rb', line 444

def inferred?
  qualifier == 'inferred'
end

#key?Boolean

Is the date marked as a keyDate?

Returns:

  • (Boolean)


378
379
380
# File 'lib/mods/date.rb', line 378

def key?
  xml.attr(:keyDate) == 'yes'
end

#pointString

The declared point of date (from the MODS @point attribute)

Returns:

  • (String)


394
395
396
397
398
# File 'lib/mods/date.rb', line 394

def point
  return if xml.attr(:point)&.empty?

  xml.attr(:point)&.downcase
end

#precisionObject



456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
# File 'lib/mods/date.rb', line 456

def precision
  return :unknown unless date_range || date

  if date_range.is_a? EDTF::Century
    :century
  elsif date_range.is_a? EDTF::Decade
    :decade
  else
    case date.precision
    when :month
      date.unspecified.unspecified?(:month) ? :year : :month
    when :day
      d = date.unspecified.unspecified?(:day) ? :month : :day
      d = date.unspecified.unspecified?(:month) ? :year : d
      d
    else
      date.precision
    end
  end
end

#qualifierString

The declared qualifier of date (from the MODS @qualifier attribute)

Returns:

  • (String)


428
429
430
# File 'lib/mods/date.rb', line 428

def qualifier
  xml.attr(:qualifier)&.downcase
end

#questionable?Boolean

Is the date declared as a questionable date?

Returns:

  • (Boolean)


452
453
454
# File 'lib/mods/date.rb', line 452

def questionable?
  qualifier == 'questionable'
end

#single?Boolean

Is this date stand-alone, or part of a MODS-encoded range?

Returns:

  • (Boolean)


404
405
406
# File 'lib/mods/date.rb', line 404

def single?
  point.nil?
end

#start?Boolean

Is this date the start of a MODS-encoded range?

Returns:

  • (Boolean)


412
413
414
# File 'lib/mods/date.rb', line 412

def start?
  point == 'start'
end

#textString

The text as encoded in the MODS

Returns:

  • (String)


350
351
352
# File 'lib/mods/date.rb', line 350

def text
  xml.text
end

#to_aArray

Return an array of all years that fall into the range of possible dates covered by the data. Note that some encodings support disjoint sets of ranges so this method could provide more accuracy than #as_range (although potentially) include a really big list of dates

Returns:

  • (Array)


338
339
340
341
342
343
344
345
# File 'lib/mods/date.rb', line 338

def to_a
  case date
  when EDTF::Set
    date.to_a
  else
    as_range.to_a
  end
end

#typeString

The declared type of date (from the MODS @type attribute)

Returns:

  • (String)


358
359
360
361
362
# File 'lib/mods/date.rb', line 358

def type
  return if xml.attr(:type)&.empty?

  xml.attr(:type)&.downcase
end