opening_hours_converter 1.8.1 → 1.9.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/lib/opening_hours_converter.rb +6 -0
- data/lib/opening_hours_converter/iterator.rb +3 -14
- data/lib/opening_hours_converter/opening_hours_builder.rb +82 -21
- data/lib/opening_hours_converter/opening_hours_date.rb +1 -1
- data/lib/opening_hours_converter/opening_hours_parser.rb +185 -30
- data/lib/opening_hours_converter/opening_hours_rule.rb +67 -38
- data/lib/opening_hours_converter/wide_interval.rb +158 -9
- data/lib/opening_hours_converter/year.rb +53 -1
- metadata +3 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 0421f6038fb3bcaae15b1e29d5a4bb90b08d829e4bd68d2d4c3501307fa8b8c7
|
4
|
+
data.tar.gz: '059ed79dab312bfa859028e9ec420ff99ae0e718a8723b98e61622fea8f85ae6'
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 9319c1fc314fe58bbad62abf9e59c3525069f7324189dda6f938dad328869cd6a5b63ba65ab6965b3e3286e8bce782777d4be88bbac541a87daba0568071e0cb
|
7
|
+
data.tar.gz: 26304defc99f58cceab36cf8bf0ae773651c2ab641b490601d1ff8b60446441af3c52234016e2a19ea73e1648ae05f014087eef9a8dcf5ce8ab1b16dcb5eea22
|
@@ -1,6 +1,11 @@
|
|
1
1
|
module OpeningHoursConverter
|
2
2
|
require 'date'
|
3
|
+
require 'pry'
|
4
|
+
require_relative './opening_hours_converter/utils'
|
3
5
|
require_relative './opening_hours_converter/date_range'
|
6
|
+
require_relative './opening_hours_converter/token'
|
7
|
+
require_relative './opening_hours_converter/tokenizer'
|
8
|
+
require_relative './opening_hours_converter/tokens_handler'
|
4
9
|
require_relative './opening_hours_converter/day'
|
5
10
|
require_relative './opening_hours_converter/week'
|
6
11
|
require_relative './opening_hours_converter/year'
|
@@ -13,4 +18,5 @@ module OpeningHoursConverter
|
|
13
18
|
require_relative './opening_hours_converter/opening_hours_rule'
|
14
19
|
require_relative './opening_hours_converter/opening_hours_time'
|
15
20
|
require_relative './opening_hours_converter/wide_interval'
|
21
|
+
require_relative './opening_hours_converter/week_index'
|
16
22
|
end
|
@@ -3,6 +3,7 @@ require 'opening_hours_converter/constants'
|
|
3
3
|
module OpeningHoursConverter
|
4
4
|
class Iterator
|
5
5
|
include Constants
|
6
|
+
include Utils
|
6
7
|
|
7
8
|
def get_iterator(date_ranges)
|
8
9
|
date_ranges_array = []
|
@@ -78,7 +79,7 @@ module OpeningHoursConverter
|
|
78
79
|
end
|
79
80
|
date_ranges[index].typical.intervals.each do |i|
|
80
81
|
next unless !i.nil? && !i.is_off
|
81
|
-
next unless (i.day_start..i.day_end).cover?(
|
82
|
+
next unless (i.day_start..i.day_end).cover?(reindex_sunday_week_to_monday_week(day.wday)) || (is_ph && year_ph.include?(Time.new(day.year, day.month, day.day)))
|
82
83
|
itr = { start: Time.new(day.year, day.month, day.day, i.start / 60, i.start % 60),
|
83
84
|
end: Time.new(day.year, day.month, day.day, i.end / 60, i.end % 60) }
|
84
85
|
datetime_result << itr unless datetime_result.include?(itr)
|
@@ -98,7 +99,7 @@ module OpeningHoursConverter
|
|
98
99
|
result.each do |interval|
|
99
100
|
(interval[:start]..interval[:end]).each do |day|
|
100
101
|
date_ranges[index].typical.intervals.each do |i|
|
101
|
-
if (i.day_start..i.day_end).cover?(
|
102
|
+
if (i.day_start..i.day_end).cover?(reindex_sunday_week_to_monday_week(day.wday))
|
102
103
|
datetime_result << { start: DateTime.new(day.year, day.month, day.day, i.start / 60, i.start % 60),
|
103
104
|
end: DateTime.new(day.year, day.month, day.day, i.end / 60, i.end % 60) }
|
104
105
|
end
|
@@ -110,10 +111,6 @@ module OpeningHoursConverter
|
|
110
111
|
datetime_result.sort_by { |a| a[:start] }
|
111
112
|
end
|
112
113
|
|
113
|
-
def fix_datetime_wday(d)
|
114
|
-
d == 0 ? 6 : d - 1
|
115
|
-
end
|
116
|
-
|
117
114
|
# A partir d'une string OH et d'une DateTime (= now par défaut), renvoyer le current state (début / fin / commentaire)
|
118
115
|
def state(opening_hours_string, time = Time.now)
|
119
116
|
date_ranges = OpeningHoursConverter::OpeningHoursParser.new.parse(opening_hours_string)
|
@@ -154,13 +151,5 @@ module OpeningHoursConverter
|
|
154
151
|
end
|
155
152
|
false
|
156
153
|
end
|
157
|
-
|
158
|
-
def datetime_to_time(datetime)
|
159
|
-
Time.new(datetime.year, datetime.month, datetime.day, datetime.hour, datetime.min, datetime.sec, datetime.zone)
|
160
|
-
end
|
161
|
-
|
162
|
-
def time_to_datetime(time)
|
163
|
-
DateTime.new(time.year, time.month, time.day, time.hour, time.min, time.sec, Rational(time.gmt_offset / 3600, 24))
|
164
|
-
end
|
165
154
|
end
|
166
155
|
end
|
@@ -10,21 +10,25 @@ module OpeningHoursConverter
|
|
10
10
|
oh_rule_added = nil
|
11
11
|
range_general = nil
|
12
12
|
range_general_for = nil
|
13
|
-
day_ph = false
|
14
|
-
off_day_ph = false
|
15
13
|
|
16
14
|
date_ranges.each_with_index do |date_range, date_range_index|
|
17
15
|
next unless !date_range.nil?
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
16
|
+
|
17
|
+
day_ph = false
|
18
|
+
off_day_ph = false
|
19
|
+
phs = []
|
20
|
+
|
21
|
+
date_range.typical.intervals.each_with_index do |interval, interval_id|
|
22
|
+
next unless interval&.day_start == -2 && interval&.day_start == interval&.day_end
|
23
|
+
|
24
|
+
if interval.is_off
|
25
|
+
off_day_ph = true
|
26
|
+
else
|
27
|
+
day_ph = true
|
27
28
|
end
|
29
|
+
|
30
|
+
phs << interval
|
31
|
+
date_range.typical.remove_interval(interval_id)
|
28
32
|
end
|
29
33
|
|
30
34
|
range_general = nil
|
@@ -44,9 +48,7 @@ module OpeningHoursConverter
|
|
44
48
|
end
|
45
49
|
|
46
50
|
next unless date_range_index == 0 || range_general.nil?
|
47
|
-
if date_range.
|
48
|
-
oh_rules = build_holiday(date_range)
|
49
|
-
elsif date_range.defines_typical_week?
|
51
|
+
if date_range.defines_typical_week?
|
50
52
|
oh_rules = if !range_general_for.nil?
|
51
53
|
build_week_diff(date_range, date_ranges[range_general_for])
|
52
54
|
else
|
@@ -72,7 +74,6 @@ module OpeningHoursConverter
|
|
72
74
|
end
|
73
75
|
oh_rule_added = true
|
74
76
|
rescue Exception => e
|
75
|
-
puts e
|
76
77
|
if oh_rule.date[0].wide_interval.type == 'holiday' && oh_rule.date[0].wide_interval.get_time_selector == 'PH'
|
77
78
|
rules[rule_index].add_ph_weekday
|
78
79
|
oh_rule_added = true
|
@@ -89,12 +90,38 @@ module OpeningHoursConverter
|
|
89
90
|
end
|
90
91
|
end
|
91
92
|
|
92
|
-
|
93
|
+
if off_day_ph || day_ph
|
94
|
+
if date_range.typical.intervals.uniq == [nil]
|
95
|
+
oh_rule.date.first.weekdays = [-2]
|
96
|
+
if off_day_ph
|
97
|
+
oh_rule.is_defined_off = off_day_ph
|
98
|
+
phs = []
|
99
|
+
else
|
100
|
+
phs.reverse.each do |interval|
|
101
|
+
oh_rule.add_time(OpeningHoursConverter::OpeningHoursTime.new(interval.start, interval.end))
|
102
|
+
end
|
103
|
+
end
|
104
|
+
else
|
105
|
+
if times_are_compatible?(oh_rule, phs)
|
106
|
+
holiday_intervals = get_compatible_intervals(oh_rule, phs)
|
107
|
+
oh_rule.add_ph_weekday if holiday_intervals[:compatible].length > 0
|
108
|
+
rules << oh_rule if !oh_rule_added
|
109
|
+
oh_rule_added = true
|
110
|
+
holiday_intervals[:incompatible].each do |interval|
|
111
|
+
rules += build_off_holiday(date_range) if off_day_ph
|
112
|
+
rules += build_holiday(date_range) if day_ph
|
113
|
+
end
|
114
|
+
else
|
115
|
+
rules << oh_rule if !oh_rule_added
|
116
|
+
oh_rule_added = true
|
117
|
+
rules += build_off_holiday(date_range) if off_day_ph
|
118
|
+
rules += build_holiday(date_range) if day_ph
|
119
|
+
end
|
120
|
+
end
|
121
|
+
end
|
93
122
|
|
94
123
|
rules << oh_rule if !oh_rule_added
|
95
124
|
|
96
|
-
rules += build_off_holiday(date_range) if off_day_ph
|
97
|
-
|
98
125
|
next unless oh_rule == oh_rules.last && oh_rule.has_overwritten_weekday?
|
99
126
|
oh_rule_over = OpeningHoursConverter::OpeningHoursRule.new
|
100
127
|
|
@@ -118,6 +145,34 @@ module OpeningHoursConverter
|
|
118
145
|
result.strip
|
119
146
|
end
|
120
147
|
|
148
|
+
def times_are_compatible?(oh_rule, phs)
|
149
|
+
if oh_rule.is_defined_off
|
150
|
+
phs.any?(&:is_off)
|
151
|
+
else
|
152
|
+
phs.any? do |ph_interval|
|
153
|
+
oh_rule.time.any? do |rule_time|
|
154
|
+
rule_time.start == ph_interval.start && rule_time.end == ph_interval.end
|
155
|
+
end
|
156
|
+
end
|
157
|
+
end
|
158
|
+
end
|
159
|
+
|
160
|
+
def get_compatible_intervals(oh_rule, phs)
|
161
|
+
compatibility = {
|
162
|
+
compatible: [],
|
163
|
+
incompatible: []
|
164
|
+
}
|
165
|
+
|
166
|
+
compatibility[:compatible] = phs.select do |ph_interval|
|
167
|
+
return false if ph_interval.is_off != oh_rule.is_defined_off
|
168
|
+
|
169
|
+
oh_rule.time.any? { |rule_time| rule_time.start == ph_interval.start && rule_time.end == ph_interval.end }
|
170
|
+
end
|
171
|
+
compatibility[:incompatible] = phs - compatibility[:compatible]
|
172
|
+
|
173
|
+
compatibility
|
174
|
+
end
|
175
|
+
|
121
176
|
def build_off_holiday(date_range)
|
122
177
|
start_year = date_range.wide_interval.start&.key?(:year) ? date_range.wide_interval.start[:year] : date_range.wide_interval.start
|
123
178
|
end_year = date_range.wide_interval.end&.key?(:year) ? date_range.wide_interval.end[:year] : date_range.wide_interval.end
|
@@ -135,9 +190,15 @@ module OpeningHoursConverter
|
|
135
190
|
def build_holiday(date_range)
|
136
191
|
start_year = date_range.wide_interval.start&.key?(:year) ? date_range.wide_interval.start[:year] : date_range.wide_interval.start
|
137
192
|
end_year = date_range.wide_interval.end&.key?(:year) ? date_range.wide_interval.end[:year] : date_range.wide_interval.end
|
138
|
-
|
139
193
|
intervals = date_range.typical.get_intervals(true)
|
140
|
-
|
194
|
+
|
195
|
+
if date_range.wide_interval.type == 'week'
|
196
|
+
intervals.each do |interval|
|
197
|
+
date_range.typical.add_interval(OpeningHoursConverter::Interval.new(-2, interval.start, -2, interval.end, interval.is_off))
|
198
|
+
end
|
199
|
+
else
|
200
|
+
date_range = OpeningHoursConverter::DateRange.new(OpeningHoursConverter::WideInterval.new.holiday('PH', start_year, end_year))
|
201
|
+
end
|
141
202
|
|
142
203
|
for i in 0..6
|
143
204
|
intervals.each do |interval|
|
@@ -156,7 +217,6 @@ module OpeningHoursConverter
|
|
156
217
|
rule.is_defined_off = rule.is_defined_off || interval.is_off
|
157
218
|
end
|
158
219
|
end
|
159
|
-
|
160
220
|
[rule]
|
161
221
|
end
|
162
222
|
|
@@ -327,6 +387,7 @@ module OpeningHoursConverter
|
|
327
387
|
|
328
388
|
def create_time_intervals(wide_interval, intervals)
|
329
389
|
days = []
|
390
|
+
|
330
391
|
for i in 0...7
|
331
392
|
days << OpeningHoursConverter::OpeningHoursRule.new
|
332
393
|
days[i].add_date(OpeningHoursConverter::OpeningHoursDate.new(wide_interval, [i]))
|
@@ -109,7 +109,7 @@ module OpeningHoursConverter
|
|
109
109
|
end
|
110
110
|
|
111
111
|
def add_overwritten_weekday(weekday)
|
112
|
-
return if @weekdays_over.include?(weekday)
|
112
|
+
return if @weekdays_over.include?(weekday)
|
113
113
|
|
114
114
|
@weekdays_over << weekday
|
115
115
|
@weekdays_over.sort!
|
@@ -1,23 +1,31 @@
|
|
1
1
|
require 'opening_hours_converter/constants'
|
2
|
+
require 'opening_hours_converter/utils'
|
2
3
|
require 'json'
|
3
4
|
|
4
5
|
module OpeningHoursConverter
|
5
6
|
class OpeningHoursParser
|
6
7
|
include Constants
|
8
|
+
include Utils
|
7
9
|
|
8
10
|
def initialize
|
9
11
|
@RGX_RULE_MODIFIER = /^(open|closed|off)$/i
|
10
12
|
@RGX_WEEK_KEY = /^week$/
|
11
|
-
@
|
13
|
+
@RGX_WEEK = /^week ([01234]?[0-9]|5[0123])(\-([01234]?[0-9]|5[0123]))?(, ?([01234]?[0-9]|5[0123])(\-([01234]?[0-9]|5[0123]))?)*$/
|
14
|
+
@RGX_WEEK_VAL = /^([01234]?[0-9]|5[0123])(\-([01234]?[0-9]|5[0123]))?(, ?([01234]?[0-9]|5[0123])(\-([01234]?[0-9]|5[0123]))?)*$/
|
15
|
+
@RGX_WEEK_WITH_MODIFIER = /^week ([01234]?[0-9]|5[0123])(\-([01234]?[0-9]|5[0123])(\/[1-9])?)?(, ?([01234]?[0-9]|5[0123])(\-([01234]?[0-9]|5[0123])(\/[1-9])?)?)*$/
|
16
|
+
@RGX_WEEK_VAL_WITH_MODIFIER = /^([01234]?[0-9]|5[0123])(\-([01234]?[0-9]|5[0123])(\/[1-9])?)?(, ?([01234]?[0-9]|5[0123])(\-([01234]?[0-9]|5[0123])(\/[1-9])?)?)*$/
|
12
17
|
@RGX_MONTH = /^(Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec)(\-(Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec))?\:?$/
|
13
18
|
@RGX_MONTHDAY = /^(Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec) ([012]?[0-9]|3[01])(\-((Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec) )?([012]?[0-9]|3[01]))?\:?$/
|
14
19
|
@RGX_TIME = /^((([01]?[0-9]|2[01234])\:[012345][0-9](\-([01]?[0-9]|2[01234])\:[012345][0-9])?(,([01]?[0-9]|2[01234])\:[012345][0-9](\-([01]?[0-9]|2[01234])\:[012345][0-9])?)*)|(24\/7))$/
|
15
20
|
@RGX_WEEKDAY = /^(((Mo|Tu|We|Th|Fr|Sa|Su)(\-(Mo|Tu|We|Th|Fr|Sa|Su))?)|(PH))(,(((Mo|Tu|We|Th|Fr|Sa|Su)(\-(Mo|Tu|We|Th|Fr|Sa|Su))?)|(PH)))*$/
|
16
21
|
@RGX_HOLIDAY = /^(PH|SH|easter)$/
|
17
22
|
@RGX_WD = /^(Mo|Tu|We|Th|Fr|Sa|Su)(\-(Mo|Tu|We|Th|Fr|Sa|Su))?$/
|
23
|
+
@RGX_WD_WITH_MODIFIER = /^(Mo|Tu|We|Th|Fr|Sa|Su)\[([1-5]|\-1)\]$/
|
18
24
|
@RGX_DAY = /^([012]?[0-9]|3[01])(\-[012]?[0-9]|3[01])?$/
|
19
25
|
@RGX_YEAR = /^(\d{4})(\-(\d{4}))?$/
|
20
26
|
@RGX_YEAR_PH = /^(\d{4})( PH|(\-(\d{4}) PH))\:?$/
|
27
|
+
@RGX_YEAR_WEEK = /^(\d{4})(\-(\d{4}))? week ([01234]?[0-9]|5[0123])(\-([01234]?[0-9]|5[0123]))?(, ?([01234]?[0-9]|5[0123])(\-([01234]?[0-9]|5[0123]))?)*\:?$/
|
28
|
+
@RGX_YEAR_WEEK_WITH_MODIFIER = /^(\d{4})(\-(\d{4}))? week ([01234]?[0-9]|5[0123])(\-([01234]?[0-9]|5[0123])(\/[1-9])?)?(, ?([01234]?[0-9]|5[0123])(\-([01234]?[0-9]|5[0123])(\/[1-9])?)?)*$/
|
21
29
|
@RGX_YEAR_MONTH_DAY = /^(\d{4}) (Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec) ([012]?[0-9]|3[01])(\-((\d{4}) )?((Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec) )?([012]?[0-9]|3[01]))?\:?$/
|
22
30
|
@RGX_YEAR_MONTH = /^(\d{4}) (Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec)(\-((\d{4}) )?((Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec)))?\:?$/
|
23
31
|
@RGX_COMMENT = /^\"[^\"]*\"$/
|
@@ -45,7 +53,9 @@ module OpeningHoursConverter
|
|
45
53
|
block.strip!
|
46
54
|
next if block.empty?
|
47
55
|
|
48
|
-
|
56
|
+
tokenizer = OpeningHoursConverter::Tokenizer.new(block)
|
57
|
+
tokens = tokenizer.tokens
|
58
|
+
# tokens = tokenize(block)
|
49
59
|
@current_token = tokens.length - 1
|
50
60
|
|
51
61
|
weekdays = {}
|
@@ -66,9 +76,9 @@ module OpeningHoursConverter
|
|
66
76
|
weekday_selector = tokens[@current_token]
|
67
77
|
weekdays_and_holidays = get_weekdays(weekday_selector)
|
68
78
|
rescue StandardError
|
69
|
-
weekdays[[{ from: 0, to: 6 }]] ||= {}
|
70
|
-
weekdays[[{ from: 0, to: 6 }]][:modifiers] ||= []
|
71
|
-
weekdays[[{ from: 0, to: 6 }]][:modifiers] << local_modifier
|
79
|
+
weekdays[[{ from: 0, to: 6, index: nil }]] ||= {}
|
80
|
+
weekdays[[{ from: 0, to: 6, index: nil }]][:modifiers] ||= []
|
81
|
+
weekdays[[{ from: 0, to: 6, index: nil }]][:modifiers] << local_modifier
|
72
82
|
else
|
73
83
|
weekdays[weekdays_and_holidays] ||= {}
|
74
84
|
weekdays[weekdays_and_holidays][:modifiers] ||= []
|
@@ -86,9 +96,9 @@ module OpeningHoursConverter
|
|
86
96
|
weekday_selector = tokens[@current_token]
|
87
97
|
weekdays_and_holidays = get_weekdays(weekday_selector)
|
88
98
|
rescue StandardError
|
89
|
-
weekdays[[{ from: 0, to: 6 }]] ||= {}
|
90
|
-
weekdays[[{ from: 0, to: 6 }]][:times] ||= []
|
91
|
-
weekdays[[{ from: 0, to: 6 }]][:times].concat(local_times)
|
99
|
+
weekdays[[{ from: 0, to: 6, index: nil }]] ||= {}
|
100
|
+
weekdays[[{ from: 0, to: 6, index: nil }]][:times] ||= []
|
101
|
+
weekdays[[{ from: 0, to: 6, index: nil }]][:times].concat(local_times)
|
92
102
|
else
|
93
103
|
weekdays[weekdays_and_holidays] ||= {}
|
94
104
|
weekdays[weekdays_and_holidays][:times] ||= []
|
@@ -98,6 +108,7 @@ module OpeningHoursConverter
|
|
98
108
|
end
|
99
109
|
end
|
100
110
|
|
111
|
+
weeks = []
|
101
112
|
months = []
|
102
113
|
years = []
|
103
114
|
holidays = []
|
@@ -108,21 +119,27 @@ module OpeningHoursConverter
|
|
108
119
|
end
|
109
120
|
if !wide_range_selector.empty?
|
110
121
|
wide_range_selector = wide_range_selector.strip
|
111
|
-
wide_range_selector = wide_range_selector.split(',')
|
112
|
-
wide_range_selector.
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
122
|
+
# wide_range_selector = wide_range_selector.split(',')
|
123
|
+
if !(@RGX_YEAR_MONTH_DAY =~ wide_range_selector).nil?
|
124
|
+
years << get_year_month_day(wide_range_selector)
|
125
|
+
elsif !(@RGX_YEAR_MONTH =~ wide_range_selector).nil?
|
126
|
+
years << get_year_month(wide_range_selector)
|
127
|
+
elsif !(@RGX_MONTHDAY =~ wide_range_selector).nil?
|
128
|
+
months << get_month_day(wide_range_selector)
|
129
|
+
elsif !(@RGX_MONTH =~ wide_range_selector).nil?
|
130
|
+
months << get_month(wide_range_selector)
|
131
|
+
elsif !(@RGX_YEAR =~ wide_range_selector).nil?
|
132
|
+
years << get_year(wide_range_selector)
|
133
|
+
elsif !(@RGX_YEAR_WEEK_WITH_MODIFIER =~ wide_range_selector).nil?
|
134
|
+
weeks << get_year_week_with_modifier(wide_range_selector)
|
135
|
+
elsif !(@RGX_YEAR_WEEK =~ wide_range_selector).nil?
|
136
|
+
weeks << get_year_week(wide_range_selector)
|
137
|
+
elsif !(@RGX_WEEK_WITH_MODIFIER =~ wide_range_selector).nil?
|
138
|
+
weeks << get_week_with_modifier(wide_range_selector)
|
139
|
+
elsif !(@RGX_WEEK =~ wide_range_selector).nil?
|
140
|
+
weeks << get_week(wide_range_selector)
|
141
|
+
else
|
142
|
+
raise ArgumentError, "Unsupported selector #{wide_range_selector}"
|
126
143
|
end
|
127
144
|
end
|
128
145
|
end
|
@@ -130,6 +147,7 @@ module OpeningHoursConverter
|
|
130
147
|
raise ArgumentError, 'Unreadable string' if @current_token == tokens.length - 1
|
131
148
|
|
132
149
|
# puts "weekdays : #{weekdays}"
|
150
|
+
# puts "weeks : #{weeks}"
|
133
151
|
# puts "months : #{months}"
|
134
152
|
# puts "years : #{years}"
|
135
153
|
|
@@ -152,6 +170,12 @@ module OpeningHoursConverter
|
|
152
170
|
end
|
153
171
|
date_ranges << date_range
|
154
172
|
end
|
173
|
+
elsif !weeks.empty?
|
174
|
+
|
175
|
+
weeks.each do |week|
|
176
|
+
date_ranges << OpeningHoursConverter::WideInterval.new.week(week[:week_indexes], week[:year_from], week[:year_to])
|
177
|
+
end
|
178
|
+
|
155
179
|
elsif !years.empty?
|
156
180
|
years.each do |year|
|
157
181
|
if !year[:from_day].nil?
|
@@ -182,8 +206,8 @@ module OpeningHoursConverter
|
|
182
206
|
end
|
183
207
|
|
184
208
|
if weekdays.empty?
|
185
|
-
weekdays[[{ from: 0, to: 6 }]] = {}
|
186
|
-
weekdays[[{ from: 0, to: 6 }]][:times] = [{ from: 0, to: 24 * 60 }]
|
209
|
+
weekdays[[{ from: 0, to: 6, index: nil }]] = {}
|
210
|
+
weekdays[[{ from: 0, to: 6, index: nil }]][:times] = [{ from: 0, to: 24 * 60 }]
|
187
211
|
end
|
188
212
|
|
189
213
|
date_ranges.each do |dr|
|
@@ -280,7 +304,14 @@ module OpeningHoursConverter
|
|
280
304
|
if end_interval.day == start_interval.day + 1 && end_interval.hour == 0 && end_interval.min == 0
|
281
305
|
end_interval -= (1 / 1440.0)
|
282
306
|
end
|
283
|
-
date_range.last.typical.add_interval(
|
307
|
+
date_range.last.typical.add_interval(
|
308
|
+
OpeningHoursConverter::Interval.new(
|
309
|
+
reindex_sunday_week_to_monday_week(start_interval.wday),
|
310
|
+
(start_interval.hour * 60 + start_interval.min),
|
311
|
+
reindex_sunday_week_to_monday_week(end_interval.wday),
|
312
|
+
(end_interval.hour * 60 + end_interval.min)
|
313
|
+
)
|
314
|
+
)
|
284
315
|
end
|
285
316
|
end
|
286
317
|
date_range
|
@@ -300,6 +331,86 @@ module OpeningHoursConverter
|
|
300
331
|
{ from: year_from, to: year_to }
|
301
332
|
end
|
302
333
|
|
334
|
+
def get_year_week_with_modifier(wrs)
|
335
|
+
year, weeks = wrs.split(' week ')
|
336
|
+
years = year.split('-')
|
337
|
+
|
338
|
+
indexes = weeks.split(',').map { |week_index|
|
339
|
+
if week_index.include?('-')
|
340
|
+
if week_index.include?('/')
|
341
|
+
from, to = week_index.split('-')
|
342
|
+
to, modifier = to.split('/')
|
343
|
+
{ from: from.to_i, to: to.to_i, modifier: modifier.to_i }
|
344
|
+
else
|
345
|
+
from, to = week_index.split('-').map(&:to_i)
|
346
|
+
{ from: from, to: to }
|
347
|
+
end
|
348
|
+
else
|
349
|
+
week_index.to_i
|
350
|
+
end
|
351
|
+
}
|
352
|
+
|
353
|
+
{ year_from: years[0].to_i, week_indexes: indexes }.tap do |hsh|
|
354
|
+
hsh[:year_to] = years.length > 1 ? years[1].to_i : nil
|
355
|
+
end
|
356
|
+
end
|
357
|
+
|
358
|
+
def get_year_week(wrs)
|
359
|
+
year, weeks = wrs.split(' week ')
|
360
|
+
# does not handle 2018,2019
|
361
|
+
years = year.split('-')
|
362
|
+
# does not handle week 1,2,3
|
363
|
+
indexes = weeks.split(',').map { |week_index|
|
364
|
+
if week_index.include?('-')
|
365
|
+
from, to = week_index.split('-').map(&:to_i)
|
366
|
+
{ from: from, to: to }
|
367
|
+
else
|
368
|
+
week_index.to_i
|
369
|
+
end
|
370
|
+
}
|
371
|
+
|
372
|
+
{ week_indexes: indexes, year_from: year[0].to_i }.tap do |hsh|
|
373
|
+
hsh[:year_to] = years.length > 1 ? year[1].to_i : nil
|
374
|
+
end
|
375
|
+
end
|
376
|
+
|
377
|
+
def get_week_with_modifier(wrs)
|
378
|
+
weeks = wrs.gsub('week ', '').split(',')
|
379
|
+
|
380
|
+
indexes = weeks.map { |week_index|
|
381
|
+
if week_index.include?('-')
|
382
|
+
if week_index.include?('/')
|
383
|
+
from, to = week_index.split('-')
|
384
|
+
to, modifier = to.split('/')
|
385
|
+
{ from: from.to_i, to: to.to_i, modifier: modifier.to_i }
|
386
|
+
else
|
387
|
+
from, to = week_index.split('-').map(&:to_i)
|
388
|
+
{ from: from, to: to }
|
389
|
+
end
|
390
|
+
else
|
391
|
+
week_index.to_i
|
392
|
+
end
|
393
|
+
}
|
394
|
+
|
395
|
+
{ week_indexes: indexes }
|
396
|
+
end
|
397
|
+
|
398
|
+
def get_week(wrs)
|
399
|
+
weeks = wrs.gsub('week ', '').split(',')
|
400
|
+
|
401
|
+
indexes = weeks.map { |week_index|
|
402
|
+
if week_index.include?('-')
|
403
|
+
from, to = week_index.split('-').map(&:to_i)
|
404
|
+
{ from: from, to: to }
|
405
|
+
else
|
406
|
+
week_index.to_i
|
407
|
+
end
|
408
|
+
}
|
409
|
+
|
410
|
+
{ week_indexes: indexes }
|
411
|
+
end
|
412
|
+
|
413
|
+
|
303
414
|
def get_month(wrs)
|
304
415
|
single_month = wrs.gsub(/\:$/, '').split('-')
|
305
416
|
month_from = OSM_MONTHS.find_index(single_month[0]) + 1
|
@@ -429,9 +540,10 @@ module OpeningHoursConverter
|
|
429
540
|
wd_to = nil
|
430
541
|
|
431
542
|
weekday_selector = weekday_selector.split(',')
|
543
|
+
|
432
544
|
weekday_selector.each do |wd|
|
433
545
|
if !(@RGX_HOLIDAY =~ wd).nil?
|
434
|
-
weekdays << { from: -2, to: -2 }
|
546
|
+
weekdays << { from: -2, to: -2, index: nil }
|
435
547
|
elsif !(@RGX_WD =~ wd).nil?
|
436
548
|
single_weekday = wd.split('-')
|
437
549
|
|
@@ -442,7 +554,16 @@ module OpeningHoursConverter
|
|
442
554
|
wd_from
|
443
555
|
end
|
444
556
|
|
445
|
-
weekdays << { from: wd_from, to: wd_to }
|
557
|
+
weekdays << { from: wd_from, to: wd_to, index: nil }
|
558
|
+
elsif !(@RGX_WD_WITH_MODIFIER =~ wd).nil?
|
559
|
+
|
560
|
+
from, to = wd[0...wd.index('[')].split('-')
|
561
|
+
index = wd[wd.index('[') + 1...wd.index(']')]
|
562
|
+
|
563
|
+
wd_from = OSM_DAYS.find_index(from)
|
564
|
+
wd_to = OSM_DAYS.find_index(to)
|
565
|
+
|
566
|
+
weekdays << { from: wd_from, to: wd_from, index: index.to_i }
|
446
567
|
else
|
447
568
|
raise ArgumentError, "Invalid weekday interval : #{wd}"
|
448
569
|
end
|
@@ -564,6 +685,7 @@ module OpeningHoursConverter
|
|
564
685
|
weekday_merge = []
|
565
686
|
wide_interval_merge = []
|
566
687
|
merged_wide_interval = []
|
688
|
+
|
567
689
|
groups.each_with_index do |group, group_index|
|
568
690
|
if !wide_interval_merge.empty?
|
569
691
|
merged_wide_interval += [wide_interval_merge.join(' ')]
|
@@ -575,7 +697,7 @@ module OpeningHoursConverter
|
|
575
697
|
wide_interval_merge = []
|
576
698
|
new_tokens << merged_wide_interval.join(',')
|
577
699
|
end
|
578
|
-
if is_weekday?(token)
|
700
|
+
if is_weekday?(token) || is_weekday_with_modifier?(token)
|
579
701
|
weekday_merge << token
|
580
702
|
if token_index == group.length - 1 && group_index == groups.length - 1
|
581
703
|
new_tokens << weekday_merge.join(',')
|
@@ -606,7 +728,10 @@ module OpeningHoursConverter
|
|
606
728
|
def is_part_of_wide_interval?(string)
|
607
729
|
is_wide_interval = false
|
608
730
|
string.split('-').each do |str|
|
609
|
-
if (!(@RGX_YEAR =~ str).nil? || !(@RGX_YEAR_MONTH =~ str).nil? || !(@RGX_YEAR_MONTH_DAY =~ str).nil? ||
|
731
|
+
if (!(@RGX_YEAR =~ str).nil? || !(@RGX_YEAR_MONTH =~ str).nil? || !(@RGX_YEAR_MONTH_DAY =~ str).nil? ||
|
732
|
+
!(@RGX_DAY =~ str).nil? || !(@RGX_MONTHDAY =~ str).nil? || !(@RGX_MONTH =~ str).nil? ||
|
733
|
+
!(@RGX_WEEK_KEY =~ str).nil? || !(@RGX_WEEK_VAL =~ str).nil? || !(@RGX_WEEK_VAL_WITH_MODIFIER =~ str).nil?) &&
|
734
|
+
((@RGX_TIME =~ str).nil? && (@RGX_WEEKDAY =~ str).nil?)
|
610
735
|
is_wide_interval = true
|
611
736
|
else
|
612
737
|
return false
|
@@ -635,8 +760,38 @@ module OpeningHoursConverter
|
|
635
760
|
!(@RGX_WEEKDAY =~ token).nil?
|
636
761
|
end
|
637
762
|
|
763
|
+
def is_weekday_with_modifier?(token)
|
764
|
+
!(@RGX_WD_WITH_MODIFIER =~ token).nil?
|
765
|
+
end
|
766
|
+
|
638
767
|
def is_year?(token)
|
639
768
|
!(@RGX_YEAR =~ token).nil?
|
640
769
|
end
|
770
|
+
|
771
|
+
def is_week_key?(token)
|
772
|
+
!(@RGX_WEEK_KEY =~ token).nil?
|
773
|
+
end
|
774
|
+
|
775
|
+
def is_week_val?(token)
|
776
|
+
!(@RGX_WEEK_VAL =~ token).nil?
|
777
|
+
end
|
778
|
+
|
779
|
+
def is_week_with_modifier?(token)
|
780
|
+
!(@RGX_WEEK_WITH_MODIFIER =~ token).nil?
|
781
|
+
end
|
782
|
+
|
783
|
+
def is_week_val_with_modifier?(token)
|
784
|
+
!(@RGX_WEEK_VAL_WITH_MODIFIER =~ token).nil?
|
785
|
+
end
|
786
|
+
|
787
|
+
def is_year_week?(token)
|
788
|
+
!(@RGX_YEAR_WEEK =~ token).nil?
|
789
|
+
end
|
790
|
+
|
791
|
+
def is_year_week_with_modifier?(token)
|
792
|
+
!(@RGX_YEAR_WEEK_WITH_MODIFIER =~ token).nil?
|
793
|
+
end
|
641
794
|
end
|
642
795
|
end
|
796
|
+
|
797
|
+
|
@@ -61,6 +61,8 @@ module OpeningHoursConverter
|
|
61
61
|
month_start = -1
|
62
62
|
day_start = -1
|
63
63
|
|
64
|
+
return result_to_string(years) if is_only_week_interval?(years)
|
65
|
+
|
64
66
|
result = {}
|
65
67
|
|
66
68
|
if !years['always'].nil?
|
@@ -120,7 +122,7 @@ module OpeningHoursConverter
|
|
120
122
|
{ day: 30, month: 11 }
|
121
123
|
else
|
122
124
|
{ day: MONTH_END_DAY[month - 1] - 1, month: month - 1 }
|
123
|
-
|
125
|
+
end
|
124
126
|
else
|
125
127
|
{ day: day - 1, month: month }
|
126
128
|
end
|
@@ -148,63 +150,90 @@ module OpeningHoursConverter
|
|
148
150
|
|
149
151
|
def result_to_string(result)
|
150
152
|
str_result = ''
|
151
|
-
result
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
|
159
|
-
|
160
|
-
|
161
|
-
if is_same_day?(interval)
|
162
|
-
str_result += "#{OSM_MONTHS[interval[:start][:month]]} #{interval[:start][:day] + 1 < 10 ? "0#{interval[:start][:day] + 1}" : interval[:start][:day] + 1}"
|
153
|
+
if is_only_week_interval?(result)
|
154
|
+
local_str = result.keys == ['always'] ? 'week ' : result.keys.length == 1 ? result.keys.first.to_s + ' week ' : result.keys.min.to_s + '-' + result.keys.max.to_s + ' week '
|
155
|
+
|
156
|
+
intervals = result[result.keys.first]
|
157
|
+
intervals.each do |interval|
|
158
|
+
local_str += "," if !(local_str[local_str.length - 1] =~ /^[0-9]$/).nil?
|
159
|
+
local_str +=
|
160
|
+
if interval[:modifier].nil?
|
161
|
+
if interval[:start][:week] == interval[:end][:week]
|
162
|
+
interval[:start][:week].to_s
|
163
163
|
else
|
164
|
-
|
164
|
+
"#{interval[:start][:week].to_s + '-' + interval[:end][:week].to_s}"
|
165
165
|
end
|
166
166
|
else
|
167
|
-
|
167
|
+
"#{interval[:start][:week].to_s + '-' + interval[:end][:week].to_s}/#{interval[:modifier].to_s}"
|
168
168
|
end
|
169
|
-
|
170
|
-
|
171
|
-
|
169
|
+
end
|
170
|
+
str_result += local_str
|
171
|
+
else
|
172
|
+
result.each do |selector, intervals|
|
173
|
+
if selector == 'always'
|
172
174
|
intervals.each do |interval|
|
173
175
|
str_result += ',' if !str_result.empty?
|
174
|
-
if
|
176
|
+
if is_full_year?(interval)
|
177
|
+
elsif starts_year?(interval) && ends_year?(interval)
|
175
178
|
str_result += "#{interval[:start][:year]}-#{interval[:end][:year]}"
|
176
|
-
|
177
|
-
|
179
|
+
elsif is_full_month?(interval)
|
180
|
+
str_result += (OSM_MONTHS[interval[:start][:month]]).to_s
|
181
|
+
elsif is_same_month?(interval)
|
182
|
+
if is_same_day?(interval)
|
183
|
+
str_result += "#{OSM_MONTHS[interval[:start][:month]]} #{interval[:start][:day] + 1 < 10 ? "0#{interval[:start][:day] + 1}" : interval[:start][:day] + 1}"
|
184
|
+
else
|
185
|
+
str_result += "#{OSM_MONTHS[interval[:start][:month]]} #{interval[:start][:day] + 1 < 10 ? "0#{interval[:start][:day] + 1}" : interval[:start][:day] + 1}-#{interval[:end][:day] + 1 < 10 ? "0#{interval[:end][:day] + 1}" : interval[:end][:day] + 1}"
|
186
|
+
end
|
187
|
+
elsif starts_month?(interval) && ends_month?(interval)
|
188
|
+
str_result += "#{OSM_MONTHS[interval[:start][:month]]}-#{OSM_MONTHS[interval[:end][:month]]}"
|
178
189
|
else
|
179
|
-
str_result += "#{
|
190
|
+
str_result += "#{OSM_MONTHS[interval[:start][:month]]} #{interval[:start][:day] + 1 < 10 ? "0#{interval[:start][:day] + 1}" : interval[:start][:day] + 1}-#{OSM_MONTHS[interval[:end][:month]]} #{interval[:end][:day] + 1 < 10 ? "0#{interval[:end][:day] + 1}" : interval[:end][:day] + 1}"
|
180
191
|
end
|
181
192
|
end
|
182
|
-
|
183
|
-
|
184
|
-
|
185
|
-
|
186
|
-
|
187
|
-
|
188
|
-
|
189
|
-
|
190
|
-
|
191
|
-
|
192
|
-
|
193
|
-
|
193
|
+
elsif selector == 'multi_year'
|
194
|
+
intervals.each do |_years, intervals|
|
195
|
+
intervals.each do |interval|
|
196
|
+
str_result += ',' if !str_result.empty?
|
197
|
+
if starts_year?(interval) && ends_year?(interval)
|
198
|
+
str_result += "#{interval[:start][:year]}-#{interval[:end][:year]}"
|
199
|
+
else
|
200
|
+
str_result += "#{interval[:start][:year]} #{OSM_MONTHS[interval[:start][:month]]} #{interval[:start][:day] + 1 < 10 ? "0#{interval[:start][:day] + 1}" : interval[:start][:day] + 1}-#{interval[:end][:year]} #{OSM_MONTHS[interval[:end][:month]]} #{interval[:end][:day] + 1 < 10 ? "0#{interval[:end][:day] + 1}" : interval[:end][:day] + 1}"
|
201
|
+
end
|
202
|
+
end
|
203
|
+
end
|
204
|
+
else
|
205
|
+
local_str = "#{selector} "
|
206
|
+
intervals.each do |interval|
|
207
|
+
if is_full_year?(interval)
|
208
|
+
elsif is_same_month?(interval)
|
209
|
+
if is_same_day?(interval)
|
210
|
+
local_str += "#{local_str.length > 5 ? ',' : ''}#{OSM_MONTHS[interval[:start][:month]]} #{interval[:start][:day] + 1 < 10 ? "0#{interval[:start][:day] + 1}" : interval[:start][:day] + 1}"
|
211
|
+
else
|
212
|
+
local_str += "#{local_str.length > 5 ? ',' : ''}#{OSM_MONTHS[interval[:start][:month]]} #{interval[:start][:day] + 1 < 10 ? "0#{interval[:start][:day] + 1}" : interval[:start][:day] + 1}-#{interval[:end][:day] + 1 < 10 ? "0#{interval[:end][:day] + 1}" : interval[:end][:day] + 1}"
|
213
|
+
end
|
194
214
|
else
|
195
|
-
local_str += "#{local_str.length > 5 ? ',' : ''}#{OSM_MONTHS[interval[:start][:month]]} #{interval[:start][:day] + 1 < 10 ? "0#{interval[:start][:day] + 1}" : interval[:start][:day] + 1}-#{interval[:end][:day] + 1 < 10 ? "0#{interval[:end][:day] + 1}" : interval[:end][:day] + 1}"
|
215
|
+
local_str += "#{local_str.length > 5 ? ',' : ''}#{OSM_MONTHS[interval[:start][:month]]} #{interval[:start][:day] + 1 < 10 ? "0#{interval[:start][:day] + 1}" : interval[:start][:day] + 1}-#{selector} #{OSM_MONTHS[interval[:end][:month]]} #{interval[:end][:day] + 1 < 10 ? "0#{interval[:end][:day] + 1}" : interval[:end][:day] + 1}"
|
196
216
|
end
|
197
|
-
|
198
|
-
local_str += "#{local_str.length > 5 ? ',' : ''}#{OSM_MONTHS[interval[:start][:month]]} #{interval[:start][:day] + 1 < 10 ? "0#{interval[:start][:day] + 1}" : interval[:start][:day] + 1}-#{selector} #{OSM_MONTHS[interval[:end][:month]]} #{interval[:end][:day] + 1 < 10 ? "0#{interval[:end][:day] + 1}" : interval[:end][:day] + 1}"
|
217
|
+
str_result += "#{!str_result.empty? ? ',' : ''}#{local_str}"
|
199
218
|
end
|
200
219
|
end
|
201
|
-
str_result += "#{!str_result.empty? ? ',' : ''}#{local_str}"
|
202
220
|
end
|
203
221
|
end
|
204
222
|
|
205
223
|
str_result.strip
|
206
224
|
end
|
207
225
|
|
226
|
+
def is_only_week_interval?(r)
|
227
|
+
r.all? do |year, intervals|
|
228
|
+
intervals.all? do |interval|
|
229
|
+
is_week_interval?(interval)
|
230
|
+
end
|
231
|
+
end
|
232
|
+
end
|
233
|
+
def is_week_interval?(interval)
|
234
|
+
!interval.is_a?(Array) && interval.key?(:start) && interval[:start].key?(:week)
|
235
|
+
end
|
236
|
+
|
208
237
|
def is_full_year?(r)
|
209
238
|
starts_year?(r) && ends_year?(r)
|
210
239
|
end
|
@@ -3,11 +3,12 @@ require 'opening_hours_converter/constants'
|
|
3
3
|
module OpeningHoursConverter
|
4
4
|
class WideInterval
|
5
5
|
include Constants
|
6
|
-
attr_accessor :start, :end, :type
|
6
|
+
attr_accessor :start, :end, :type, :indexes
|
7
7
|
|
8
8
|
def initialize
|
9
9
|
@start = nil
|
10
10
|
@end = nil
|
11
|
+
@indexes = nil
|
11
12
|
@type = nil
|
12
13
|
end
|
13
14
|
|
@@ -87,13 +88,11 @@ module OpeningHoursConverter
|
|
87
88
|
'jours fériés'
|
88
89
|
else
|
89
90
|
"les jours fériés de #{@start[:year]} à #{@end[:year]}"
|
90
|
-
|
91
|
+
end
|
92
|
+
elsif !@start[:year]
|
93
|
+
'jours fériés'
|
91
94
|
else
|
92
|
-
|
93
|
-
'jours fériés'
|
94
|
-
else
|
95
|
-
"les jours fériés de #{@start[:year]}"
|
96
|
-
end
|
95
|
+
"les jours fériés de #{@start[:year]}"
|
97
96
|
end
|
98
97
|
when 'always'
|
99
98
|
result = 'tout le temps'
|
@@ -135,6 +134,17 @@ module OpeningHoursConverter
|
|
135
134
|
self
|
136
135
|
end
|
137
136
|
|
137
|
+
def week(week_indexes, start_year = nil, end_year = nil)
|
138
|
+
raise(ArgumentError, 'weeks are required (array of ints)') if week_indexes.nil? || !week_indexes.is_a?(Array)
|
139
|
+
@start = { year: start_year }
|
140
|
+
@indexes = week_indexes
|
141
|
+
if !start_year.nil? && !end_year.nil? && end_year != start_year
|
142
|
+
@end = { year: end_year }
|
143
|
+
end
|
144
|
+
@type = 'week'
|
145
|
+
self
|
146
|
+
end
|
147
|
+
|
138
148
|
def year(start_year, end_year = nil)
|
139
149
|
raise(ArgumentError, 'start_year is required') if start_year.nil?
|
140
150
|
@start = { year: start_year }
|
@@ -212,6 +222,17 @@ module OpeningHoursConverter
|
|
212
222
|
else
|
213
223
|
my = to_day
|
214
224
|
o = o.to_day
|
225
|
+
|
226
|
+
if my.is_a?(Array)
|
227
|
+
if o.is_a?(Array)
|
228
|
+
return false
|
229
|
+
else
|
230
|
+
return my.all? { |day| day.contains?(o) }
|
231
|
+
end
|
232
|
+
elsif o.is_a?(Array)
|
233
|
+
return o.all? { |day| contains?(day) }
|
234
|
+
end
|
235
|
+
|
215
236
|
result = has_superior_or_equal_start_day?(my, o) && has_inferior_or_equal_end_day?(my, o)
|
216
237
|
end
|
217
238
|
result
|
@@ -227,6 +248,22 @@ module OpeningHoursConverter
|
|
227
248
|
my = to_day
|
228
249
|
o = o.to_day
|
229
250
|
|
251
|
+
if my.is_a?(Array)
|
252
|
+
if o.is_a?(Array)
|
253
|
+
return my.any? do |day|
|
254
|
+
o.any? do |o_day|
|
255
|
+
day.touch?(o_day)
|
256
|
+
end
|
257
|
+
end
|
258
|
+
else
|
259
|
+
return my.any? { |day| day.touch?(o) }
|
260
|
+
end
|
261
|
+
elsif o.is_a?(Array)
|
262
|
+
return o.any? { |day| day.touch?(my) }
|
263
|
+
end
|
264
|
+
# solution poour les weeks, on peut convertir un wide interval week en array de wide interval days et comparer les wide interval week
|
265
|
+
# un par un (long si deux wide interval multiweek)
|
266
|
+
# problem : comment calculer les weeks always ? comparer sur l'année en cours si o est always, les années de o sinon
|
230
267
|
result = ((my_start_is_before_o_end?(my, o) && my_start_is_after_o_start?(my, o)) ||
|
231
268
|
(my_end_is_before_o_end?(my, o) && my_end_is_after_o_start?(my, o))) ||
|
232
269
|
((my_start_is_before_o_end?(o, my) && my_start_is_after_o_start?(o, my)) ||
|
@@ -390,10 +427,33 @@ module OpeningHoursConverter
|
|
390
427
|
o.start[:day] >= my.start[:day]))
|
391
428
|
end
|
392
429
|
|
430
|
+
def sort_days_array(days_array, by = :start)
|
431
|
+
if days_array.all? { |day| day.start && !day.start[:year].nil? }
|
432
|
+
days_array.sort_by { |day| [day.send(by)[:year], day.send(by)[:month], day.send(by)[:day]] }
|
433
|
+
else
|
434
|
+
days_array.sort_by { |day| [day.send(by)[:month], day.send(by)[:day]] }
|
435
|
+
end
|
436
|
+
|
437
|
+
end
|
438
|
+
|
393
439
|
def has_superior_or_equal_start_day?(my, o)
|
394
440
|
result = false
|
395
441
|
if has_start_year?(o) && has_start_year?(my)
|
396
|
-
|
442
|
+
if o.is_a?(Array)
|
443
|
+
if my.is_a?(Array)
|
444
|
+
o = sort_days_array o
|
445
|
+
my = sort_days_array my
|
446
|
+
has_superior_or_equal_start_day?(my.first, o.first)
|
447
|
+
else
|
448
|
+
o = sort_days_array o
|
449
|
+
has_superior_or_equal_start_day?(my, o.first)
|
450
|
+
end
|
451
|
+
elsif my.is_a?(Array)
|
452
|
+
my = sort_days_array my
|
453
|
+
has_superior_or_equal_start_day?(my.first, o)
|
454
|
+
else
|
455
|
+
result = o.start[:year] > my.start[:year] || (o.start[:year] == my.start[:year] && has_superior_start_month?(my, o))
|
456
|
+
end
|
397
457
|
elsif !has_start_year?(my)
|
398
458
|
result = has_superior_start_month?(my, o)
|
399
459
|
end
|
@@ -433,7 +493,11 @@ module OpeningHoursConverter
|
|
433
493
|
end
|
434
494
|
|
435
495
|
def has_start_year?(date)
|
436
|
-
|
496
|
+
if date.is_a?(Array)
|
497
|
+
date.all? { |d| !d.start[:year].nil? }
|
498
|
+
else
|
499
|
+
!date.start[:year].nil?
|
500
|
+
end
|
437
501
|
end
|
438
502
|
|
439
503
|
def has_end_year?(date)
|
@@ -450,6 +514,23 @@ module OpeningHoursConverter
|
|
450
514
|
return false if @type == 'always'
|
451
515
|
self_to_day = to_day
|
452
516
|
o_to_day = o.to_day
|
517
|
+
return false if self_to_day.is_a?(Array) != o_to_day.is_a?(Array)
|
518
|
+
|
519
|
+
if self_to_day.is_a?(Array)
|
520
|
+
if o_to_day.is_a?(Array)
|
521
|
+
return false unless o_to_day.length == self_to_day.length
|
522
|
+
return self_to_day.all? do |self_day|
|
523
|
+
o_to_day.any? do |o_day|
|
524
|
+
self_day.equals(o_day)
|
525
|
+
end
|
526
|
+
end
|
527
|
+
else
|
528
|
+
return self_to_day.all? { |day| self_to_day.equals(o_to_day) }
|
529
|
+
end
|
530
|
+
elsif o_to_day.is_a?(Array)
|
531
|
+
return o_to_day.all? { |day| equals(day) }
|
532
|
+
end
|
533
|
+
|
453
534
|
(self_to_day.start[:year] == o_to_day.start[:year] &&
|
454
535
|
self_to_day.start[:month] == o_to_day.start[:month] &&
|
455
536
|
self_to_day.start[:day] == o_to_day.start[:day]) &&
|
@@ -461,8 +542,11 @@ module OpeningHoursConverter
|
|
461
542
|
|
462
543
|
def width
|
463
544
|
return Float::INFINITY if @type == 'always'
|
545
|
+
|
464
546
|
in_day = to_day
|
465
547
|
days_count = 0
|
548
|
+
return in_day.map(&:width).sum if in_day.is_a?(Array)
|
549
|
+
|
466
550
|
if in_day.end
|
467
551
|
if in_day.start[:year] && in_day.end[:year]
|
468
552
|
if in_day.start[:year] != in_day.end[:year]
|
@@ -541,6 +625,7 @@ module OpeningHoursConverter
|
|
541
625
|
end
|
542
626
|
|
543
627
|
def to_day
|
628
|
+
# les semaines rentrent en opposition avec cette maniere de faire : il n'y a pas un debut et une fin il y en a plusieurs (1-53/2)
|
544
629
|
case @type
|
545
630
|
when 'day'
|
546
631
|
if @end.nil?
|
@@ -560,6 +645,70 @@ module OpeningHoursConverter
|
|
560
645
|
else
|
561
646
|
OpeningHoursConverter::WideInterval.new.day(1, 1, @start[:year], 31, 12, @end[:year])
|
562
647
|
end
|
648
|
+
when 'holiday'
|
649
|
+
if @start && @start[:year]
|
650
|
+
if @end && @end[:year]
|
651
|
+
weeks = []
|
652
|
+
(@start[:year]..@end[:year]).each do |year|
|
653
|
+
weeks += get_public_holidays_for_year(year)
|
654
|
+
end
|
655
|
+
weeks
|
656
|
+
else
|
657
|
+
get_public_holidays_for_year(@start[:year])
|
658
|
+
end
|
659
|
+
else
|
660
|
+
get_public_holidays_for_year
|
661
|
+
end
|
662
|
+
when 'week'
|
663
|
+
if @start && @start[:year]
|
664
|
+
if @end && @end[:year]
|
665
|
+
weeks = []
|
666
|
+
(@start[:year]..@end[:year]).each do |year|
|
667
|
+
weeks += get_weeks_for_year(year)
|
668
|
+
end
|
669
|
+
weeks
|
670
|
+
else
|
671
|
+
get_weeks_for_year(@start[:year])
|
672
|
+
end
|
673
|
+
else
|
674
|
+
get_weeks_for_year
|
675
|
+
end
|
676
|
+
end
|
677
|
+
end
|
678
|
+
|
679
|
+
def get_weeks_for_year(year = Time.now.year)
|
680
|
+
weeks_as_days = []
|
681
|
+
@indexes.each do |week_index|
|
682
|
+
if week_index.is_a?(Integer)
|
683
|
+
week = OpeningHoursConverter::WeekIndex.week_from_index(week_index, year)
|
684
|
+
weeks_as_days << OpeningHoursConverter::WideInterval.new.day(week[:from].day, week[:from].month, week[:from].year,
|
685
|
+
week[:to].day, week[:to].month, week[:to].year)
|
686
|
+
else
|
687
|
+
if week_index.key?(:modifier)
|
688
|
+
i = 0
|
689
|
+
(week_index[:from]..week_index[:to]).map do |index|
|
690
|
+
if i % week_index[:modifier] == 0
|
691
|
+
week = OpeningHoursConverter::WeekIndex.week_from_index(index, year)
|
692
|
+
weeks_as_days << OpeningHoursConverter::WideInterval.new.day(week[:from].day, week[:from].month, week[:from].year,
|
693
|
+
week[:to].day, week[:to].month, week[:to].year)
|
694
|
+
end
|
695
|
+
i += 1
|
696
|
+
end
|
697
|
+
else
|
698
|
+
(week_index[:from]..week_index[:to]).map do |index|
|
699
|
+
week = OpeningHoursConverter::WeekIndex.week_from_index(index, year)
|
700
|
+
weeks_as_days << OpeningHoursConverter::WideInterval.new.day(week[:from].day, week[:from].month, week[:from].year,
|
701
|
+
week[:to].day, week[:to].month, week[:to].year)
|
702
|
+
end
|
703
|
+
end
|
704
|
+
end
|
705
|
+
end
|
706
|
+
|
707
|
+
weeks_as_days
|
708
|
+
end
|
709
|
+
def get_public_holidays_for_year(year = Time.now.year)
|
710
|
+
OpeningHoursConverter::PublicHoliday.ph_for_year(year).map do |holiday|
|
711
|
+
OpeningHoursConverter::WideInterval.new.day(holiday.day, holiday.month, holiday.year)
|
563
712
|
end
|
564
713
|
end
|
565
714
|
end
|
@@ -82,7 +82,59 @@ module OpeningHoursConverter
|
|
82
82
|
def self.build_day_array_from_dates(dates, get_iterator=false)
|
83
83
|
years = {}
|
84
84
|
dates.each do |date|
|
85
|
-
|
85
|
+
|
86
|
+
if date.wide_interval.type == 'week'
|
87
|
+
if date.wide_interval.start.nil? || date.wide_interval.start[:year].nil?
|
88
|
+
date.wide_interval.indexes.each do |week_index|
|
89
|
+
if week_index.is_a? Integer
|
90
|
+
years["always"] ||= []
|
91
|
+
years["always"] << { start: { week: week_index }, end: { week: week_index } }
|
92
|
+
elsif week_index.is_a?(Hash) && week_index.key?(:modifier)
|
93
|
+
# week range with modifier
|
94
|
+
years["always"] ||= []
|
95
|
+
years["always"] << { start: { week: week_index[:from] }, end: { week: week_index[:to] }, modifier: week_index[:modifier] }
|
96
|
+
else
|
97
|
+
# week range
|
98
|
+
years["always"] ||= []
|
99
|
+
years["always"] << { start: { week: week_index[:from] }, end: { week: week_index[:to] } }
|
100
|
+
end
|
101
|
+
end
|
102
|
+
else
|
103
|
+
if date.wide_interval.end.nil? || date.wide_interval.end[:year].nil?
|
104
|
+
date.wide_interval.indexes.each do |week_index|
|
105
|
+
if week_index.is_a? Integer
|
106
|
+
years[date.wide_interval.start[:year]] ||= []
|
107
|
+
years[date.wide_interval.start[:year]] << { start: { week: week_index }, end: { week: week_index } }
|
108
|
+
elsif week_index.is_a?(Hash) && week_index.key?(:modifier)
|
109
|
+
# week range with modifier
|
110
|
+
years[date.wide_interval.start[:year]] ||= []
|
111
|
+
years[date.wide_interval.start[:year]] << { start: { week: week_index[:from] }, end: { week: week_index[:to] }, modifier: week_index[:modifier] }
|
112
|
+
else
|
113
|
+
# week range
|
114
|
+
years[date.wide_interval.start[:year]] ||= []
|
115
|
+
years[date.wide_interval.start[:year]] << { start: { week: week_index[:from] }, end: { week: week_index[:to] } }
|
116
|
+
end
|
117
|
+
end
|
118
|
+
else
|
119
|
+
date.wide_interval.start[:year].upto(date.wide_interval.end[:year]) do |year|
|
120
|
+
date.wide_interval.indexes.each do |week_index|
|
121
|
+
if week_index.is_a? Integer
|
122
|
+
years[year] ||= []
|
123
|
+
years[year] << { start: { week: week_index }, end: { week: week_index } }
|
124
|
+
elsif week_index.is_a?(Hash) && week_index.key?(:modifier)
|
125
|
+
# week range with modifier
|
126
|
+
years[year] ||= []
|
127
|
+
years[year] << { start: { week: week_index[:from] }, end: { week: week_index[:to] }, modifier: week_index[:modifier] }
|
128
|
+
else
|
129
|
+
# week range
|
130
|
+
years[year] ||= []
|
131
|
+
years[year] << { start: { week: week_index[:from] }, end: { week: week_index[:to] } }
|
132
|
+
end
|
133
|
+
end
|
134
|
+
end
|
135
|
+
end
|
136
|
+
end
|
137
|
+
elsif !date.wide_interval.start.nil? && !date.wide_interval.start[:year].nil?
|
86
138
|
if date.wide_interval.end.nil? || date.wide_interval.end[:year].nil? || date.wide_interval.start[:year] == date.wide_interval.end[:year]
|
87
139
|
if !years[date.wide_interval.start[:year]].nil?
|
88
140
|
years = process_single_year(date.wide_interval, years)
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: opening_hours_converter
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.
|
4
|
+
version: 1.9.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Ziserman Martin
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2019-05-
|
11
|
+
date: 2019-05-29 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: json
|
@@ -79,8 +79,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
79
79
|
- !ruby/object:Gem::Version
|
80
80
|
version: '0'
|
81
81
|
requirements: []
|
82
|
-
|
83
|
-
rubygems_version: 2.7.3
|
82
|
+
rubygems_version: 3.0.3
|
84
83
|
signing_key:
|
85
84
|
specification_version: 4
|
86
85
|
summary: Datetime range to openinghours, openinghours to datetime range
|