从Time对象获取下一个/上个月

tcu*_*rdt 34 ruby

我有一个Time对象,想找到下一个/上个月.添加减去天数不起作用,因为每月的天数不同.

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

随着人们不得不照顾滚动,月份的增量也会下降

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)
Run Code Online (Sandbox Code Playgroud)

我发现的唯一工作是

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)
Run Code Online (Sandbox Code Playgroud)

有没有更优雅的方式做到这一点,我没有看到?你会怎么做?

Jos*_*ter 79

Ruby on Rails

注意:这只适用于Rails(感谢史蒂夫!)但我保留在这里,以防其他人使用Rails并希望使用这些更直观的方法.

超级简单 - 谢谢Ruby on Rails!

Time.now + 1.month

Time.now - 1.month  
Run Code Online (Sandbox Code Playgroud)

或者,如果它与当前时间有关,则为另一个选项(仅限Rails 3+).

1.month.from_now

1.month.ago
Run Code Online (Sandbox Code Playgroud)

J.P

  • @Steve它不假设做日期算术30天.这实际上非常神奇.试试吧!(请参阅activeSupport中的ActiveSupport :: Duration,Date#plus_with_duration和integer/time.rb).例如>> Time.utc(2010,2,1)+ 1.months.=> Mon Mar 01 00:00:00 UTC 2010 >> Time.utc(2010,3,1)+ 1.months => Thu Apr 01 00:00:00 UTC 2010 >> Time.utc(2010,4, 1)+ 1.months => Sat May 01 00:00:00 UTC 2010或者极端的例子:>> Time.utc(2010,1,31)+ 1.months => Sun Feb 28 00:00:00 UTC 2010 (9认同)

Kon*_*udy 21

我个人更喜欢使用:

Time.now.beginning_of_month - 1.day      # previous month
Time.now.end_of_month + 1.day            # next month
Run Code Online (Sandbox Code Playgroud)

它始终有效,并且与一个月中的天数无关.

在此API文档中查找更多信息

  • 这仅适用于Ruby on Rails. (13认同)

and*_*hin 13

您可以使用标准类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
Run Code Online (Sandbox Code Playgroud)


Ste*_*sen 10

没有内置方法Time可以在Ruby中执行您想要的操作.我建议你在模块中编写方法来完成这项工作,并扩展Time类以使其在其余代码中的使用变得简单.

您可以使用DateTime,但方法(<<>>)的命名方式不会使之前未使用它们的人明白其目的.


小智 6

在它下面工作

前一个月:

Time.now.months_since(-1)
Run Code Online (Sandbox Code Playgroud)

下个月:

Time.now.months_since(1)
Run Code Online (Sandbox Code Playgroud)


小智 6

如果您不想加载并依赖其他库,可以使用以下内容:

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
Run Code Online (Sandbox Code Playgroud)


小智 5

我只想添加我的普通 ruby​​ 解决方案以确保完整性,将 strftime 中的格式替换为所需的输出

DateTime.now.prev_month.strftime("%Y-%m-%d")
DateTime.now.next_month.strftime("%Y-%m-%d")
Run Code Online (Sandbox Code Playgroud)