periodical 0.1.1

Sign up to get free protection for your applications and to get access to all the features.
data/README.md ADDED
@@ -0,0 +1,45 @@
1
+ Periodical
2
+ =========
3
+
4
+ * Author: Samuel G. D. Williams (<http://www.oriontransfer.co.nz>)
5
+ * Copyright (C) 2012 Samuel G. D. Williams.
6
+ * Released under the MIT license.
7
+
8
+ Periodical is a simple framework for working with durations and periods. A duration measures a range of time bounded by a `from` date and `to` date. A period is a relative unit of time such as `4 weeks`.
9
+
10
+ Basic Usage
11
+ -----------
12
+
13
+ The main use case for this framework involves periodic billing or accounting (e.g. calculating fortnightly rental payments).
14
+
15
+ duration = Periodical::Duration.new(Date.parse("2010-01-01"), Date.parse("2010-02-01"))
16
+ period = Periodical::Period.new(2, :weeks)
17
+
18
+ # How many periods in the duration?
19
+ count = duration / period
20
+
21
+ # Calculate the date which is 2 * (2 weeks)
22
+ next = period.advance(duration.from, 2)
23
+
24
+ License
25
+ -------
26
+
27
+ Copyright (c) 2010, 2011 Samuel G. D. Williams. <http://www.oriontransfer.co.nz>
28
+
29
+ Permission is hereby granted, free of charge, to any person obtaining a copy
30
+ of this software and associated documentation files (the "Software"), to deal
31
+ in the Software without restriction, including without limitation the rights
32
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
33
+ copies of the Software, and to permit persons to whom the Software is
34
+ furnished to do so, subject to the following conditions:
35
+
36
+ The above copyright notice and this permission notice shall be included in
37
+ all copies or substantial portions of the Software.
38
+
39
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
40
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
41
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
42
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
43
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
44
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
45
+ THE SOFTWARE.
@@ -0,0 +1,72 @@
1
+ # Copyright (c) 2012 Samuel G. D. Williams. <http://www.oriontransfer.co.nz>
2
+ #
3
+ # Permission is hereby granted, free of charge, to any person obtaining a copy
4
+ # of this software and associated documentation files (the "Software"), to deal
5
+ # in the Software without restriction, including without limitation the rights
6
+ # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7
+ # copies of the Software, and to permit persons to whom the Software is
8
+ # furnished to do so, subject to the following conditions:
9
+ #
10
+ # The above copyright notice and this permission notice shall be included in
11
+ # all copies or substantial portions of the Software.
12
+ #
13
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14
+ # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15
+ # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16
+ # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17
+ # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18
+ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
19
+ # THE SOFTWARE.
20
+
21
+ require 'date'
22
+
23
+ module Periodical
24
+ class Duration
25
+ def initialize(from, to)
26
+ @from = from
27
+ @to = to
28
+ end
29
+
30
+ attr :from
31
+ attr :to
32
+
33
+ def days
34
+ @to - @from
35
+ end
36
+
37
+ def weeks
38
+ days / 7
39
+ end
40
+
41
+ def whole_months
42
+ (@to.year * 12 + @to.month) - (@from.year * 12 + @from.month)
43
+ end
44
+
45
+ def months
46
+ whole = self.whole_months
47
+
48
+ partial_start = @from >> whole
49
+ partial_end = @from >> whole + 1
50
+
51
+ return whole + (@to - partial_start) / (partial_end - partial_start)
52
+ end
53
+
54
+ def whole_years
55
+ @to.year - @from.year
56
+ end
57
+
58
+ def years
59
+ whole = self.whole_years
60
+
61
+ partial_start = @from >> (whole * 12)
62
+ partial_end = @from >> ((whole + 1) * 12)
63
+
64
+ return whole + (@to - partial_start) / (partial_end - partial_start)
65
+ end
66
+
67
+ # Calculate the number of periods between from and to
68
+ def / period
69
+ self.send(period.unit) / period.count
70
+ end
71
+ end
72
+ end
@@ -0,0 +1,101 @@
1
+ # Copyright (c) 2012 Samuel G. D. Williams. <http://www.oriontransfer.co.nz>
2
+ #
3
+ # Permission is hereby granted, free of charge, to any person obtaining a copy
4
+ # of this software and associated documentation files (the "Software"), to deal
5
+ # in the Software without restriction, including without limitation the rights
6
+ # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7
+ # copies of the Software, and to permit persons to whom the Software is
8
+ # furnished to do so, subject to the following conditions:
9
+ #
10
+ # The above copyright notice and this permission notice shall be included in
11
+ # all copies or substantial portions of the Software.
12
+ #
13
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14
+ # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15
+ # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16
+ # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17
+ # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18
+ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
19
+ # THE SOFTWARE.
20
+
21
+ module Periodical
22
+ class Period
23
+ VALID_UNITS = [:days, :weeks, :months, :years]
24
+
25
+ # Accepts strings in the format of "2 weeks" or "weeks"
26
+ def self.parse(value)
27
+ if Array === value
28
+ parts = value
29
+ else
30
+ parts = value.to_s.split(/\s+/, 2)
31
+ end
32
+
33
+ if parts.size == 1
34
+ if parts[0].to_i == 0
35
+ count = 1
36
+ unit = parts[0].to_sym
37
+ else
38
+ count = parts[0].to_i
39
+ unit = :days
40
+
41
+ if count == 7
42
+ count = 1
43
+ unit = :weeks
44
+ end
45
+
46
+ if count == 365
47
+ count = 1
48
+ unit = :years
49
+ end
50
+ end
51
+ else
52
+ count = parts[0].to_i
53
+ unit = parts[1].gsub(/\s+/, '_').downcase.to_sym
54
+ end
55
+
56
+ unless VALID_UNITS.include? unit
57
+ raise ArgumentError.new("Invalid unit specified #{unit}!")
58
+ end
59
+
60
+ if count == 0
61
+ raise ArgumentError.new("Count must be non-zero!")
62
+ end
63
+
64
+ return self.new(count, unit)
65
+ end
66
+
67
+ def initialize(count = 1, unit = :days)
68
+ @count = count
69
+ @unit = unit
70
+ end
71
+
72
+ def to_s
73
+ "#{@count} #{@unit}"
74
+ end
75
+
76
+ def to_formatted_s
77
+ if @count == 1
78
+ @unit.to_s.gsub(/s$/, '')
79
+ else
80
+ to_s
81
+ end
82
+ end
83
+
84
+ def advance(date, multiple = 1)
85
+ total = multiple * @count
86
+
87
+ if unit == :days
88
+ date + total
89
+ elsif unit == :weeks
90
+ date + (total * 7)
91
+ elsif unit == :months
92
+ date >> total
93
+ elsif unit == :years
94
+ date >> (total * 12)
95
+ end
96
+ end
97
+
98
+ attr :unit
99
+ attr :count
100
+ end
101
+ end
@@ -0,0 +1,29 @@
1
+ # Copyright (c) 2012 Samuel G. D. Williams. <http://www.oriontransfer.co.nz>
2
+ #
3
+ # Permission is hereby granted, free of charge, to any person obtaining a copy
4
+ # of this software and associated documentation files (the "Software"), to deal
5
+ # in the Software without restriction, including without limitation the rights
6
+ # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7
+ # copies of the Software, and to permit persons to whom the Software is
8
+ # furnished to do so, subject to the following conditions:
9
+ #
10
+ # The above copyright notice and this permission notice shall be included in
11
+ # all copies or substantial portions of the Software.
12
+ #
13
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14
+ # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15
+ # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16
+ # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17
+ # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18
+ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
19
+ # THE SOFTWARE.
20
+
21
+ module Periodical
22
+ module VERSION
23
+ MAJOR = 0
24
+ MINOR = 1
25
+ TINY = 1
26
+
27
+ STRING = [MAJOR, MINOR, TINY].join('.')
28
+ end
29
+ end
data/lib/periodical.rb ADDED
@@ -0,0 +1,22 @@
1
+ # Copyright (c) 2012 Samuel G. D. Williams. <http://www.oriontransfer.co.nz>
2
+ #
3
+ # Permission is hereby granted, free of charge, to any person obtaining a copy
4
+ # of this software and associated documentation files (the "Software"), to deal
5
+ # in the Software without restriction, including without limitation the rights
6
+ # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7
+ # copies of the Software, and to permit persons to whom the Software is
8
+ # furnished to do so, subject to the following conditions:
9
+ #
10
+ # The above copyright notice and this permission notice shall be included in
11
+ # all copies or substantial portions of the Software.
12
+ #
13
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14
+ # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15
+ # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16
+ # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17
+ # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18
+ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
19
+ # THE SOFTWARE.
20
+
21
+ require 'periodical/period'
22
+ require 'periodical/duration'
data/test/helper.rb ADDED
@@ -0,0 +1,4 @@
1
+
2
+ $LOAD_PATH.unshift File.expand_path("../../lib/", __FILE__)
3
+
4
+ require 'test/unit'
@@ -0,0 +1,34 @@
1
+
2
+ require 'helper'
3
+
4
+ require 'periodical'
5
+
6
+ class DurationTest < Test::Unit::TestCase
7
+ def setup
8
+ end
9
+
10
+ def test_duration
11
+ duration = Periodical::Duration.new(Date.parse("2010-01-01"), Date.parse("2010-02-01"))
12
+ assert_equal 31, duration.days
13
+ assert_equal Rational(31, 7), duration.weeks
14
+ assert_equal 1, duration.months
15
+ assert_equal Rational(31, 365), duration.years
16
+
17
+ assert_equal 1, duration.whole_months
18
+ assert_equal 0, duration.whole_years
19
+ end
20
+
21
+ def test_weekly_period
22
+ duration = Periodical::Duration.new(Date.parse("2010-01-01"), Date.parse("2010-02-01"))
23
+ period = Periodical::Period.new(2, :weeks)
24
+
25
+ assert_equal Rational(31, 14), duration / period
26
+ end
27
+
28
+ def test_monthly_period
29
+ duration = Periodical::Duration.new(Date.parse("2010-01-01"), Date.parse("2011-03-01"))
30
+ period = Periodical::Period.new(2, :months)
31
+
32
+ assert_equal Rational(14, 2), duration / period
33
+ end
34
+ end
@@ -0,0 +1,15 @@
1
+
2
+ require 'helper'
3
+
4
+ require 'periodical'
5
+
6
+ class PeriodTest < Test::Unit::TestCase
7
+ def setup
8
+ end
9
+
10
+ def test_advance
11
+ duration = Periodical::Duration.new(Date.parse("2010-01-01"), Date.parse("2011-01-01"))
12
+ period = Periodical::Period.new(1, :months)
13
+ assert_equal duration.to, period.advance(duration.from, 12)
14
+ end
15
+ end
metadata ADDED
@@ -0,0 +1,53 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: periodical
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.1
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Samuel Williams
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2012-07-26 00:00:00.000000000 Z
13
+ dependencies: []
14
+ description:
15
+ email: samuel.williams@oriontransfer.co.nz
16
+ executables: []
17
+ extensions: []
18
+ extra_rdoc_files: []
19
+ files:
20
+ - lib/periodical/duration.rb
21
+ - lib/periodical/period.rb
22
+ - lib/periodical/version.rb
23
+ - lib/periodical.rb
24
+ - test/helper.rb
25
+ - test/test_duration.rb
26
+ - test/test_period.rb
27
+ - README.md
28
+ homepage: http://www.oriontransfer.co.nz/
29
+ licenses: []
30
+ post_install_message:
31
+ rdoc_options: []
32
+ require_paths:
33
+ - lib
34
+ required_ruby_version: !ruby/object:Gem::Requirement
35
+ none: false
36
+ requirements:
37
+ - - ! '>='
38
+ - !ruby/object:Gem::Version
39
+ version: '0'
40
+ required_rubygems_version: !ruby/object:Gem::Requirement
41
+ none: false
42
+ requirements:
43
+ - - ! '>='
44
+ - !ruby/object:Gem::Version
45
+ version: '0'
46
+ requirements: []
47
+ rubyforge_project:
48
+ rubygems_version: 1.8.23
49
+ signing_key:
50
+ specification_version: 3
51
+ summary: Periodical is a simple framework for working with durations and periods.
52
+ test_files: []
53
+ has_rdoc: