scheduling 0.1.1 → 0.1.2

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,4 +1,8 @@
1
- === 0.1.0 / 2013-08-16
1
+ === 0.1.1 / 2013-08-19
2
2
 
3
3
  * Initial release:
4
4
 
5
+ === 0.1.2 / 2013-08-19
6
+
7
+ Add Quarterly regularity class, which brings Date.quarterly, Date.q1, Date.q2, Date.q3, Date.q4, Date#qday, Date#quarter, and Date#next_quarter.
8
+
@@ -6,7 +6,7 @@
6
6
 
7
7
  == Description
8
8
 
9
- Plan and keep track of project/activity scheduling, including budgeting and accounting.
9
+ Classes for making schedules, that are regular (yearly, monthly, quarterly, etc.), irregular, or both (compound). Once a schedule is made, and given a target date range, the date of all occurances can be determined.
10
10
 
11
11
  == Features
12
12
 
@@ -2,6 +2,7 @@ require 'scheduling/version'
2
2
  require 'scheduling/intersection'
3
3
 
4
4
  require 'scheduling/regularity/monthly'
5
+ require 'scheduling/regularity/quarterly'
5
6
  require 'scheduling/regularity/yearly'
6
7
 
7
8
  require 'scheduling/schedule/regular_schedule'
@@ -0,0 +1,82 @@
1
+ class Date
2
+ def self.q1(year)
3
+ Date.new(year,1)
4
+ end
5
+
6
+ def self.q2(year)
7
+ Date.new(year,4)
8
+ end
9
+
10
+ def self.q3(year)
11
+ Date.new(year,7)
12
+ end
13
+
14
+ def self.q4(year)
15
+ Date.new(year,10)
16
+ end
17
+
18
+ def quarter
19
+ 1 + ((month - 1) / 3)
20
+ end
21
+
22
+ def self.quarterly year, quarter = 1, qday = 1
23
+ case quarter
24
+ when 1
25
+ self.q1(year) + (qday - 1)
26
+ when 2
27
+ self.q2(year) + (qday - 1)
28
+ when 3
29
+ self.q3(year) + (qday - 1)
30
+ when 4
31
+ self.q4(year) + (qday - 1)
32
+ else
33
+ raise ArgumentError, "quarter #{quarter} is not 1-4"
34
+ end
35
+ end
36
+
37
+ def qday
38
+ 1 + (self - Date.quarterly(self.year, quarter)).to_i
39
+ end
40
+
41
+ def next_quarter count = 1
42
+ raise ArgumentError, "count #{count} is < 1" if count < 1
43
+
44
+ quarter = self.quarter + count % 4
45
+ year = self.year + count / 4
46
+
47
+ if quarter > 4
48
+ year += 1
49
+ quarter = (quarter - 4)
50
+ end
51
+
52
+ Date.quarterly(year, quarter, self.qday)
53
+ end
54
+ end
55
+
56
+ module Scheduling
57
+ class Quarterly < Struct.new(:qday)
58
+ def occurances time_range
59
+ raise RangeDecreasingError if time_range.decreasing?
60
+ cur = Date.quarterly(time_range.min.year, time_range.min.quarter, qday)
61
+
62
+ start = time_range.min
63
+ if cur < start
64
+ cur = cur.next_quarter
65
+ end
66
+
67
+ occurances = []
68
+
69
+ stop = time_range.last
70
+ if time_range.exclude_end?
71
+ stop -= 1
72
+ end
73
+
74
+ while cur <= stop
75
+ occurances.push cur
76
+ cur = cur.next_quarter
77
+ end
78
+
79
+ return occurances
80
+ end
81
+ end
82
+ end
@@ -1,4 +1,4 @@
1
1
  module Scheduling
2
2
  # scheduling version
3
- VERSION = "0.1.1"
3
+ VERSION = "0.1.2"
4
4
  end
