1. 28 7月, 2017 1 次提交
    • S
      Add missing support for modulo operations on durations · 0e08dffe
      Sayan Chakraborty 提交于
      Rails 5.1 introduce an `ActiveSupport::Duration::Scalar` class as
      a wrapper around a numeric value as a way of ensuring a duration
      was the outcome of an expression. However the implementation was
      missing support for modulo operations. This commit adds support
      for those operations and should result in a duration being
      returned from expressions involving them.
      
      Fixes #29603 and #29743.
      0e08dffe
  2. 27 7月, 2017 1 次提交
    • A
      Fix division where a duration is the denominator · bfa878d3
      Andrew White 提交于
      PR #29163 introduced a change in behavior when a duration was
      the denominator in a calculation - this was incorrect as dividing
      by a duration should always return a `Numeric`. The behavior of
      previous versions of Rails has been restored.
      
      Fixes #29592.
      bfa878d3
  3. 11 7月, 2017 1 次提交
  4. 09 7月, 2017 1 次提交
  5. 02 7月, 2017 1 次提交
  6. 01 7月, 2017 1 次提交
  7. 20 6月, 2017 1 次提交
  8. 20 5月, 2017 1 次提交
    • A
      Fix implicit calculations with scalars and durations · 28938dd6
      Andrew White 提交于
      Previously calculations where the scalar is first would be converted
      to a duration of seconds but this causes issues with dates being
      converted to times, e.g:
      
          Time.zone = "Beijing"           # => Asia/Shanghai
          date = Date.civil(2017, 5, 20)  # => Mon, 20 May 2017
          2 * 1.day                       # => 172800 seconds
          date + 2 * 1.day                # => Mon, 22 May 2017 00:00:00 CST +08:00
      
      Now the `ActiveSupport::Duration::Scalar` calculation methods will try
      to maintain the part structure of the duration where possible, e.g:
      
          Time.zone = "Beijing"           # => Asia/Shanghai
          date = Date.civil(2017, 5, 20)  # => Mon, 20 May 2017
          2 * 1.day                       # => 2 days
          date + 2 * 1.day                # => Mon, 22 May 2017
      
      Fixes #29160, #28970.
      28938dd6
  9. 16 3月, 2017 1 次提交
  10. 15 3月, 2017 1 次提交
    • A
      Remove implicit coercion deprecation of durations · a91ea1d5
      Andrew White 提交于
      In #28204 we deprecated implicit conversion of durations to a
      numeric which represented the number of seconds in the duration
      because of unwanted side effects with calculations on durations
      and dates. This unfortunately had the side effect of forcing a
      explicit cast when configuring third-party libraries like
      expiration in Redis, e.g:
      
          redis.expire("foo", 5.minutes)
      
      To work around this we've removed the deprecation and added a
      private class that wraps the numeric and can perform calculation
      involving durations and ensure that they remain a duration
      irrespective of the order of operations.
      a91ea1d5
  11. 02 3月, 2017 1 次提交
    • A
      Deprecate implicit coercion of `ActiveSupport::Duration` · 75924c45
      Andrew White 提交于
      Currently `ActiveSupport::Duration` implicitly converts to a seconds
      value when used in a calculation except for the explicit examples of
      addition and subtraction where the duration is the receiver, e.g:
      
          >> 2 * 1.day
          => 172800
      
      This results in lots of confusion especially when using durations
      with dates because adding/subtracting a value from a date treats
      integers as a day and not a second, e.g:
      
          >> Date.today
          => Wed, 01 Mar 2017
          >> Date.today + 2 * 1.day
          => Mon, 10 Apr 2490
      
      To fix this we're implementing `coerce` so that we can provide a
      deprecation warning with the intent of removing the implicit coercion
      in Rails 5.2, e.g:
      
          >> 2 * 1.day
          DEPRECATION WARNING: Implicit coercion of ActiveSupport::Duration
          to a Numeric is deprecated and will raise a TypeError in Rails 5.2.
          => 172800
      
      In Rails 5.2 it will raise `TypeError`, e.g:
      
          >> 2 * 1.day
          TypeError: ActiveSupport::Duration can't be coerced into Integer
      
      This is the same behavior as with other types in Ruby, e.g:
      
          >> 2 * "foo"
          TypeError: String can't be coerced into Integer
          >> "foo" * 2
          => "foofoo"
      
      As part of this deprecation add `*` and `/` methods to `AS::Duration`
      so that calculations that keep the duration as the receiver work
      correctly whether the final receiver is a `Date` or `Time`, e.g:
      
          >> Date.today
          => Wed, 01 Mar 2017
          >> Date.today + 1.day * 2
          => Fri, 03 Mar 2017
      
      Fixes #27457.
      75924c45
  12. 26 2月, 2017 1 次提交
    • N
      Add Duration#before and #after as aliases for #ago and #since · 2d84a6bc
      Nick Johnstone 提交于
      It's common in test cases at my job to have code like this:
      
          let(:today) { customer_start_date + 2.weeks }
          let(:earlier_date) { today - 5.days }
      
      With this change, we can instead write
      
          let(:today) { 2.weeks.after(customer_start_date) }
          let(:earlier_date) { 5.days.before(today) }
      
      Closes #27721
      2d84a6bc
  13. 12 1月, 2017 1 次提交
    • A
      Add additional tests for #27610 · 2a5ae2b7
      Andrew White 提交于
      Since 1.month no longer equals 30.days add some tests to ensure that
      addition maintains the same day in the month or is the last day in
      the month if the month has less days than the current day. Also add
      a test for the behaviour of 12.months == 1.year.
      2a5ae2b7
  14. 10 1月, 2017 1 次提交
    • A
      Fix inconsistent results when parsing large durations and constructing durations from code · cb9d0e48
      Andrey Novikov 提交于
          ActiveSupport::Duration.parse('P3Y') == 3.years # It should be true
      
      Duration parsing made independent from any moment of time:
      Fixed length in seconds is assigned to each duration part during parsing.
      
      Changed duration of months and years in seconds to more accurate and logical:
      
       1. The value of 365.2425 days in Gregorian year is more accurate
          as it accounts for every 400th non-leap year.
      
       2. Month's length is bound to year's duration, which makes
          sensible comparisons like `12.months == 1.year` to be `true`
          and nonsensical ones like `30.days == 1.month` to be `false`.
      
      Calculations on times and dates with durations shouldn't be affected as
      duration's numeric value isn't used in calculations, only parts are used.
      
      Methods on `Numeric` like `2.days` now use these predefined durations
      to avoid duplicating of duration constants through the codebase and
      eliminate creation of intermediate durations.
      cb9d0e48
  15. 26 12月, 2016 1 次提交
  16. 16 12月, 2016 1 次提交
  17. 30 11月, 2016 1 次提交
    • S
      Treat combined durations as a single unit · 32f215c3
      Sean Griffin 提交于
      Prior to this commit, `3.months - 3.months` would result in a duration
      that has the "parts" of `[[:months, 3], [:months, -3]]`. This would mean
      that it was subtly different than `2.months - 2.months`. When applied to
      a time, the date might actually change if the resulting day doesn't
      exist however many months in the future, even though in both cases we
      just wanted to add `0`, which should always be an identity operation.
      
      With this change, we now store the parts as a hash, so `3.months -
      3.months` is simply stored as `{ months: 0 }`.
      32f215c3
  18. 05 11月, 2016 1 次提交
  19. 01 11月, 2016 1 次提交
    • A
      Ensure duration parsing is consistent across DST changes · 8931916f
      Andrew White 提交于
      Previously `ActiveSupport::Duration.parse` used `Time.current` and
      `Time#advance` to calculate the number of seconds in the duration
      from an arbitrary collection of parts. However as `advance` tries to
      be consistent across DST boundaries this meant that either the
      duration was shorter or longer depending on the time of year.
      
      This was fixed by using an absolute reference point in UTC which
      isn't subject to DST transitions. An arbitrary date of Jan 1st, 2000
      was chosen for no other reason that it seemed appropriate.
      
      Additionally, duration parsing should now be marginally faster as we
      are no longer creating instances of `ActiveSupport::TimeWithZone`
      every time we parse a duration string.
      
      Fixes #26941.
      8931916f
  20. 29 10月, 2016 1 次提交
  21. 02 9月, 2016 1 次提交
  22. 16 8月, 2016 1 次提交
  23. 07 8月, 2016 2 次提交
  24. 12 7月, 2016 1 次提交
    • P
      AS::Duration should serialize empty values correctly. (#25656) · 629dde29
      Paul Sadauskas 提交于
      The current implementation serializes zero-length durations incorrectly (it serializes as `"-P"`), and cannot un-serialize itself:
      
      ```
      [1] pry(main)> ActiveSupport::Duration.parse(0.minutes.iso8601)
      ActiveSupport::Duration::ISO8601Parser::ParsingError: Invalid ISO 8601 duration: "-P" is empty duration
      from /Users/rando/.gem/ruby/2.3.1/gems/activesupport-5.0.0/lib/active_support/duration/iso8601_parser.rb:96:in `raise_parsing_error'
      ```
      
      Postgres empty intervals are serialized as `"PT0S"`, which is also parseable by the Duration deserializer, so I've modified the `ISO8601Serializer` to do the same.
      
      Additionally, the `#normalize` function returned a negative sign if `parts` was blank (all zero). Even though this fix does not rely on the sign, I've gone ahead and corrected that, too, in case a future refactoring of `#serialize` uses it.
      629dde29
  25. 19 5月, 2016 1 次提交
  26. 28 4月, 2016 2 次提交
  27. 19 4月, 2016 1 次提交
  28. 18 4月, 2016 1 次提交
  29. 07 6月, 2015 1 次提交
  30. 13 1月, 2015 1 次提交
    • D
      Removing :en in favor of I18n.default_locale in duration#inspect · f76d1aa5
      Dominik Masur 提交于
      Hi there,
      
      i have an app without english as available locale. So i got an error when we try to inspect something like 1.day. This is done automatically when we use the dalli cache.
      
      I would like to change the :en to ::I18n.default_locale to be sure that this is always constant and is an available locale.
      
      Tests are all green with this change.
      
      Calculating -------------------------------------
      :locale => :en                              2.024k i/100ms
      :locale => ::I18n.default_locale   2.236k i/100ms
      -------------------------------------------------
      :locale => :en                                  25.758k (±26.3%) i/s -    117.392k
      :locale => ::I18n.default_locale       26.311k (±18.1%) i/s -    127.452k
      f76d1aa5
  31. 05 11月, 2014 1 次提交
  32. 04 11月, 2014 1 次提交
  33. 03 10月, 2014 1 次提交
  34. 22 9月, 2014 1 次提交
  35. 15 9月, 2014 1 次提交
  36. 25 8月, 2014 2 次提交
    • R
      Skip #eql? tests on Rubinius for AS::Duration · 61a371cf
      Robin Dupret 提交于
      Since Rubinius is relying on #instance_of? for its definition of #eql?
      (http://git.io/MtmbbA) but ActiveSupport::Duration should behave like
      is_a? it returns true with `Fixnum`.
      
      Thus, for the moment, the last assertion is failing so we have to skip
      this test.
      61a371cf
    • R
      Follow-up to #16560 · d5578cd1
      Robin Dupret 提交于
      For the sake of backward-compatibility, we need to make #instance_of?
      return true for Fixnum. On the other hand, the method should still
      give true for ActiveSupport::Duration itself which was not the case
      before.
      d5578cd1
  37. 18 8月, 2014 1 次提交
    • R
      Define the Duration#instance_of? method · eb73d7da
      Robin Dupret 提交于
      Since Duration is extending from ProxyObject which extends itself from
      BasicObject, the Duration object doesn't respond to the #instance_of?
      method. Thus, the #method_missing hook get triggered, delegating the
      method to its `value` attribute.
      
      However, Rubinius' #eql? definition relies on #instance_of?, thus this
      will equal to true with a Fixnum (since its `value` attribute is a
      Fixnum) while it should not.
      
      The previous behavior was wrong anyway, no matter the implementation.
      eb73d7da