开发者

get next/previous month from a Time object

I have a Time object and would like to f开发者_运维问答ind the next/previous month. Adding subtracting days does not work as the days per month vary.

time = Time.parse('21-12-2008 10:51 UTC')
next_month = time + 31 * 24 * 60 * 60

Incrementing the month also falls down as one would have to take care of the rolling

time = Time.parse('21-12-2008 10:51 UTC')
next_month = Time.utc(time.year, time.month+1)

time = Time.parse('01-12-2008 10:51 UTC')
previous_month = Time.utc(time.year, time.month-1)

The only thing I found working was

time = Time.parse('21-12-2008 10:51 UTC')
d = Date.new(time.year, time.month, time.day)
d >>= 1
next_month = Time.utc(d.year, d.month, d.day, time.hour, time.min, time.sec, time.usec)

Is there a more elegant way of doing this that I am not seeing? How would you do it?


Ruby on Rails

Note: This only works in Rails (Thanks Steve!) but I'm keeping it here in case others are using Rails and wish to use these more intuitive methods.

Super simple - thank you Ruby on Rails!

Time.now + 1.month

Time.now - 1.month  

Or, another option if it's in relation to the current time (Rails 3+ only).

1.month.from_now

1.month.ago


Personally I prefer using:

Time.now.beginning_of_month - 1.day      # previous month
Time.now.end_of_month + 1.day            # next month

It always works and is independent from the number of days in a month.

Find more info in this API doc


you can use standard class DateTime

require 'date'

dt = Time.new().to_datetime
=> #<DateTime: 2010-04-23T22:31:39+03:00 (424277622199937/172800000,1/8,2299161)>

dt2 = dt >> 1
=> #<DateTime: 2010-05-23T22:31:39+03:00 (424282806199937/172800000,1/8,2299161)>

t = dt2.to_time
=> 2010-05-23 22:31:39 +0200


There are no built-in methods on Time to do what you want in Ruby. I suggest you write methods to do this work in a module and extend the Time class to make their use simple in the rest of your code.

You can use DateTime, but the methods (<< and >>) are not named in a way that makes their purpose obvious to someone that hasn't used them before.


below it works

previous month:

Time.now.months_since(-1)

next month:

Time.now.months_since(1)


If you do not want to load and rely on additional libraries you can use something like:

module MonthRotator
  def current_month
    self.month
  end

  def month_away
    new_month, new_year = current_month == 12 ? [1, year+1] : [(current_month + 1), year]
    Time.local(new_year, new_month, day, hour, sec)
  end

  def month_ago
    new_month, new_year = current_month == 1 ? [12, year-1] : [(current_month - 1), year]
    Time.local(new_year, new_month, day, hour, sec)
  end
end

class Time
  include MonthRotator
end


require 'minitest/autorun'

class MonthRotatorTest < MiniTest::Unit::TestCase
  describe "A month rotator Time extension" do
    it 'should return a next month' do
      next_month_date = Time.local(2010, 12).month_away
      assert_equal next_month_date.month, 1
      assert_equal next_month_date.year, 2011
    end

    it 'should return previous month' do
      previous_month_date = Time.local(2011, 1).month_ago
      assert_equal previous_month_date.month, 12
      assert_equal previous_month_date.year, 2010
    end
  end
end


I just want to add my plain ruby solution for completeness replace the format in strftime to desired output

DateTime.now.prev_month.strftime("%Y-%m-%d")
DateTime.now.next_month.strftime("%Y-%m-%d")


You can try convert to datetime.

Time gives you current date, and DateTime allows you to operate with.

Look at this:

irb(main):041:0> Time.new.strftime("%d/%m/%Y")
        => "21/05/2015"

irb(main):040:0> Time.new.to_datetime.prev_month.strftime("%d/%m/%Y")
    => "21/04/2015"


Here is a solution on plain ruby without RoR, works on old ruby versions.

t=Time.local(2000,"jan",1,20,15,1,0);
curmon=t.mon;
prevmon=(Time.local(t.year,t.mon,1,0,0,0,0)-1).mon ;
puts "#{curmon} #{prevmon}"


You can get the previous month info by this code

require 'time'
time = Time.parse('2021-09-29 12:31 UTC')
time.to_date.prev_month.strftime("%b %Y")


Some of the solutions assume rails. But, in pure ruby you can do the following

require 'date'    

d = Date.now
last_month = d<<1

last_month.strftime("%Y-%m-%d")


Im using the ActiveSupport::TimeZone for this example, but just in case you are using Rails or ActiveSupport it might come in handy.

If you want the previous month you can substract 1 month

time = Time.zone.parse('21-12-2008 10:51 UTC')
time.ago(1.month)


$ irb
irb(main):001:0> time = Time.now
=> 2016-11-21 10:16:31 -0800
irb(main):002:0> year = time.year
=> 2016
irb(main):003:0> month = time.month
=> 11
irb(main):004:0> last_month = month - 1
=> 10
irb(main):005:0> puts time
2016-11-21 10:16:31 -0800
=> nil
irb(main):006:0> puts year
2016
=> nil
irb(main):007:0> puts month
11
=> nil
irb(main):008:0> puts last_month
10
=> nil
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