Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
431 views
in Technique[技术] by (71.8m points)

ruby on rails - How to divide a time period into multiple periods

I have a time period in two variables, from start_date to end_date. Is there an easy way to split it into a smaller periods, rounding the values up.

Here's an example:

I have period from 15.01.2016 to 10.06.2016. I want to split it into months, so I will have six periods:

01.01.2016 - 31.01.2016  
01.02.2016 - 31.02.2016   
01.03.2016 - 31.03.2016  
01.04.2016 - 31.04.2016  
01.05.2016 - 31.05.2016  
01.06.2016 - 31.06.2016 

I want to include the time between 01.01.2016 and 15.01.2016 regardless of the fact that it is not in the original period.

I've been looking for some ideas, but at this time it seems that the only way is using the start date and iterating using DateAndTime::Calculations to determine the borders of intervals, until hitting the end date.

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)
from = Date.parse('15.01.2016')
to   = Date.parse('10.06.2016')
(from..to).group_by(&:month).map do |group|
  group.last.first.beginning_of_month..group.last.last.end_of_month
end
# => [Fri, 01 Jan 2016..Sun, 31 Jan 2016,
#  Mon, 01 Feb 2016..Mon, 29 Feb 2016,
#  Tue, 01 Mar 2016..Thu, 31 Mar 2016,
#  Fri, 01 Apr 2016..Sat, 30 Apr 2016,
#  Sun, 01 May 2016..Tue, 31 May 2016,
#  Wed, 01 Jun 2016..Thu, 30 Jun 2016]

Or, map dates to strings, if you need string representation:

(from..to).group_by(&:month).map do |group|
  "#{group.last.first.beginning_of_month} - #{group.last.last.end_of_month}"
end

# => ["2016-01-01 - 2016-01-31",
#     "2016-02-01 - 2016-02-29",
#     "2016-03-01 - 2016-03-31",
#     "2016-04-01 - 2016-04-30",
#     "2016-05-01 - 2016-05-31",
#     "2016-06-01 - 2016-06-30"]

To get precisely what you want, you can format the string representation of the dates:

(from..to).group_by(&:month).map do |group|
  "#{group.last.first.beginning_of_month.strftime('%d-%m-%Y')} - #{group.last.last.end_of_month.strftime('%d-%m-%Y')}"
end
#=> ["01-01-2016 - 31-01-2016",
#    "01-02-2016 - 29-02-2016",
#    "01-03-2016 - 31-03-2016",
#    "01-04-2016 - 30-04-2016",
#    "01-05-2016 - 31-05-2016",
#    "01-06-2016 - 30-06-2016"]

EDIT

To make sure ranges do not mix up because of different years, include it in grouping along with month:

from = Date.parse('15.01.2016')
to   = Date.parse('10.02.2017')
(from..to).group_by {|a| [a.year, a.month]}.map do |group|
  "#{group.last.first.beginning_of_month.strftime('%d-%m-%Y')} - #{group.last.last.end_of_month.strftime('%d-%m-%Y')}"
end
# => ["01-01-2016 - 31-01-2016",
#  "01-02-2016 - 29-02-2016",
#  "01-03-2016 - 31-03-2016",
#  "01-04-2016 - 30-04-2016",
#  "01-05-2016 - 31-05-2016",
#  "01-06-2016 - 30-06-2016",
#  "01-07-2016 - 31-07-2016",
#  "01-08-2016 - 31-08-2016",
#  "01-09-2016 - 30-09-2016",
#  "01-10-2016 - 31-10-2016",
#  "01-11-2016 - 30-11-2016",
#  "01-12-2016 - 31-12-2016",
#  "01-01-2017 - 31-01-2017",
#  "01-02-2017 - 28-02-2017"]

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...