zone_ranger 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
data/.gitignore ADDED
@@ -0,0 +1,21 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ coverage
6
+ InstalledFiles
7
+ lib/bundler/man
8
+ pkg
9
+ rdoc
10
+ spec/reports
11
+ test/tmp
12
+ test/version_tmp
13
+ tmp
14
+ .ruby-version
15
+ .rbenv*
16
+ .DS_Store
17
+
18
+ # YARD artifacts
19
+ .yardoc
20
+ _yardoc
21
+ doc/
data/Gemfile ADDED
@@ -0,0 +1,3 @@
1
+ source 'https://rubygems.org'
2
+
3
+ gemspec
data/Gemfile.lock ADDED
@@ -0,0 +1,35 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ zone_ranger (0.0.1)
5
+ activesupport (~> 3.0.20)
6
+ i18n
7
+ tzinfo (~> 0.3.35)
8
+
9
+ GEM
10
+ remote: https://rubygems.org/
11
+ specs:
12
+ activesupport (3.0.20)
13
+ diff-lcs (1.2.4)
14
+ i18n (0.6.5)
15
+ rake (10.1.0)
16
+ rspec (2.14.1)
17
+ rspec-core (~> 2.14.0)
18
+ rspec-expectations (~> 2.14.0)
19
+ rspec-mocks (~> 2.14.0)
20
+ rspec-core (2.14.5)
21
+ rspec-expectations (2.14.2)
22
+ diff-lcs (>= 1.1.3, < 2.0)
23
+ rspec-mocks (2.14.3)
24
+ timecop (0.3.5)
25
+ tzinfo (0.3.37)
26
+
27
+ PLATFORMS
28
+ ruby
29
+
30
+ DEPENDENCIES
31
+ bundler (~> 1.3)
32
+ rake
33
+ rspec
34
+ timecop (~> 0.3.5)
35
+ zone_ranger!
data/LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2013 Rigor
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy of
6
+ this software and associated documentation files (the "Software"), to deal in
7
+ the Software without restriction, including without limitation the rights to
8
+ use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
9
+ the Software, and to permit persons to whom the Software is furnished to do so,
10
+ subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
17
+ FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
18
+ COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
19
+ IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
20
+ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,4 @@
1
+ zone-ranger
2
+ ===========
3
+
4
+ To determine if a time falls between two points
data/Rakefile ADDED
@@ -0,0 +1 @@
1
+ require "bundler/gem_tasks"
@@ -0,0 +1,182 @@
1
+ require 'active_support/all'
2
+
3
+ module ZoneRanger
4
+ class Core
5
+
6
+ attr_reader :start_time_string, :repeat_type
7
+ attr_reader :duration_in_minutes
8
+
9
+ def initialize start_date_time, duration_in_minutes, timezone, options={}
10
+
11
+ @start_time_string = start_date_time
12
+ @duration_in_minutes = duration_in_minutes
13
+ @timezone = timezone
14
+
15
+ @ending = options.fetch(:ending, nil)
16
+
17
+ @repeat_type = options.fetch(:repeat, nil)
18
+
19
+ end
20
+
21
+ def repeat?
22
+ !!@repeat_type
23
+ end
24
+
25
+ def daily?
26
+ @repeat_type == :daily
27
+ end
28
+
29
+ def weekly?
30
+ @repeat_type == :weekly
31
+ end
32
+
33
+ def monthly_by_day_of_week?
34
+ @repeat_type == :monthly_by_day_of_week
35
+ end
36
+
37
+ def monthly_by_day_of_month?
38
+ @repeat_type == :monthly_by_day_of_month
39
+ end
40
+
41
+ def timezone_object
42
+ ActiveSupport::TimeZone.new((@timezone || "UTC"))
43
+ end
44
+
45
+ def includes? time_point=Time.now.utc
46
+ return false if not_started_yet?(time_point) || expired?(time_point)
47
+
48
+ if repeat?
49
+ included_in_repeating_timeframe? time_point
50
+ else
51
+ static_include? time_point
52
+ end
53
+ end
54
+
55
+ def static_include? time_point
56
+ zoned_time(time_point).between?(*time_range(time_point))
57
+ end
58
+
59
+ def expired? time=Time.now.utc
60
+ return false unless @ending
61
+ zoned_time(time) > zoned_end_date
62
+ end
63
+
64
+ def zoned_time time=nil
65
+ tzone = timezone_object
66
+ if time.nil?
67
+ tzone.now
68
+ else
69
+ time.in_time_zone(tzone)
70
+ end
71
+ end
72
+
73
+ def zoned_date time=Time.now.utc
74
+ zoned_time(time).to_date
75
+ end
76
+
77
+ def zoned_end_date
78
+ timezone_object.parse("#{@ending} 23:59:59 #{utc_offset}")
79
+ end
80
+
81
+ def utc_offset
82
+ ActiveSupport::TimeZone.seconds_to_utc_offset(zoned_time.utc_offset)
83
+ end
84
+
85
+ def not_started_yet? time
86
+ start_on > zoned_date
87
+ end
88
+
89
+ def start_on
90
+ parsed_time_string.to_date
91
+ end
92
+
93
+ def started?
94
+ !not_started_yet?
95
+ end
96
+
97
+ def time_range current_day=Time.now.utc, options={}
98
+
99
+ offset = options.fetch(:offset, 0)
100
+
101
+ start_date = if repeat?
102
+ #if daily?
103
+ # shift to the day being checked
104
+ start_time = zoned_time(current_day + offset.days)
105
+ start_time.to_date
106
+ #end
107
+ else
108
+ parsed_time_string.to_date
109
+ end
110
+
111
+ b_start = timezone_object.parse(parsed_time_string.strftime("#{start_date} %H:%M")).in_time_zone(timezone_object)
112
+ b_end = b_start + duration_in_minutes.minutes
113
+
114
+ [b_start, b_end]
115
+ end
116
+
117
+ def parsed_time_string
118
+ timezone_object.parse(start_time_string)
119
+ end
120
+
121
+ protected
122
+
123
+ def included_in_repeating_timeframe? time_point
124
+ repeat? && (daily? && include_for_daily?(time_point) ||
125
+ weekly? && include_for_weekly?(time_point) ||
126
+ monthly_by_day_of_week? && include_for_monthly_dow?(time_point) ||
127
+ monthly_by_day_of_month? && include_for_monthly_dom?(time_point))
128
+ end
129
+
130
+ def include_for_daily? time_point
131
+ zoned_time(time_point).between?(*time_range(time_point, :offset => -1)) || zoned_time(time_point).between?(*time_range(time_point))
132
+ end
133
+
134
+ def include_for_weekly? time_point
135
+ start_date = zoned_time(time_point).to_date
136
+ start_at, end_at = time_range(time_point)
137
+
138
+ if crosses_midnight?
139
+ wday1 = parsed_time_string.wday
140
+ wday2 = parsed_time_string.tomorrow.wday
141
+
142
+ case start_date.wday
143
+ when wday1
144
+ zoned_time(time_point).between?(start_at, end_at)
145
+ when wday2
146
+ yesterday_start, yesterday_end = time_range(zoned_time(time_point), :offset => -1)
147
+ zoned_time(time_point).between?(yesterday_start, yesterday_end)
148
+ else false
149
+ end
150
+ else
151
+ Util.wday_match?(start_at, parsed_time_string) && zoned_time(time_point).between?(start_at, end_at)
152
+ end
153
+ end
154
+
155
+ def include_for_monthly_dow? time_point
156
+ start_date = parsed_time_string.to_date
157
+
158
+ start_week = Util.week_of_month(start_date)
159
+ time_week = Util.week_of_month(zoned_time(time_point))
160
+
161
+ start_week == time_week && include_for_weekly?(time_point)
162
+ end
163
+
164
+ def include_for_monthly_dom? time_point
165
+ original_day = parsed_time_string.day
166
+ today_day = zoned_time(time_point).day
167
+
168
+ if today_day == original_day
169
+ static_include? time_point
170
+ elsif (today_day == parsed_time_string.tomorrow.day) && crosses_midnight?
171
+ zoned_time(time_point).between?(*time_range(time_point, :offset => -1))
172
+ else
173
+ false
174
+ end
175
+ end
176
+
177
+ def crosses_midnight?
178
+ Util.crosses_one_utc_midnight?(parsed_time_string, @duration_in_minutes)
179
+ end
180
+
181
+ end
182
+ end
@@ -0,0 +1,47 @@
1
+ module ZoneRanger
2
+ class Util
3
+
4
+ def self.week_of_month time
5
+ day_num = time.day
6
+ days_in_month = Time.days_in_month(time.month)
7
+
8
+ if day_num < 8
9
+ 1
10
+ elsif day_num < 15
11
+ 2
12
+ elsif day_num < 22
13
+ 3
14
+ elsif day_num < days_in_month - 7
15
+ 4 # fourth but not last
16
+ else
17
+ :last # last
18
+ end
19
+ end
20
+
21
+ def self.crosses_one_utc_midnight? start, duration
22
+ # a utc midnight is when the start day is different the blackout ends on
23
+ day1 = start.utc.to_date
24
+ day2 = (start + duration.minutes).utc.to_date
25
+ day1 != day2
26
+ end
27
+
28
+ def self.wday_match? date1, date2
29
+ date1.wday == date2.wday
30
+ end
31
+
32
+ def self.calculate_duration_in_minutes starting, ending
33
+ start_hour = starting.strftime("%H")
34
+ start_minutes = starting.strftime("%M")
35
+ start_in_minutes = (start_hour.to_i * 60) + start_minutes.to_i
36
+
37
+ finish_hour = ending.strftime("%H").to_i
38
+ finish_minutes = (finish_hour * 60) + ending.strftime("%M").to_i
39
+
40
+ d = finish_minutes - start_in_minutes
41
+ d += 1440 if d < 0
42
+
43
+ d
44
+ end
45
+
46
+ end
47
+ end
@@ -0,0 +1,3 @@
1
+ module ZoneRanger
2
+ VERSION = "0.0.1"
3
+ end
@@ -0,0 +1,3 @@
1
+ require "zone_ranger/version"
2
+ require 'zone_ranger/util'
3
+ require 'zone_ranger/core'
data/spec/core_spec.rb ADDED
@@ -0,0 +1,260 @@
1
+ require 'spec_helper'
2
+
3
+ describe ZoneRanger::Core do
4
+
5
+ def timeize t_or_s
6
+ t_or_s.is_a?(Time) ? t_or_s : Time.parse(t_or_s)
7
+ end
8
+
9
+ def validate_active zr, time
10
+ Timecop.freeze(timeize(time))
11
+ zr.includes?(timeize(time)).should(be_true, "#{time.to_s} expected ACTIVE")
12
+ Timecop.return
13
+ end
14
+
15
+ def validate_inactive zr, time
16
+ Timecop.freeze(timeize(time))
17
+ zr.includes?(timeize(time)).should(be_false, "#{time.to_s} expected INACTIVE")
18
+ Timecop.return
19
+ end
20
+
21
+ describe "standard operation" do
22
+ it "should require a start time, duration, and timezone" do
23
+ expect{ ZoneRanger::Core.new.includes? Time.now, 30 }.to raise_error ArgumentError
24
+ expect{ ZoneRanger::Core.new.includes? Time.now }.to raise_error ArgumentError
25
+ end
26
+
27
+ it "should not throw error if all fields are supplied" do
28
+ ZoneRanger::Core.new("#{Time.now - 300}", 30, "Eastern Time (US & Canada)").includes?
29
+ end
30
+
31
+ it "should accept a Time parameter" do
32
+ ZoneRanger::Core.new("#{Time.now - 300}", 30, "Eastern Time (US & Canada)").includes? Time.now.utc
33
+ end
34
+
35
+ it "should repeat? if told" do
36
+ zr = ZoneRanger::Core.new('2013-04-01 06:00 -04:00', 30, "Eastern Time (US & Canada)", :repeat => :daily)
37
+ zr.repeat?.should be_true
38
+ end
39
+
40
+ it "should have a timezone" do
41
+ zr = ZoneRanger::Core.new('2013-04-01 06:00 -04:00', 30, "Eastern Time (US & Canada)")
42
+ zr.timezone_object.should be_a ActiveSupport::TimeZone
43
+ end
44
+ end
45
+
46
+ describe "#time_range" do
47
+ context "no repeat" do
48
+ it "should return the correct time range - same day" do
49
+ zr = ZoneRanger::Core.new('2013-04-01 06:00 -04:00', 30, "Eastern Time (US & Canada)")
50
+ zr.time_range.should eql([Time.parse('2013-04-01 06:00 -04:00'), Time.parse('2013-04-01 06:30 -04:00')])
51
+ end
52
+
53
+ it "should return the correct time range - crossing midnight in user's timezone" do
54
+ zr = ZoneRanger::Core.new('2013-04-01 23:01 -04:00', 60, "Eastern Time (US & Canada)")
55
+ zr.time_range.should eql([Time.parse('2013-04-01 23:01 -04:00'), Time.parse('2013-04-02 00:01 -04:00')])
56
+ end
57
+
58
+ it "should work with other time zones" do
59
+ zr = ZoneRanger::Core.new('2013-04-01 23:01 -07:00', 60, "Pacific Time (US & Canada)")
60
+ zr.time_range.should eql([Time.parse('2013-04-01 23:01 -07:00'), Time.parse('2013-04-02 00:01 -07:00')])
61
+ end
62
+ end
63
+
64
+ context "repeat daily" do
65
+ it "should return the correct time range - same day" do
66
+ zr = ZoneRanger::Core.new('2013-04-01 06:00 -04:00', 30, "Eastern Time (US & Canada)", :repeat => :daily)
67
+ zr.time_range(Time.parse('2013-04-02 06:00 -04:00')).should eql([Time.parse('2013-04-02 06:00 -04:00'), Time.parse('2013-04-02 06:30 -04:00')])
68
+ end
69
+
70
+ it "should return the correct time range - crossing midnight in user's timezone" do
71
+ zr = ZoneRanger::Core.new('2013-04-01 23:01 -04:00', 60, "Eastern Time (US & Canada)", :repeat => :daily)
72
+ zr.time_range(Time.parse('2013-04-02 06:00 -04:00')).should eql([Time.parse('2013-04-02 23:01 -04:00'), Time.parse('2013-04-03 00:01 -04:00')])
73
+ end
74
+
75
+ it "should work with other time zones" do
76
+ zr = ZoneRanger::Core.new('2013-04-01 23:01 -07:00', 60, "Pacific Time (US & Canada)", :repeat => :daily)
77
+ zr.time_range(Time.parse('2013-04-02 06:00 -07:00')).should eql([Time.parse('2013-04-02 23:01 -07:00'), Time.parse('2013-04-03 00:01 -07:00')])
78
+ end
79
+ end
80
+ end
81
+
82
+ describe "#expired?" do
83
+ let(:zr_daily) { ZoneRanger::Core.new('2013-04-01 23:01 -04:00', 60, "Eastern Time (US & Canada)", :repeat => :daily, :ending => '2013-06-01')}
84
+ let(:zr_weekly) { ZoneRanger::Core.new('2013-04-01 00:01:00 -07:00', 60, "Pacific Time (US & Canada)", :ending => '2013-06-01', :repeat => :weekly)}
85
+ let(:zr_monthly_by_day_of_month) { ZoneRanger::Core.new('2013-04-01 00:01:00 -07:00', 60, "Pacific Time (US & Canada)", :ending => '2013-06-01', :repeat => :monthly_by_day_of_month)}
86
+ let(:zr_monthly_by_day_of_week) { ZoneRanger::Core.new('2013-04-01 00:01:00 -07:00', 60, "Pacific Time (US & Canada)", :ending => '2013-06-01', :repeat => :monthly_by_day_of_week)}
87
+
88
+ it "should return true if the checked time is past the expired time" do
89
+ [zr_daily, zr_weekly, zr_monthly_by_day_of_month, zr_monthly_by_day_of_week].each do |zr|
90
+ zr.expired?(Time.parse('2013-06-02 00:00:00 -07:00')).should(be_true, "#{zr.repeat_type} expected EXPIRED")
91
+ end
92
+ end
93
+
94
+ it "should be false if the checked time is before the expired time" do
95
+ [zr_daily, zr_weekly, zr_monthly_by_day_of_month, zr_monthly_by_day_of_week].each do |zr|
96
+ zr.expired?(Time.parse('2013-06-01 00:00:00 -07:00')).should(be_false, "#{zr.repeat_type} expected ACTIVE")
97
+ zr.expired?(Time.parse('2013-05-01 00:00:00 -07:00')).should(be_false, "#{zr.repeat_type} expected ACTIVE")
98
+ end
99
+ end
100
+ end
101
+
102
+ describe "#includes?" do
103
+
104
+ context "expired" do
105
+ let(:daily_with_end) { ZoneRanger::Core.new("09:58 -04:00", 841, "Eastern Time (US & Canada)", :repeat => :daily, :ending => '2013-07-17') }
106
+
107
+ it "should never return true after the end date - not near UTC midnight" do
108
+ validate_inactive daily_with_end, "Fri Jul 19 11:57:22 -0400 2013"
109
+ validate_active daily_with_end, "Fri Jul 16 11:57:22 -0400 2013"
110
+ validate_active daily_with_end, "Fri Jul 17 23:58:22 -0400 2013"
111
+ end
112
+ end
113
+
114
+ context "giving a time" do # does the present time fall in the given timeframe?
115
+
116
+ let(:zr) { ZoneRanger::Core.new('2013-04-01 23:01:00 -07:00', 60, "Pacific Time (US & Canada)") }
117
+
118
+ context "in timeframe" do # present time is inside timeframe
119
+ it "should be active" do
120
+ validate_active(zr, '2013-04-01 23:01:01 -07:00')
121
+ validate_active(zr, '2013-04-02 00:00:00 -07:00')
122
+ end
123
+ end
124
+ context "outside timeframe" do # present time is outside timeframe
125
+ it "should not be active" do
126
+ validate_inactive(zr, '2013-04-01 23:00:01 -07:00')
127
+ validate_inactive(zr, '2013-04-02 00:02:00 -07:00')
128
+ end
129
+ end
130
+
131
+ context "over utc midnight" do
132
+ let(:set_timeframe_over_two_days){ ZoneRanger::Core.new("2013-07-24 23:01 UTC", 120, "UTC", :repeat => :weekly, :ending => Time.parse("2013-07-25 UTC")) }
133
+
134
+ it "should be active in timeframe" do
135
+ validate_active(set_timeframe_over_two_days, "2013-07-24 23:02 UTC")
136
+ validate_active(set_timeframe_over_two_days, "2013-07-25 01:00 UTC")
137
+ end
138
+
139
+ it "should not be active in timeframe" do
140
+ validate_inactive(set_timeframe_over_two_days, "2013-07-24 23:00 UTC")
141
+ validate_inactive(set_timeframe_over_two_days, "2013-07-25 01:02 UTC")
142
+ end
143
+ end
144
+
145
+ context "repeated" do
146
+ context "daily" do
147
+ let(:zr_daily) { ZoneRanger::Core.new('2013-04-01 23:01:00 -07:00', 60, "Pacific Time (US & Canada)", :repeat => :daily) }
148
+ let(:zr_daily_no_start_date) { ZoneRanger::Core.new('23:01:00 -07:00', 60, "Pacific Time (US & Canada)", :repeat => :daily) }
149
+
150
+ it "should cover until midnight every day" do
151
+ (1..8).each do |i|
152
+ validate_active(zr_daily, "2013-04-0#{i} 23:59:01 -07:00")
153
+ validate_active(zr_daily_no_start_date, "2013-04-0#{i} 23:59:01 -07:00")
154
+ end
155
+ end
156
+
157
+ it "should cover after midnight every day" do
158
+ (1..8).each do |i|
159
+ validate_active(zr_daily, "2013-04-0#{i+1} 00:00:00 -07:00")
160
+ validate_active(zr_daily_no_start_date, "2013-04-0#{i+1} 00:00:00 -07:00")
161
+ end
162
+ end
163
+
164
+ it "should not cover after midnight from the day before if before starting time" do
165
+ validate_inactive(zr_daily, "2013-03-31 00:00:00 -07:00")
166
+ validate_active(zr_daily_no_start_date, "2013-03-31 00:00:00 -07:00")
167
+ end
168
+ end
169
+
170
+ context "weekly" do
171
+ let(:zr_weekly) { ZoneRanger::Core.new('2013-04-01 00:01:00 -07:00', 60, "Pacific Time (US & Canada)", :repeat => :weekly) }
172
+
173
+ it "should cover only on the day of week, and in time range" do
174
+ validate_active(zr_weekly, '2013-04-01 00:01:01 -07:00')
175
+ validate_active(zr_weekly, '2013-04-01 00:59:59 -07:00')
176
+
177
+ # next week
178
+ validate_active(zr_weekly, '2013-04-08 00:01:01 -07:00')
179
+ validate_active(zr_weekly, '2013-04-08 00:59:59 -07:00')
180
+ end
181
+
182
+ it "should not cover if on the day of week, but not in time range" do
183
+ validate_inactive(zr_weekly, '2013-04-08 00:00:59 -07:00')
184
+ validate_inactive(zr_weekly, '2013-04-08 01:02:59 -07:00')
185
+ end
186
+
187
+ it "should not cover if not on the day of week and in time range" do
188
+ validate_inactive(zr_weekly, '2013-04-07 00:01:01 -07:00')
189
+ validate_inactive(zr_weekly, '2013-04-07 00:59:59 -07:00')
190
+ end
191
+ end
192
+
193
+ context "monthly" do
194
+ context "day of the month" do
195
+
196
+ let(:zr_monthly_dom) { ZoneRanger::Core.new('2013-04-01 00:01:00 -07:00', 60, "Pacific Time (US & Canada)", :repeat => :monthly_by_day_of_month) }
197
+ let(:zr_monthly_dom2) { ZoneRanger::Core.new("2013-07-17 09:58 -04:00", 120, "Eastern Time (US & Canada)", :repeat => :monthly_by_day_of_month) }
198
+
199
+ it "should be active if on the day of the month of start_date and within the timeframe" do
200
+ validate_active(zr_monthly_dom, '2013-05-01 00:02:00 -07:00')
201
+ validate_active(zr_monthly_dom, '2013-05-01 00:59:00 -07:00')
202
+ validate_active(zr_monthly_dom, '2013-06-01 00:02:00 -07:00')
203
+ validate_active(zr_monthly_dom, '2013-06-01 00:59:00 -07:00')
204
+ end
205
+
206
+ it "should not be active if on the day of the month of start_date and within the timeframe but start_date is in the future" do
207
+ validate_inactive(zr_monthly_dom, '2013-03-01 00:02:00 -07:00')
208
+ validate_inactive(zr_monthly_dom, '2013-03-01 00:59:00 -07:00')
209
+ end
210
+
211
+ it "should not be active if within the timeframe but not on the day of the month" do
212
+ validate_inactive(zr_monthly_dom, '2013-04-03 00:02:00 -07:00')
213
+ validate_inactive(zr_monthly_dom, '2013-04-03 00:59:00 -07:00')
214
+ validate_inactive(zr_monthly_dom2, "Thu Jul 18 9:59:22 -0400 2013")
215
+ end
216
+
217
+
218
+
219
+ end
220
+
221
+ context "day of the week" do
222
+ let(:zr_monthly_dow) { ZoneRanger::Core.new('2013-04-01 00:01:00 -07:00', 60, "Pacific Time (US & Canada)", :repeat => :monthly_by_day_of_week) }
223
+
224
+ it "should be active if on the same weekday and xth week and inside timeframe" do
225
+ validate_active(zr_monthly_dow, "2013-04-01 00:02:00 -07:00")
226
+ validate_active(zr_monthly_dow, "2013-04-01 01:00:00 -07:00")
227
+
228
+ # next period
229
+ validate_active(zr_monthly_dow, "2013-05-06 00:02:00 -07:00")
230
+ validate_active(zr_monthly_dow, "2013-05-06 01:00:00 -07:00")
231
+ end
232
+
233
+ it "should not be active if on xth week and inside timeframe but not on same weekday" do
234
+ validate_inactive(zr_monthly_dow, "2013-05-05 00:02:00 -07:00")
235
+ validate_inactive(zr_monthly_dow, "2013-05-05 01:00:00 -07:00")
236
+ end
237
+
238
+ it "should not be active if on the same weekday and inside timeframe but not on xth week" do
239
+ validate_inactive(zr_monthly_dow, "2013-04-08 00:02:00 -07:00")
240
+ validate_inactive(zr_monthly_dow, "2013-04-08 01:00:00 -07:00")
241
+ end
242
+
243
+ it "should not be active if on the same weekday and xth week but outside timeframe" do
244
+ validate_inactive(zr_monthly_dow, "2013-04-01 00:00:00 -07:00")
245
+ validate_inactive(zr_monthly_dow, "2013-04-01 01:02:00 -07:00")
246
+
247
+ # next period
248
+ validate_inactive(zr_monthly_dow, "2013-05-06 00:00:00 -07:00")
249
+ validate_inactive(zr_monthly_dow, "2013-05-06 01:02:00 -07:00")
250
+ end
251
+ end
252
+
253
+ end
254
+ end
255
+
256
+ end
257
+
258
+ end
259
+
260
+ end
@@ -0,0 +1,4 @@
1
+ require 'zone_ranger'
2
+ require 'bundler/setup'
3
+
4
+ require 'timecop'
data/spec/util_spec.rb ADDED
@@ -0,0 +1,24 @@
1
+ require 'spec_helper'
2
+
3
+ describe ZoneRanger::Util do
4
+ it "should pass" do
5
+ end
6
+
7
+ describe '#crosses_one_utc_midnight?' do
8
+ # let(:does_cross) { Factory(:check_blackout_period,
9
+ # :repeat_type => "daily",
10
+ # :start_time => "19:58", :end_time => "1:38", :start_date => nil)}
11
+ # let(:does_not_cross) { Factory(:check_blackout_period,
12
+ # :repeat_type => "daily",
13
+ # :start_time => "10:58", :end_time => "11:38", :start_date => nil)}
14
+ # let(:crossing_utc_weekly_blackout) { Factory(:check_blackout_period, :repeat_type => "weekly",
15
+ # :start_time => "19:58", :end_time => "1:30", :start_date => Date.parse('2013-07-17'))}
16
+
17
+ # it "should cross one midnight" do
18
+ # does_cross.send(:crosses_one_utc_midnight?).should be_true
19
+ # does_not_cross.send(:crosses_one_utc_midnight?).should be_false
20
+ # crossing_utc_weekly_blackout.send(:crosses_one_utc_midnight?).should be_true
21
+ # end
22
+ # end
23
+ end
24
+ end
@@ -0,0 +1,30 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'zone_ranger/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "zone_ranger"
8
+ spec.version = ZoneRanger::VERSION
9
+ spec.authors = ["Hubert Liu"]
10
+ spec.email = ["hubert.liu@rigor.com"]
11
+ spec.description = "Time Zone Ranger"
12
+ spec.summary = "Time Zone Ranger"
13
+ spec.homepage = "https://github.com/Rigor/zone_ranger"
14
+ spec.license = "MIT"
15
+
16
+ spec.files = `git ls-files`.split($/)
17
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
18
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
19
+ spec.require_paths = ["lib"]
20
+
21
+ spec.add_development_dependency "bundler", "~> 1.3"
22
+ spec.add_development_dependency "rake"
23
+ spec.add_development_dependency "rspec"
24
+ spec.add_development_dependency "timecop", "~> 0.3.5"
25
+
26
+ spec.add_runtime_dependency "activesupport", "~> 3.0.20"
27
+ spec.add_runtime_dependency 'i18n' # required by active_support
28
+ spec.add_runtime_dependency 'tzinfo', '~> 0.3.35'
29
+ #spec.add_runtime_dependency 'tzinfo-data'
30
+ end
metadata ADDED
@@ -0,0 +1,185 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: zone_ranger
3
+ version: !ruby/object:Gem::Version
4
+ hash: 29
5
+ prerelease:
6
+ segments:
7
+ - 0
8
+ - 0
9
+ - 1
10
+ version: 0.0.1
11
+ platform: ruby
12
+ authors:
13
+ - Hubert Liu
14
+ autorequire:
15
+ bindir: bin
16
+ cert_chain: []
17
+
18
+ date: 2013-09-16 00:00:00 Z
19
+ dependencies:
20
+ - !ruby/object:Gem::Dependency
21
+ name: bundler
22
+ prerelease: false
23
+ requirement: &id001 !ruby/object:Gem::Requirement
24
+ none: false
25
+ requirements:
26
+ - - ~>
27
+ - !ruby/object:Gem::Version
28
+ hash: 9
29
+ segments:
30
+ - 1
31
+ - 3
32
+ version: "1.3"
33
+ type: :development
34
+ version_requirements: *id001
35
+ - !ruby/object:Gem::Dependency
36
+ name: rake
37
+ prerelease: false
38
+ requirement: &id002 !ruby/object:Gem::Requirement
39
+ none: false
40
+ requirements:
41
+ - - ">="
42
+ - !ruby/object:Gem::Version
43
+ hash: 3
44
+ segments:
45
+ - 0
46
+ version: "0"
47
+ type: :development
48
+ version_requirements: *id002
49
+ - !ruby/object:Gem::Dependency
50
+ name: rspec
51
+ prerelease: false
52
+ requirement: &id003 !ruby/object:Gem::Requirement
53
+ none: false
54
+ requirements:
55
+ - - ">="
56
+ - !ruby/object:Gem::Version
57
+ hash: 3
58
+ segments:
59
+ - 0
60
+ version: "0"
61
+ type: :development
62
+ version_requirements: *id003
63
+ - !ruby/object:Gem::Dependency
64
+ name: timecop
65
+ prerelease: false
66
+ requirement: &id004 !ruby/object:Gem::Requirement
67
+ none: false
68
+ requirements:
69
+ - - ~>
70
+ - !ruby/object:Gem::Version
71
+ hash: 25
72
+ segments:
73
+ - 0
74
+ - 3
75
+ - 5
76
+ version: 0.3.5
77
+ type: :development
78
+ version_requirements: *id004
79
+ - !ruby/object:Gem::Dependency
80
+ name: activesupport
81
+ prerelease: false
82
+ requirement: &id005 !ruby/object:Gem::Requirement
83
+ none: false
84
+ requirements:
85
+ - - ~>
86
+ - !ruby/object:Gem::Version
87
+ hash: 47
88
+ segments:
89
+ - 3
90
+ - 0
91
+ - 20
92
+ version: 3.0.20
93
+ type: :runtime
94
+ version_requirements: *id005
95
+ - !ruby/object:Gem::Dependency
96
+ name: i18n
97
+ prerelease: false
98
+ requirement: &id006 !ruby/object:Gem::Requirement
99
+ none: false
100
+ requirements:
101
+ - - ">="
102
+ - !ruby/object:Gem::Version
103
+ hash: 3
104
+ segments:
105
+ - 0
106
+ version: "0"
107
+ type: :runtime
108
+ version_requirements: *id006
109
+ - !ruby/object:Gem::Dependency
110
+ name: tzinfo
111
+ prerelease: false
112
+ requirement: &id007 !ruby/object:Gem::Requirement
113
+ none: false
114
+ requirements:
115
+ - - ~>
116
+ - !ruby/object:Gem::Version
117
+ hash: 85
118
+ segments:
119
+ - 0
120
+ - 3
121
+ - 35
122
+ version: 0.3.35
123
+ type: :runtime
124
+ version_requirements: *id007
125
+ description: Time Zone Ranger
126
+ email:
127
+ - hubert.liu@rigor.com
128
+ executables: []
129
+
130
+ extensions: []
131
+
132
+ extra_rdoc_files: []
133
+
134
+ files:
135
+ - .gitignore
136
+ - Gemfile
137
+ - Gemfile.lock
138
+ - LICENSE
139
+ - README.md
140
+ - Rakefile
141
+ - lib/zone_ranger.rb
142
+ - lib/zone_ranger/core.rb
143
+ - lib/zone_ranger/util.rb
144
+ - lib/zone_ranger/version.rb
145
+ - spec/core_spec.rb
146
+ - spec/spec_helper.rb
147
+ - spec/util_spec.rb
148
+ - zone_ranger.gemspec
149
+ homepage: https://github.com/Rigor/zone_ranger
150
+ licenses:
151
+ - MIT
152
+ post_install_message:
153
+ rdoc_options: []
154
+
155
+ require_paths:
156
+ - lib
157
+ required_ruby_version: !ruby/object:Gem::Requirement
158
+ none: false
159
+ requirements:
160
+ - - ">="
161
+ - !ruby/object:Gem::Version
162
+ hash: 3
163
+ segments:
164
+ - 0
165
+ version: "0"
166
+ required_rubygems_version: !ruby/object:Gem::Requirement
167
+ none: false
168
+ requirements:
169
+ - - ">="
170
+ - !ruby/object:Gem::Version
171
+ hash: 3
172
+ segments:
173
+ - 0
174
+ version: "0"
175
+ requirements: []
176
+
177
+ rubyforge_project:
178
+ rubygems_version: 1.8.15
179
+ signing_key:
180
+ specification_version: 3
181
+ summary: Time Zone Ranger
182
+ test_files:
183
+ - spec/core_spec.rb
184
+ - spec/spec_helper.rb
185
+ - spec/util_spec.rb