class ActiveSupport::Duration::ISO8601Serializer
:nodoc:
Serializes duration to string according to ISO 8601 Duration format.
def initialize(duration, precision: nil)
Serializes duration to string according to ISO 8601 Duration format.
def initialize(duration, precision: nil) @duration = duration @precision = precision end
def normalize
Zero parts are removed as not significant.
Parts are summarized (as they can become repetitive due to addition, etc).
Return pair of duration's parts and whole duration sign.
def normalize parts = @duration.parts.each_with_object(Hash.new(0)) do |(k, v), p| p[k] += v unless v.zero? end # If all parts are negative - let's make a negative duration sign = "" if parts.values.all? { |v| v < 0 } sign = "-" parts.transform_values!(&:-@) end [parts, sign] end
def serialize
def serialize parts, sign = normalize return "PT0S" if parts.empty? output = +"P" output << "#{parts[:years]}Y" if parts.key?(:years) output << "#{parts[:months]}M" if parts.key?(:months) output << "#{parts[:weeks]}W" if parts.key?(:weeks) output << "#{parts[:days]}D" if parts.key?(:days) time = +"" time << "#{parts[:hours]}H" if parts.key?(:hours) time << "#{parts[:minutes]}M" if parts.key?(:minutes) if parts.key?(:seconds) time << "#{sprintf(@precision ? "%0.0#{@precision}f" : '%g', parts[:seconds])}S" end output << "T#{time}" unless time.empty? "#{sign}#{output}" end