Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Conflict with ISO8601 serializer and parser on ActiveSupport::Duration #34655

Closed
crashtech opened this issue Dec 7, 2018 · 2 comments · Fixed by #38046
Closed

Conflict with ISO8601 serializer and parser on ActiveSupport::Duration #34655

crashtech opened this issue Dec 7, 2018 · 2 comments · Fixed by #38046

Comments

@crashtech
Copy link

crashtech commented Dec 7, 2018

Steps to reproduce

duration = ActiveSupport::Duration.build(1000000)
duration_iso = duration.iso8601
ActiveSupport::Duration.parse(duration_iso)

Expected behavior

{:weeks => 1, :days=>4, :hours=>13, :minutes=>46, :seconds=>40}

Actual behavior

ActiveSupport::Duration::ISO8601Parser::ParsingError: Invalid ISO 8601 duration: "P1W4DT13H46M40S" mixing weeks with other date parts not allowed

System configuration

Rails 5.2.1
Ruby 2.3.1

There's an Exception prohibiting mixing weeks with other date pieces. Although it seems a correct Exception, it makes the process confusing since I could measure a duration by "2 months and 1 week" in any other aspect, and it would also provide a correct behavior on ActiveSupport::Duration#parse

The solutions simply remove the exception and allow it to move forward.
https://github.com/rails/rails/blob/master/activesupport/lib/active_support/duration/iso8601_parser.rb#L106

@rails-bot
Copy link

rails-bot bot commented Mar 10, 2019

This issue has been automatically marked as stale because it has not been commented on for at least three months.
The resources of the Rails team are limited, and so we are asking for your help.
If you can still reproduce this error on the 5-2-stable branch or on master, please reply with all of the information you have about it in order to keep the issue open.
Thank you for all your contributions.

@rails-bot rails-bot bot added the stale label Mar 10, 2019
@rails-bot rails-bot bot closed this as completed Mar 17, 2019
@quedvi
Copy link

quedvi commented Nov 28, 2019

I can confirm this bug is still present in Rails 5.2.3 / Ruby 2.6.3

Checking the ISO8601, mixing of week with other date parts is not allowed. Therefore I would suggest to change the ActiveSupport::Duration::ISO8601Serializer to:

 def serialize
    parts, sign = normalize
    return "PT0S" if parts.empty?

    if parts.key?(:weeks) && parts.except(:weeks).present?
      parts[:days] = (parts[:days] || 0) + 7 * parts[:weeks]
      parts.delete(:weeks)
    end

    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

There was a pull request: #34683, to solve this issue but it never got merged.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants