carray-timeindex 0.9.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -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: []