mirror of
https://github.com/plashchynski/crono.git
synced 2026-03-14 06:16:35 +01:00
Merge pull request #34 from lhz/intervals
Added :within option to Period to run only within given time interval.
This commit is contained in:
@@ -6,6 +6,8 @@ require 'active_support/all'
|
||||
require 'crono/version'
|
||||
require 'crono/logging'
|
||||
require 'crono/period'
|
||||
require 'crono/time_of_day'
|
||||
require 'crono/interval'
|
||||
require 'crono/job'
|
||||
require 'crono/scheduler'
|
||||
require 'crono/config'
|
||||
|
||||
43
lib/crono/interval.rb
Normal file
43
lib/crono/interval.rb
Normal file
@@ -0,0 +1,43 @@
|
||||
module Crono
|
||||
# Interval describes a period between two specific times of day
|
||||
class Interval
|
||||
attr_accessor :from, :to
|
||||
|
||||
def self.parse(value)
|
||||
from_to =
|
||||
case value
|
||||
when Array then value
|
||||
when Hash then value.values_at(:from, :to)
|
||||
when String then value.split('-')
|
||||
else
|
||||
fail "Unknown interval format: #{value.inspect}"
|
||||
end
|
||||
from, to = from_to.map { |v| TimeOfDay.parse(v) }
|
||||
new from, to
|
||||
end
|
||||
|
||||
def initialize(from, to)
|
||||
@from, @to = from, to
|
||||
end
|
||||
|
||||
def within?(value)
|
||||
tod = ((value.is_a? TimeOfDay) ? value : TimeOfDay.parse(value))
|
||||
if @from <= @to
|
||||
tod >= @from && tod < @to
|
||||
else
|
||||
tod >= @from || tod < @to
|
||||
end
|
||||
end
|
||||
|
||||
def next_within(time, period)
|
||||
begin
|
||||
time = period.since(time)
|
||||
end until within? TimeOfDay.parse(time)
|
||||
time
|
||||
end
|
||||
|
||||
def to_s
|
||||
"#{@from}-#{@to}"
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -4,15 +4,25 @@ module Crono
|
||||
DAYS = [:monday, :tuesday, :wednesday, :thursday, :friday, :saturday,
|
||||
:sunday]
|
||||
|
||||
def initialize(period, at: nil, on: nil)
|
||||
def initialize(period, at: nil, on: nil, within: nil)
|
||||
@period = period
|
||||
@at_hour, @at_min = parse_at(at) if at
|
||||
@interval = Interval.parse(within) if within
|
||||
@on = parse_on(on) if on
|
||||
end
|
||||
|
||||
def next(since: nil)
|
||||
return initial_next unless since
|
||||
@next = @period.since(since)
|
||||
if @interval
|
||||
if since
|
||||
@next = @interval.next_within(since, @period)
|
||||
else
|
||||
return initial_next if @interval.within?(initial_next)
|
||||
@next = @interval.next_within(initial_next, @period)
|
||||
end
|
||||
else
|
||||
return initial_next unless since
|
||||
@next = @period.since(since)
|
||||
end
|
||||
@next = @next.beginning_of_week.advance(days: @on) if @on
|
||||
@next = @next.change(time_atts)
|
||||
return @next if @next.future?
|
||||
@@ -21,6 +31,7 @@ module Crono
|
||||
|
||||
def description
|
||||
desc = "every #{@period.inspect}"
|
||||
desc += " between #{@interval.from} and #{@interval.to} UTC" if @interval
|
||||
desc += format(' at %.2i:%.2i', @at_hour, @at_min) if @at_hour && @at_min
|
||||
desc += " on #{DAYS[@on].capitalize}" if @on
|
||||
desc
|
||||
|
||||
36
lib/crono/time_of_day.rb
Normal file
36
lib/crono/time_of_day.rb
Normal file
@@ -0,0 +1,36 @@
|
||||
module Crono
|
||||
# TimeOfDay describes a certain hour and minute (on any day)
|
||||
class TimeOfDay
|
||||
include Comparable
|
||||
|
||||
attr_accessor :hour, :min
|
||||
|
||||
def self.parse(value)
|
||||
time =
|
||||
case value
|
||||
when String then Time.parse(value).utc
|
||||
when Hash then Time.now.change(value).utc
|
||||
when Time then value.utc
|
||||
else
|
||||
fail "Unknown TimeOfDay format: #{value.inspect}"
|
||||
end
|
||||
new time.hour, time.min
|
||||
end
|
||||
|
||||
def initialize(hour, min)
|
||||
@hour, @min = hour, min
|
||||
end
|
||||
|
||||
def to_i
|
||||
@hour * 60 + @min
|
||||
end
|
||||
|
||||
def to_s
|
||||
'%02d:%02d' % [@hour, @min]
|
||||
end
|
||||
|
||||
def <=>(other)
|
||||
to_i <=> other.to_i
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -110,6 +110,17 @@ describe Crono::Period do
|
||||
expect(@period.next.utc.to_s).to be_eql Time.now.beginning_of_hour.advance(minutes: 15).utc.to_s
|
||||
end
|
||||
end
|
||||
|
||||
it 'should return next hour minutes within the given interval' do
|
||||
Timecop.freeze(Time.now.change(hour: 16, min: 10)) do
|
||||
@period = Crono::Period.new(1.hour, at: { min: 15 }, within: '08:00-16:00')
|
||||
expect(@period.next.utc.to_s).to be_eql Time.now.tomorrow.change(hour: 8, min: 15).utc.to_s
|
||||
end
|
||||
Timecop.freeze(Time.now.change(hour: 16, min: 10)) do
|
||||
@period = Crono::Period.new(1.hour, at: { min: 15 }, within: '23:00-07:00')
|
||||
expect(@period.next.utc.to_s).to be_eql Time.now.change(hour: 23, min: 15).utc.to_s
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
Reference in New Issue
Block a user