Skip to content

Instantly share code, notes, and snippets.

@peterfei
Forked from msg7086/Gemfile
Created October 25, 2015 04:26
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save peterfei/f52d7b9b39bdb69fa481 to your computer and use it in GitHub Desktop.
Save peterfei/f52d7b9b39bdb69fa481 to your computer and use it in GitHub Desktop.
source 'https://rubygems.org'
gem 'activesupport'
gem 'rspec-rails'
require 'active_support'
require 'active_support/core_ext'
class Schedule
NO_REPEAT = 0
R_DAY = 1
R_WDAY = 2
R_WEEK = 3
R_MONTH = 4
EOL = 10.years.since
attr_accessor :current_start, :current_end
def initialize start_time:, end_time:, repeat: 0, last_time: nil
@start_time = start_time
@end_time = end_time
@repeat = repeat
@last_time = last_time
@current_start = @start_time
@current_end = @end_time
end
# return: nil if no next, else a schedule start from next date
def next_time!
return if @current_start.nil?
return @current_start = nil if @repeat == NO_REPEAT
offset = 0
case @repeat
when R_DAY then offset = 1.day
when R_WDAY then offset = @current_start.wday == 5 ? 3.days : 1.day
when R_WEEK then offset = 7.days
when R_MONTH then offset = find_next_month_offset
end
duration = @current_end - @current_start
@current_start += offset
@current_end = @current_start + duration
return @current_start = nil if @last_time && @current_start > @last_time
return @current_start = nil if @current_start > EOL
@current_start
end
# next month at the end of the month could be more than 1 month offset
# next month of 3/31 is 5/31
def find_next_month_offset
length = 0
this_month = @current_start
loop do
length += 1
next_month = this_month + length.months
break if next_month.day == this_month.day
end
length.month
end
def conflicts? sch
# @start within sch?
return true if @current_start >= sch.current_start && @current_start <= sch.current_end
# @end within sch?
return true if @current_end >= sch.current_start && @current_end <= sch.current_end
# @ contains sch?
return true if @current_start <= sch.current_start && @current_end >= sch.current_end
# safe
false
end
end
class ScheduleService
def self.conflicts? s1, s2
# if both schedule exists?
while !s1.current_start.nil? && !s2.current_start.nil?
# check if they conflicts
return true if s1.conflicts? s2
# find the next date to compare
if s1.current_start < s2.current_start
s1.next_time!
else
s2.next_time!
end
end
false
end
end
require './main'
describe Schedule do
it 'generates future events by month' do
t = Time.new(2015,1,31)
s = Schedule.new start_time: t, end_time: t + 40.minutes, repeat: 4, last_time: t + 1.year
tlist = []
while !s.current_start.nil? do
tlist << s.current_start
s.next_time!
end
expect(tlist.size).to eq 8
end
it 'generates future events by week' do
t = Time.new(2015,1,31)
s = Schedule.new start_time: t, end_time: t + 40.minutes, repeat: 3, last_time: t + 1.year
tlist = []
while !s.current_start.nil? do
tlist << s.current_start
s.next_time!
end
expect(tlist.size).to eq 53
end
it 'generates future events by workday' do
t = Time.new(2015,2,2) # It's monday
s = Schedule.new start_time: t, end_time: t + 40.minutes, repeat: 2, last_time: t + 1.month
tlist = []
while !s.current_start.nil? do
tlist << s.current_start
s.next_time!
end
expect(tlist.size).to eq 21
end
it 'generates future events by day' do
t = Time.new(2015,1,31)
s = Schedule.new start_time: t, end_time: t + 40.minutes, repeat: 1, last_time: t + 1.month
tlist = []
while !s.current_start.nil? do
tlist << s.current_start
s.next_time!
end
expect(tlist.size).to eq 29
end
end
describe ScheduleService do
it '日程【2015-07-08 16:00:00,2015-07-08 17:00:00,不重复】与日程【2015-07-06 16:00:00,2015-07-06 16:30:00,每天重复,没有截止日期】冲突' do
s1 = Schedule.new start_time: Time.new(2015, 7, 8, 16), end_time: Time.new(2015, 7, 8, 17)
s2 = Schedule.new start_time: Time.new(2015, 7, 6, 16), end_time: Time.new(2015, 7, 6, 16, 30), repeat: Schedule::R_DAY
expect(ScheduleService.conflicts? s1, s2).to be true
end
it '日程【2015-07-08 16:00:00,2015-07-08 17:00:00,每工作日重复,没有截止日期】与日程【2015-07-11 16:00:00,2015-07-11 17:00:00,每周重复,没有截止日期】 不冲突' do
s1 = Schedule.new start_time: Time.new(2015, 7, 8, 16), end_time: Time.new(2015, 7, 8, 17), repeat: Schedule::R_WDAY
s2 = Schedule.new start_time: Time.new(2015, 7, 11, 16), end_time: Time.new(2015, 7, 11, 17), repeat: Schedule::R_WEEK
expect(ScheduleService.conflicts? s1, s2).to be false
end
it '日程【2015-05-31 16:00:00,2015-05-31 17:00:00,每月重复,截止2015-07-15】与日程【2015-06-10 16:00:00,2015-06-10 17:00:00,每天重复,没有截止日期】不冲突' do
s1 = Schedule.new start_time: Time.new(2015, 5, 31, 16), end_time: Time.new(2015, 5, 31, 17), repeat: Schedule::R_MONTH, last_time: Time.new(2015, 7, 15)
s2 = Schedule.new start_time: Time.new(2015, 6, 10, 16), end_time: Time.new(2015, 6, 10, 17), repeat: Schedule::R_DAY
expect(ScheduleService.conflicts? s1, s2).to be false
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment