mirror of
https://github.com/plashchynski/crono.git
synced 2026-04-18 06:59:51 +02: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/version'
|
||||||
require 'crono/logging'
|
require 'crono/logging'
|
||||||
require 'crono/period'
|
require 'crono/period'
|
||||||
|
require 'crono/time_of_day'
|
||||||
|
require 'crono/interval'
|
||||||
require 'crono/job'
|
require 'crono/job'
|
||||||
require 'crono/scheduler'
|
require 'crono/scheduler'
|
||||||
require 'crono/config'
|
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,
|
DAYS = [:monday, :tuesday, :wednesday, :thursday, :friday, :saturday,
|
||||||
:sunday]
|
:sunday]
|
||||||
|
|
||||||
def initialize(period, at: nil, on: nil)
|
def initialize(period, at: nil, on: nil, within: nil)
|
||||||
@period = period
|
@period = period
|
||||||
@at_hour, @at_min = parse_at(at) if at
|
@at_hour, @at_min = parse_at(at) if at
|
||||||
|
@interval = Interval.parse(within) if within
|
||||||
@on = parse_on(on) if on
|
@on = parse_on(on) if on
|
||||||
end
|
end
|
||||||
|
|
||||||
def next(since: nil)
|
def next(since: nil)
|
||||||
return initial_next unless since
|
if @interval
|
||||||
@next = @period.since(since)
|
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.beginning_of_week.advance(days: @on) if @on
|
||||||
@next = @next.change(time_atts)
|
@next = @next.change(time_atts)
|
||||||
return @next if @next.future?
|
return @next if @next.future?
|
||||||
@@ -21,6 +31,7 @@ module Crono
|
|||||||
|
|
||||||
def description
|
def description
|
||||||
desc = "every #{@period.inspect}"
|
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 += format(' at %.2i:%.2i', @at_hour, @at_min) if @at_hour && @at_min
|
||||||
desc += " on #{DAYS[@on].capitalize}" if @on
|
desc += " on #{DAYS[@on].capitalize}" if @on
|
||||||
desc
|
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
|
expect(@period.next.utc.to_s).to be_eql Time.now.beginning_of_hour.advance(minutes: 15).utc.to_s
|
||||||
end
|
end
|
||||||
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
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
Reference in New Issue
Block a user