Class: Mods::Date

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

Defined Under Namespace

Classes: CenturyFormat, DecadeAsYearDashFormat, EdtfFormat, EmbeddedBCYearFormat, EmbeddedThreeDigitYearFormat, EmbeddedYearFormat, EmbeddedYearWithBracketsFormat, ExtractorDateFormat, Iso8601Format, MMDDYYFormat, MMDDYYYYFormat, MarcFormat, MysteryCenturyFormat, OneOrTwoDigitYearFormat, RomanNumeralCenturyFormat, RomanNumeralYearFormat, 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.


286
287
288
289
# File 'lib/mods/date.rb', line 286

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


263
264
265
# File 'lib/mods/date.rb', line 263

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

def self.from_element(xml)
  case xml.attr(:encoding)
  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 = Mods::Date if xml.text =~ /\p{Hebrew}/
    date_class ||= [
      MMDDYYYYFormat,
      MMDDYYFormat,
      YearRangeFormat,
      DecadeAsYearDashFormat,
      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)

279
280
281
282
283
284
# File 'lib/mods/date.rb', line 279

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:


270
271
272
273
# File 'lib/mods/date.rb', line 270

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)

401
402
403
# File 'lib/mods/date.rb', line 401

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)

296
297
298
299
300
# File 'lib/mods/date.rb', line 296

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)

337
338
339
# File 'lib/mods/date.rb', line 337

def encoding
  xml.attr(:encoding)
end

#encoding?Boolean

Was an encoding provided?

Returns:

  • (Boolean)

353
354
355
# File 'lib/mods/date.rb', line 353

def encoding?
  !encoding.nil?
end

#end?Boolean

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

Returns:

  • (Boolean)

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

def end?
  point == 'end'
end

#inferred?Boolean

Is the date declared as an inferred date?

Returns:

  • (Boolean)

409
410
411
# File 'lib/mods/date.rb', line 409

def inferred?
  qualifier == 'inferred'
end

#key?Boolean

Is the date marked as a keyDate?

Returns:

  • (Boolean)

345
346
347
# File 'lib/mods/date.rb', line 345

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

#pointString

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

Returns:

  • (String)

361
362
363
# File 'lib/mods/date.rb', line 361

def point
  xml.attr(:point)
end

#precisionObject


421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
# File 'lib/mods/date.rb', line 421

def precision
  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)

393
394
395
# File 'lib/mods/date.rb', line 393

def qualifier
  xml.attr(:qualifier)
end

#questionable?Boolean

Is the date declared as a questionable date?

Returns:

  • (Boolean)

417
418
419
# File 'lib/mods/date.rb', line 417

def questionable?
  qualifier == 'questionable'
end

#single?Boolean

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

Returns:

  • (Boolean)

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

def single?
  point.nil?
end

#start?Boolean

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

Returns:

  • (Boolean)

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

def start?
  point == 'start'
end

#textString

The text as encoded in the MODS

Returns:

  • (String)

321
322
323
# File 'lib/mods/date.rb', line 321

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)

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

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)

329
330
331
# File 'lib/mods/date.rb', line 329

def type
  xml.attr(:type)
end