timesteps 0.9.3 → 0.9.5
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 +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
|