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.
@@ -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
@@ -0,0 +1,2 @@
1
+ carray-timeindex
2
+ ================
@@ -0,0 +1,11 @@
1
+ GEMSPEC = "carray-timeindex.gemspec"
2
+
3
+ task :install do
4
+ spec = eval File.read(GEMSPEC)
5
+ system %{
6
+ gem build #{GEMSPEC}; gem install #{spec.full_name}.gem
7
+ }
8
+ end
9
+
10
+ require 'rspec/core/rake_task'
11
+ RSpec::Core::RakeTask.new
@@ -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,2 @@
1
+ require "timesteps"
2
+ require "carray-timeindex/core"
@@ -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: []