Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Refacto : periods #24

Open
wants to merge 12 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
37 changes: 20 additions & 17 deletions lib/opening_hours_converter.rb
Original file line number Diff line number Diff line change
@@ -1,21 +1,24 @@
module OpeningHoursConverter
require 'date'
require_relative './opening_hours_converter/utils'
require_relative './opening_hours_converter/utils/utils'
require_relative './opening_hours_converter/utils/constants'
require_relative './opening_hours_converter/utils/public_holiday'
require_relative './opening_hours_converter/utils/week_index'

require_relative './opening_hours_converter/date_range_list'
require_relative './opening_hours_converter/date_range_lists/period_list'
require_relative './opening_hours_converter/date_range_lists/week_list'

require_relative './opening_hours_converter/date_range'
require_relative './opening_hours_converter/token'
require_relative './opening_hours_converter/tokenizer'
require_relative './opening_hours_converter/tokens_handler'
require_relative './opening_hours_converter/day'
require_relative './opening_hours_converter/week'
require_relative './opening_hours_converter/year'
require_relative './opening_hours_converter/public_holiday'
require_relative './opening_hours_converter/interval'
require_relative './opening_hours_converter/iterator'
require_relative './opening_hours_converter/opening_hours_builder'
require_relative './opening_hours_converter/opening_hours_date'
require_relative './opening_hours_converter/opening_hours_parser'
require_relative './opening_hours_converter/opening_hours_rule'
require_relative './opening_hours_converter/opening_hours_time'
require_relative './opening_hours_converter/wide_interval'
require_relative './opening_hours_converter/week_index'
require_relative './opening_hours_converter/date_ranges/period'
require_relative './opening_hours_converter/date_ranges/week'

require_relative './opening_hours_converter/date_range_tip'

require_relative './opening_hours_converter/tokens/token'
require_relative './opening_hours_converter/tokens/token_data'
require_relative './opening_hours_converter/tokens/tokenizer'
require_relative './opening_hours_converter/tokens/tokens_handler'

require_relative './opening_hours_converter/parser'
end
139 changes: 100 additions & 39 deletions lib/opening_hours_converter/date_range.rb
Original file line number Diff line number Diff line change
@@ -1,61 +1,122 @@
require 'opening_hours_converter/utils/constants'

module OpeningHoursConverter
class DateRange
attr_accessor :wide_interval, :typical, :comment
include Constants

def to_s(template = nil)
if template.nil?
get
else
get_with_template(template)
end
end

def get
return '' if always?

if known_year
return "#{@from.to_s('YEAR')}" if full_year?
if same_year?
return "#{@from.to_s('YEAR MONTH DAY')}" if same_day?
return "#{@from.to_s('YEAR MONTH DAY')}-#{@to.to_s('DAY')}" if same_month?
return "#{@from.to_s('YEAR MONTH DAY')}-#{@to.to_s('MONTH DAY')}"
else
return "#{@from.to_s('YEAR')}-#{@to.to_s('YEAR')}" if start_year? && end_year?
return "#{@from.to_s('YEAR MONTH DAY')}-#{@to.to_s('YEAR MONTH DAY')}"
end
else
return "#{@from.to_s('MONTH DAY')}" if same_day?
return "#{@from.to_s('MONTH DAY')}-#{@to.to_s('DAY')}" if same_month?
return "#{@from.to_s('MONTH DAY')}-#{@to.to_s('MONTH DAY')}"
end
end

def get_with_template template
template.gsub!('FROM DAY', @from.day.to_s)
template.gsub!('FROM MONTH', OSM_MONTHS[@from.month - 1])
template.gsub!('FROM YEAR', @from.year.to_s) if known_years
template.gsub!('TO DAY', @to.day.to_s)
template.gsub!('TO MONTH', OSM_MONTHS[@to.month - 1])
template.gsub!('TO YEAR', @to.year.to_s) if known_years

def initialize(wide_interval = nil)
@wide_interval = nil
@typical = nil
@comment = ''
update_range(wide_interval)
template
end

def defines_typical_day?
@typical.instance_of?(OpeningHoursConverter::Day)
def always?
false && is_a?(Always)
end

def defines_typical_week?
@typical.instance_of?(OpeningHoursConverter::Week)
def full_month?
return false if always?
return false unless same_month?

from.month == to.month && from.day == 1 && to.day == last_day_of_month(to.month - 1, to.year || Date.today.year)
end

def update_range(wide_interval)
@wide_interval = !wide_interval.nil? ? wide_interval : OpeningHoursConverter::WideInterval.new.always
def full_year?
return false if always?
return false unless same_year?

start_year? && end_year?
end

return unless @typical.nil?
def start_year?
from.day == 1 && from.month == 1
end

@typical = case @wide_interval.type
when 'day'
if @wide_interval.end.nil?
OpeningHoursConverter::Day.new
else
OpeningHoursConverter::Week.new
end
else
OpeningHoursConverter::Week.new
end
def end_year?
to.month == 12 && to.day == 31
end

def add_comment(comment = '')
@comment += comment if comment
def same_year?
from.year == to.year
end

def has_same_typical?(date_range)
defines_typical_day? == date_range.defines_typical_day? && @typical.same_as?(date_range.typical)
def same_month?
same_year? && from.month == to.month
end

def is_general_for?(date_range)
defines_typical_day? == date_range.defines_typical_day? && @wide_interval.contains?(date_range.wide_interval) && @comment == date_range.comment
def same_day?
from.date == to.date
end

def is_holiday?
result = @wide_interval.type == 'holiday'
if !result
@typical.intervals.each do |i|
if !i.nil?
result = true if i.day_start == -2 && i.day_end == -2
end
end
end
result
def == period
return false if always? != period.always?
return true if always? && period.always?

