Class: Arclight::YearRange

Inherits:
Object
  • Object
show all
Defined in:
lib/arclight/year_range.rb

Overview

A range of years that handles gaps, such as [1999, 2000, 2002]. Primary usage is: “‘ range = YearRange.new(’1999/2004’) range.years => [1999, 2000, 2001, 2002, 2003, 2004] range.to_s => ‘1999-2004’ range << range.parse_ranges() range.years => [1999, 2000, 2001, 2002, 2003, 2004, 2010] range.to_s => ‘1999-2004, 2010’ “‘

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(dates = nil) ⇒ YearRange

Returns a new instance of YearRange.

Parameters:

  • `dates` (Array<String>)

    in the form YYYY/YYYY



18
19
20
21
# File 'lib/arclight/year_range.rb', line 18

def initialize(dates = nil)
  @years = []
  self << parse_ranges(dates) if dates.present?
end

Instance Attribute Details

#yearsObject

Returns the value of attribute years.



15
16
17
# File 'lib/arclight/year_range.rb', line 15

def years
  @years
end

Instance Method Details

#<<(other) ⇒ Object

Parameters:

  • `other` (Array<Integer>)

    the set of years to add



32
33
34
35
36
37
38
# File 'lib/arclight/year_range.rb', line 32

def <<(other)
  return self if other.blank?

  @years |= other # will remove duplicates
  @years.sort!
  self
end

#gaps?Boolean

Returns are there gaps between the years, such as 1999, 2000, 2002?.

Returns:

  • (Boolean)

    are there gaps between the years, such as 1999, 2000, 2002?



68
69
70
71
72
# File 'lib/arclight/year_range.rb', line 68

def gaps?
  return false if years.blank?

  (years.min..years.max).to_a != years
end

#parse_range(dates) ⇒ Array<Integer>

Returns the set of years in the given range.

Parameters:

  • `dates` (String)

    in the form YYYY/YYYY

Returns:

  • (Array<Integer>)

    the set of years in the given range

Raises:

  • (ArgumentError)


42
43
44
45
46
47
48
49
50
51
# File 'lib/arclight/year_range.rb', line 42

def parse_range(dates)
  return if dates.blank?

  start_year, end_year = dates.split('/').map { |date| to_year_from_iso8601(date) }
  return [start_year] if end_year.blank?
  raise ArgumentError, "Range is too large: #{dates}" if (end_year - start_year) > 1000
  raise ArgumentError, "Range is inverted: #{dates}" unless start_year <= end_year

  (start_year..end_year).to_a
end

#parse_ranges(dates) ⇒ Array<Integer>

Returns the set of years in the given range.

Parameters:

  • `dates` (Array<String>)

    in the form YYYY/YYYY

Returns:

  • (Array<Integer>)

    the set of years in the given range



55
56
57
# File 'lib/arclight/year_range.rb', line 55

def parse_ranges(dates)
  dates.map { |date| parse_range(date) }.flatten.sort.uniq
end

#to_sString

Returns a concise, human-readable version of the year range, including gaps.

Returns:

  • (String)

    a concise, human-readable version of the year range, including gaps



24
25
26
27
28
29
# File 'lib/arclight/year_range.rb', line 24

def to_s
  return if years.empty?
  return to_s_for_streak(years) unless gaps?

  to_s_with_gaps
end

#to_year_from_iso8601(date) ⇒ Object

Parameters:

  • `date` (String)

    a date in one of these formats: YYYY, YYYY-MM, YYYY-MM-DD, and YYYYMMDD



61
62
63
64
65
# File 'lib/arclight/year_range.rb', line 61

def to_year_from_iso8601(date)
  return if date.blank?

  date.split('-').first[0..3].to_i # Time.parse doesn't work here
end