@@ -0,0 +1,164 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
2
+
3
+ describe Date do
4
+
5
+ describe '.q1' do
6
+ it 'should produce a date starting Jan 1 of the given year' do
7
+ [1910, 2000, 2111].each do |year|
8
+ date = Date.q1(year)
9
+ date.month.should eq(1)
10
+ date.day.should eq(1)
11
+ end
12
+ end
13
+ end
14
+
15
+ describe '.q2' do
16
+ it 'should produce a date starting Apr 1 of the given year' do
17
+ [1910, 2000, 2111].each do |year|
18
+ date = Date.q2(year)
19
+ date.month.should eq(4)
20
+ date.day.should eq(1)
21
+ end
22
+ end
23
+ end
24
+
25
+ describe '.q3' do
26
+ it 'should produce a date starting July 1 of the given year' do
27
+ [1910, 2000, 2111].each do |year|
28
+ date = Date.q3(year)
29
+ date.month.should eq(7)
30
+ date.day.should eq(1)
31
+ end
32
+ end
33
+ end
34
+
35
+ describe '.q4' do
36
+ it 'should produce a date starting Oct 1 of the given year' do
37
+ [1910, 2000, 2111].each do |year|
38
+ date = Date.q4(year)
39
+ date.month.should eq(10)
40
+ date.day.should eq(1)
41
+ end
42
+ end
43
+ end
44
+
45
+ describe '#quarter' do
46
+ it 'should return 1 for quarters 1-3' do
47
+ [1,2,3].each do |quarter|
48
+ Date.new(2000,quarter).quarter.should eq(1)
49
+ end
50
+ end
51
+
52
+ it 'should return 2 for quarters 4-6' do
53
+ [4,5,6].each do |quarter|
54
+ Date.new(2000,quarter).quarter.should eq(2)
55
+ end
56
+ end
57
+
58
+ it 'should return 3 for quarters 7-9' do
59
+ [7,8,9].each do |quarter|
60
+ Date.new(2000,quarter).quarter.should eq(3)
61
+ end
62
+ end
63
+
64
+ it 'should return 4 for quarters 10-12' do
65
+ [10,11,12].each do |quarter|
66
+ Date.new(2000,quarter).quarter.should eq(4)
67
+ end
68
+ end
69
+ end
70
+
71
+ describe '.quarterly' do
72
+ it 'should produce a Date instance' do
73
+ Date.quarterly(2000).should be_a Date
74
+ end
75
+
76
+ it 'should produce a date with given qday' do
77
+ [1,10,20,70,89].each do |qday|
78
+ Date.quarterly(1995,2,qday).qday.should eq(qday)
79
+ end
80
+ end
81
+ end
82
+
83
+ describe '#qday' do
84
+ it 'should return the number of days since the start of the last quarter' do
85
+ [
86
+ Date.new(2000,3,28),
87
+ Date.new(1999,10,15),
88
+ Date.new(2006,8,11),
89
+ Date.new(2045,12,31)
90
+ ].each do |date|
91
+ date.qday.should eq(1 + (date - Date.quarterly(date.year, date.quarter)))
92
+ end
93
+ end
94
+ end
95
+
96
+ describe '#next_quarter' do
97
+ it 'should return the a date that is number of quarters in the future' do
98
+ [
99
+ #{ :start => Date.quarterly(2000,3,28), :q_incr => 2, :expected => Date.quarterly(2001, 1, 28) },
100
+ #{ :start => Date.quarterly(2012,1), :q_incr => 5, :expected => Date.quarterly(2013, 2) },
101
+ #{ :start => Date.quarterly(2030,4,45), :q_incr => 11, :expected => Date.quarterly(2033, 3, 45) },
102
+ ].each do |hash|
103
+ hash[:start].next_quarter(hash[:q_incr]).should eq(hash[:expected])
104
+ end
105
+ end
106
+ end
107
+ end
108
+
109
+ describe Quarterly do
110
+ describe '#occurances' do
111
+ context 'time range spans less than 1 quarter' do
112
+ context 'original time not in qday range' do
113
+ it 'should return empty array' do
114
+ [
115
+ {:qday => 15, :range => Date.quarterly(2003,1,16)..Date.quarterly(2003,2,14)},
116
+ {:qday => 15, :range => Date.quarterly(2003,1,16)...Date.quarterly(2003,2,15)},
117
+ {:qday => 2, :range => Date.new(2021,1,3)...Date.new(2021,2,1)},
118
+ ].each do |hash|
119
+ Quarterly.new(hash[:qday]).occurances(hash[:range]).should be_empty
120
+ end
121
+ end
122
+ end
123
+
124
+ context 'original time is in qday range' do
125
+ it 'should return array with 1 element' do
126
+ [
127
+ {:qday => 15, :range => Date.quarterly(2003,1,16)...Date.quarterly(2003,2,16)},
128
+ {:qday => 15, :range => Date.quarterly(2003,1,14)...Date.quarterly(2003,2,15)},
129
+ {:qday => 10, :range => Date.quarterly(2003,3,88)..Date.quarterly(2003,4,22)},
130
+ {:qday => 22, :range => Date.quarterly(2003,3)...Date.quarterly(2003,4)},
131
+ ].each do |hash|
132
+ Quarterly.new(hash[:qday]).occurances(hash[:range]).count.should eq(1)
133
+ end
134
+ end
135
+ end
136
+ end
137
+
138
+ context 'time range spans more than 1 quarter but less than 2' do
139
+ context 'original time not in qday range' do
140
+ it 'should return array with 1 element' do
141
+ [
142
+ {:qday => 15, :range => Date.quarterly(2003,1,16)..Date.quarterly(2003,3,14)},
143
+ {:qday => 15, :range => Date.quarterly(2003,1,14)...Date.quarterly(2003,2,15)},
144
+ {:qday => 2, :range => Date.quarterly(2020,4,3)...Date.quarterly(2021,1,5)},
145
+ ].each do |hash|
146
+ Quarterly.new(hash[:qday]).occurances(hash[:range]).count.should eq(1)
147
+ end
148
+ end
149
+ end
150
+
151
+ context 'original time is in qday range' do
152
+ it 'should return array with 2 elements' do
153
+ [
154
+ {:qday => 15, :range => Date.quarterly(2003,1,15)...Date.quarterly(2003,3,15)},
155
+ {:qday => 15, :range => Date.quarterly(2003,1,16)...Date.quarterly(2003,3,16)},
156
+ {:qday => 22, :range => Date.quarterly(2003,3,1)...Date.quarterly(2004)},
157
+ ].each do |hash|
158
+ Quarterly.new(hash[:qday]).occurances(hash[:range]).count.should eq(2)
159
+ end
160
+ end
161
+ end
162
+ end
163
+ end
164
+ end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: scheduling
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.1
4
+ version: 0.1.2
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2013-08-19 00:00:00.000000000 Z
12
+ date: 2013-08-20 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: bundler
@@ -111,6 +111,7 @@ files:
111
111
  - lib/scheduling.rb
