time_scales 0.1.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.
@@ -0,0 +1,9 @@
1
+ module TimeScales
2
+ module Frame
3
+
4
+ class NullFrame < Frame::Base
5
+ include Singleton
6
+ end
7
+
8
+ end
9
+ end
@@ -0,0 +1,258 @@
1
+ module TimeScales
2
+ module Frame
3
+
4
+ module PartComponents
5
+
6
+ module HasYearOfScheme
7
+ def self.included(other)
8
+ other.extend HasYearOfScheme::ClassMixin
9
+ end
10
+
11
+ attr_reader :year_of_scheme
12
+
13
+ alias year year_of_scheme
14
+
15
+ private
16
+
17
+ def _initialize(args_array)
18
+ super
19
+ @year_of_scheme = ensure_fixnum( args_array.shift )
20
+ end
21
+
22
+ def prepare_time_struct(struct)
23
+ struct.year = (struct.year || 1) + year_of_scheme - 1
24
+ super
25
+ end
26
+
27
+ module ClassMixin
28
+ protected
29
+
30
+ def _parts
31
+ super << Parts::YearOfScheme
32
+ end
33
+ end
34
+ end
35
+
36
+ module HasMonthOfYear
37
+ def self.included(other)
38
+ other.extend HasMonthOfYear::ClassMixin
39
+ end
40
+
41
+ attr_reader :month_of_year
42
+
43
+ alias month month_of_year
44
+
45
+ private
46
+
47
+ def _initialize(args_array)
48
+ super
49
+ @month_of_year = ensure_fixnum( args_array.shift )
50
+ end
51
+
52
+ def prepare_time_struct(struct)
53
+ struct.month = (struct.month || 1) + month_of_year - 1
54
+ super
55
+ end
56
+
57
+ module ClassMixin
58
+ protected
59
+
60
+ def _parts
61
+ super << Parts::MonthOfYear
62
+ end
63
+ end
64
+ end
65
+
66
+ module HasDayOfMonth
67
+ def self.included(other)
68
+ other.extend HasDayOfMonth::ClassMixin
69
+ end
70
+
71
+ attr_reader :day_of_month
72
+
73
+ alias day day_of_month
74
+
75
+ private
76
+
77
+ def _initialize(args_array)
78
+ super
79
+ @day_of_month = ensure_fixnum( args_array.shift )
80
+ end
81
+
82
+ def prepare_time_struct(struct)
83
+ struct.day = (struct.day || 1) + day_of_month - 1
84
+ super
85
+ end
86
+
87
+ module ClassMixin
88
+ protected
89
+
90
+ def _parts
91
+ super << Parts::DayOfMonth
92
+ end
93
+ end
94
+ end
95
+
96
+ module HasDayOfYear
97
+ def self.included(other)
98
+ other.extend HasDayOfYear::ClassMixin
99
+ end
100
+
101
+ attr_reader :day_of_year
102
+
103
+ alias day day_of_year
104
+
105
+ private
106
+
107
+ def _initialize(args_array)
108
+ super
109
+ @day_of_year = ensure_fixnum( args_array.shift )
110
+ end
111
+
112
+ def prepare_time_struct(struct)
113
+ struct.day = (struct.day || 1) + day_of_year - 1
114
+ super
115
+ end
116
+
117
+ module ClassMixin
118
+ protected
119
+
120
+ def _parts
121
+ super << Parts::DayOfYear
122
+ end
123
+ end
124
+ end
125
+
126
+ module HasHourOfDay
127
+ def self.included(other)
128
+ other.extend HasHourOfDay::ClassMixin
129
+ end
130
+
131
+ attr_reader :hour_of_day
132
+
133
+ alias hour hour_of_day
134
+
135
+ private
136
+
137
+ def _initialize(args_array)
138
+ super
139
+ @hour_of_day = ensure_fixnum( args_array.shift )
140
+ end
141
+
142
+ def prepare_time_struct(struct)
143
+ struct.hour = struct.hour.to_i + hour_of_day
144
+ super
145
+ end
146
+
147
+ module ClassMixin
148
+ protected
149
+
150
+ def _parts
151
+ super << Parts::HourOfDay
152
+ end
153
+ end
154
+ end
155
+
156
+ module HasMinuteOfHour
157
+ def self.included(other)
158
+ other.extend HasMinuteOfHour::ClassMixin
159
+ end
160
+
161
+ attr_reader :minute_of_hour
162
+
163
+ alias minute minute_of_hour
164
+
165
+ private
166
+
167
+ def _initialize(args_array)
168
+ super
169
+ @minute_of_hour = ensure_fixnum( args_array.shift )
170
+ end
171
+
172
+ def prepare_time_struct(struct)
173
+ struct.minute = struct.minute.to_i + minute_of_hour
174
+ super
175
+ end
176
+
177
+ module ClassMixin
178
+ protected
179
+
180
+ def _parts
181
+ super << Parts::MinuteOfHour
182
+ end
183
+ end
184
+ end
185
+
186
+ module HasMonthOfQuarter
187
+ def self.included(other)
188
+ other.extend HasMonthOfQuarter::ClassMixin
189
+ end
190
+
191
+ attr_reader :month_of_quarter
192
+
193
+ alias month month_of_quarter
194
+
195
+ private
196
+
197
+ def _initialize(args_array)
198
+ super
199
+ @month_of_quarter = ensure_fixnum( args_array.shift )
200
+ end
201
+
202
+ def prepare_time_struct(struct)
203
+ struct.month = (struct.month || 1) + month_of_quarter - 1
204
+ super
205
+ end
206
+
207
+ module ClassMixin
208
+ protected
209
+
210
+ def _parts
211
+ super << Parts::MonthOfQuarter
212
+ end
213
+ end
214
+ end
215
+
216
+ module HasQuarterOfYear
217
+ def self.included(other)
218
+ other.extend HasQuarterOfYear::ClassMixin
219
+ end
220
+
221
+ attr_reader :quarter_of_year
222
+
223
+ alias quarter quarter_of_year
224
+
225
+ private
226
+
227
+ def _initialize(args_array)
228
+ super
229
+ @quarter_of_year = ensure_fixnum( args_array.shift )
230
+ end
231
+
232
+ def prepare_time_struct(struct)
233
+ to_month =
234
+ (struct.month || 1) +
235
+ 3 * (quarter_of_year - 1)
236
+ if to_month > 12
237
+ struct.year = (struct.year || 1) + 1
238
+ to_month -= 12
239
+ struct.month = to_month
240
+ else
241
+ struct.month = to_month
242
+ end
243
+ super
244
+ end
245
+
246
+ module ClassMixin
247
+ protected
248
+
249
+ def _parts
250
+ super << Parts::QuarterOfYear
251
+ end
252
+ end
253
+ end
254
+
255
+ end
256
+
257
+ end
258
+ end
@@ -0,0 +1,45 @@
1
+ module TimeScales
2
+ module Frame
3
+
4
+ class PartDef
5
+ attr_reader :key, :value, :part
6
+
7
+ def initialize(key, value=nil)
8
+ @key = key
9
+ @value = value
10
+ end
11
+
12
+ def scale
13
+ possible_parts.first.scale
14
+ end
15
+
16
+ def outer_scope!
17
+ @part = possible_parts.length == 1 ?
18
+ possible_parts.first :
19
+ possible_parts.detect { |part| part.default_for_unit? }
20
+ end
21
+
22
+ def component_of!(scope)
23
+ @part = possible_parts.detect { |part|
24
+ scope.subdivision === part.scope
25
+ }
26
+ end
27
+
28
+ private
29
+
30
+ def possible_parts
31
+ @possible_parts ||= begin
32
+ parts = Parts.all.select { |part| part === key }
33
+ if parts.empty?
34
+ parts = Parts.all.select { |part| part.subdivision === key }
35
+ end
36
+ if parts.empty?
37
+ raise NoPartOrUnitForKeyError, "No part or unit matches key #{key.inspect}"
38
+ end
39
+ parts
40
+ end
41
+ end
42
+ end
43
+
44
+ end
45
+ end
@@ -0,0 +1,53 @@
1
+ module TimeScales
2
+ module Frame
3
+
4
+ class PartDefs
5
+
6
+ class << self
7
+ private :new
8
+
9
+ def from_key_value_map(kvm)
10
+ part_defs = kvm.map { |part_key, value|
11
+ PartDef.new( part_key, value )
12
+ }
13
+ new( part_defs )
14
+ end
15
+
16
+ def from_keys(part_keys)
17
+ part_defs = part_keys.map { |key| PartDef.new(key) }
18
+ new( part_defs )
19
+ end
20
+ end
21
+
22
+ def initialize(part_defs)
23
+ @part_defs = part_defs
24
+ end
25
+
26
+ def parts
27
+ @parts ||= assembly_sequence.map { |pd| pd.part }
28
+ end
29
+
30
+ def part_values
31
+ assembly_sequence.map { |pd| pd.value }
32
+ end
33
+
34
+ private
35
+
36
+ attr_reader :part_defs
37
+
38
+ def assembly_sequence
39
+ return [] if part_defs.empty?
40
+ @assembly_sequence ||= begin
41
+ seq = part_defs.sort_by { |ps| -ps.scale }
42
+ seq.first.outer_scope!
43
+ seq[0..-2].zip( seq[1..-1] ).each do |a,b|
44
+ b.component_of! a.part
45
+ end
46
+ seq
47
+ end
48
+ end
49
+
50
+ end
51
+
52
+ end
53
+ end
@@ -0,0 +1,83 @@
1
+ module TimeScales
2
+ module Frame
3
+
4
+ module Precisions
5
+
6
+ module HasYearOfSchemePrecision
7
+ def succ_begin_time
8
+ @end_time ||= Time.new( begin_time.year + 1 )
9
+ end
10
+ end
11
+
12
+ module Has_N_MonthsOfSchemePrecision
13
+ def succ_begin_time
14
+ @succ_begin_time ||= begin
15
+ succ_y = year_of_scheme
16
+ succ_m = begin_time.month + n_months_precision
17
+ if succ_m > 12
18
+ succ_y += 1 ; succ_m = 1
19
+ end
20
+ Time.new( succ_y, succ_m )
21
+ end
22
+ end
23
+
24
+ private
25
+
26
+ # Precision unit size in months. A year must be divisible
27
+ # by this value.
28
+ def n_months_precision
29
+ raise NotImplementedError, "Subclass responsibility"
30
+ end
31
+ end
32
+
33
+ module HasMonthOfSchemePrecision
34
+ include Has_N_MonthsOfSchemePrecision
35
+
36
+ private
37
+
38
+ def n_months_precision
39
+ 1
40
+ end
41
+ end
42
+
43
+ module HasQuarterOfSchemePrecision
44
+ include Has_N_MonthsOfSchemePrecision
45
+
46
+ private
47
+
48
+ def n_months_precision
49
+ 3
50
+ end
51
+ end
52
+
53
+ module HasDayOfSchemePrecision
54
+ # Gets us to the early part of the next day, regardless
55
+ # of DST handling, leap seconds, etc.
56
+ SECONDS_IN_26_HOURS = 60 * 60 * 26
57
+
58
+ def succ_begin_time
59
+ t = begin_time + SECONDS_IN_26_HOURS
60
+ @succ_begin_time ||= Time.new(t.year, t.month, t.day)
61
+ end
62
+ end
63
+
64
+ module HasHourOfSchemePrecision
65
+ SECONDS_PER_HOUR = 60 * 60
66
+
67
+ def succ_begin_time
68
+ @succ_begin_time ||= begin_time + SECONDS_PER_HOUR
69
+ end
70
+ end
71
+
72
+ module HasMinuteOfSchemePrecision
73
+ SECONDS_PER_MINUTE = 60
74
+
75
+ def succ_begin_time
76
+ @succ_begin_time ||= begin_time + SECONDS_PER_MINUTE
77
+ end
78
+ end
79
+
80
+ end
81
+
82
+ end
83
+ end