(Time.now.utc.to_date + 1.month + 15.days)! = (Time.now.utc.to_date + 15.days + 1.month)

How is this possible?

Time.now.utc.to_date + 1.month + 15.days #=> Mon, 01 Dec 2014
Time.now.utc.to_date + 15.days + 1.month #=> Sun, 30 Nov 2014

Has anyone seen this?

/ change

I think I asked the question in the wrong way. How do you guys explain this then?

Time.now.utc.to_date + (15.days + 1.month) #=> Mon, 08 Dec 2014
Time.now.utc.to_date + (1.month + 15.days) #=> Tue, 09 Dec 2014

(15.days + 1.month) #=> 3888000
(1.month + 15.days) #=> 3888000
+4
source share
4 answers

First we look at Integer # month , it returns an instance ActiveSupport::Duration. On the rail console:

~/rails/rfinan (1296000):1 > elapsed = 1.month
=> 2592000
~/rails/rfinan (1296000):1 > elapsed.value
=> 2592000
~/rails/rfinan (1296000):1 > elapsed.parts
=> [[:months,1]]
~/rails/rfinan (1296000):1 > elapsed.is_a? ActiveSupport::Duration
=> true

This time is for the method: ActiveSupport :: Duration # +

~/rails/rfinan (1296000):1 > sum1 = 1.month + 15.days
=> 3888000
~/rails/rfinan (1296000):1 > sum2 = 15.days + 1.month
=> 3888000
~/rails/rfinan (1296000):1 > sum1.value
=> 3888000
~/rails/rfinan (1296000):1 > sum1.parts
=> [[:months,1],[:days,15]]
~/rails/rfinan (1296000):1 > sum2.value
=> 3888000
~/rails/rfinan (1296000):1 > sum2.parts
=> [[:days,15],[:months,1]]
~/rails/rfinan (1296000):1 > sum1 == sum2
=> true
~/rails/rfinan (1296000):1 > sum1.value == sum2.value
=> true
~/rails/rfinan (1296000):1 > sum1.parts == sum2.parts
=> false

Now Date # + , ActiveSupport version.

def plus_with_duration(other) #:nodoc:
  if ActiveSupport::Duration === other
    other.since(self)
  else
    plus_without_duration(other)
  end
end
alias_method :plus_without_duration, :+
alias_method :+, :plus_with_duration

: : + Date ActiveSupport:: Duration , ActiveSupport:: Duration #, , ActiveSupport:: Duration # sum, Date # advance :

  def sum(sign, time = ::Time.current) #:nodoc:
    parts.inject(time) do |t,(type,number)|
      if t.acts_like?(:time) || t.acts_like?(:date)
        if type == :seconds
          t.since(sign * number)
        else
          t.advance(type => sign * number)
        end
      else
        raise ::ArgumentError, "expected a time or date, got #{time.inspect}"
      end
    end
  end

Remmember sum1.parts!= sum2.parts?, sum . , #

def advance(options)
  options = options.dup
  d = self
  d = d >> options.delete(:years) * 12 if options[:years]
  d = d >> options.delete(:months)     if options[:months]
  d = d +  options.delete(:weeks) * 7  if options[:weeks]
  d = d +  options.delete(:days)       if options[:days]
  d
end

recive month: 1 Date # " > stdlib, ActiveSupport:: Duration #+. irb:

~ (main) > Date.new(2014,10,31) >> 1
=> #<Date: 2014-11-30 ((2456992j,0s,0n),+0s,2299161j)>
~ (main) > Date.new(2014,10,31) >> 2
=> #<Date: 2014-12-31 ((2457023j,0s,0n),+0s,2299161j)>
~ (main) > Date.new(2014,10,31) >> 3
=> #<Date: 2015-01-31 ((2457054j,0s,0n),+0s,2299161j)>
~ (main) > Date.new(2014,10,31) >> 4
=> #<Date: 2015-02-28 ((2457082j,0s,0n),+0s,2299161j)>
~ (main) > Date.new(2014,10,31) >> 5
=> #<Date: 2015-03-31 ((2457113j,0s,0n),+0s,2299161j)>
~ (main) > Date.new(2014,10,31) >> 12
=> #<Date: 2015-10-31 ((2457327j,0s,0n),+0s,2299161j)>
~ (main) > Date.new(2014,10,31) >> 1200
=> #<Date: 2114-10-31 ((2493486j,0s,0n),+0s,2299161j)>
~ (main) > Date.new(2014,10,31) >> 12000
=> #<Date: 3014-10-31 ((2822204j,0s,0n),+0s,2299161j)>

, # → , . , . , .

, Date # + ActiveSupport:: Duration # +, .

Anwer - # +, ActiveSupport:: Duration (say duration), ., duration.parts, .

+6

31 , - . , , 31- + 1 .

:

  • + 1 = ​​16-
  • 16-Nov + 15 = 1-Dec

:

  • + 15 = 31-.
  • 31-Oct + 1 Month = 30-Nov
+5

31 . 15 16 , 31 . - 31 , 31 , 30 .

, 16 . 15 01 .

+4

:

(15.days + 1.month) #=> 3888000
(1.month + 15.days) #=> 3888000

, (Rails Numeric < Object). , :

> 3888000 / 60 / 60 / 24
 => 45

45 = 30 + 15. , , 1.month 30 Numerics. . : http://api.rubyonrails.org/classes/Numeric.html#method-i-seconds

, Numerics, rails advance(options), Date. . github: https://github.com/rails/rails/blob/ffc273577a795bb41068bfc2a1bb575ec51a9712/activesupport/lib/active_support/core_ext/time/calculations.rb#L99

, Time.now.utc.to_date + (1.month + 15.days) + () advance(options) :

(Time.now.utc.to_date.advance(month:1)).advance(days:15) #fistCase

Time.now.utc.to_date + (15.days + 1.month), :

(Time.now.utc.to_date.advance(days:15)).advance(month:1) #secondCase

, #firstCase:

oct16 = Date.new(2014, 10, 16)
 > oct16 + (1.month + 15.days)
 => Mon, 01 Dec 2014
 > (oct16.advance(months:1)).advance(days:15)
 => Mon, 01 Dec 2014

#firstCase , (: 1), -16, .advance(: 15) -16 Dez-01

#secondCase:

> oct16 + (15.days + 1.month)
 => Sun, 30 Nov 2014
> (oct16.advance(days:15)).advance(months:1)
 => Sun, 30 Nov 2014 

The conclusion of #secondCase is that it calls an advance (days: 15), which leads to October 31, what does it call an advance (months: 1) according to the last result that will give us November 31, but wait! Nov-31 does not exist! Therefore, the translator is smart enough to understand this, since you were on the last day of the month (October-31), when you add 1.month or advance (months: 1), you ask him to take you on the last day of the next month, in this case - November 30th.

This is an agreement.

+2
source

All Articles