timesteps 0.9.6 → 1.0.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.yardopts +1 -0
- data/{LICENSES → LICENSE} +0 -0
- data/NEWS.md +8 -0
- data/Note.ja.md +9 -0
- data/README.md +15 -7
- data/lib/timesteps/datetime_parse_timestamp.rb +21 -12
- data/lib/timesteps/datetime_timestep.rb +64 -0
- data/lib/timesteps/datetimelike.rb +6 -17
- data/lib/timesteps/grads.rb +39 -18
- data/lib/timesteps/time.rb +14 -0
- data/lib/timesteps/timeperiod.rb +50 -47
- data/lib/timesteps/timestep.rb +480 -248
- data/lib/timesteps/timestep_calendar.rb +49 -29
- data/lib/timesteps/timestep_converter.rb +19 -22
- data/lib/timesteps/timestep_datetime_ext.rb +6 -16
- data/lib/timesteps/timestep_pair.rb +37 -24
- data/lib/timesteps/timestep_query.rb +12 -4
- data/lib/timesteps/timestep_range.rb +155 -0
- data/lib/timesteps.rb +4 -0
- data/spec/allleap_spec.rb +4 -15
- data/spec/fixed360day_spec.rb +4 -15
- data/spec/noleap_spec.rb +2 -13
- data/spec/timestep_spec.rb +4 -27
- data/timesteps.gemspec +3 -3
- metadata +9 -4
@@ -1,4 +1,6 @@
|
|
1
1
|
|
2
|
+
autoload :TZInfo, "tzinfo"
|
3
|
+
|
2
4
|
class TimeStep
|
3
5
|
|
4
6
|
class Calendar
|
@@ -23,12 +25,11 @@ class TimeStep
|
|
23
25
|
|
24
26
|
# Construct the object
|
25
27
|
#
|
26
|
-
def initialize (calendar = "standard",
|
28
|
+
def initialize (calendar = "standard", tz: nil)
|
27
29
|
unless calendar.is_a?(String)
|
28
30
|
raise ArgumentError, "argument calendar '#{calendar}' should be string"
|
29
31
|
end
|
30
32
|
@name = calendar
|
31
|
-
@bc = bc
|
32
33
|
case @name.downcase.intern
|
33
34
|
when :standard, :gregorian
|
34
35
|
@calendar = :standard
|
@@ -43,22 +44,30 @@ class TimeStep
|
|
43
44
|
when SYM_360_day
|
44
45
|
@calendar = SYM_360_day
|
45
46
|
end
|
47
|
+
if tz
|
48
|
+
raise "'standard' calendar needed for tz" unless @calendar == :standard
|
49
|
+
case tz
|
50
|
+
when nil
|
51
|
+
when String
|
52
|
+
@tz = TZInfo::Timezone.get(tz)
|
53
|
+
when TZInfo::Timezone
|
54
|
+
@tz = tz
|
55
|
+
else
|
56
|
+
raise "invalid tz specification"
|
57
|
+
end
|
58
|
+
end
|
46
59
|
end
|
47
60
|
|
48
|
-
attr_reader :name, :calendar
|
49
|
-
|
61
|
+
attr_reader :name, :calendar, :tz
|
62
|
+
|
50
63
|
def inspect
|
51
|
-
"#<TimeStep::Calendar calendar='#{@calendar.to_s}'
|
64
|
+
"#<TimeStep::Calendar calendar='#{@calendar.to_s}'>"
|
52
65
|
end
|
53
66
|
|
54
67
|
def == (other)
|
55
|
-
return @calendar == other.calendar
|
56
|
-
end
|
57
|
-
|
58
|
-
def bc?
|
59
|
-
return @bc ? true : false
|
68
|
+
return @calendar == other.calendar
|
60
69
|
end
|
61
|
-
|
70
|
+
|
62
71
|
def valid_datetime_type? (time)
|
63
72
|
return false unless time.is_a?(DateTimeType[@calendar])
|
64
73
|
case @calendar
|
@@ -77,10 +86,31 @@ class TimeStep
|
|
77
86
|
# and creates an date time instance.
|
78
87
|
#
|
79
88
|
# @return [DateTime object]
|
80
|
-
def parse (timespec, format: nil)
|
81
|
-
return DateTime.parse_timestamp(timespec, calendar: @calendar.to_s,
|
89
|
+
def parse (timespec, format: nil, offset: nil)
|
90
|
+
return DateTime.parse_timestamp(timespec, calendar: @calendar.to_s, format: format, tz: @tz, offset: offset)
|
82
91
|
end
|
83
|
-
|
92
|
+
|
93
|
+
def time_new (year, month, day, hour=0, min=0, sec=0, offset=0)
|
94
|
+
case @calendar
|
95
|
+
when :standard
|
96
|
+
time = DateTime.new(year, month, day, hour, min, sec, offset, Date::ITALY)
|
97
|
+
when :proleptic_gregorian
|
98
|
+
time = DateTime.new(year, month, day, hour, min, sec, offset, Date::GREGORIAN)
|
99
|
+
when :proleptic_julian
|
100
|
+
time = DateTime.new(year, month, day, hour, min, sec, offset, Date::JULIAN)
|
101
|
+
when :noleap
|
102
|
+
time = DateTime::NoLeap.new(year, month, day, hour, min, sec, offset)
|
103
|
+
when :allleap
|
104
|
+
time = DateTime::AllLeap.new(year, month, day, hour, min, sec, offset)
|
105
|
+
when SYM_360_day
|
106
|
+
time = DateTime::Fixed360Day.new(year, month, day, hour, min, sec, offset)
|
107
|
+
end
|
108
|
+
if @tz
|
109
|
+
time = @tz.to_local(time)
|
110
|
+
end
|
111
|
+
return time
|
112
|
+
end
|
113
|
+
|
84
114
|
def jday2date (jday)
|
85
115
|
case @calendar
|
86
116
|
when :standard
|
@@ -96,27 +126,17 @@ class TimeStep
|
|
96
126
|
when SYM_360_day
|
97
127
|
time = DateTime::Fixed360Day.jd(jday, 0, 0, 0, 0)
|
98
128
|
end
|
129
|
+
if @tz
|
130
|
+
time = @tz.to_local(time)
|
131
|
+
end
|
99
132
|
return time
|
100
133
|
end
|
101
134
|
|
102
135
|
def date2jday (year, month, day)
|
103
|
-
|
104
|
-
when :standard
|
105
|
-
time = DateTime.new(year, month, day, 0, 0, 0, 0, Date::ITALY)
|
106
|
-
when :proleptic_gregorian
|
107
|
-
time = DateTime.new(year, month, day, 0, 0, 0, 0, Date::GREGORIAN)
|
108
|
-
when :proleptic_julian
|
109
|
-
time = DateTime.new(year, month, day, 0, 0, 0, 0, Date::JULIAN)
|
110
|
-
when :noleap
|
111
|
-
time = DateTime::NoLeap.new(year, month, day, 0, 0, 0, 0)
|
112
|
-
when :allleap
|
113
|
-
time = DateTime::AllLeap.new(year, month, day, 0, 0, 0, 0)
|
114
|
-
when SYM_360_day
|
115
|
-
time = DateTime::Fixed360Day.new(year, month, day, 0, 0, 0, 0)
|
116
|
-
end
|
117
|
-
return time.jd
|
136
|
+
return time_new(year, month, day).jd
|
118
137
|
end
|
119
138
|
|
120
139
|
end
|
121
140
|
|
122
141
|
end
|
142
|
+
|
@@ -2,12 +2,11 @@ require "timesteps"
|
|
2
2
|
|
3
3
|
class TimeStep::Converter
|
4
4
|
|
5
|
-
def initialize (reference, name: "reference", calendar: "standard"
|
5
|
+
def initialize (reference, name: "reference", calendar: "standard")
|
6
6
|
@calendar = calendar
|
7
|
-
@bc = bc
|
8
7
|
case reference
|
9
8
|
when String
|
10
|
-
@reference = TimeStep.new(reference, calendar: calendar
|
9
|
+
@reference = TimeStep.new(reference, calendar: calendar)
|
11
10
|
when TimeStep
|
12
11
|
@reference = reference
|
13
12
|
else
|
@@ -21,9 +20,9 @@ class TimeStep::Converter
|
|
21
20
|
# Append or reset new target time step for the given name.
|
22
21
|
#
|
23
22
|
def add_timestep (spec, name:)
|
24
|
-
@pair[name] = TimeStep::Pair.new(@reference, spec, calendar: @calendar
|
23
|
+
@pair[name] = TimeStep::Pair.new(@reference, spec, calendar: @calendar)
|
25
24
|
@target[name] = @pair[name].to
|
26
|
-
return @
|
25
|
+
return @pair[name]
|
27
26
|
end
|
28
27
|
|
29
28
|
# Append or reset new target time step for the given name.
|
@@ -35,14 +34,14 @@ class TimeStep::Converter
|
|
35
34
|
# Return target time step of the given name.
|
36
35
|
#
|
37
36
|
def [] (name)
|
38
|
-
return @
|
37
|
+
return @pair[name]
|
39
38
|
end
|
40
39
|
|
41
40
|
# Relete target of the given name.
|
42
41
|
#
|
43
42
|
def delete (name)
|
44
|
-
@pair.delete(name)
|
45
43
|
@target.delete(name)
|
44
|
+
@pair.delete(name)
|
46
45
|
end
|
47
46
|
|
48
47
|
# Returns the time represented by the given index as DateTime object
|
@@ -56,11 +55,18 @@ class TimeStep::Converter
|
|
56
55
|
|
57
56
|
# Converts index refering `from` timestep to index refering `to`timestep.
|
58
57
|
#
|
59
|
-
def forward (*indices, with_time:
|
58
|
+
def forward (*indices, with_time: nil)
|
60
59
|
if with_time
|
61
|
-
|
62
|
-
|
63
|
-
|
60
|
+
case with_time
|
61
|
+
when String
|
62
|
+
hash = {
|
63
|
+
"time" => time_at(*indices).map{|t| t.strftime(with_time) }
|
64
|
+
}
|
65
|
+
else
|
66
|
+
hash = {
|
67
|
+
"time" => time_at(*indices)
|
68
|
+
}
|
69
|
+
end
|
64
70
|
else
|
65
71
|
hash = {}
|
66
72
|
end
|
@@ -70,8 +76,8 @@ class TimeStep::Converter
|
|
70
76
|
return hash
|
71
77
|
end
|
72
78
|
|
73
|
-
def range (
|
74
|
-
indices = @reference.range(
|
79
|
+
def range (other, with_time: false)
|
80
|
+
indices = @reference.range(other)
|
75
81
|
return forward(*indices, with_time: with_time)
|
76
82
|
end
|
77
83
|
|
@@ -80,14 +86,5 @@ class TimeStep::Converter
|
|
80
86
|
return forward(*indices, with_time: with_time)
|
81
87
|
end
|
82
88
|
|
83
|
-
def valid? (*indices)
|
84
|
-
hash = {}
|
85
|
-
@pair.each do |name, conv|
|
86
|
-
hash[name] = conv.to.valid?(*conv.forward(*indices))
|
87
|
-
end
|
88
|
-
return hash
|
89
|
-
end
|
90
|
-
|
91
|
-
|
92
89
|
end
|
93
90
|
|
@@ -46,28 +46,18 @@ class TimeStep
|
|
46
46
|
#
|
47
47
|
# @return [Integer]
|
48
48
|
def difference_in_years (other)
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
end
|
53
|
-
if self.year < other.year && self.compare_md(other) > 0
|
54
|
-
extra = 1
|
55
|
-
end
|
56
|
-
return self.year - other.year + extra
|
49
|
+
my = self
|
50
|
+
other = other.new_offset(self.offset)
|
51
|
+
return my.year - other.year + my.compare_md(other).quo(2)
|
57
52
|
end
|
58
53
|
|
59
54
|
# Calculate difference between the object and other object in months.
|
60
55
|
#
|
61
56
|
# @return [Integer]
|
62
57
|
def difference_in_months (other)
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
end
|
67
|
-
if self.month < other.month && self.compare_d(other) > 0
|
68
|
-
extra = 1
|
69
|
-
end
|
70
|
-
return 12*(self.year - other.year) + self.month - other.month + extra
|
58
|
+
my = self
|
59
|
+
other = other.new_offset(self.offset)
|
60
|
+
return 12*(my.year - other.year) + my.month - other.month + my.compare_d(other).quo(2)
|
71
61
|
end
|
72
62
|
|
73
63
|
end
|
@@ -8,21 +8,19 @@ class TimeStep::Pair
|
|
8
8
|
# The `from` and `to` arguments are either TimeStep or a string representing
|
9
9
|
# the time step definition ("<INTERVAL> since <TIME>").
|
10
10
|
# If a string representing the time step definition is given as an argument
|
11
|
-
# `from` or `to`, the options `calendar`
|
11
|
+
# `from` or `to`, the options `calendar` are used to construct
|
12
12
|
# TimeStep. The option `calendar` specifies the calendar for datetime
|
13
|
-
# calculation.
|
14
|
-
# timestamp for negative year.
|
13
|
+
# calculation.
|
15
14
|
#
|
16
15
|
# @param from [TimeStep, String]
|
17
16
|
# @param to [TimeStep, String]
|
18
17
|
# @option calendar [String, TimeStep::Calendar]
|
19
|
-
# @option bc [Boolean]
|
20
18
|
#
|
21
|
-
def initialize (from, to, calendar: "standard"
|
19
|
+
def initialize (from, to, calendar: "standard")
|
22
20
|
|
23
21
|
case from
|
24
22
|
when String
|
25
|
-
@from = TimeStep.new(from, calendar: calendar
|
23
|
+
@from = TimeStep.new(from, calendar: calendar)
|
26
24
|
when TimeStep
|
27
25
|
@from = from
|
28
26
|
else
|
@@ -31,7 +29,7 @@ class TimeStep::Pair
|
|
31
29
|
|
32
30
|
case to
|
33
31
|
when String
|
34
|
-
@to = TimeStep.new(to, calendar: calendar
|
32
|
+
@to = TimeStep.new(to, calendar: calendar)
|
35
33
|
when TimeStep
|
36
34
|
@to = to
|
37
35
|
else
|
@@ -66,13 +64,17 @@ class TimeStep::Pair
|
|
66
64
|
"#<TimeStep::Pair from='#{from.inspect}' to='#{to.inspect}'>"
|
67
65
|
end
|
68
66
|
|
67
|
+
def invert
|
68
|
+
return TimeStep::Pair.new(@to, @from)
|
69
|
+
end
|
70
|
+
|
69
71
|
# Returns true if other has same contents of `from` and `to` as self has.
|
70
72
|
#
|
71
73
|
# @return [Boolean]
|
72
74
|
def == (other)
|
73
75
|
return @from == other.from && @to == other.to
|
74
76
|
end
|
75
|
-
|
77
|
+
|
76
78
|
# Returns the time represented by the given index as DateTime object
|
77
79
|
#
|
78
80
|
# @param indices [Numeric,Array<Numeric>]
|
@@ -85,10 +87,16 @@ class TimeStep::Pair
|
|
85
87
|
# Converts index refering `from` timestep to index refering `to`timestep.
|
86
88
|
#
|
87
89
|
def forward (*indices, &block)
|
88
|
-
if indices.size == 1
|
90
|
+
if indices.empty? || indices.size == 1 && indices.first.is_a?(Range)
|
91
|
+
return forward(*@from.range(*indices), &block)
|
92
|
+
elsif indices.size == 1
|
89
93
|
index = indices.first.to_r
|
90
94
|
if @numeric_conversion
|
91
|
-
|
95
|
+
if @to_interval == 0
|
96
|
+
value = 0
|
97
|
+
else
|
98
|
+
value = (index*@from_interval + @difference).quo(@to_interval)
|
99
|
+
end
|
92
100
|
else
|
93
101
|
case @from_symbol
|
94
102
|
when :years, :months
|
@@ -97,12 +105,14 @@ class TimeStep::Pair
|
|
97
105
|
target = @from_origin + index*(@from_interval.quo(86400))
|
98
106
|
end
|
99
107
|
case @to_symbol
|
100
|
-
when :years
|
101
|
-
|
108
|
+
when :years
|
109
|
+
diff = target.difference_in_years(@to_origin)
|
110
|
+
value = diff.quo(@to.numeric)
|
102
111
|
when :months
|
103
|
-
|
112
|
+
diff = target.difference_in_months(@to_origin)
|
113
|
+
value = diff.quo(@to.numeric)
|
104
114
|
else
|
105
|
-
value = (target.ajd - @to_origin.ajd).quo(@to_interval)
|
115
|
+
value = (target.ajd - @to_origin.ajd).quo(@to_interval)*86400
|
106
116
|
end
|
107
117
|
end
|
108
118
|
value = value.to_i if value.denominator == 1
|
@@ -126,18 +136,19 @@ class TimeStep::Pair
|
|
126
136
|
return forward(*indices) {|index| @to.time_at(index) }
|
127
137
|
end
|
128
138
|
|
129
|
-
def range (ge: nil, gt: nil, lt: nil, le: nil)
|
130
|
-
indices = @from.range(ge: ge, gt: gt, lt: lt, le: le)
|
131
|
-
return forward(*indices)
|
132
|
-
end
|
133
|
-
|
134
139
|
# Converts index refering `to` timestep to index refering `from` timestep.
|
135
140
|
#
|
136
141
|
def inverse (*indices, &block)
|
137
|
-
if indices.size == 1
|
142
|
+
if indices.empty? || indices.size == 1 && indices.first.is_a?(Range)
|
143
|
+
return inverse(*@to.range(*indices), &block)
|
144
|
+
elsif indices.size == 1
|
138
145
|
index = indices.first.to_r
|
139
146
|
if @numeric_conversion
|
140
|
-
|
147
|
+
if @from_interval == 0
|
148
|
+
value = 0
|
149
|
+
else
|
150
|
+
value = (index*@to_interval - @difference).quo(@from_interval)
|
151
|
+
end
|
141
152
|
else
|
142
153
|
case @to_symbol
|
143
154
|
when :years, :months
|
@@ -147,11 +158,13 @@ class TimeStep::Pair
|
|
147
158
|
end
|
148
159
|
case @from_symbol
|
149
160
|
when :years
|
150
|
-
|
161
|
+
diff = target.difference_in_years(@from_origin)
|
162
|
+
value = diff.quo(@from.numeric)
|
151
163
|
when :months
|
152
|
-
|
164
|
+
diff = target.difference_in_months(@from_origin)
|
165
|
+
value = diff.quo(@from.numeric)
|
153
166
|
else
|
154
|
-
value = (target.ajd - @from_origin.ajd).quo(@from_interval)
|
167
|
+
value = (target.ajd - @from_origin.ajd).quo(@from_interval)*86400
|
155
168
|
end
|
156
169
|
end
|
157
170
|
value = value.to_i if value.denominator == 1
|
@@ -4,11 +4,11 @@ class TimeStep::Query
|
|
4
4
|
|
5
5
|
def initialize (timestep, format: nil)
|
6
6
|
@timestep = timestep
|
7
|
-
@format =
|
7
|
+
@format = format
|
8
8
|
end
|
9
9
|
|
10
10
|
def __format__ (time)
|
11
|
-
return ( @
|
11
|
+
return ( @format.nil? ) ? time : time.strftime(@format)
|
12
12
|
end
|
13
13
|
|
14
14
|
private :__format__
|
@@ -19,7 +19,7 @@ class TimeStep::Query
|
|
19
19
|
|
20
20
|
def just_before_time_of (time)
|
21
21
|
idx = @timestep.index_at(time)
|
22
|
-
if idx.
|
22
|
+
if idx.denominator == 1
|
23
23
|
time0 = time
|
24
24
|
else
|
25
25
|
time0 = @timestep.time_at(idx.floor)
|
@@ -29,7 +29,7 @@ class TimeStep::Query
|
|
29
29
|
|
30
30
|
def just_after_time_of (time)
|
31
31
|
idx = @timestep.index_at(time)
|
32
|
-
if idx.
|
32
|
+
if idx.denominator == 1
|
33
33
|
time0 = time
|
34
34
|
else
|
35
35
|
time0 = @timestep.time_at(idx.ceil)
|
@@ -47,3 +47,11 @@ class TimeStep::Query
|
|
47
47
|
|
48
48
|
end
|
49
49
|
|
50
|
+
class TimeStep
|
51
|
+
|
52
|
+
def query (format = nil)
|
53
|
+
return TimeStep::Query.new(self, format: format)
|
54
|
+
end
|
55
|
+
|
56
|
+
end
|
57
|
+
|
@@ -0,0 +1,155 @@
|
|
1
|
+
require "forwardable"
|
2
|
+
|
3
|
+
class TimeStep::Range
|
4
|
+
|
5
|
+
extend Forwardable
|
6
|
+
|
7
|
+
def initialize (timestep, start = nil, last = nil, count: nil, ends: "[]")
|
8
|
+
|
9
|
+
raise "'ends' option should be one of '[]', '()', '(]', '[)" unless ends =~ /\A[\[\(][\]\)]\z/
|
10
|
+
include_start = ends[0] == "["
|
11
|
+
include_last = ends[1] == "]"
|
12
|
+
|
13
|
+
if last
|
14
|
+
case start
|
15
|
+
when Numeric
|
16
|
+
when Time
|
17
|
+
start = timestep.index_at(start.to_datetime)
|
18
|
+
when DateTime, DateTimeLike, String
|
19
|
+
start = timestep.index_at(start)
|
20
|
+
else
|
21
|
+
raise "unknown type of argument"
|
22
|
+
end
|
23
|
+
case last
|
24
|
+
when Numeric
|
25
|
+
when Time
|
26
|
+
last = timestep.index_at(last.to_datetime)
|
27
|
+
when DateTime, DateTimeLike, String
|
28
|
+
last = timestep.index_at(last)
|
29
|
+
else
|
30
|
+
raise "unknown argument"
|
31
|
+
end
|
32
|
+
else
|
33
|
+
case start
|
34
|
+
when Integer
|
35
|
+
count = start
|
36
|
+
start = 0
|
37
|
+
last = count - 1
|
38
|
+
when String
|
39
|
+
raise "count should be set" unless count.is_a?(Integer)
|
40
|
+
start = timestep.index_at(start)
|
41
|
+
last = start + count - 1
|
42
|
+
when TimePeriod
|
43
|
+
period = range
|
44
|
+
return initialize(timestep, period.origin..period.last, ends: period.ends)
|
45
|
+
else
|
46
|
+
raise "unknown argument"
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
if include_start
|
51
|
+
start = start.ceil
|
52
|
+
else
|
53
|
+
start = start.floor + 1
|
54
|
+
end
|
55
|
+
|
56
|
+
if include_last
|
57
|
+
last = last.floor
|
58
|
+
else
|
59
|
+
last = last.ceil - 1
|
60
|
+
end
|
61
|
+
|
62
|
+
@timestep = timestep.new_origin(timestep.time_at(start))
|
63
|
+
@start_time = timestep.time_at(start)
|
64
|
+
@last_time = timestep.time_at(last)
|
65
|
+
|
66
|
+
@start = @timestep.index_at(@start_time)
|
67
|
+
@last = @timestep.index_at(@last_time)
|
68
|
+
@count = @last - @start + 1
|
69
|
+
end
|
70
|
+
|
71
|
+
attr_reader :timestep, :count, :start, :last, :start_time, :last_time
|
72
|
+
|
73
|
+
def_delegators :@timestep, :numeric, :symbol, :interval,
|
74
|
+
:origin, :offset, :calendar, :definition,
|
75
|
+
:parse, :time_at, :index_at, :duration_at, :[]
|
76
|
+
|
77
|
+
|
78
|
+
# FIXME
|
79
|
+
def valid? (*indices)
|
80
|
+
if @count
|
81
|
+
if indices.size == 1
|
82
|
+
index = indices.first
|
83
|
+
if index >= 0 and index < @count
|
84
|
+
return true
|
85
|
+
else
|
86
|
+
return false
|
87
|
+
end
|
88
|
+
else
|
89
|
+
return indices.map{|index| valid?(index) }
|
90
|
+
end
|
91
|
+
else
|
92
|
+
if indices.size == 1
|
93
|
+
return true
|
94
|
+
else
|
95
|
+
return indices.map{|index| true }
|
96
|
+
end
|
97
|
+
end
|
98
|
+
end
|
99
|
+
|
100
|
+
# Returns TimeStep object which has origin time determined
|
101
|
+
# by the given `index`.
|
102
|
+
#
|
103
|
+
# @param index [Numeric]
|
104
|
+
#
|
105
|
+
# @return [TimeStep]
|
106
|
+
def shift_origin (index)
|
107
|
+
case with
|
108
|
+
when :index, "index"
|
109
|
+
timestep = @timestep.shift_origin(index)
|
110
|
+
return TimeStep::Range.new(timestep, count: @count)
|
111
|
+
when :duration, "duration", :days, "days"
|
112
|
+
timestep = @timestep.shift_origin(index, with: "duration")
|
113
|
+
return TimeStep::Range.new(timestep, count: @count)
|
114
|
+
end
|
115
|
+
end
|
116
|
+
|
117
|
+
# Returns TimeStep object which has origin time specified
|
118
|
+
# by the given `time`.
|
119
|
+
#
|
120
|
+
# @param time [DateTime]
|
121
|
+
#
|
122
|
+
# @return [TimeStep]
|
123
|
+
def new_origin (time, truncate: false)
|
124
|
+
timestep = @timestep.new_origin(time, truncate: truncate)
|
125
|
+
return TimeStep::Range.new(timestep, count: @count)
|
126
|
+
end
|
127
|
+
|
128
|
+
include Enumerable
|
129
|
+
|
130
|
+
def each_time (&block)
|
131
|
+
if block
|
132
|
+
(@start..@last).each do |k|
|
133
|
+
block.call(@timestep.time_at(k))
|
134
|
+
end
|
135
|
+
else
|
136
|
+
return Enumerator.new {|y|
|
137
|
+
(@start..@last).each do |k|
|
138
|
+
y << @timestep.time_at(k)
|
139
|
+
end
|
140
|
+
}
|
141
|
+
end
|
142
|
+
end
|
143
|
+
|
144
|
+
alias each each_time
|
145
|
+
|
146
|
+
def each_index (&block)
|
147
|
+
(@start..@last).each(&block)
|
148
|
+
end
|
149
|
+
|
150
|
+
def map_index (&block)
|
151
|
+
(@start..@last).map(&block)
|
152
|
+
end
|
153
|
+
|
154
|
+
end
|
155
|
+
|
data/lib/timesteps.rb
CHANGED
@@ -1,5 +1,6 @@
|
|
1
1
|
|
2
2
|
require "date"
|
3
|
+
require "timesteps/time"
|
3
4
|
require "timesteps/datetimelike"
|
4
5
|
require "timesteps/datetimelike_format"
|
5
6
|
require "timesteps/datetime_noleap"
|
@@ -12,3 +13,6 @@ require "timesteps/timestep"
|
|
12
13
|
require "timesteps/timestep_pair"
|
13
14
|
require "timesteps/timestep_converter"
|
14
15
|
require "timesteps/timeperiod"
|
16
|
+
require "timesteps/timestep_range"
|
17
|
+
require "timesteps/datetime_timestep"
|
18
|
+
require "timesteps/timestep_query"
|
data/spec/allleap_spec.rb
CHANGED
@@ -123,17 +123,6 @@ describe "AllLeap.parse_timestamp" do
|
|
123
123
|
|
124
124
|
end
|
125
125
|
|
126
|
-
example "with bc option" do
|
127
|
-
|
128
|
-
d1 = DateTime::AllLeap.new(0, 1, 1, 0, 0, 0, 0)
|
129
|
-
d2 = DateTime.parse_timestamp('BC 0001-1-1 00:00:00', calendar: "allleap")
|
130
|
-
d3 = DateTime.parse_timestamp('-0001-1-1 00:00:00', calendar: "allleap", bc: true)
|
131
|
-
|
132
|
-
is_asserted_by { d2 == d1 }
|
133
|
-
is_asserted_by { d3 == d1 }
|
134
|
-
|
135
|
-
end
|
136
|
-
|
137
126
|
example '2000-12-31 24:00:00' do
|
138
127
|
|
139
128
|
d1 = DateTime::AllLeap.new(2001, 1, 1, 0, 0, 0, 0)
|
@@ -301,8 +290,8 @@ describe "AllLeap#difference_in_years" do
|
|
301
290
|
d3 = DateTime::AllLeap.new(2002, 3, 5, 9, 35, 11.5, 9.quo(24))
|
302
291
|
d4 = DateTime::AllLeap.new(2002, 3, 5, 9, 35, 12.5, 9.quo(24))
|
303
292
|
|
304
|
-
is_asserted_by { d2.difference_in_years(d1) ==
|
305
|
-
is_asserted_by { d3.difference_in_years(d1) ==
|
293
|
+
is_asserted_by { d2.difference_in_years(d1) == 1.quo(2) }
|
294
|
+
is_asserted_by { d3.difference_in_years(d1) == 1.quo(2) }
|
306
295
|
is_asserted_by { d4.difference_in_years(d1) == 1 }
|
307
296
|
|
308
297
|
end
|
@@ -319,8 +308,8 @@ describe "AllLeap#difference_in_months" do
|
|
319
308
|
d4 = DateTime::AllLeap.new(2001, 4, 5, 9, 35, 12.5, 9.quo(24))
|
320
309
|
d5 = DateTime::AllLeap.new(2002, 3, 5, 9, 35, 12.5, 9.quo(24))
|
321
310
|
|
322
|
-
is_asserted_by { d2.difference_in_months(d1) ==
|
323
|
-
is_asserted_by { d3.difference_in_months(d1) ==
|
311
|
+
is_asserted_by { d2.difference_in_months(d1) == 1.quo(2) }
|
312
|
+
is_asserted_by { d3.difference_in_months(d1) == 1.quo(2) }
|
324
313
|
is_asserted_by { d4.difference_in_months(d1) == 1 }
|
325
314
|
is_asserted_by { d5.difference_in_months(d1) == 12 }
|
326
315
|
|
data/spec/fixed360day_spec.rb
CHANGED
@@ -133,17 +133,6 @@ describe "Fixed360Day.parse_timestamp" do
|
|
133
133
|
|
134
134
|
end
|
135
135
|
|
136
|
-
example "with bc option" do
|
137
|
-
|
138
|
-
d1 = DateTime::Fixed360Day.new(0, 1, 1, 0, 0, 0, 0)
|
139
|
-
d2 = DateTime.parse_timestamp('BC 0001-1-1 00:00:00', calendar: "360_day")
|
140
|
-
d3 = DateTime.parse_timestamp('-0001-1-1 00:00:00', calendar: "360_day", bc: true)
|
141
|
-
|
142
|
-
is_asserted_by { d2 == d1 }
|
143
|
-
is_asserted_by { d3 == d1 }
|
144
|
-
|
145
|
-
end
|
146
|
-
|
147
136
|
example '2000-12-31 24:00:00' do
|
148
137
|
|
149
138
|
d1 = DateTime::Fixed360Day.new(2001, 1, 1, 0, 0, 0, 0)
|
@@ -312,8 +301,8 @@ describe "Fixed360Day#difference_in_years" do
|
|
312
301
|
d3 = DateTime::Fixed360Day.new(2002, 3, 5, 9, 35, 11.5, 9.quo(24))
|
313
302
|
d4 = DateTime::Fixed360Day.new(2002, 3, 5, 9, 35, 12.5, 9.quo(24))
|
314
303
|
|
315
|
-
is_asserted_by { d2.difference_in_years(d1) ==
|
316
|
-
is_asserted_by { d3.difference_in_years(d1) ==
|
304
|
+
is_asserted_by { d2.difference_in_years(d1) == 1.quo(2) }
|
305
|
+
is_asserted_by { d3.difference_in_years(d1) == 1.quo(2) }
|
317
306
|
is_asserted_by { d4.difference_in_years(d1) == 1 }
|
318
307
|
|
319
308
|
end
|
@@ -330,8 +319,8 @@ describe "Fixed360Day#difference_in_months" do
|
|
330
319
|
d4 = DateTime::Fixed360Day.new(2001, 4, 5, 9, 35, 12.5, 9.quo(24))
|
331
320
|
d5 = DateTime::Fixed360Day.new(2002, 3, 5, 9, 35, 12.5, 9.quo(24))
|
332
321
|
|
333
|
-
is_asserted_by { d2.difference_in_months(d1) ==
|
334
|
-
is_asserted_by { d3.difference_in_months(d1) ==
|
322
|
+
is_asserted_by { d2.difference_in_months(d1) == 1.quo(2) }
|
323
|
+
is_asserted_by { d3.difference_in_months(d1) == 1.quo(2) }
|
335
324
|
is_asserted_by { d4.difference_in_months(d1) == 1 }
|
336
325
|
is_asserted_by { d5.difference_in_months(d1) == 12 }
|
337
326
|
|