112
112
  - lib/scheduling/intersection.rb
113
113
  - lib/scheduling/regularity/monthly.rb
114
+ - lib/scheduling/regularity/quarterly.rb
114
115
  - lib/scheduling/regularity/yearly.rb
115
116
  - lib/scheduling/schedule/compound_schedule.rb
116
117
  - lib/scheduling/schedule/irregular_schedule.rb
@@ -119,6 +120,7 @@ files:
119
120
  - scheduling.gemspec
120
121
  - spec/intersection_spec.rb
121
122
  - spec/regularity/monthly_spec.rb
123
+ - spec/regularity/quarterly_spec.rb
122
124
  - spec/regularity/yearly_spec.rb
123
125
  - spec/schedule/compound_schedule_spec.rb
124
126
  - spec/schedule/irregular_schedule_spec.rb
@@ -140,7 +142,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
140
142
  version: '0'
141
143
  segments:
142
144
  - 0
143
- hash: -3343969679380982067
145
+ hash: -1329761715509626376
144
146
  required_rubygems_version: !ruby/object:Gem::Requirement
145
147
  none: false
146
148
  requirements:
@@ -149,7 +151,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
149
151
  version: '0'
150
152
  segments:
151
153
  - 0
152
- hash: -3343969679380982067
154
+ hash: -1329761715509626376
153
155
  requirements: []
154
156
  rubyforge_project:
155
157
  rubygems_version: 1.8.23
@@ -159,6 +161,7 @@ summary: Make schedules, regular (yearly, monthly, etc.) or otherwise.
159
161
  test_files:
160
162
  - spec/intersection_spec.rb
161
163
  - spec/regularity/monthly_spec.rb
164
+ - spec/regularity/quarterly_spec.rb
162
165
  - spec/regularity/yearly_spec.rb
163
166
  - spec/schedule/compound_schedule_spec.rb
164
167
  - spec/schedule/irregular_schedule_spec.rb