beginning_of_fortnight 1.0.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.
Files changed (2) hide show
  1. data/lib/beginning_of_fortnight.rb +189 -0
  2. metadata +62 -0
@@ -0,0 +1,189 @@
1
+ #
2
+ # Author:: Simon Baird
3
+ # Source:: https://github.com/simonbaird/beginning_of_fortnight
4
+ # License:: 'BSD-new' where the copyright holder is Simon Baird
5
+ #
6
+ # Extends ActiveSupport to provide these methods for Time and Date objects:
7
+ # * beginning_of_fortnight
8
+ # * end_of_fortnight
9
+ # * next_fortnight
10
+ #
11
+ # These methods should work similarly to beginning_of_week, end_of_week and next_week.
12
+ #
13
+ # This gem requires that you have a version of activesupport that defines beginning_of_week.
14
+ #
15
+ # =Installation
16
+ #
17
+ # sudo gem install beginning_of_fortnight
18
+ #
19
+ # =Usage
20
+ #
21
+ # ===Basic usage
22
+ #
23
+ # require 'rubygems'
24
+ # require 'beginning_of_fortnight'
25
+ #
26
+ # now = Time.now
27
+ # puts now.beginning_of_fortnight
28
+ # puts now.end_of_fortnight
29
+ #
30
+ # ===Explicitly setting a reference date
31
+ #
32
+ # require 'rubygems'
33
+ # require 'beginning_of_fortnight'
34
+ #
35
+ # now = Time.now
36
+ #
37
+ # # Globally define fortnights such that this date is the first half of a fortnight
38
+ # ref_date = Time.parse('13-Oct-2010')
39
+ # BeginningOfFortnight.reference_date = ref_date
40
+ #
41
+ # puts now.beginning_of_fortnight # uses ref_date
42
+ #
43
+ # # Change your mind...
44
+ # BeginningOfFortnight.reference_date = Time.parse('20-Oct-2010')
45
+ # puts now.beginning_of_fortnight # should be different
46
+ #
47
+ # # You can also pass in a single use reference date if you want to mix it up
48
+ # other_ref_date = Time.parse('27-Oct-2010')
49
+ # puts now.beginning_of_fortnight(other_ref_date)
50
+ #
51
+ #
52
+
53
+ begin
54
+ # Try to load just the time components
55
+ # (Only possible in ActiveRecord 3.0)
56
+ require 'active_support/time'
57
+ rescue LoadError
58
+ # Presume we must have ActiveRecord 2.x so require the whole lot of active_support
59
+ # (Decided it's not worth the effort to try to cherry pick just the time components)
60
+ require 'active_support'
61
+ end
62
+
63
+ #
64
+ # Just a namespace and an accessor for the reference
65
+ # date used to define fortnight boundaries.
66
+ #
67
+ #--
68
+ # (Maybe this could use cattr_accessor. Not sure if it's worth it).
69
+ #++
70
+ #
71
+ module BeginningOfFortnight
72
+ #
73
+ # Fairly arbitrary choice of reference date
74
+ #
75
+ DEFAULT_REF_DATE = Time.at(0)
76
+
77
+ #
78
+ # Provide an accessor for @@reference_date. Uses the default value if not set.
79
+ #
80
+ def self.reference_date
81
+ (@@reference_date ||= DEFAULT_REF_DATE).to_time
82
+ end
83
+
84
+ #
85
+ # The 'reference_date' here is used to define where the fortnight boundary should be.
86
+ # The way it works is that the reference_date is specified such that it falls in the first
87
+ # half of the fortnightly period.
88
+ #
89
+ # You can just ignore this it will use a default value but if you want to be explicit then
90
+ # set a date, for example:
91
+ #
92
+ # # Define fortnight boundary
93
+ # BeginningOfFortnight.reference_date = Time.parse('13-Oct-2010')
94
+ #
95
+ # # A date should work also
96
+ # BeginningOfFortnight.reference_date = Date.new(2010,10,13)
97
+ #
98
+ def self.reference_date=(reference_date)
99
+ @@reference_date = reference_date
100
+ end
101
+ end
102
+
103
+
104
+ #
105
+ # These methods should work similar to beginning_of_week and friends.
106
+ #
107
+ # In all these methods, if the optional argument <tt>reference_date</tt>
108
+ # is not given then the default reference date is used. See
109
+ # BeginningOfFortnight#reference_date.
110
+ #
111
+ # reference_date can be a Date or a Time object.
112
+ #
113
+ #--
114
+ # ActiveRecord 2.x puts these methods in a big long name space,
115
+ # ie ActiveSupport::CoreExtensions::Time::Calculations
116
+ # ActiveSupport 3.x just adds methods directly to Time.
117
+ # Will try the 3.x approach and hopefully it will work okay in 2.x also.
118
+ #++
119
+ #
120
+ class Time
121
+ #
122
+ # The beginning of the fortnight.
123
+ #
124
+ def beginning_of_fortnight(reference_date=nil)
125
+ # Can pass in a reference date, otherwise use the configured default
126
+ reference_date ||= BeginningOfFortnight.reference_date
127
+
128
+ # The to_time is in case reference_date is passed in as a Date object
129
+ reference_week = reference_date.to_time.beginning_of_week
130
+
131
+ # How many weeks since reference week?
132
+ weeks_since_reference = ((self - reference_week) / 1.week).to_i
133
+
134
+ #
135
+ # If the reference time is later than self, ie in the future,
136
+ # then we flip the odd/even test here.
137
+ #
138
+ # Some explanation:
139
+ #
140
+ # In this diagram, '|' is a fortnight boundary, '+' is a week boundary and R is the reference week.
141
+ # R
142
+ # | a + b | c + d |
143
+ #
144
+ # The value of weeks_since_reference for dates at a, b, c and d is as follows:
145
+ # When self is earlier than reference_date:
146
+ # a (in first half) : -1, hence odd weeks_since_reference is in first half
147
+ # b (in second half): 0, hence even weeks_since_reference is in second half (because -0.5.to_i is 0 for example)
148
+ # When self is later than reference_date:
149
+ # c (in first half) : 0, hence even weeks_since_reference is in first half
150
+ # d (in second half): 1, hence odd weeks_since_reference is in second half
151
+ #
152
+ in_first_half = (reference_week > self ? weeks_since_reference.odd? : weeks_since_reference.even?)
153
+
154
+ # The value of in_first_half decides which week to use
155
+ (in_first_half ? self : self - 1.week).beginning_of_week
156
+ end
157
+
158
+ #
159
+ # The end of the fortnight.
160
+ #
161
+ def end_of_fortnight(reference_date=nil)
162
+ (beginning_of_fortnight(reference_date) + 1.week).end_of_week
163
+ end
164
+
165
+ #
166
+ # The start of the fortnight after this one.
167
+ #
168
+ def next_fortnight(reference_date=nil)
169
+ beginning_of_fortnight(reference_date) + 2.weeks
170
+ end
171
+ end
172
+
173
+ #
174
+ # The Date methods are defined dynamically.
175
+ #
176
+ # See:
177
+ # * Time#beginning_of_fortnight
178
+ # * Time#end_of_fortnight
179
+ # * Time#next_fortnight
180
+ #
181
+ class Date
182
+ # Going to be lazy here... in a good way (?)
183
+ # Redoing the in_first_half logic for Date objects is not quite trivial
184
+ [:beginning_of_fortnight, :end_of_fortnight, :next_fortnight].each do |method|
185
+ define_method(method) do |*args|
186
+ self.to_time.send(method,*args).to_date
187
+ end
188
+ end
189
+ end
metadata ADDED
@@ -0,0 +1,62 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: beginning_of_fortnight
3
+ version: !ruby/object:Gem::Version
4
+ prerelease: false
5
+ segments:
6
+ - 1
7
+ - 0
8
+ - 0
9
+ version: 1.0.0
10
+ platform: ruby
11
+ authors:
12
+ - Simon Baird
13
+ autorequire:
14
+ bindir: bin
15
+ cert_chain: []
16
+
17
+ date: 2011-03-16 00:00:00 +10:00
18
+ default_executable:
19
+ dependencies: []
20
+
21
+ description: Extends ActiveSupport to provides beginning/end_of_fortnight methods similar to beginning/end_of_week
22
+ email: simon.baird@gmail.com
23
+ executables: []
24
+
25
+ extensions: []
26
+
27
+ extra_rdoc_files: []
28
+
29
+ files:
30
+ - lib/beginning_of_fortnight.rb
31
+ has_rdoc: true
32
+ homepage: http://github.com/simonbaird/beginning_of_fortnight
33
+ licenses: []
34
+
35
+ post_install_message:
36
+ rdoc_options: []
37
+
38
+ require_paths:
39
+ - lib
40
+ required_ruby_version: !ruby/object:Gem::Requirement
41
+ requirements:
42
+ - - ">="
43
+ - !ruby/object:Gem::Version
44
+ segments:
45
+ - 0
46
+ version: "0"
47
+ required_rubygems_version: !ruby/object:Gem::Requirement
48
+ requirements:
49
+ - - ">="
50
+ - !ruby/object:Gem::Version
51
+ segments:
52
+ - 0
53
+ version: "0"
54
+ requirements: []
55
+
56
+ rubyforge_project:
57
+ rubygems_version: 1.3.6
58
+ signing_key:
59
+ specification_version: 3
60
+ summary: beginning_of_fortnight for ActiveSupport
61
+ test_files: []
62
+