class ISO8601::Date

A Date representation.

@example

d = ISO8601::Date.new('2014-05-28')
d.year  # => 2014
d.month # => 5

@example Week dates

d = ISO8601::Date.new('2014-W15-2')
d.day   # => 27
d.wday  # => 2
d.week # => 15

Attributes

atoms[R]

The original atoms

separator[R]

The separator used in the original ISO 8601 string.

Public Class Methods

new(input) click to toggle source

@param [String] input The date pattern

# File lib/iso8601/date.rb, line 36
def initialize(input)
  @original = input
  @atoms = atomize(input)
  @date = compose(@atoms)
end

Public Instance Methods

+(other) click to toggle source

Forwards the date the given amount of days.

@param [Numeric] other The days to add

@return [ISO8601::Date] New date resulting of the addition

# File lib/iso8601/date.rb, line 56
def +(other)
  other = other.to_days if other.respond_to?(:to_days)
  ISO8601::Date.new((@date + other).iso8601)
end
-(other) click to toggle source

Backwards the date the given amount of days.

@param [Numeric] other The days to remove

@return [ISO8601::Date] New date resulting of the substraction

# File lib/iso8601/date.rb, line 67
def -(other)
  other = other.to_days if other.respond_to?(:to_days)
  ISO8601::Date.new((@date - other).iso8601)
end
==(other) click to toggle source

@param [#hash] other The contrast to compare against

@return [Boolean]

# File lib/iso8601/date.rb, line 82
def ==(other)
  (hash == other.hash)
end
eql?(other) click to toggle source

@param [#hash] other The contrast to compare against

@return [Boolean]

# File lib/iso8601/date.rb, line 90
def eql?(other)
  (hash == other.hash)
end
hash() click to toggle source

@return [Fixnum]

# File lib/iso8601/date.rb, line 96
def hash
  [atoms, self.class].hash
end
to_a() click to toggle source

Converts self to an array of atoms.

# File lib/iso8601/date.rb, line 74
def to_a
  [year, month, day]
end
week() click to toggle source

The calendar week number (1-53)

@return [Integer]

# File lib/iso8601/date.rb, line 46
def week
  @date.cweek
end

Private Instance Methods

atomize(input) click to toggle source

Splits the date component into valid atoms.

Acceptable patterns:

  • YYYY

  • YYYY-MM but not YYYYMM

  • YYYY-MM-DD, YYYYMMDD

  • YYYY-Www, YYYYWdd

  • YYYY-Www-D, YYYYWddD

  • YYYY-DDD, YYYYDDD

@param [String] input

@return [Array<Integer>]

rubocop:disable Metrics/AbcSize

# File lib/iso8601/date.rb, line 119
def atomize(input)
  week_date = parse_weekdate(input)
  return atomize_week_date(input, week_date[2], week_date[1]) unless week_date.nil?

  _, sign, year, separator, day = parse_ordinal(input)
  return atomize_ordinal(year, day, separator, sign) unless year.nil?

  _, year, separator, month, day = parse_date(input)

  raise(ISO8601::Errors::UnknownPattern, @original) if year.nil?

  @separator = separator

  [year, month, day].compact.map(&:to_i)
end
atomize_ordinal(year, day, separator, sign) click to toggle source

Parses an ordinal date (YYYY-DDD) and returns its atoms.

@param [String] year in YYYY form. @param [String] day in DDD form. @param [String] separator the separator found in the input. @param [String] sign the sign found in the input.

@return [Array<Integer>] date atoms.

# File lib/iso8601/date.rb, line 181
def atomize_ordinal(year, day, separator, sign)
  date = parse([year, day].join('-'))
  sign = "#{sign}1".to_i
  @separator = separator

  [sign * date.year, date.month, date.day]
end
atomize_week_date(input, separator, sign) click to toggle source

Parses a week date (YYYY-Www-D, YYYY-Www) and returns its atoms.

@param [String] input the date string. @param [String] separator the separator found in the input. @param [String] sign the sign found in the input.

@return [Array<Integer>] date atoms.

# File lib/iso8601/date.rb, line 164
def atomize_week_date(input, separator, sign)
  date = parse(input)
  sign = "#{sign}1".to_i
  @separator = separator

  [sign * date.year, date.month, date.day]
end
compose(atoms) click to toggle source

Wraps ::Date.new to play nice with ArgumentError.

@param [Array<Integer>] atoms The date atoms.

@return [::Date]

# File lib/iso8601/date.rb, line 207
def compose(atoms)
  ::Date.new(*atoms)
rescue ArgumentError
  raise ISO8601::Errors::RangeError, @original
end
parse(string) click to toggle source

Wraps ::Date.parse to play nice with ArgumentError.

@param [String] string The formatted date.

@return [::Date]

# File lib/iso8601/date.rb, line 195
def parse(string)
  ::Date.parse(string)
rescue ArgumentError
  raise ISO8601::Errors::RangeError, @original
end
parse_date(input) click to toggle source
# File lib/iso8601/date.rb, line 144
def parse_date(input)
  /^
    ([+-]?\d{4})   # YYYY
    (?:
      (-?)(\d{2})  # YYYY-MM
      (?:
        \2(\d{2})  # YYYY-MM-DD
      )?
    )?
  $/x.match(input).to_a.compact
end
parse_ordinal(input) click to toggle source
# File lib/iso8601/date.rb, line 140
def parse_ordinal(input)
  /^([+-]?)(\d{4})(-?)(\d{3})$/.match(input).to_a.compact
end
parse_weekdate(input) click to toggle source

rubocop:enable Metrics/AbcSize

# File lib/iso8601/date.rb, line 136
def parse_weekdate(input)
  /^([+-]?)\d{4}(-?)W\d{2}(?:\2\d)?$/.match(input)
end