简体   繁体   中英

When advancing a date by one month to a shorter month, how can I advance to the first of the next month?

I want to move from one date to the same day of the next month. Currently I use this function

Time.now.utc + 1.month

It works correctly with most days, but at the end of months where the next month is shorter, I want to move forward to the first of the month following instead. For example:

Thursday, July 31 = $25.99 USD
Saturday, August 31 = $25.99 USD
Wednesday, October 1= $25.99 USD # instead of September 30
Saturday, November 1= $25.99 USD

and so on.

[67] pry(main)> now = Time.parse('2021-01-30 20:17:40')
=> 2021-01-30 20:17:40 +0700
[68] pry(main)> now.next_month
=> 2021-02-28 20:17:40 +0700

I want it to return 2021-03-01

Please help me!

Yes, generally with Ruby's built-in date functions, advancing by a month will shorten the amount by which it skips to keep your new date in the month following the original date.

What you can do is to take a multi-step approach:

  1. Take your original date, and get a new date by advancing one month
  2. Look at the day components of each date. If the new date's day is less than the original's, then the month's jump in step 1 has been shortened.
  3. If it hasn't been shortened, then the new date is fine
  4. If it has been shortened, you can manually move to the start of the following month

Here's a quick and dirty method using Rails' time helpers to hopefully make it clearer:

def advance_by_one_month(date)
  next_date = date.next_month
  if next_date.day < date.day
    next_date.next_month.beginning_of_month
  else
    next_date
  end
end

and in action:

%> d = Date.new(2021, 8, 31)
# => Tue, 31 Aug 2021
%> advance_by_one_month(d)
# => Fri, 01 Oct 2021

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM