periodical 0.1.1

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.
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: