如何检测 Rails 中的日期是否连续?
How to detect if dates are consecutive in Rails?
我想检查连续的日期,如果它们 连续,则以不同的方式显示它们。
我正在处理每次销售有多个日期的旧货销售。然后我想循环浏览每个日期,并将任何连续的日期分组以显示为一组:例如:4 月 28 日 - 4 月 30 日
我还需要考虑非连续日期:
例如:4 月 15 日、4 月 28 日 - 30 日
此外,周日期需要被识别为非连续的(因此基本上避免步骤检查):
例如:4 月 16 日、4 月 23 日、4 月 30 日
到目前为止,我正在记录每个未通过的日期并正确排序它们。
garage_sale_dates.where("date > ?",Time.now).order(:date)
感谢您的帮助!如果需要任何其他信息,请告诉我。
使用 Date 你可以做减法,它会是这样的:
date1 = 1.day.ago
date2 = 2.day.ago
(date1.to_date - date2.to_date).to_i
=> 1
一个简单的脚本就可以解决问题
def date_list(dates)
result = []
dates.each do |date|
if result.empty? || (date - result.last.last).to_i != 1
result << [date]
else
result.last << date
end
end
result
end
# make sure dates is an array of dates
dates = [Thu, 28 Apr 2016, Fri, 29 Apr 2016, Sun, 01 May 2016, Mon, 02 May 2016, Tue, 03 May 2016, Thu, 05 May 2016, Fri, 06 May 2016, Sat, 07 May 2016, Sun, 08 May 2016]
#this would give you an array of date ranges that you wanted
date_list(dates)
=> [
[Thu, 28 Apr 2016, Fri, 29 Apr 2016],
[Sun, 01 May 2016, Mon, 02 May 2016, Tue, 03 May 2016],
[Thu, 05 May 2016, Fri, 06 May 2016, Sat, 07 May 2016, Sun, 08 May 2016]
]
您可以使用 Enumerable
的 slice_before
method
dates = [Date.yesterday, Date.today, Date.tomorrow, Date.parse('2016-05-01'), Date.parse('2016-05-02'), Date.parse('2016-05-05')]
# => [Wed, 27 Apr 2016, Thu, 28 Apr 2016, Fri, 29 Apr 2016, Sun, 01 May 2016, Mon, 02 May 2016, Thu, 05 May 2016]
prev = dates.first
dates.slice_before { |d| prev, prev2 = d, prev; prev2 + 1.day != d }.to_a
# => [[Wed, 27 Apr 2016, Thu, 28 Apr 2016, Fri, 29 Apr 2016], [Sun, 01 May 2016, Mon, 02 May 2016], [Thu, 05 May 2016]]
然后您可以简单地将结果中的 2 个或更多元素数组与“-”连接起来,并保持单个元素数组不变:
prev = dates.first
dates.slice_before { |d| prev, prev2 = d, prev; prev2 + 1.day != d }.
map{|d| d.size > 1 ? "#{d.first.to_s} - #{d.last.to_s}" : d.first.to_s }
# => ["2016-04-27 - 2016-04-29", "2016-05-01 - 2016-05-02", "2016-05-05"]
文档中甚至有一个注释示例在技术上等同于您的示例(但处理的是整数,而不是日期)。
我使用 chunk_while
method 找到了一个更简单的解决方案(可从 Ruby 2.4.6 获得)。
基于:
dates = [Date.yesterday, Date.today, Date.tomorrow, Date.parse('2020-05-01'), Date.parse('2020-05-02'), Date.parse('2020-05-05')]
# => [Thu, 26 Mar 2020, Fri, 27 Mar 2020, Sat, 28 Mar 2020, Fri, 01 May 2020, Sat, 02 May 2020, Tue, 05 May 2020]
dates.chunk_while { |date_before, date_after| (date_after - date_before).to_i == 1 }.to_a
# => [[Thu, 26 Mar 2020, Fri, 27 Mar 2020, Sat, 28 Mar 2020], [Fri, 01 May 2020, Sat, 02 May 2020], [Tue, 05 May 2020]]
我认为它更具可读性,并且获得相同结果所需的步骤更少。
添加到 Matouš Borák 的答案中,如果您想更改日期格式,使其与问题中的要求相匹配,即 Apr 15、Apr 28 - 30
dates = [Date.yesterday, Date.today, Date.tomorrow, Date.parse('2021-10-01'), Date.parse('2021-10-02'), Date.parse('2021-10-05')]
# => [Wed, 01 Sep 2021, Thu, 02 Sep 2021, Fri, 03 Sep 2021, Fri, 01 Oct 2021, Sat, 02 Oct 2021, Tue, 05 Oct 2021]
prev = dates.first
dates.slice_before { |d| prev, prev2 = d, prev; prev2 + 1.day != d }.
map{|d| d.size > 1 ? "#{d.first.strftime('%b %d')} - #{d.last.strftime('%d')}" : d.first.strftime('%b %d') }
# => ["Sep 01 - 03", "Oct 01 - 02", "Oct 05"]
我想检查连续的日期,如果它们 连续,则以不同的方式显示它们。
我正在处理每次销售有多个日期的旧货销售。然后我想循环浏览每个日期,并将任何连续的日期分组以显示为一组:例如:4 月 28 日 - 4 月 30 日
我还需要考虑非连续日期: 例如:4 月 15 日、4 月 28 日 - 30 日
此外,周日期需要被识别为非连续的(因此基本上避免步骤检查): 例如:4 月 16 日、4 月 23 日、4 月 30 日
到目前为止,我正在记录每个未通过的日期并正确排序它们。
garage_sale_dates.where("date > ?",Time.now).order(:date)
感谢您的帮助!如果需要任何其他信息,请告诉我。
使用 Date 你可以做减法,它会是这样的:
date1 = 1.day.ago
date2 = 2.day.ago
(date1.to_date - date2.to_date).to_i
=> 1
一个简单的脚本就可以解决问题
def date_list(dates)
result = []
dates.each do |date|
if result.empty? || (date - result.last.last).to_i != 1
result << [date]
else
result.last << date
end
end
result
end
# make sure dates is an array of dates
dates = [Thu, 28 Apr 2016, Fri, 29 Apr 2016, Sun, 01 May 2016, Mon, 02 May 2016, Tue, 03 May 2016, Thu, 05 May 2016, Fri, 06 May 2016, Sat, 07 May 2016, Sun, 08 May 2016]
#this would give you an array of date ranges that you wanted
date_list(dates)
=> [
[Thu, 28 Apr 2016, Fri, 29 Apr 2016],
[Sun, 01 May 2016, Mon, 02 May 2016, Tue, 03 May 2016],
[Thu, 05 May 2016, Fri, 06 May 2016, Sat, 07 May 2016, Sun, 08 May 2016]
]
您可以使用 Enumerable
slice_before
method
dates = [Date.yesterday, Date.today, Date.tomorrow, Date.parse('2016-05-01'), Date.parse('2016-05-02'), Date.parse('2016-05-05')]
# => [Wed, 27 Apr 2016, Thu, 28 Apr 2016, Fri, 29 Apr 2016, Sun, 01 May 2016, Mon, 02 May 2016, Thu, 05 May 2016]
prev = dates.first
dates.slice_before { |d| prev, prev2 = d, prev; prev2 + 1.day != d }.to_a
# => [[Wed, 27 Apr 2016, Thu, 28 Apr 2016, Fri, 29 Apr 2016], [Sun, 01 May 2016, Mon, 02 May 2016], [Thu, 05 May 2016]]
然后您可以简单地将结果中的 2 个或更多元素数组与“-”连接起来,并保持单个元素数组不变:
prev = dates.first
dates.slice_before { |d| prev, prev2 = d, prev; prev2 + 1.day != d }.
map{|d| d.size > 1 ? "#{d.first.to_s} - #{d.last.to_s}" : d.first.to_s }
# => ["2016-04-27 - 2016-04-29", "2016-05-01 - 2016-05-02", "2016-05-05"]
文档中甚至有一个注释示例在技术上等同于您的示例(但处理的是整数,而不是日期)。
我使用 chunk_while
method 找到了一个更简单的解决方案(可从 Ruby 2.4.6 获得)。
基于
dates = [Date.yesterday, Date.today, Date.tomorrow, Date.parse('2020-05-01'), Date.parse('2020-05-02'), Date.parse('2020-05-05')]
# => [Thu, 26 Mar 2020, Fri, 27 Mar 2020, Sat, 28 Mar 2020, Fri, 01 May 2020, Sat, 02 May 2020, Tue, 05 May 2020]
dates.chunk_while { |date_before, date_after| (date_after - date_before).to_i == 1 }.to_a
# => [[Thu, 26 Mar 2020, Fri, 27 Mar 2020, Sat, 28 Mar 2020], [Fri, 01 May 2020, Sat, 02 May 2020], [Tue, 05 May 2020]]
我认为它更具可读性,并且获得相同结果所需的步骤更少。
添加到 Matouš Borák 的答案中,如果您想更改日期格式,使其与问题中的要求相匹配,即 Apr 15、Apr 28 - 30
dates = [Date.yesterday, Date.today, Date.tomorrow, Date.parse('2021-10-01'), Date.parse('2021-10-02'), Date.parse('2021-10-05')]
# => [Wed, 01 Sep 2021, Thu, 02 Sep 2021, Fri, 03 Sep 2021, Fri, 01 Oct 2021, Sat, 02 Oct 2021, Tue, 05 Oct 2021]
prev = dates.first
dates.slice_before { |d| prev, prev2 = d, prev; prev2 + 1.day != d }.
map{|d| d.size > 1 ? "#{d.first.strftime('%b %d')} - #{d.last.strftime('%d')}" : d.first.strftime('%b %d') }
# => ["Sep 01 - 03", "Oct 01 - 02", "Oct 05"]