Accelerate recurring events calculating.

This commit is contained in:
BoHung Chiu 2022-07-21 23:31:58 +08:00
parent dfb7f23a3d
commit 7cccdd2006
1 changed files with 54 additions and 57 deletions

View File

@ -17,6 +17,7 @@ class Event
field :recurring, type: Boolean,default: false field :recurring, type: Boolean,default: false
field :frequency field :frequency
field :period field :period
field :recurring_end_date, type: DateTime
field :create_user_id field :create_user_id
field :update_user_id field :update_user_id
field :module_key field :module_key
@ -147,69 +148,65 @@ class Event
(date2.year-date1.year)*12+(date2.month-date1.month) (date2.year-date1.year)*12+(date2.month-date1.month)
end end
def self.recurring_event(start_date,end_date) def self.recurring_event(start_date,end_date)
@recurring_events = self.where(:recurring => true) @recurring_events = self.where(:recurring => true).any_of({:recurring_end_date=>nil}, {:recurring_end_date.gte=>start_date.utc})
@recurring = [] @recurring = []
@recurring_events.each do |re| @recurring_events.each do |re|
edit_url = Rails.application.routes.url_helpers.edit_admin_calendar_path(:locale=>I18n.locale, :id=>re.id) has_recurring_end_date = re.recurring_end_date.present?
delete_url = Rails.application.routes.url_helpers.admin_calendar_path(:locale=>I18n.locale, :id=>re.id) data = re.as_json
data = {:id => re.id.to_s, :title=>re.title, :note=>re.note || "", :allDay => re.all_day, :recurring => re.recurring, :calendar => re.calendar_type.id.to_s, :color => (re.calendar_type.color rescue nil), :edit_url => edit_url, :delete_url => delete_url, :url_linked => re.url_to_fronted} period_str = nil
case re.period is_month = false
when 'Daily' is_year = false
days = (end_date.to_date-re.start.to_date).to_i days = 1
interval = nil
if re.period == 'Daily'
period_str = 'day'
interval = 1.day
elsif re.period == 'Weekly'
period_str = 'week'
days = 7
interval = 1.week
elsif re.period == 'Monthly'
period_str = 'month'
is_month = true
days = 30
elsif re.period == 'Yearly'
period_str = 'year'
is_year = true
days = 365
end
if period_str
org_start = re.start
@start_date = re.start
@end_date = re.end
freq = re.frequency.to_i freq = re.frequency.to_i
start_key = (start_date.to_date-re.start.to_date).to_i interval = freq.send(period_str)
start_key = 1 if start_key<0 if is_month
(start_key..days).each do |i| add_interval = ((start_date.year * 12 + start_date.month) - (@start_date.year * 12 + @start_date.month) - 1)
if i%freq==0 elsif is_year
@start_date = re.start + i add_interval = (start_date.year - @start_date.year - 1)
@end_date = re.end + i else
@recurring << data.merge({:start => @start_date, :end => @end_date}) add_interval = (((start_date - @start_date - 1.day).to_i / 1.day) / days)
end
end end
when "Weekly" if add_interval < 0
@start_date = re.start add_interval = add_interval % freq
@end_date = re.end
@i = TimeDifference.between(re.start.to_date,end_date.to_date).in_weeks.to_i
(1..@i).each do |i|
@start_date += (7*re.frequency.to_i)
@end_date += (7*re.frequency.to_i)
@recurring << data.merge({:start => @start_date, :end => @end_date})
end
when "Monthly"
if !(start_date..end_date).cover?(re.start) && start_date.to_datetime>re.start
sd = re.start
ed = re.end
end_datetime = end_date.to_datetime
start_datetime = start_date.to_datetime
months = self.get_diff_month(sd,start_datetime)..self.get_diff_month(sd,end_datetime)
months.each do |diff_month|
if (diff_month%re.frequency.to_i)==0
sd_tp = sd + diff_month.month
ed_tp = ed + diff_month.month
if sd_tp>start_date
@recurring << data.merge({:start => sd_tp, :end => ed_tp})
end
end
end
end end
when "Yearly" rest = add_interval % freq
if !(start_date..end_date).cover?(re.start) if rest != 0
sd = re.start add_interval += (freq - rest)
ed = re.end
start_datetime = start_date.to_datetime
end_datetime = end_date.to_datetime
if start_datetime>sd && start_datetime.year != sd.year
((start_datetime.year-sd.year)..(end_datetime.year-sd.year)).each do |year_diff|
if (year_diff%re.frequency.to_i)==0
sd_tp = sd + year_diff.year
ed_tp = ed + year_diff.year
if (start_date..end_date)&(sd_tp..ed_tp)
@recurring << data.merge({:start => sd_tp, :end => ed_tp})
end
end
end
end
end end
add_interval = add_interval.send(period_str)
@start_date += add_interval
@end_date += add_interval
new_end_date = has_recurring_end_date ? [re.recurring_end_date,end_date].min : end_date
while @start_date <= new_end_date do
if @start_date >= start_date && @start_date != org_start
@recurring << data.merge({:start => @start_date.to_json.gsub('"',''), :end => @end_date.to_json.gsub('"','')})
end
@start_date += interval
@end_date += interval
end
else
next
end end
end end