timesteps 0.9.3 → 0.9.5
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/Note.ja.md +14 -0
- data/README.md +277 -25
- data/lib/timesteps.rb +6 -3
- data/lib/timesteps/calendar.rb +31 -18
- data/lib/timesteps/datetime_360day.rb +38 -0
- data/lib/timesteps/datetime_allleap.rb +34 -0
- data/lib/timesteps/datetime_noleap.rb +39 -0
- data/lib/timesteps/datetimelike.rb +0 -104
- data/lib/timesteps/parse_timestamp.rb +56 -41
- data/lib/timesteps/timestep.rb +154 -53
- data/lib/timesteps/{timestepconverter.rb → timestep_converter.rb} +38 -8
- data/lib/timesteps/{timestepdatetimeext.rb → timestep_datetime_ext.rb} +1 -1
- data/lib/timesteps/{timesteppair.rb → timestep_pair.rb} +28 -54
- data/spec/allleap_spec.rb +5 -5
- data/spec/fixed360day_spec.rb +5 -5
- data/spec/noleap_spec.rb +5 -5
- data/spec/timestep_spec.rb +56 -0
- data/spec/timesteppair_spec.rb +0 -1
- data/timesteps.gemspec +8 -5
- metadata +16 -9
@@ -0,0 +1,34 @@
|
|
1
|
+
class DateTime
|
2
|
+
|
3
|
+
# datetime class represents `allleap` or `366_day` calendar
|
4
|
+
#
|
5
|
+
class AllLeap < DateTimeLike
|
6
|
+
|
7
|
+
extend DateTimeLikeExtension
|
8
|
+
|
9
|
+
# Number of days per year
|
10
|
+
DPY = 366
|
11
|
+
|
12
|
+
# Numbers of days per months
|
13
|
+
DPM = [0,31,29,31,30,31,30,31,31,30,31,30,31]
|
14
|
+
|
15
|
+
# Astronomical Julian day number of UNIX epoch
|
16
|
+
UNIX_EPOCH_IN_AJD = Rational(4891223,2)
|
17
|
+
|
18
|
+
def valid_date?
|
19
|
+
if @month != 2
|
20
|
+
return Date.valid_date?(@year, @month, @day)
|
21
|
+
else
|
22
|
+
return ( @day >= 1 and @day <= 29 )
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
private :valid_date?
|
27
|
+
|
28
|
+
def leap?
|
29
|
+
true
|
30
|
+
end
|
31
|
+
|
32
|
+
end
|
33
|
+
|
34
|
+
end
|
@@ -0,0 +1,39 @@
|
|
1
|
+
|
2
|
+
class DateTime
|
3
|
+
|
4
|
+
# datetime class represents `noleap` or `365_day` calendar
|
5
|
+
#
|
6
|
+
class NoLeap < DateTimeLike
|
7
|
+
|
8
|
+
extend DateTimeLikeExtension
|
9
|
+
|
10
|
+
# Number of days per year
|
11
|
+
DPY = 365
|
12
|
+
|
13
|
+
# Numbers of days per months
|
14
|
+
DPM = [0,31,28,31,30,31,30,31,31,30,31,30,31]
|
15
|
+
|
16
|
+
# Astronomical Julian day number of UNIX epoch
|
17
|
+
UNIX_EPOCH_IN_AJD = Rational(4877859,2)
|
18
|
+
|
19
|
+
def valid_date?
|
20
|
+
if @month != 2
|
21
|
+
return Date.valid_date?(@year, @month, @day)
|
22
|
+
else
|
23
|
+
return ( @day >= 1 and @day <= 28 )
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
private :valid_date?
|
28
|
+
|
29
|
+
def strftime (spec)
|
30
|
+
DateTime.new(@year, @month, @day, @hour, @minute, @second, @offset).strftime(spec)
|
31
|
+
end
|
32
|
+
|
33
|
+
def leap?
|
34
|
+
false
|
35
|
+
end
|
36
|
+
|
37
|
+
end
|
38
|
+
|
39
|
+
end
|
@@ -424,107 +424,3 @@ class DateTimeLike
|
|
424
424
|
|
425
425
|
end
|
426
426
|
|
427
|
-
class DateTime
|
428
|
-
|
429
|
-
# datetime class represents `noleap` or `365_day` calendar
|
430
|
-
#
|
431
|
-
class NoLeap < DateTimeLike
|
432
|
-
|
433
|
-
extend DateTimeLikeExtension
|
434
|
-
|
435
|
-
# Number of days per year
|
436
|
-
DPY = 365
|
437
|
-
|
438
|
-
# Numbers of days per months
|
439
|
-
DPM = [0,31,28,31,30,31,30,31,31,30,31,30,31]
|
440
|
-
|
441
|
-
# Astronomical Julian day number of UNIX epoch
|
442
|
-
UNIX_EPOCH_IN_AJD = Rational(4877859,2)
|
443
|
-
|
444
|
-
def valid_date?
|
445
|
-
if @month != 2
|
446
|
-
return Date.valid_date?(@year, @month, @day)
|
447
|
-
else
|
448
|
-
return ( @day >= 1 and @day <= 28 )
|
449
|
-
end
|
450
|
-
end
|
451
|
-
|
452
|
-
private :valid_date?
|
453
|
-
|
454
|
-
def strftime (spec)
|
455
|
-
DateTime.new(@year, @month, @day, @hour, @minute, @second, @offset).strftime(spec)
|
456
|
-
end
|
457
|
-
|
458
|
-
def leap?
|
459
|
-
false
|
460
|
-
end
|
461
|
-
|
462
|
-
end
|
463
|
-
|
464
|
-
# datetime class represents `allleap` or `366_day` calendar
|
465
|
-
#
|
466
|
-
class AllLeap < DateTimeLike
|
467
|
-
|
468
|
-
extend DateTimeLikeExtension
|
469
|
-
|
470
|
-
# Number of days per year
|
471
|
-
DPY = 366
|
472
|
-
|
473
|
-
# Numbers of days per months
|
474
|
-
DPM = [0,31,29,31,30,31,30,31,31,30,31,30,31]
|
475
|
-
|
476
|
-
# Astronomical Julian day number of UNIX epoch
|
477
|
-
UNIX_EPOCH_IN_AJD = Rational(4891223,2)
|
478
|
-
|
479
|
-
def valid_date?
|
480
|
-
if @month != 2
|
481
|
-
return Date.valid_date?(@year, @month, @day)
|
482
|
-
else
|
483
|
-
return ( @day >= 1 and @day <= 29 )
|
484
|
-
end
|
485
|
-
end
|
486
|
-
|
487
|
-
private :valid_date?
|
488
|
-
|
489
|
-
def leap?
|
490
|
-
true
|
491
|
-
end
|
492
|
-
|
493
|
-
end
|
494
|
-
|
495
|
-
# datetime class represents `360_day` calendar
|
496
|
-
#
|
497
|
-
class Fixed360Day < DateTimeLike
|
498
|
-
|
499
|
-
extend DateTimeLikeExtension
|
500
|
-
|
501
|
-
# Number of days per year
|
502
|
-
DPY = 360
|
503
|
-
|
504
|
-
# Numbers of days per months
|
505
|
-
DPM = [0,30,30,30,30,30,30,30,30,30,30,30,30]
|
506
|
-
|
507
|
-
# Astronomical Julian day number of UNIX epoch
|
508
|
-
UNIX_EPOCH_IN_AJD = Rational(4811039,2)
|
509
|
-
|
510
|
-
def valid_date?
|
511
|
-
if @day >= 31
|
512
|
-
return false
|
513
|
-
end
|
514
|
-
if @month != 2
|
515
|
-
return Date.valid_date?(@year, @month, @day)
|
516
|
-
else
|
517
|
-
return ( @day >= 1 and @day <= 30 )
|
518
|
-
end
|
519
|
-
end
|
520
|
-
|
521
|
-
private :valid_date?
|
522
|
-
|
523
|
-
def leap?
|
524
|
-
raise NotImplementedError
|
525
|
-
end
|
526
|
-
|
527
|
-
end
|
528
|
-
|
529
|
-
end
|
530
|
-
|
@@ -1,48 +1,63 @@
|
|
1
1
|
class DateTime
|
2
2
|
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
3
|
+
# @private
|
4
|
+
SYM_365_day = "365_day".intern
|
5
|
+
# @private
|
6
|
+
SYM_366_day = "366_day".intern
|
7
|
+
# @private
|
8
|
+
SYM_360_day = "360_day".intern
|
9
|
+
|
10
|
+
# Parses the given datetime expression and creates an instance.
|
11
|
+
# `DateTime._parse()` is called internally.
|
12
|
+
#
|
13
|
+
# @param spec [String]
|
14
|
+
# @option bc [Boolean]
|
15
|
+
#
|
16
|
+
# @return [DateTimeFixedDPY]
|
17
|
+
|
18
|
+
def self.parse_timestamp (spec, calendar: "standard", bc: false, format: nil)
|
19
|
+
raise "invalid option 'calendar'" if self != DateTime
|
20
|
+
case calendar.downcase.intern
|
21
|
+
when :standard, :gregorian
|
22
|
+
klass = DateTime
|
23
|
+
start = Date::ITALY
|
24
|
+
when :proleptic_gregorian
|
25
|
+
klass = DateTime
|
26
|
+
start = Date::GREGORIAN
|
27
|
+
when :proleptic_julian, :julian
|
28
|
+
klass = DateTime
|
29
|
+
start = Date::JULIAN
|
30
|
+
when :noleap, SYM_365_day
|
31
|
+
klass = DateTime::NoLeap
|
32
|
+
start = nil
|
33
|
+
when :allleap, SYM_366_day
|
34
|
+
klass = DateTime::AllLeap
|
35
|
+
start = nil
|
36
|
+
when SYM_360_day
|
37
|
+
klass = DateTime::Fixed360Day
|
38
|
+
start = nil
|
39
|
+
end
|
40
|
+
if format
|
41
|
+
hash = DateTime._strptime(spec, format)
|
42
|
+
raise "timestring doesn't match with format" unless hash
|
43
|
+
else
|
14
44
|
hash = DateTime._parse(spec)
|
15
|
-
year, month, day, hour, minute, second, sec_fraction, offset =
|
16
|
-
hash.values_at(:year, :mon, :mday, :hour, :min, :sec, :sec_fraction, :offset)
|
17
|
-
if bc and year < 0
|
18
|
-
year = year + 1
|
19
|
-
end
|
20
|
-
hour ||= 0
|
21
|
-
minute ||= 0
|
22
|
-
second ||= 0.0
|
23
|
-
sec_fraction ||= 0.0
|
24
|
-
offset ||= 0
|
25
|
-
if hour == 24 && minute == 0 && second == 0.0
|
26
|
-
self.new(year, month, day, 23, minute, second + sec_fraction, offset.quo(86400), start) + 1.quo(24)
|
27
|
-
else
|
28
|
-
self.new(year, month, day, hour, minute, second + sec_fraction, offset.quo(86400), start)
|
29
|
-
end
|
30
45
|
end
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
+
year, month, day, hour, minute, second, sec_fraction, offset =
|
47
|
+
hash.values_at(:year, :mon, :mday, :hour, :min, :sec, :sec_fraction, :offset)
|
48
|
+
if bc and year < 0
|
49
|
+
year = year + 1
|
50
|
+
end
|
51
|
+
hour ||= 0
|
52
|
+
minute ||= 0
|
53
|
+
second ||= 0.0
|
54
|
+
sec_fraction ||= 0.0
|
55
|
+
offset ||= 0
|
56
|
+
if hour == 24 && minute == 0 && second == 0.0
|
57
|
+
klass.new(year, month, day, 23, minute, second + sec_fraction, offset.quo(86400), start) + 1.quo(24)
|
58
|
+
else
|
59
|
+
klass.new(year, month, day, hour, minute, second + sec_fraction, offset.quo(86400), start)
|
60
|
+
end
|
46
61
|
end
|
47
62
|
|
48
63
|
end
|
data/lib/timesteps/timestep.rb
CHANGED
@@ -13,12 +13,19 @@ class TimeStep
|
|
13
13
|
# * "3 days since 2001-01-01 00:00:00 +00:00"
|
14
14
|
# * "10 years since 1901-01-01 00:00:00 +00:00"
|
15
15
|
# The symbol for time unit symbols should be one of
|
16
|
+
# * ayears, ayear (astronomical year: 365.242198781 day)
|
16
17
|
# * years, year
|
17
18
|
# * months, month
|
18
19
|
# * days, day, d
|
19
|
-
# * hours, hr, h
|
20
|
-
# * minutes, minute, min
|
21
|
-
# * seconds, second, sec, s
|
20
|
+
# * hours, hour, hrs, hr, h
|
21
|
+
# * minutes, minute, mins, min
|
22
|
+
# * seconds, second, secs, sec, s
|
23
|
+
# * milliseconds, millisecond, msecs, msec, ms
|
24
|
+
# * microseconds, microsecond, msecs, msec, ms
|
25
|
+
# If you have already origin time object or general date string,
|
26
|
+
# you can use `since` option,
|
27
|
+
# TimeStep.new("3 hours", since: time)
|
28
|
+
# TimeStep.new("3 hours", since: "2001010121", format: '%Y%m%d%H')
|
22
29
|
# The option `calendar` specifies the calendar for datetime calculation,
|
23
30
|
# * standard, gregorian -> DateTime with Date::ITALY as start
|
24
31
|
# * proleptic_gregorian -> DateTime with Date::GREGORIAN as start
|
@@ -32,30 +39,43 @@ class TimeStep
|
|
32
39
|
# some methods (#each etc).
|
33
40
|
#
|
34
41
|
# @param spec [String]
|
42
|
+
# @option since [DateTime, DateTimeLike, String]
|
43
|
+
# @option format [String]
|
35
44
|
# @option calendar [String, TimeStep::Calendar]
|
36
45
|
# @option bc [Boolean]
|
37
46
|
# @option count [Integer] number of time steps (as hint for some methods)
|
38
47
|
#
|
39
|
-
def initialize (spec, calendar: "standard", bc: false
|
48
|
+
def initialize (spec, since: nil, format: nil, count: nil, calendar: "standard", bc: false)
|
40
49
|
case calendar
|
41
50
|
when String
|
42
51
|
@calendar = Calendar.new(calendar, bc: bc)
|
43
52
|
else
|
44
53
|
@calendar = calendar
|
45
54
|
end
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
55
|
+
if since
|
56
|
+
parse_interval(spec)
|
57
|
+
case since
|
58
|
+
when String
|
59
|
+
@origin = @calendar.parse(since, format: format)
|
60
|
+
else
|
61
|
+
raise "mismatch time object with calendar" unless @calendar.valid_datetime_type?(since)
|
62
|
+
@origin = since
|
63
|
+
end
|
64
|
+
else
|
65
|
+
intervalspec, originspec = spec.split(/\s+since\s+/)
|
66
|
+
parse_interval(intervalspec)
|
67
|
+
@origin = @calendar.parse(originspec)
|
68
|
+
end
|
69
|
+
@intervalspec = format("%g %s", @numeric, @symbol)
|
70
|
+
@originspec = @origin.strftime("%Y-%m-%d %H:%M:%S.%N %:z")
|
71
|
+
@definition = format("%s since %s", @intervalspec, @originspec)
|
52
72
|
@count = count
|
53
73
|
end
|
54
74
|
|
55
75
|
# @private
|
56
76
|
PATTERN_NUMERIC = '[\+\-]?\d*(?:\.\d+)?(?:[eE][\+\-]?\d+)?'
|
57
77
|
# @private
|
58
|
-
PATTERN_UNITS = 'years?|months?|days?|hours?|minutes?|seconds?|d|
|
78
|
+
PATTERN_UNITS = 'ayears?|years?|months?|days?|hours?|minutes?|seconds?|d|hrs?|hrs?|h|mins?|secs?|s|milliseconds?|msecs?|ms|microseconds?'
|
59
79
|
|
60
80
|
def parse_interval (spec)
|
61
81
|
if spec.strip =~ /(#{PATTERN_NUMERIC}|)\s*(#{PATTERN_UNITS})/
|
@@ -70,29 +90,39 @@ class TimeStep
|
|
70
90
|
end
|
71
91
|
@interval = @numeric
|
72
92
|
case symbol
|
73
|
-
when
|
93
|
+
when /\Aayears?/
|
94
|
+
@symbol = :days
|
95
|
+
@numeric *= 365.242198781.to_r
|
96
|
+
@interval = @numeric * 86400
|
97
|
+
when /\Ayears?/
|
74
98
|
unless numeric.denominator == 1
|
75
99
|
raise "numeric factor for year should be an integer"
|
76
100
|
end
|
77
101
|
@symbol = :years
|
78
102
|
@interval *= 356.242*86400
|
79
|
-
when
|
103
|
+
when /\Amonths?/
|
80
104
|
unless numeric.denominator == 1
|
81
105
|
raise "numeric factor for month should be an integer"
|
82
106
|
end
|
83
107
|
@symbol = :months
|
84
108
|
@interval *= 30.4368*86400
|
85
|
-
when
|
109
|
+
when /\A(days?|d)/
|
86
110
|
@symbol = :days
|
87
111
|
@interval *= 86400
|
88
|
-
when
|
112
|
+
when /\A(hours?|hrs?|h)/
|
89
113
|
@symbol = :hours
|
90
114
|
@interval *= 3600
|
91
|
-
when
|
115
|
+
when /\A(minutes?|mins?)/
|
92
116
|
@symbol = :minutes
|
93
117
|
@interval *= 60
|
94
|
-
when
|
118
|
+
when /\A(seconds?|secs?|s)/
|
95
119
|
@symbol = :seconds
|
120
|
+
when /\A(milliseconds?|msecs?|ms)/
|
121
|
+
@symbol = :seconds
|
122
|
+
@interval *= 1.quo(1000)
|
123
|
+
when /\Amicroseconds?/
|
124
|
+
@symbol = :seconds
|
125
|
+
@interval *= 1.quo(1000000)
|
96
126
|
end
|
97
127
|
end
|
98
128
|
|
@@ -100,7 +130,7 @@ class TimeStep
|
|
100
130
|
|
101
131
|
attr_reader :definition,
|
102
132
|
:intervalspec,
|
103
|
-
:
|
133
|
+
:originspec,
|
104
134
|
:numeric,
|
105
135
|
:symbol,
|
106
136
|
:interval,
|
@@ -131,6 +161,14 @@ class TimeStep
|
|
131
161
|
end
|
132
162
|
return limit
|
133
163
|
end
|
164
|
+
|
165
|
+
def set_limit (time, format: nil)
|
166
|
+
case time
|
167
|
+
when String
|
168
|
+
time = @calendar.parse(time, format: format)
|
169
|
+
end
|
170
|
+
self.limit = time
|
171
|
+
end
|
134
172
|
|
135
173
|
def valid? (*indices)
|
136
174
|
if @count
|
@@ -153,11 +191,11 @@ class TimeStep
|
|
153
191
|
end
|
154
192
|
end
|
155
193
|
|
156
|
-
def
|
194
|
+
def debug_info
|
157
195
|
return {
|
158
196
|
"definition" => @definition.clone,
|
159
197
|
"intervalspec" => @intervalspec.clone,
|
160
|
-
"
|
198
|
+
"originspec" => @originspec.clone,
|
161
199
|
"calendar" => @calendar.name,
|
162
200
|
"numeric" => @numeric,
|
163
201
|
"symbol" => @symbol.to_s,
|
@@ -168,6 +206,10 @@ class TimeStep
|
|
168
206
|
}
|
169
207
|
end
|
170
208
|
|
209
|
+
private :debug_info
|
210
|
+
|
211
|
+
# Returns the value as a string for inspection.
|
212
|
+
#
|
171
213
|
def inspect
|
172
214
|
"#<TimeStep definition='#{definition}' calendar='#{calendar.name}'>"
|
173
215
|
end
|
@@ -188,6 +230,8 @@ class TimeStep
|
|
188
230
|
return ( 86400 * index.to_r ).quo(@interval)
|
189
231
|
end
|
190
232
|
|
233
|
+
private :user_to_days, :days_to_user
|
234
|
+
|
191
235
|
# Returns the time represented by the given amount as DateTime object
|
192
236
|
#
|
193
237
|
# @param indices [Numeric,Array<Numeric>]
|
@@ -220,58 +264,110 @@ class TimeStep
|
|
220
264
|
end
|
221
265
|
end
|
222
266
|
|
267
|
+
# Calculate the time difference in days from origin at the index.
|
268
|
+
#
|
269
|
+
# @param indices [Array]
|
270
|
+
# @return [DateTime, Array<DateTime>]
|
271
|
+
def days_at (*indices)
|
272
|
+
if indices.size == 1
|
273
|
+
index = indices.first
|
274
|
+
case @symbol
|
275
|
+
when :years
|
276
|
+
unless index.denominator == 1
|
277
|
+
raise "index for years should be an integer"
|
278
|
+
end
|
279
|
+
days = @origin.next_year(@numeric*index) - @origin
|
280
|
+
when :months
|
281
|
+
unless index.denominator == 1
|
282
|
+
raise "index for years should be an integer"
|
283
|
+
end
|
284
|
+
days = @origin.next_month(@numeric*index) - @origin
|
285
|
+
else
|
286
|
+
days = user_to_days(index)
|
287
|
+
end
|
288
|
+
days = days.to_i if days.denominator == 1
|
289
|
+
return days
|
290
|
+
else
|
291
|
+
return indices.map{ |index| days_at(index) }
|
292
|
+
end
|
293
|
+
end
|
294
|
+
|
223
295
|
# Returns the index for the given time in the unit represented by the object
|
224
296
|
#
|
225
297
|
# @param times [DateTime] time object
|
226
298
|
#
|
227
299
|
# @return [Numeric]
|
228
|
-
def index_at (*times)
|
300
|
+
def index_at (*times, format: nil)
|
229
301
|
if times.size == 1
|
230
302
|
time = times.first
|
231
|
-
time = @calendar.parse(time) if time.is_a?(String)
|
303
|
+
time = @calendar.parse(time, format: format) if time.is_a?(String)
|
232
304
|
case @symbol
|
233
305
|
when :years
|
234
|
-
|
306
|
+
index = time.difference_in_years(@origin).quo(@numeric.to_i)
|
235
307
|
when :months
|
236
|
-
|
308
|
+
index = time.difference_in_months(@origin).quo(@numeric.to_i)
|
237
309
|
else
|
238
310
|
jday = @calendar.date2jday(time.year, time.month, time.day)
|
239
|
-
fday = time.fraction
|
311
|
+
fday = time.fraction
|
240
312
|
udays = days_to_user(jday - @origin.jd)
|
241
|
-
utime = days_to_user(
|
242
|
-
|
313
|
+
utime = days_to_user(time.fraction - time.offset - (@origin.fraction - @origin.offset))
|
314
|
+
index = udays + utime
|
243
315
|
end
|
316
|
+
index = index.to_i if index.denominator == 1
|
317
|
+
return index
|
244
318
|
else
|
245
|
-
return times.map{|time| index_at(time) }
|
319
|
+
return times.map{|time| index_at(time, format: format) }
|
246
320
|
end
|
247
321
|
end
|
248
322
|
|
249
|
-
|
250
|
-
|
251
|
-
|
252
|
-
|
253
|
-
|
254
|
-
if
|
255
|
-
|
256
|
-
|
257
|
-
|
258
|
-
|
259
|
-
|
323
|
+
def range (ge: nil, gt: nil, lt: nil, le: nil)
|
324
|
+
raise "lower limit is not given" if ge.nil? and gt.nil?
|
325
|
+
raise "upper limit is not given" if lt.nil? and le.nil?
|
326
|
+
raise "lower limits are duplicated" if ge and gt
|
327
|
+
raise "upper limits are duplicated" if lt and le
|
328
|
+
if ge
|
329
|
+
case ge
|
330
|
+
when Numeric
|
331
|
+
min = ge.floor
|
332
|
+
else
|
333
|
+
min = prev_index_of(ge)
|
334
|
+
end
|
335
|
+
end
|
336
|
+
if gt
|
337
|
+
case gt
|
338
|
+
when Numeric
|
339
|
+
if lt.to_r.denominator == 1
|
340
|
+
min = gt.to_i + 1
|
341
|
+
else
|
342
|
+
min = gt.ceil
|
260
343
|
end
|
261
|
-
|
262
|
-
|
263
|
-
|
264
|
-
|
344
|
+
else
|
345
|
+
min = next_index_of(gt)
|
346
|
+
end
|
347
|
+
end
|
348
|
+
if lt
|
349
|
+
case lt
|
350
|
+
when Numeric
|
351
|
+
if lt.to_r.denominator == 1
|
352
|
+
max = lt.to_i - 1
|
353
|
+
else
|
354
|
+
max = lt.floor
|
265
355
|
end
|
266
|
-
return @origin.next_month(@numeric*index) - @origin
|
267
356
|
else
|
268
|
-
|
357
|
+
max = prev_index_of(lt)
|
269
358
|
end
|
270
|
-
else
|
271
|
-
return indices.map{ |index| days_at(index) }
|
272
359
|
end
|
360
|
+
if le
|
361
|
+
case le
|
362
|
+
when Numeric
|
363
|
+
max = le.ceil
|
364
|
+
else
|
365
|
+
max = next_index_of(le)
|
366
|
+
end
|
367
|
+
end
|
368
|
+
return (min..max).to_a
|
273
369
|
end
|
274
|
-
|
370
|
+
|
275
371
|
# Returns TimeStep object which has origin time determined
|
276
372
|
# by the given `index`.
|
277
373
|
#
|
@@ -280,7 +376,12 @@ class TimeStep
|
|
280
376
|
# @return [TimeStep]
|
281
377
|
def shift_origin (index)
|
282
378
|
time = time_at(index)
|
283
|
-
return TimeStep.new(@intervalspec
|
379
|
+
return TimeStep.new(@intervalspec, since: time, calendar: @calendar)
|
380
|
+
end
|
381
|
+
|
382
|
+
def shift_origin_with_days (days)
|
383
|
+
time = @origin + days
|
384
|
+
return TimeStep.new(@intervalspec, since: time, calendar: @calendar)
|
284
385
|
end
|
285
386
|
|
286
387
|
# Returns TimeStep object which has origin time specified
|
@@ -326,7 +427,7 @@ class TimeStep
|
|
326
427
|
#
|
327
428
|
#
|
328
429
|
def in (unit)
|
329
|
-
return TimeStep::Pair.new(self, format("%s since %s", unit, @
|
430
|
+
return TimeStep::Pair.new(self, format("%s since %s", unit, @originspec), calendar: @calendar)
|
330
431
|
end
|
331
432
|
|
332
433
|
def next_index_of (time)
|
@@ -336,7 +437,7 @@ class TimeStep
|
|
336
437
|
end
|
337
438
|
index = index_at(time).to_r
|
338
439
|
if index.denominator == 1
|
339
|
-
return index + 1
|
440
|
+
return index.to_i + 1
|
340
441
|
else
|
341
442
|
return index.ceil
|
342
443
|
end
|
@@ -354,8 +455,8 @@ class TimeStep
|
|
354
455
|
return time_at(prev_index_of(time))
|
355
456
|
end
|
356
457
|
|
357
|
-
def parse (time)
|
358
|
-
return @calendar.parse(time)
|
458
|
+
def parse (time, format: nil)
|
459
|
+
return @calendar.parse(time, format: format)
|
359
460
|
end
|
360
461
|
|
361
462
|
end
|