carray-timeindex 0.9.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.
- checksums.yaml +7 -0
- data/README.md +2 -0
- data/Rakefile +11 -0
- data/carray-timeindex.gemspec +23 -0
- data/lib/carray-timeindex.rb +2 -0
- data/lib/carray-timeindex/core.rb +737 -0
- metadata +67 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 153dcf26b31edb8e20d73fb215d9e162ce99ae236358ade3d3960aa3948d5787
|
4
|
+
data.tar.gz: 82ff276b24790f304e3cdf23ec2e0ec6cbc6a865af4f12c66e59e7bc1097bb79
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 234f5551eef62046111adb11a414ea40a4dfb5e2a0dc95c8960178e7d5e7b736e81a5b0bc1128367abdd54b2b170b921586be8daec7fffcf6e0b8c9864181112
|
7
|
+
data.tar.gz: 79f4ee563e9fec51a5de2687f75abb68faec0b3d79857b228dd44924ddc0388da37e125ed2b573af59350f10333b85e406fbc5368d039a1faeac883b665e6133
|
data/README.md
ADDED
data/Rakefile
ADDED
@@ -0,0 +1,23 @@
|
|
1
|
+
|
2
|
+
Gem::Specification::new do |s|
|
3
|
+
version = "0.9.0"
|
4
|
+
|
5
|
+
files = Dir.glob("**/*") - [
|
6
|
+
Dir.glob("carray-timeindex*.gem"),
|
7
|
+
].flatten
|
8
|
+
|
9
|
+
s.platform = Gem::Platform::RUBY
|
10
|
+
s.name = "carray-timeindex"
|
11
|
+
s.summary = "TimeIndex in Ruby"
|
12
|
+
s.description = <<-HERE
|
13
|
+
TimeIndex in Ruby
|
14
|
+
HERE
|
15
|
+
s.version = version
|
16
|
+
s.author = "Hiroki Motoyoshi"
|
17
|
+
s.email = ""
|
18
|
+
s.homepage = 'https://github.com/himotoyoshi/carray-timeindex'
|
19
|
+
s.files = files
|
20
|
+
s.required_ruby_version = ">= 2.4.1"
|
21
|
+
s.add_runtime_dependency 'carray', '~> 1.3', '>= 1.3.8'
|
22
|
+
end
|
23
|
+
|
@@ -0,0 +1,737 @@
|
|
1
|
+
require "carray"
|
2
|
+
require "timesteps"
|
3
|
+
require "stringio"
|
4
|
+
|
5
|
+
autoload :CADataFrame, "carray-dataframe"
|
6
|
+
|
7
|
+
class TimeStep
|
8
|
+
|
9
|
+
def to_ca (n = 1)
|
10
|
+
return CATimeIndex.new(self, count: n)
|
11
|
+
end
|
12
|
+
|
13
|
+
end
|
14
|
+
|
15
|
+
class TimeStep::Range
|
16
|
+
|
17
|
+
def to_ca
|
18
|
+
return CATimeIndex.new(@timestep, count: @count)
|
19
|
+
end
|
20
|
+
|
21
|
+
end
|
22
|
+
|
23
|
+
class CATimeIndex < CArray
|
24
|
+
|
25
|
+
def self.concat (*args)
|
26
|
+
reference = args.shift
|
27
|
+
ts_ref = reference.timestep
|
28
|
+
array = [reference]
|
29
|
+
args.each_with_index do |series, i|
|
30
|
+
array << series.new_timestep(ts_ref)
|
31
|
+
end
|
32
|
+
return CATimeIndex.new(ts_ref) { CArray.bind(:int64, array, 0) }
|
33
|
+
end
|
34
|
+
|
35
|
+
def self.datetime_new (year=0, month=1, day=1, hour=0, minute=0, second=0.0, offset: 0, unit: nil)
|
36
|
+
params = [year, month, day, hour, minute, second]
|
37
|
+
size = params.map {|x| x.is_a?(Numeric) ? 1 : x.size }.max
|
38
|
+
ref = CArray.object(size)
|
39
|
+
arrays = params.map {|x| x.is_a?(Numeric) ? ref.template{ x } : x.to_ca }
|
40
|
+
CArray.join(arrays).to_a.each_with_index do |(*args), i|
|
41
|
+
ref[i] = DateTime.new(*args, offset)
|
42
|
+
end
|
43
|
+
return CATimeIndex.from_time_array(ref, unit || "sec", since: ref[0])
|
44
|
+
end
|
45
|
+
|
46
|
+
def self.range (since, last = nil, format: nil, offset: nil, calendar: "standard", count: nil, unit: nil, freq: "days", ends: "[]")
|
47
|
+
raise "'ends' option should be one of '[]', '()', '(]', '[)" unless ends =~ /\A[\[\(][\]\)]\z/
|
48
|
+
if freq.is_a?(Numeric)
|
49
|
+
numeric, symbol = TimeStep.split_interval_spec(unit)
|
50
|
+
freq = format("%g %s", freq, symbol)
|
51
|
+
end
|
52
|
+
freqstep = TimeStep.new(freq, since: since, format: format, calendar: calendar, offset: offset)
|
53
|
+
timestep = if unit
|
54
|
+
TimeStep.new(unit, since: since, format: format, calendar: calendar, offset: offset)
|
55
|
+
else
|
56
|
+
freqstep
|
57
|
+
end
|
58
|
+
pair = freqstep.to(timestep)
|
59
|
+
index = freqstep.range(since, last, count: count, ends: ends).map_index{|k| pair.forward(k) }
|
60
|
+
CATimeIndex.from_index_array(index, timestep, calendar: calendar, offset: offset)
|
61
|
+
end
|
62
|
+
|
63
|
+
def self.from_time_array (array, spec, since: nil, format: nil, offset: nil, calendar: "standard")
|
64
|
+
timestep = case spec
|
65
|
+
when TimeStep
|
66
|
+
spec
|
67
|
+
when String
|
68
|
+
TimeStep.new(spec, since: since, format: format, calendar: calendar, offset: offset)
|
69
|
+
else
|
70
|
+
raise "'spec' argument should be a String or a TimeStep"
|
71
|
+
end
|
72
|
+
array = array.to_ca unless array.kind_of?(CArray)
|
73
|
+
index = array.convert(:int64) {|t| timestep.index_at(t).floor }
|
74
|
+
return self.new(timestep) { index }
|
75
|
+
end
|
76
|
+
|
77
|
+
def self.from_index_array (array, spec, since: nil, format: nil, calendar: "standard", offset: nil)
|
78
|
+
since = array.timestep.origin if array.is_a?(CATimeIndex) && since.nil?
|
79
|
+
timestep = case spec
|
80
|
+
when TimeStep
|
81
|
+
spec
|
82
|
+
when String
|
83
|
+
TimeStep.new(spec, since: since, format: format, calendar: calendar, offset: offset)
|
84
|
+
else
|
85
|
+
raise "'spec' argument should be a String or a TimeStep"
|
86
|
+
end
|
87
|
+
array = array.to_ca unless array.kind_of?(CArray)
|
88
|
+
return self.new(timestep) { array }
|
89
|
+
end
|
90
|
+
|
91
|
+
def initialize (spec, since: nil, calendar: "standard", offset: nil, count: nil, freq: nil, &block)
|
92
|
+
|
93
|
+
@timestep = case spec
|
94
|
+
when TimeStep
|
95
|
+
spec
|
96
|
+
when String
|
97
|
+
TimeStep.new(spec, calendar: calendar, offset: offset)
|
98
|
+
else
|
99
|
+
raise "'spec' should be a TimeStep or String object"
|
100
|
+
end
|
101
|
+
|
102
|
+
@timestep = @timestep.new_origin(since) if since
|
103
|
+
|
104
|
+
if block
|
105
|
+
# initialize with block return value
|
106
|
+
index = block.call
|
107
|
+
index = index.to_ca unless index.kind_of?(CArray)
|
108
|
+
index = index.int64 unless index.data_type != CA_INT64
|
109
|
+
super(:int64, [index.size])
|
110
|
+
self[] = index
|
111
|
+
else
|
112
|
+
raise "count should be given unless block is given" unless count
|
113
|
+
raise "count argument should be an integer" unless count.is_a?(Integer)
|
114
|
+
super(:int64, [count])
|
115
|
+
if freq
|
116
|
+
target = case freq
|
117
|
+
when TimeStep
|
118
|
+
freq
|
119
|
+
when String
|
120
|
+
TimeStep.new(freq, calendar: @timestep.calendar, offset: @timestep.offset)
|
121
|
+
else
|
122
|
+
raise "argument shoud be an TimeStep or String or CATimeIndex"
|
123
|
+
end
|
124
|
+
target = target.new_origin(@timestep.origin)
|
125
|
+
self[] = CATimeIndex.new(target, count: count).time.
|
126
|
+
convert(:int64) {|t| timestep.index_at(t).floor }
|
127
|
+
else
|
128
|
+
self.seq!
|
129
|
+
end
|
130
|
+
end
|
131
|
+
|
132
|
+
end
|
133
|
+
|
134
|
+
attr_reader :timestep
|
135
|
+
|
136
|
+
def new_timestep (spec, since: nil, &block)
|
137
|
+
since = @timestep.origin unless since
|
138
|
+
target = case spec
|
139
|
+
when TimeStep
|
140
|
+
spec
|
141
|
+
when String
|
142
|
+
TimeStep.new(spec, since: since)
|
143
|
+
when CATimeIndex
|
144
|
+
spec.timestep
|
145
|
+
else
|
146
|
+
raise "argument shoud be an TimeStep or String or CATimeIndex"
|
147
|
+
end
|
148
|
+
pair = @timestep.to(target)
|
149
|
+
obj = CATimeIndex.new(target) { convert {|i| pair.forward(i).floor } }
|
150
|
+
obj = block.call(obj).new_timestep(@timestep) if block
|
151
|
+
return obj
|
152
|
+
end
|
153
|
+
|
154
|
+
alias in new_timestep
|
155
|
+
|
156
|
+
def shift_origin (index, with: "index")
|
157
|
+
timestep = @timestep.shift_origin(index, with: with)
|
158
|
+
return new_timestep(timestep)
|
159
|
+
end
|
160
|
+
|
161
|
+
def new_origin (origin)
|
162
|
+
timestep = @timestep.new_origin(origin)
|
163
|
+
return new_timestep(timestep)
|
164
|
+
end
|
165
|
+
|
166
|
+
def new_offset (offset)
|
167
|
+
origin = @timestep.origin.new_offset(offset)
|
168
|
+
return new_timestep(@timestep.new_origin(origin))
|
169
|
+
end
|
170
|
+
|
171
|
+
def time (*args)
|
172
|
+
index = self[*args]
|
173
|
+
return @timestep.time_at(index) if index.is_a?(Numeric)
|
174
|
+
return index.convert(:object) {|i| @timestep.time_at(i) }
|
175
|
+
end
|
176
|
+
|
177
|
+
REGEXP_DATETIME = /\A
|
178
|
+
([+\-]?\d{1,4})
|
179
|
+
(?:\-(\d{1,2}))?
|
180
|
+
(?:\-(\d{1,2}))?
|
181
|
+
(?:\s+
|
182
|
+
(\d{1,2})
|
183
|
+
(?::(\d{1,2}))?
|
184
|
+
(?::(\d{1,2}))?
|
185
|
+
)?
|
186
|
+
\z/x
|
187
|
+
|
188
|
+
def expand_to_period (spec)
|
189
|
+
if spec =~ REGEXP_DATETIME
|
190
|
+
interval = "year"
|
191
|
+
interval = "month" if $2
|
192
|
+
interval = "day" if $3
|
193
|
+
interval = "hour" if $4
|
194
|
+
interval = "minute" if $5
|
195
|
+
interval = "second" if $6
|
196
|
+
else
|
197
|
+
return nil
|
198
|
+
end
|
199
|
+
origin = @timestep.parse(spec)
|
200
|
+
return TimePeriod.new(unit, since: origin, calendar: @timestep.calendar)
|
201
|
+
end
|
202
|
+
|
203
|
+
private :expand_to_period
|
204
|
+
|
205
|
+
def match (spec)
|
206
|
+
case spec
|
207
|
+
when Range
|
208
|
+
idx1 = spec.begin
|
209
|
+
idx1 = expand_to_period(idx1).start if idx1.is_a?(String)
|
210
|
+
idx2 = spec.end
|
211
|
+
idx2 = expand_to_period(idx2).last if idx2.is_a?(String)
|
212
|
+
return (self >= idx1).and(self <= idx2)
|
213
|
+
when String
|
214
|
+
period = expand_to_period(spec)
|
215
|
+
return (self >= period.start).and(self <= period.last)
|
216
|
+
else
|
217
|
+
raise "argument should be a Range or String"
|
218
|
+
end
|
219
|
+
end
|
220
|
+
|
221
|
+
def to_ca
|
222
|
+
return CATimeIndex.new(@timestep) { super }
|
223
|
+
end
|
224
|
+
|
225
|
+
def spec_to_timestep (spec)
|
226
|
+
case spec
|
227
|
+
when TimeStep
|
228
|
+
return spec
|
229
|
+
when String
|
230
|
+
case spec
|
231
|
+
when /since/
|
232
|
+
return TimeStep.new(spec, offset: @timestep.offset, calendar: @timestep.calendar)
|
233
|
+
else
|
234
|
+
return TimeStep.new(spec, since: @timestep.parse("0000-01-01"), offset: @timestep.offset, calendar: @timestep.calendar)
|
235
|
+
end
|
236
|
+
else
|
237
|
+
raise "'spec' argument '#{spec}' can't be convert to timestep"
|
238
|
+
end
|
239
|
+
end
|
240
|
+
|
241
|
+
private :spec_to_timestep
|
242
|
+
|
243
|
+
def round_to_array (array, direction: nil)
|
244
|
+
raise "'array' should be CATimeIndex" unless array.is_a?(CATimeIndex)
|
245
|
+
target = array.in(@timestep)
|
246
|
+
index = target.double.section(self)
|
247
|
+
case direction
|
248
|
+
when :up, "up"
|
249
|
+
time = target.time.project(index.ceil)
|
250
|
+
return CATimeIndex.from_time_array(time, @timestep)
|
251
|
+
when :down, "down"
|
252
|
+
time = target.time.project(index.floor)
|
253
|
+
return CATimeIndex.from_time_array(time, @timestep)
|
254
|
+
end
|
255
|
+
end
|
256
|
+
|
257
|
+
private :round_to_array
|
258
|
+
|
259
|
+
def round (*args, direction: nil, to: nil)
|
260
|
+
case args.size
|
261
|
+
when 1
|
262
|
+
num = 1
|
263
|
+
spec = args[0]
|
264
|
+
when 2
|
265
|
+
num = args[0]
|
266
|
+
spec = args[1]
|
267
|
+
else
|
268
|
+
raise "invalid number of argumets"
|
269
|
+
end
|
270
|
+
|
271
|
+
if spec.is_a?(CATimeIndex)
|
272
|
+
if num == 1
|
273
|
+
return round_to_array(spec, direction: direction)
|
274
|
+
else
|
275
|
+
raise "invalid numeric for array"
|
276
|
+
end
|
277
|
+
end
|
278
|
+
|
279
|
+
timestep = spec_to_timestep(spec)
|
280
|
+
|
281
|
+
pair = @timestep.to(timestep)
|
282
|
+
|
283
|
+
case to
|
284
|
+
when nil
|
285
|
+
case direction
|
286
|
+
when :up, "up"
|
287
|
+
index = convert{ |i| pair.inverse( pair.forward(i).ceil + num - 1 ) }
|
288
|
+
when :down, "down"
|
289
|
+
index = convert{ |i| pair.inverse( pair.forward(i).floor ) }
|
290
|
+
else
|
291
|
+
index = convert{ |i| pair.inverse( pair.forward(i).round ) }
|
292
|
+
end
|
293
|
+
when :end, "end"
|
294
|
+
case direction
|
295
|
+
when :up, "up"
|
296
|
+
index = convert{ |i| pair.inverse( pair.forward(i).floor + num ) - 1 }
|
297
|
+
when :down, "down"
|
298
|
+
index = convert{ |i| pair.inverse( pair.forward(i).floor ) - 1 }
|
299
|
+
else
|
300
|
+
raise "can't round with 'to' option"
|
301
|
+
end
|
302
|
+
when :start, "start"
|
303
|
+
case direction
|
304
|
+
when :up, "up"
|
305
|
+
index = convert{ |i| pair.inverse( pair.forward(i).floor + num ) }
|
306
|
+
when :down, "down"
|
307
|
+
index = convert{ |i| pair.inverse( pair.forward(i).floor ) }
|
308
|
+
else
|
309
|
+
raise "can't round with 'to' option"
|
310
|
+
end
|
311
|
+
else
|
312
|
+
raise "unknown 'to' option '#{to}'"
|
313
|
+
end
|
314
|
+
|
315
|
+
return CATimeIndex.from_index_array(index, @timestep)
|
316
|
+
end
|
317
|
+
|
318
|
+
private :round
|
319
|
+
|
320
|
+
def floor (*args, to: nil)
|
321
|
+
return round(*args, direction: :down, to: to)
|
322
|
+
end
|
323
|
+
|
324
|
+
def ceil (*args, to: nil)
|
325
|
+
return round(*args, direction: :up, to: to)
|
326
|
+
end
|
327
|
+
|
328
|
+
def next (*args)
|
329
|
+
case args.size
|
330
|
+
when 1
|
331
|
+
num = 1
|
332
|
+
spec = args[0]
|
333
|
+
when 2
|
334
|
+
num = args[0]
|
335
|
+
spec = args[1]
|
336
|
+
else
|
337
|
+
raise "invalid number of argumets"
|
338
|
+
end
|
339
|
+
return self.in(spec) {|t| t + num }
|
340
|
+
end
|
341
|
+
|
342
|
+
def prev (*args)
|
343
|
+
case args.size
|
344
|
+
when 1
|
345
|
+
num = 1
|
346
|
+
spec = args[0]
|
347
|
+
when 2
|
348
|
+
num = args[0]
|
349
|
+
spec = args[1]
|
350
|
+
else
|
351
|
+
raise "invalid number of argumets"
|
352
|
+
end
|
353
|
+
return self.in(spec) {|i| i - num }
|
354
|
+
end
|
355
|
+
|
356
|
+
def [] (*argv)
|
357
|
+
obj = super
|
358
|
+
obj = CATimeIndex.from_index_array(obj, @timestep) if obj.kind_of?(CArray)
|
359
|
+
return obj
|
360
|
+
end
|
361
|
+
|
362
|
+
def ajd
|
363
|
+
return convert(:float64) {|i| @timestep.time_at(i).ajd }
|
364
|
+
end
|
365
|
+
|
366
|
+
def jd
|
367
|
+
return convert(:int64) {|i| @timestep.time_at(i).jd }
|
368
|
+
end
|
369
|
+
|
370
|
+
def year
|
371
|
+
unit = TimeStep.new("years", since: @timestep.parse("0000-01-01"), calendar: @timestep.calendar)
|
372
|
+
pair = @timestep.to(unit)
|
373
|
+
return convert(:int64) {|i| pair.forward(i) }
|
374
|
+
end
|
375
|
+
|
376
|
+
def month
|
377
|
+
unit = TimeStep.new("months", since: @timestep.parse("0000-01-01"), calendar: @timestep.calendar)
|
378
|
+
pair = @timestep.to(unit)
|
379
|
+
return convert(:int32) {|i| pair.forward(i) % 12 + 1 }
|
380
|
+
end
|
381
|
+
|
382
|
+
def day
|
383
|
+
return convert(:int32) {|i| @timestep.time_at(i).day }
|
384
|
+
end
|
385
|
+
|
386
|
+
def wday
|
387
|
+
return convert(:int32) {|i| @timestep.time_at(i).wday }
|
388
|
+
end
|
389
|
+
|
390
|
+
def is_sunday
|
391
|
+
return convert(:boolean) {|i| @timestep.time_at(i).sunday? }
|
392
|
+
end
|
393
|
+
|
394
|
+
def is_monday
|
395
|
+
return convert(:boolean) {|i| @timestep.time_at(i).monday? }
|
396
|
+
end
|
397
|
+
|
398
|
+
def is_tuesday
|
399
|
+
return convert(:boolean) {|i| @timestep.time_at(i).tuesday? }
|
400
|
+
end
|
401
|
+
|
402
|
+
def is_wednesday
|
403
|
+
return convert(:boolean) {|i| @timestep.time_at(i).wednesday? }
|
404
|
+
end
|
405
|
+
|
406
|
+
def is_thursday
|
407
|
+
return convert(:boolean) {|i| @timestep.time_at(i).thursday? }
|
408
|
+
end
|
409
|
+
|
410
|
+
def is_friday
|
411
|
+
return convert(:boolean) {|i| @timestep.time_at(i).friday? }
|
412
|
+
end
|
413
|
+
|
414
|
+
def is_saturday
|
415
|
+
return convert(:boolean) {|i| @timestep.time_at(i).saturday? }
|
416
|
+
end
|
417
|
+
|
418
|
+
def hour
|
419
|
+
unit = TimeStep.new("hours", since: @timestep.parse("0000-01-01"), calendar: @timestep.calendar)
|
420
|
+
pair = @timestep.to(unit)
|
421
|
+
return convert(:int32) {|i| pair.forward(i) % 24 }
|
422
|
+
end
|
423
|
+
|
424
|
+
def minute
|
425
|
+
unit = TimeStep.new("minutes", since: @timestep.parse("0000-01-01"), calendar: @timestep.calendar)
|
426
|
+
pair = @timestep.to(unit)
|
427
|
+
return convert(:int32) {|i| pair.forward(i) % 60 }
|
428
|
+
end
|
429
|
+
|
430
|
+
def second
|
431
|
+
unit = TimeStep.new("seconds", since: @timestep.parse("0000-01-01"), calendar: @timestep.calendar)
|
432
|
+
pair = @timestep.to(unit)
|
433
|
+
return convert(:int32) {|i| pair.forward(i).floor % 60 }
|
434
|
+
end
|
435
|
+
|
436
|
+
def second_fraction
|
437
|
+
unit = TimeStep.new("seconds", since: @timestep.parse("0000-01-01"), calendar: @timestep.calendar)
|
438
|
+
pair = @timestep.to(unit)
|
439
|
+
return convert(:float64) {|i| s = pair.forward(i); s - s.floor }
|
440
|
+
end
|
441
|
+
|
442
|
+
def next_year (n = 1)
|
443
|
+
index = convert {|i| @timestep.index_at( @timestep.time_at(i).next_year(n) ) }
|
444
|
+
return CATimeIndex.new(@timestep) { index }
|
445
|
+
end
|
446
|
+
|
447
|
+
def prev_year (n = 1)
|
448
|
+
return next_year(-n)
|
449
|
+
end
|
450
|
+
|
451
|
+
def next_month (n = 1)
|
452
|
+
index = convert {|i| @timestep.index_at( @timestep.time_at(i).next_month(n) ) }
|
453
|
+
return CATimeIndex.new(@timestep) { index }
|
454
|
+
end
|
455
|
+
|
456
|
+
def prev_month (n = 1)
|
457
|
+
return next_month(-n)
|
458
|
+
end
|
459
|
+
|
460
|
+
def next_day (n = 1)
|
461
|
+
index = convert {|i| @timestep.index_at( @timestep.time_at(i).next_day(n) ) }
|
462
|
+
return CATimeIndex.new(@timestep) { index }
|
463
|
+
end
|
464
|
+
|
465
|
+
def prev_day (n = 1)
|
466
|
+
return next_day(-n)
|
467
|
+
end
|
468
|
+
|
469
|
+
def next_hour (n = 1)
|
470
|
+
unit = TimeStep.new("hours", since: @timestep.parse("1970-01-01"), calendar: @timestep.calendar)
|
471
|
+
pair = @timestep.to(unit)
|
472
|
+
return CATimeIndex.new(@timestep) { convert {|i| pair.inverse(pair.forward(i) + n) } }
|
473
|
+
end
|
474
|
+
|
475
|
+
def prev_hour (n = 1)
|
476
|
+
return next_hour(-n)
|
477
|
+
end
|
478
|
+
|
479
|
+
def next_minute (n = 1)
|
480
|
+
unit = TimeStep.new("minutes", since: @timestep.parse("1970-01-01"), calendar: @timestep.calendar)
|
481
|
+
pair = @timestep.to(unit)
|
482
|
+
return CATimeIndex.new(@timestep) { convert {|i| pair.inverse(pair.forward(i) + n) } }
|
483
|
+
end
|
484
|
+
|
485
|
+
def prev_minute (n = 1)
|
486
|
+
return next_minute(-n)
|
487
|
+
end
|
488
|
+
|
489
|
+
def next_second (n = 1)
|
490
|
+
unit = TimeStep.new("seconds", since: @timestep.parse("1970-01-01"), calendar: @timestep.calendar)
|
491
|
+
pair = @timestep.to(unit)
|
492
|
+
return CATimeIndex.new(@timestep) { convert {|i| pair.inverse(pair.forward(i) + n) } }
|
493
|
+
end
|
494
|
+
|
495
|
+
def prev_second (n = 1)
|
496
|
+
return next_second(-n)
|
497
|
+
end
|
498
|
+
|
499
|
+
def offset
|
500
|
+
value = @timestep.offset
|
501
|
+
if value.denominator == 1
|
502
|
+
return template(:int) { value }
|
503
|
+
else
|
504
|
+
return template(:object) { value }
|
505
|
+
end
|
506
|
+
end
|
507
|
+
|
508
|
+
def < (other)
|
509
|
+
case other
|
510
|
+
when String
|
511
|
+
if period = expand_to_period(other)
|
512
|
+
self < period.first
|
513
|
+
else
|
514
|
+
self < @timestep.parse(other)
|
515
|
+
end
|
516
|
+
when DateTime, DateTimeLike
|
517
|
+
return self < @timestep.index_at(other)
|
518
|
+
when CATimeIndex
|
519
|
+
return super(other.new_timestep(@timestep))
|
520
|
+
else
|
521
|
+
super
|
522
|
+
end
|
523
|
+
end
|
524
|
+
|
525
|
+
alias lt <
|
526
|
+
|
527
|
+
def <= (other)
|
528
|
+
case other
|
529
|
+
when String
|
530
|
+
if period = expand_to_period(other)
|
531
|
+
return self <= period.last
|
532
|
+
else
|
533
|
+
return self <= @timestep.parse(other)
|
534
|
+
end
|
535
|
+
when DateTime, DateTimeLike
|
536
|
+
return self <= @timestep.index_at(other)
|
537
|
+
when CATimeIndex
|
538
|
+
return super(other.new_timestep(@timestep))
|
539
|
+
else
|
540
|
+
super
|
541
|
+
end
|
542
|
+
end
|
543
|
+
|
544
|
+
alias le <=
|
545
|
+
|
546
|
+
def > (other)
|
547
|
+
case other
|
548
|
+
when String
|
549
|
+
if period = expand_to_period(other)
|
550
|
+
return self > period.last
|
551
|
+
else
|
552
|
+
return self > @timestep.parse(other)
|
553
|
+
end
|
554
|
+
when DateTime, DateTimeLike
|
555
|
+
return self > @timestep.index_at(other)
|
556
|
+
when CATimeIndex
|
557
|
+
return super(other.new_timestep(@timestep))
|
558
|
+
else
|
559
|
+
super
|
560
|
+
end
|
561
|
+
end
|
562
|
+
|
563
|
+
alias gt >
|
564
|
+
|
565
|
+
def >= (other)
|
566
|
+
case other
|
567
|
+
when String
|
568
|
+
if period = expand_to_period(other)
|
569
|
+
return self >= period.start
|
570
|
+
else
|
571
|
+
return self >= @timestep.parse(other)
|
572
|
+
end
|
573
|
+
when DateTime, DateTimeLike
|
574
|
+
return self >= @timestep.index_at(other)
|
575
|
+
when CATimeIndex
|
576
|
+
return super(other.new_timestep(@timestep))
|
577
|
+
else
|
578
|
+
super
|
579
|
+
end
|
580
|
+
end
|
581
|
+
|
582
|
+
alias ge >=
|
583
|
+
|
584
|
+
def eq (other)
|
585
|
+
case other
|
586
|
+
when String
|
587
|
+
return eq(@timestep.parse(other))
|
588
|
+
when DateTime, DateTimeLike
|
589
|
+
return eq(@timestep.index_at(other))
|
590
|
+
when CATimeIndex
|
591
|
+
return super(other.new_timestep(@timestep))
|
592
|
+
else
|
593
|
+
super
|
594
|
+
end
|
595
|
+
end
|
596
|
+
|
597
|
+
def + (other)
|
598
|
+
case other
|
599
|
+
when String
|
600
|
+
numeric, spec = TimeStep.split_interval_spec(other)
|
601
|
+
if numeric < 0
|
602
|
+
return self - "#{-numeric.to_i} #{spec}"
|
603
|
+
end
|
604
|
+
case spec
|
605
|
+
when /\-end\z/
|
606
|
+
case numeric
|
607
|
+
when 0
|
608
|
+
return self
|
609
|
+
else
|
610
|
+
spec = spec.sub(/\-end\z/, '')
|
611
|
+
return (self + "#{(numeric.to_i-1)} #{spec}").ceil(spec, to: :end)
|
612
|
+
end
|
613
|
+
when /\-start\z/
|
614
|
+
case numeric
|
615
|
+
when 0
|
616
|
+
return self
|
617
|
+
else
|
618
|
+
spec = spec.sub(/\-start\z/, '')
|
619
|
+
return (self + "#{(numeric.to_i-1)} #{spec}").floor(spec, to: :start)
|
620
|
+
end
|
621
|
+
when /\Ayears?\z/
|
622
|
+
next_year(numeric)
|
623
|
+
when /\Amonths?\z/
|
624
|
+
next_month(numeric)
|
625
|
+
when /\Aweeks?\z/
|
626
|
+
next_day(7*numeric)
|
627
|
+
when /\Adays?\z/
|
628
|
+
next_day(numeric)
|
629
|
+
when /\Ahours?\z/
|
630
|
+
next_hour(numeric)
|
631
|
+
when /\Aminutes?\z/
|
632
|
+
next_minute(numeric)
|
633
|
+
when /\Aseconds?\z/
|
634
|
+
next_seconds(numeric)
|
635
|
+
else
|
636
|
+
return self.next(numeric, spec)
|
637
|
+
end
|
638
|
+
else
|
639
|
+
return CATimeIndex.new(@timestep) { add(other) }
|
640
|
+
end
|
641
|
+
end
|
642
|
+
|
643
|
+
def - (other)
|
644
|
+
case other
|
645
|
+
when DateTime, DateTimeLike
|
646
|
+
return sub(@timestep.index_at(other))
|
647
|
+
when CATimeIndex
|
648
|
+
return sub(other.new_timestep(@timestep))
|
649
|
+
when String
|
650
|
+
numeric, spec = TimeStep.split_interval_spec(other)
|
651
|
+
if numeric < 0
|
652
|
+
return self + "#{-numeric.to_i} #{spec}"
|
653
|
+
end
|
654
|
+
case spec
|
655
|
+
when /\-end\z/
|
656
|
+
case numeric
|
657
|
+
when 0
|
658
|
+
return self
|
659
|
+
else
|
660
|
+
spec = spec.sub(/\-end\z/, '')
|
661
|
+
return (self - "#{numeric.to_i} #{spec}").ceil(spec, to: :end)
|
662
|
+
end
|
663
|
+
when /\-start\z/
|
664
|
+
case numeric
|
665
|
+
when 0
|
666
|
+
return self
|
667
|
+
else
|
668
|
+
spec = spec.sub(/\-start\z/, '')
|
669
|
+
return (self - "#{numeric.to_i} #{spec}").floor(spec, to: :start)
|
670
|
+
end
|
671
|
+
when /\Ayears?\z/
|
672
|
+
prev_year(numeric)
|
673
|
+
when /\Amonths?\z/
|
674
|
+
prev_month(numeric)
|
675
|
+
when /\Aweeks?\z/
|
676
|
+
prev_day(7*numeric)
|
677
|
+
when /\Adays?\z/
|
678
|
+
prev_day(numeric)
|
679
|
+
when /\Ahours?\z/
|
680
|
+
prev_hour(numeric)
|
681
|
+
when /\Aminutes?\z/
|
682
|
+
prev_minute(numeric)
|
683
|
+
when /\Aseconds?\z/
|
684
|
+
prev_seconds(numeric)
|
685
|
+
else
|
686
|
+
return self.prev(numeric, spec)
|
687
|
+
end
|
688
|
+
else
|
689
|
+
return CATimeIndex.new(@timestep) { sub(other) }
|
690
|
+
end
|
691
|
+
end
|
692
|
+
|
693
|
+
def strftime (format)
|
694
|
+
return time.str_strftime(format)
|
695
|
+
end
|
696
|
+
|
697
|
+
def concat (*others)
|
698
|
+
return CATimeIndex.concat(self, *others)
|
699
|
+
end
|
700
|
+
|
701
|
+
def inspect
|
702
|
+
io = StringIO.new
|
703
|
+
io.puts "CATimeIndex: rows#=#{elements()}"
|
704
|
+
io.puts "timestep = " + @timestep.definition
|
705
|
+
body = CADataFrame.new({element: self.int64, "time value": time})
|
706
|
+
# body = CArray.join([(0...self.size).to_ca,self.int64,self.time])
|
707
|
+
io.puts body.inspect.each_line.to_a[1..-1]
|
708
|
+
return io.string.chomp
|
709
|
+
end
|
710
|
+
|
711
|
+
def to_html
|
712
|
+
io = StringIO.new
|
713
|
+
io.puts "CATimeIndex: rows#=#{elements()}<br>"
|
714
|
+
io.puts "timestep = " + @timestep.definition + "<br>"
|
715
|
+
body = CADataFrame.new({element: self.int64, "time value": time})
|
716
|
+
io.puts body.to_html.each_line.to_a[1..-1]
|
717
|
+
return io.string.chomp
|
718
|
+
end
|
719
|
+
|
720
|
+
["shift"].each do |method_name|
|
721
|
+
class_eval %{
|
722
|
+
def #{method_name} (*args)
|
723
|
+
return CATimeIndex.from_index_array(super, @timestep)
|
724
|
+
end
|
725
|
+
}
|
726
|
+
end
|
727
|
+
|
728
|
+
def marshal_dump()
|
729
|
+
return [self.int64, @timestep]
|
730
|
+
end
|
731
|
+
|
732
|
+
def marshal_load (data)
|
733
|
+
index, timestep = *data
|
734
|
+
initialize(timestep) { index}
|
735
|
+
end
|
736
|
+
|
737
|
+
end
|
metadata
ADDED
@@ -0,0 +1,67 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: carray-timeindex
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.9.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Hiroki Motoyoshi
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2020-07-05 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: carray
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '1.3'
|
20
|
+
- - ">="
|
21
|
+
- !ruby/object:Gem::Version
|
22
|
+
version: 1.3.8
|
23
|
+
type: :runtime
|
24
|
+
prerelease: false
|
25
|
+
version_requirements: !ruby/object:Gem::Requirement
|
26
|
+
requirements:
|
27
|
+
- - "~>"
|
28
|
+
- !ruby/object:Gem::Version
|
29
|
+
version: '1.3'
|
30
|
+
- - ">="
|
31
|
+
- !ruby/object:Gem::Version
|
32
|
+
version: 1.3.8
|
33
|
+
description: " TimeIndex in Ruby\n"
|
34
|
+
email: ''
|
35
|
+
executables: []
|
36
|
+
extensions: []
|
37
|
+
extra_rdoc_files: []
|
38
|
+
files:
|
39
|
+
- README.md
|
40
|
+
- Rakefile
|
41
|
+
- carray-timeindex.gemspec
|
42
|
+
- lib/carray-timeindex.rb
|
43
|
+
- lib/carray-timeindex/core.rb
|
44
|
+
homepage: https://github.com/himotoyoshi/carray-timeindex
|
45
|
+
licenses: []
|
46
|
+
metadata: {}
|
47
|
+
post_install_message:
|
48
|
+
rdoc_options: []
|
49
|
+
require_paths:
|
50
|
+
- lib
|
51
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
52
|
+
requirements:
|
53
|
+
- - ">="
|
54
|
+
- !ruby/object:Gem::Version
|
55
|
+
version: 2.4.1
|
56
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
57
|
+
requirements:
|
58
|
+
- - ">="
|
59
|
+
- !ruby/object:Gem::Version
|
60
|
+
version: '0'
|
61
|
+
requirements: []
|
62
|
+
rubyforge_project:
|
63
|
+
rubygems_version: 2.7.6
|
64
|
+
signing_key:
|
65
|
+
specification_version: 4
|
66
|
+
summary: TimeIndex in Ruby
|
67
|
+
test_files: []
|