我正在为订单进行付款安排,客户可以选择当月支付。之后也可以改变它。为此,我使用了advance方法作为日期,它在创建时正常工作,但在更新时失败。这是我的代码:
创建,如果日期是31,如果月份没有第31天,则会正确地更改为月份的最后一天。
months = params[:payment][:months].to_i
pay_day = params[:payment][:pay_day].to_i
today = Date.today
first_date = today.change(months: 1).change(day: pay_day)
months_between = (today.year * 12 + today.month) - (first_date.year * 12 + first_date.month)
quota = (invoice_total)/months
payment_number = 1
months.times do |i|
payment = Payment.new(invoice: current_invoice, payment_type: PaymentType.find(params[:payment][:payment_type_id]), payment_number: payment_number, value: quota, max_payment_date: first_date.advance(months: +(months_between+i+1)))
payment.save
payment_number = payment_number + 1
end
更新代码,例如,在2月份"无效日期"中失败,但正确更新1月。
pay_day = params[:payment][:pay_day].to_i
@invoice.payments.each do |payment|
if payment.actual_payment_date.nil?
reference_month = payment.max_payment_date.change(months: 1).change(day: pay_day)
months_between = (payment.max_payment_date.year * 12 + payment.max_payment_date.month) - (reference_month.year * 12 + reference_month.month)
payment.update_attributes(max_payment_date: reference_month.advance(months: +(months_between)))
payment.save
end
end
它基本上是相同的代码,有谁知道为什么在第一部分它正常工作,但不是第二部分?
由于
答案 0 :(得分:2)
ActiveSupport救援:
def correct_day(day, date = Date.today)
end_of_month = date.end_of_month.day
day < end_of_month ? day : end_of_month
end
让我们用[timecop:
进行测试Timecop.freeze(Date.new(2000, 02)) do
correct_day(32) # => 29 - 2000 was a leap year.
correct_day(15) # => 15
end
Timecop.freeze(Date.new(2015, 10, 11)) do
correct_day(32) # => 31
correct_day(15) # => 15
end
这是你在模型中实现它的方法:
class Invoice < ActiveRecord::Base
has_many :payments
# Creates a payment for each month
# @param [Integer] months
# @param [Ingeger] preferred_day - defaults to the last day of the month
def split_payments(months = 12, preferred_day = 31)
(1..months).map do |i|
payments.create(
pay_day: calculate_payment_date(created_at + i.months, preferred_day),
payment_number: i
# ... More attributes
)
end
end
def change_payment_date(preferred_day)
payments.sort_by(:payment_number).map do |payment|
date = created_at + payment.payment_number.months
payment.update_attributes(
pay_day: calculate_payment_date(date, preferred_day)
)
end
end
private
def calculate_payment_date(date, preferred_day)
end_of_month = date.end_of_month
pref = date.beginning_of_month + (preferred_day - 1).days
pref < end_of_month ? pref : end_of_month
end
end