[RUBY-ON-RAILS] 루비 : 날짜의 범위를 만들기
RUBY-ON-RAILS루비 : 날짜의 범위를 만들기
나는 예 : 날짜 시간의 범위를 만들기 위해 우아한 방법을 찾고 있어요 :
def DateRange(start_time, end_time, period)
...
end
>> results = DateRange(DateTime.new(2013,10,10,12), DateTime.new(2013,10,10,14), :hourly)
>> puts results
2013-10-10:12:00:00
2013-10-10:13:00:00
2013-10-10:14:00:00
구성하는 단계는, 예를 들어 있어야 시간별, 일별, 월별.
나는 시간이 포함 싶습니다, 즉 END_TIME을 포함한다.
추가 요구 사항은 다음과 같습니다 :
우아한 해결책이 있습니까?
해결법
-
==============================
1.CaptainPete의 기본 @ 사용하여, 나는 ActiveSupport :: 날짜 시간 # 사전 전화를 사용하도록 수정했습니다. 달 "과": 년 "시간 간격은`로, 균일하지 않은 경우의 차이는 발효
CaptainPete의 기본 @ 사용하여, 나는 ActiveSupport :: 날짜 시간 # 사전 전화를 사용하도록 수정했습니다. 달 "과": 년 "시간 간격은`로, 균일하지 않은 경우의 차이는 발효
require 'active_support/all' class RailsDateRange < Range # step is similar to DateTime#advance argument def every(step, &block) c_time = self.begin.to_datetime finish_time = self.end.to_datetime foo_compare = self.exclude_end? ? :< : :<= arr = [] while c_time.send( foo_compare, finish_time) do arr << c_time c_time = c_time.advance(step) end return arr end end # Convenience method def RailsDateRange(range) RailsDateRange.new(range.begin, range.end, range.exclude_end?) end
내 방법은 배열을 반환합니다. 비교를 위해, 또한 배열을 반환하는 CaptainPete의 대답 @ 변경 :
RailsDateRange((4.years.ago)..Time.now).every(years: 1) => [Tue, 13 Oct 2009 11:30:07 -0400, Wed, 13 Oct 2010 11:30:07 -0400, Thu, 13 Oct 2011 11:30:07 -0400, Sat, 13 Oct 2012 11:30:07 -0400, Sun, 13 Oct 2013 11:30:07 -0400] DateRange((4.years.ago)..Time.now).every(1.year) => [2009-10-13 11:30:07 -0400, 2010-10-13 17:30:07 -0400, 2011-10-13 23:30:07 -0400, 2012-10-13 05:30:07 -0400, 2013-10-13 11:30:07 -0400]
RailsDateRange((5.months.ago)..Time.now).every(months: 1) => [Mon, 13 May 2013 11:31:55 -0400, Thu, 13 Jun 2013 11:31:55 -0400, Sat, 13 Jul 2013 11:31:55 -0400, Tue, 13 Aug 2013 11:31:55 -0400, Fri, 13 Sep 2013 11:31:55 -0400, Sun, 13 Oct 2013 11:31:55 -0400] DateRange((5.months.ago)..Time.now).every(1.month) => [2013-05-13 11:31:55 -0400, 2013-06-12 11:31:55 -0400, 2013-07-12 11:31:55 -0400, 2013-08-11 11:31:55 -0400, 2013-09-10 11:31:55 -0400, 2013-10-10 11:31:55 -0400]
RailsDateRange((4.years.ago)..Time.now).every(years: 1) => [Tue, 13 Oct 2009 11:30:07 -0400, Wed, 13 Oct 2010 11:30:07 -0400, Thu, 13 Oct 2011 11:30:07 -0400, Sat, 13 Oct 2012 11:30:07 -0400, Sun, 13 Oct 2013 11:30:07 -0400] DateRange((4.years.ago)..Time.now).every(1.year) => [2009-10-13 11:30:07 -0400, 2010-10-13 17:30:07 -0400, 2011-10-13 23:30:07 -0400, 2012-10-13 05:30:07 -0400, 2013-10-13 11:30:07 -0400]
-
==============================
2.오류를 반올림, 범위는 당신이 원하는하지 않은, 순서를 열거 할 .succ 메소드를 호출하지 않습니다.
오류를 반올림, 범위는 당신이 원하는하지 않은, 순서를 열거 할 .succ 메소드를 호출하지 않습니다.
아니 한 줄하지만, 짧은 도우미 기능은 충분합니다 :
def datetime_sequence(start, stop, step) dates = [start] while dates.last < (stop - step) dates << (dates.last + step) end return dates end datetime_sequence(DateTime.now, DateTime.now + 1.day, 1.hour) # [Mon, 30 Sep 2013 08:28:38 -0400, Mon, 30 Sep 2013 09:28:38 -0400, ...]
참고 그러나,이 격렬하게 비효율적 인 메모리 현명한 큰 범위에 대해 수 있습니다.
또는, 당신은 시대 이후 초를 사용할 수 있습니다 :
start = DateTime.now stop = DateTime.now + 1.day (start.to_i..stop.to_i).step(1.hour) # => #<Enumerator: 1380545483..1380631883:step(3600 seconds)>
당신은 정수의 범위를해야합니다,하지만 당신은 쉽게 날짜 시간으로 다시 변환 할 수 있습니다 :
Time.at(i).to_datetime
-
==============================
3.
module RangeWithStepTime def step(step_size = 1, &block) return to_enum(:step, step_size) unless block_given? # Defer to Range for steps other than durations on times return super unless step_size.kind_of? ActiveSupport::Duration # Advance through time using steps time = self.begin op = exclude_end? ? :< : :<= while time.send(op, self.end) yield time time = step_size.parts.inject(time) { |t, (type, number)| t.advance(type => number) } end self end end Range.prepend(RangeWithStepTime)
이는 기존의 API를 사용하여 범위에 대한 우리의 기간에 대한 지원을 추가합니다. 그것은 당신이 우리가 단순히 "단지 작품"으로 기대하는 스타일로 일반 범위를 사용할 수 있습니다.
# Now the question's invocation becomes even # simpler and more flexible step = 2.months + 4.days + 22.3.seconds ( Time.now .. 7.months.from_now ).step(step) do |time| puts "It's #{time} (#{time.to_f})" end # It's 2013-10-17 13:25:07 +1100 (1381976707.275407) # It's 2013-12-21 13:25:29 +1100 (1387592729.575407) # It's 2014-02-25 13:25:51 +1100 (1393295151.8754072) # It's 2014-04-29 13:26:14 +1000 (1398741974.1754072)
... 단계 초 그들을 통해 스테핑, 내부적으로 정수로 시간을 다음 개체에 DATERANGE <범위 클래스 + DATERANGE "생성자"를 사용하여 #every를 추가로 변환하는 것이 었습니다. 이것은 원래 시간대에 작동하지 않았다. 시간대에 대한 지원이 추가되었다하지만 또 다른 문제는 몇 가지 단계 기간은 동적 사실 (예를 들어 1.month)와 함께 발견되었다.
읽기 Rubinius '범위의 구현은 누군가가 ActiveSupport :: 기간에 대한 지원을 추가 할 수있는 방법을 명확하게되었다; 그래서 접근 방식은 다시 작성했다. #advance 팁과이 문제를 디버깅, 아름답게 기록되기위한 범위 # 단계의 Rubinius '구현에 댄 구엔에 많은 감사합니다 : D
-
==============================
4.당신이 갖고 싶어 N 경우 값이 고르게 두 날짜 당신은 할 수 사이에 확산
당신이 갖고 싶어 N 경우 값이 고르게 두 날짜 당신은 할 수 사이에 확산
n = 8 beginning = Time.now - 1.day ending = Time.now diff = ending - beginning result = [] (n).times.each do | x | result << (beginning + ((x*diff)/(n-1)).seconds) end result
이는 제공
2015-05-20 16:20:23 +0100 2015-05-20 19:46:05 +0100 2015-05-20 23:11:48 +0100 2015-05-21 02:37:31 +0100 2015-05-21 06:03:14 +0100 2015-05-21 09:28:57 +0100 2015-05-21 12:54:40 +0100 2015-05-21 16:20:23 +0100
-
==============================
5.당신은 반복에 대한 잠금을 얻기 위해 시작 시간과 종료 시간에 DateTime.parse를 사용하여 배열을 채울 필요가있다. 예를 들어;
당신은 반복에 대한 잠금을 얻기 위해 시작 시간과 종료 시간에 DateTime.parse를 사용하여 배열을 채울 필요가있다. 예를 들어;
#Seconds ((DateTime.parse(@startdt) - DateTime.now) * 24 * 60 * 60).to_i.abs #Minutes ((DateTime.parse(@startdt) - DateTime.now) * 24 * 60).to_i.abs
등등. 이 값이 있으면, 할 수 있습니다 당신이 원하는 시간의 어떤 조각의 배열을 채우기 통해 루프. 나는, 당신은 아마 이것에 대한 배열을 구체화 할 필요가 없습니다 불구하고 @fotanus에 동의하지만, 나는 당신의 목표는 정말 말할 수 있도록 그렇게 무엇인지 모른다.
-
==============================
6.아이스 큐브 - 루비 날짜 재발 도서관은 여기에 도움 또는 구현을 보일 것? 그것은 성공적으로 RFC 5545 규격의 모든 예를 커버하고있다.
아이스 큐브 - 루비 날짜 재발 도서관은 여기에 도움 또는 구현을 보일 것? 그것은 성공적으로 RFC 5545 규격의 모든 예를 커버하고있다.
schedule = IceCube::Schedule.new(2013,10,10,12) schedule.add_recurrence_rule IceCube::Rule.hourly.until(Time.new(2013,10,10,14)) schedule.all_occurrences # => [ # [0] 2013-10-10 12:00:00 +0100, # [1] 2013-10-10 13:00:00 +0100, # [2] 2013-10-10 14:00:00 +0100 #]
-
==============================
7.또 다른 해결책은 UNIQ 방법을 사용하는 것입니다. 예를 고려해
또 다른 해결책은 UNIQ 방법을 사용하는 것입니다. 예를 고려해
date_range = (Date.parse('2019-01-05')..Date.parse('2019-03-01')) date_range.uniq { |d| d.month } # => [Sat, 05 Jan 2019, Fri, 01 Feb 2019] date_range.uniq { |d| d.cweek } # => [Sat, 05 Jan 2019, Mon, 07 Jan 2019, Mon, 14 Jan 2019, Mon, 21 Jan 2019, Mon, 28 Jan 2019, Mon, 04 Feb 2019, Mon, 11 Feb 2019, Mon, 18 Feb 2019, Mon, 25 Feb 2019]
참고 이러한 접근 점은 최소 및 최대 범위 것을
-
==============================
8.당신이 할 수 있도록 한 시간은 하루 1 / 24입니다
당신이 할 수 있도록 한 시간은 하루 1 / 24입니다
d1 = DateTime.now d2 = d1 + 1 d1.step(d2, 1/24r){|d| p d}
1 / 24R은 합리적이고보다 정확한보다 플로트이다.
from https://stackoverflow.com/questions/19093487/ruby-create-range-of-dates by cc-by-sa and MIT license
'RUBY-ON-RAILS' 카테고리의 다른 글
[RUBY-ON-RAILS] 설정 / 환경 / development.rb에서 "consider_all_requests_local"의 목적? (0) | 2020.03.01 |
---|---|
[RUBY-ON-RAILS] 3.1 제한 사용자가 만든 개체 레일 (0) | 2020.03.01 |
[RUBY-ON-RAILS] 3.2 레일 : Heroku가 푸시 거부, 더 세다 지원하는 응용 프로그램은 감지되지 (0) | 2020.03.01 |
[RUBY-ON-RAILS] 레일 : LINK_TO에서 GET 쿼리 문자열 매개 변수 보존 (0) | 2020.03.01 |
[RUBY-ON-RAILS] 루비 레일에 - f.select에서 다중 선택 (0) | 2020.03.01 |