class ISO8601::Time
A Time
representation
@example
t = Time.new('10:11:12') t = Time.new('T10:11:12.5Z') t.hour # => 10 t.minute # => 11 t.second # => 12.5 t.zone # => '+00:00'
Attributes
The original atoms
The second atom
The separator used in the original ISO 8601 string.
Public Class Methods
@param [String] input The time pattern @param [Date] base The base date to determine the time
# File lib/iso8601/time.rb, line 38 def initialize(input, base = ::Date.today) @original = input @base = base @atoms = atomize(input) @time = compose(@atoms, @base) @second = @time.second + @time.second_fraction.to_f.round(1) end
Public Instance Methods
Forwards the time the given amount of seconds.
@param [Numeric] other The seconds to add
@return [ISO8601::Time] New time resulting of the addition
# File lib/iso8601/time.rb, line 74 def +(other) moment = @time.to_time.localtime(zone) + other.to_f.round(1) base = ::Date.parse(moment.strftime('%Y-%m-%d')) self.class.new(moment.strftime('T%H:%M:%S.%L%:z'), base) end
Backwards the date the given amount of seconds.
@param [Numeric] other The seconds to remove
@return [ISO8601::Time] New time resulting of the substraction
# File lib/iso8601/time.rb, line 87 def -(other) moment = @time.to_time.localtime(zone) - other.to_f.round(1) base = ::Date.parse(moment.strftime('%Y-%m-%d')) self.class.new(moment.strftime('T%H:%M:%S.%L%:z'), base) end
@param [#hash] other The contrast to compare against
@return [Boolean]
# File lib/iso8601/time.rb, line 50 def ==(other) (hash == other.hash) end
@param [#hash] other The contrast to compare against
@return [Boolean]
# File lib/iso8601/time.rb, line 58 def eql?(other) (hash == other.hash) end
@return [Fixnum]
# File lib/iso8601/time.rb, line 64 def hash [atoms, self.class].hash end
Converts self to an array of atoms.
# File lib/iso8601/time.rb, line 104 def to_a [hour, minute, second, zone] end
Converts self to a time component representation.
# File lib/iso8601/time.rb, line 96 def to_s second_format = format((second % 1).zero? ? '%02d' : '%04.1f', second) format("T%02d:%02d:#{second_format}#{zone}", *atoms) end
Private Instance Methods
Splits the time component into valid atoms. Acceptable patterns: hh, hh:mm or hhmm and hh:mm:ss or hhmmss. Any form can be prepended by `T`.
@param [String] input
@return [Array<Integer, Float>]
rubocop:disable Metrics/AbcSize
# File lib/iso8601/time.rb, line 120 def atomize(input) _, time, zone = parse_timezone(input) _, hour, separator, minute, second = parse_time(time) raise(ISO8601::Errors::UnknownPattern, @original) if hour.nil? @separator = separator require_separator = require_separator(minute) hour = hour.to_i minute = minute.to_i second = parse_second(second) atoms = [hour, minute, second, zone].compact raise(ISO8601::Errors::UnknownPattern, @original) unless valid_zone?(zone, require_separator) atoms end
Wraps ::DateNew.new to play nice with ArgumentError.
@param [Array<Integer>] atoms The time atoms. @param [::Date] base The base date to start computing time.
@return [::DateTime]
# File lib/iso8601/time.rb, line 183 def compose(atoms, base) ::DateTime.new(base.year, base.month, base.day, *atoms) rescue ArgumentError raise ISO8601::Errors::RangeError, @original end
# File lib/iso8601/time.rb, line 157 def parse_second(second) second.nil? ? 0.0 : second.tr(',', '.').to_f end
# File lib/iso8601/time.rb, line 149 def parse_time(time) /^(?: (\d{2})(:?)(\d{2})\2(\d{2}(?:[.,]\d+)?) | (\d{2})(:?)(\d{2}) | (\d{2}) )$/x.match(time).to_a.compact end
# File lib/iso8601/time.rb, line 145 def parse_timezone(timezone) /^T?(.+?)(Z|[+-].+)?$/.match(timezone).to_a end
rubocop:enable Metrics/AbcSize
# File lib/iso8601/time.rb, line 141 def require_separator(input) !input.nil? end
@param [String] zone The timezone offset as Z or +-hh. @param [Boolean] require_separator
Flag to determine if the separator
consistency check is required as patterns with only hour atom have no separator but the timezone can.
# File lib/iso8601/time.rb, line 166 def valid_zone?(zone, require_separator) zone_regexp = /^(Z|[+-]\d{2}(?:(:?)\d{2})?)$/ _, offset, separator = zone_regexp.match(zone).to_a.compact wrong_pattern = !zone.nil? && offset.nil? invalid_separators = zone.to_s.match(/^[+-]\d{2}:?\d{2}$/) && (@separator != separator) if require_separator !(wrong_pattern || invalid_separators) end