我正在Ruby on Rails中创建一个库式系统,我正在尝试计算过期天数,同时排除借用项目时的周末。现在我只计算“dayslate”作为截止日期和项目实际返回日期之间的差异,但我想排除周末,因为项目只能在工作日返回。
这是我第一次使用Ruby和Rails的真实体验,所以如果我遗漏了一些明显的东西,我很抱歉。感谢您提供的任何帮助。
这是我对“返回”功能的代码:
def return
@product = Product.find(params[:id])
today = Date.today
dayslate = today - @product.due_date
if @product.due_date >= today
@product.borrower = @product.check_out = @product.due_date = @product.extended_checkout = nil
@product.save!
flash[:notice] = "Okay, it's checked in!"
redirect_to(products_url)
else
@product.borrower = @product.check_out = @product.due_date = @product.extended_checkout = nil
@product.save!
flash[:notice] = "Checked in, but it was #{dayslate} days late!"
redirect_to(products_url)
end
end
答案 0 :(得分:24)
这是一段代码,用于查找日期范围对象中工作日的数量
require 'date'
# Calculate the number of weekdays since 14 days ago
p ( (Date.today - 14)..(Date.today) ).select {|d| (1..5).include?(d.wday) }.size
这就是我在你的情况下使用它的方式。
class Product
def days_late
weekdays_in_date_range( self.due_date..(Date.today) )
end
protected
def weekdays_in_date_range(range)
# You could modify the select block to also check for holidays
range.select { |d| (1..5).include?(d.wday) }.size
end
end
答案 1 :(得分:2)
如果假期对您很重要(例如,如果假期是您不希望将某一天计为工作日),您可能需要查看http://rubyforge.org/projects/holidays/。如果你将@ md5sum提到的循环与支票结合起来,看看工作日是否是假日,那么你可能是金色的。
答案 2 :(得分:2)
答案 3 :(得分:2)
sunday, saturday = 0, 6
weekend = [sunday, saturday]
((start_date..end_date).collect(&:wday) - weekend).count
答案 4 :(得分:1)
您可以查看this页面,看看是否可以在循环中添加计数器并检查每次迭代的当前日期。
答案 5 :(得分:1)
关于@Marini的帖子,可以消除产生一系列日期的开销:
def weekdays(date1, date2)
wday = date1.wday
(0..(date2-date1)).count {|offset| ((wday + offset) % 7 % 6) > 0}
end
% 7
将每个偏移量转换为工作日,% 6
为周六(6)或周日(0)返回0
答案 6 :(得分:1)
计算current_month的工作日
start_date = Date.today.beginning_of_month
end_date = Date.today.end_of_month
(start_date..end_date).select{|a| a.wday < 6 && a.wday > 0}.count
答案 7 :(得分:1)
我认为这比接受的答案更简单,更易读:
require 'date'
to = Date.parse('2017-02-02')
from = to - 14
(from..to).count { |d| !d.sunday? && !d.saturday? }
#=> 11
答案 8 :(得分:1)
我找到了一种更快的周末计算方法,你可以按(start_date..end_date).size - weekend_count
计算不包括周末的天数:
def weekend_count(start_date, end_date)
size = (end_date - start_date).to_i
count = 0
if start_date.wday != 0
size -= (7 - start_date.wday).to_i
count += 1
end
left_over = size % 7
if left_over == 0
count = (count / 7) * 2
else
size -= left_over
count += (size / 7) * 2 + 1
end
count
end
与[0, 6].include? date.wday
比较,请参阅我的benchmark结果:
Distance 10
Optimized result: 4
Normal result: 4
user system total real
Optimized 0.000000 0.000000 0.000000 ( 0.000018)
Normal 0.000000 0.000000 0.000000 ( 0.000032)
Distance 100
Optimized result: 29
Normal result: 29
user system total real
Optimized 0.000000 0.000000 0.000000 ( 0.000006)
Normal 0.000000 0.000000 0.000000 ( 0.000094)
Distance 1000
Optimized result: 286
Normal result: 286
user system total real
Optimized 0.000000 0.000000 0.000000 ( 0.000010)
Normal 0.000000 0.000000 0.000000 ( 0.000650)
Distance 10000
Optimized result: 2858
Normal result: 2858
user system total real
Optimized 0.000000 0.000000 0.000000 ( 0.000013)
Normal 0.000000 0.000000 0.000000 ( 0.004995)
Distance 100000
Optimized result: 28572
Normal result: 28572
user system total real
Optimized 0.000000 0.000000 0.000000 ( 0.000011)
Normal 0.060000 0.000000 0.060000 ( 0.064223)
答案 9 :(得分:0)
中微子非常正确地将显示/渲染/重定向中涉及的所有逻辑移动到模型中。
E.g。
class ProductLoan
def due_date_passed?
days_late > 0
end
def days_late
Date.today - due_date
end
def complete!
self.borrower = self.check_out = self.due_date = self.extended_checkout = nil
save
end
end
class ReturnsController
def create
@product = ProductLoan.find(params[:id])
if @product.due_date_passed?
flash[:notice] = "Okay, it's checked in!"
else
flash[:notice] = "Checked in, but it was #{@product.days_late} days late!"
end
@product.complete!
redirect_to products_url
end
end
我只是在没有测试的情况下输入了这个,但是,这些行中的某些内容可以计算出不包括周末的日子:
class DateOffsetCalculator
DAYS_IN_A_WEEK = 7
DAYS_IN_A_WEEKEND = 2
def initialize(date)
@date = date
end
def compute
days_passed - weekend_days_passed
end
def days_passed
(Date.today - @date).to_i
end
def weekend_days_passed
weekends_passed * DAYS_IN_A_WEEKEND
end
def weekends_passed
rounded_up_week_days / DAYS_IN_A_WEEK
end
def rounded_up_week_days
days_passed + commercial_working_day_correction
end
def commercial_working_day_correction
@date.cwday - 1
end
end
答案 10 :(得分:0)
顶级解决方案很好,我知道我不应该担心性能,但是我有一部分因为通过生成集合并迭代计算工作日的数量而烦恼,因为计算时间是线性函数两个日期之间的差异。
如果您仔细考虑,答案可以在固定时间内以数学方式计算。你可以分两个部分来考虑它:
第1部分 -
之间的周数如果天数差异超过一周,您可以将每个7天工作周计为5个工作日,并“删除”整整几周。
第2部分 - 部分周的日子
减去整整一周后,您可以查看7天跨越两天之间有多少个工作日的简化问题。如果您构建一个表,您将看到一个非常简单的规则,或者您可以重复获胜解决方案中使用的逻辑,但只能在最多7天的时间间隔内。