from == period.from && to == period.to
end

def <=> period, part = :from
part == :from ? from <=> period.from : to <=> period.to
end

def touch? period
return false if self == period
return true if always?

to == period.from || from == period.to
end

def overlap? period
return true if self == period
return true if always?

(from < period.from && to > period.from) || (from < period.to && to > period.to)
end

def contains? period
return false if self == period
return true if always?

from <= period.from && to >= period.to
end

def width
return Float::INFINITY if always?

to - from
end
end
end
62 changes: 62 additions & 0 deletions lib/opening_hours_converter/date_range_list.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
module OpeningHoursConverter
class DateRangeList
attr_accessor :date_ranges

def to_s(template: nil, as_period: true)
date_ranges.map(&:to_s).join(',')
end

def width
return 0 if date_ranges.length == 0

date_ranges.map(&:width).sum
end

def == date_range
date_ranges.all? { |dr| dr == date_range } if date_range.is_a?(DateRange)
date_ranges == date_range.date_ranges if date_range.is_a?(DateRangeList)
end

def touch? date_range
date_ranges.any? { |dr| dr.touch? date_range } if date_range.is_a?(DateRange)
date_ranges.any? { |dr| date_range.any? { |dr2| dr.touch? dr2 } } if date_range.is_a?(DateRangeList)
end

def contains? date_range
date_ranges.any? { |dr| p.contains? date_range } if date_range.is_a?(DateRange)
date_range.all? { |dr2| date_ranges.any? { |dr| dr.contains? dr2 } } if date_range.is_a?(DateRangeList)
end

def known_years?
date_ranges.all?(&:known_years)
end

def years_to_s
if consecutives?(years)
"#{sorted_date_ranges(part = :from).first.to_s('FROM YEAR')}-#{sorted_date_ranges(part = :to).last.to_s('TO YEAR')}"
else
consecutives(years).map do |year|
if year.is_a?(Integer)
year.to_s
elsif year.is_a?(Hash)
"#{year[:from]}-#{year[:to]}"
end
end.join(',')
end
end

def all_years_similar?
years.all? { |year| same_days(year, years.first) }
end

def years
sorted_date_ranges.map do |date_range|
[date_range.from.year, date_range.to.year]
end.flatten.uniq.compact
end

def sorted_date_ranges(part = :from)
@date_ranges.sort { |date_range1, date_range2| date_range1.send(part) <=> date_range2.send(part) }
end
end
end
129 changes: 129 additions & 0 deletions lib/opening_hours_converter/date_range_lists/period_list.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,129 @@
require 'opening_hours_converter/utils/constants'
require 'opening_hours_converter/utils/utils'

module OpeningHoursConverter
class PeriodList < DateRangeList
include Constants
include Utils
attr_accessor :periods

def initialize(periods = [])
@date_ranges = periods
@periods = periods
end

def to_s
return '' if periods.length == 0
if periods.length == 1
periods.first.to_s
else
if known_years?
if periods.all?(&:full_year?)
years_to_s
else
years_to_s + ' ' + months_with_days_to_s
end
else
months_with_days_to_s
end
end
end

def months_with_days_to_s
months_with_days(years.first).map do |month, days|
if month.is_a?(Integer) && days.is_a?(Array)
days = consecutives(days.map(&:day))

result = "#{OSM_MONTHS[month - 1]} "
result += days.map do |day|
if day.is_a?(Integer)
day.to_s
elsif day.is_a?(Hash)
"#{day[:from]}-#{day[:to]}"
end
end.join(',')
elsif month[0] == month[1]
if days[0].day == 1 && days[1].day == last_day_of_month(month[0] - 1, years.first || Date.today.year)
OSM_MONTHS[month[0] - 1]
else
"#{OSM_MONTHS[month[0] - 1]} #{days[0].day}-#{days[1].day}"
end
else
"#{OSM_MONTHS[month[0] - 1]} #{days[0].day}-#{OSM_MONTHS[month[1] - 1]} #{days[1].day}"
end
end.join(',')
end

def months
sorted_date_ranges.map do |period|
[period.from.month, period.to.month]
end.flatten.uniq.compact
end

def days
sorted_date_ranges.map do |period|
[period.from.day, period.to.day]
end.flatten.uniq.compact
end

def months_with_days(year = nil)
m = {}
if years.nil?
months.each do |month|
periods.select { |period|
period.from.month == month || period.to.month == month
}.each do |period|
if period.from.month != period.to.month
m[[period.from.month, period.to.month]] = [period.from, period.to]
else

(period.from.date..period.to.date).map do |date|
break unless date.month == month

m[month] ||= []
m[month] << date
end
end
end
end
else
months.each do |month|
periods.select { |period|
(period.from.year == year || period.to.year == year) &&
(period.from.month == month || period.to.month == month)
}.map do |period|
if period.from.month != period.to.month
m[[period.from.month, period.to.month]] = [period.from, period.to]
else
if period.full_month?
m[[period.from.month, period.to.month]] = [period.from, period.to]
else
(period.from.date..period.to.date).map do |date|
break unless date.month == month

m[month] ||= []
m[month] << date
end
end
end
end
end
end
m
end

def same_days(year1, year2)
days_for_year(year1).map { |d| [d.month, d.day] unless d.month == 2 && d.day == 29 }.compact.sort == days_for_year(year2).map { |d| [d.month, d.day] unless d.month == 2 && d.day == 29 }.compact.sort
end

def days_for_year(year)
periods.select { |period| period.from.year == year || period.to.year == year}.map do |period|
(period.from.date..period.to.date).map do |date|
break unless date.year == year

date
end
end.flatten
end
end
end
Loading