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.
@@ -2,7 +2,7 @@ require "timesteps"
2
2
 
3
3
  class TimeStep::Converter
4
4
 
5
- def initialize (reference, calendar: "standard", bc: false)
5
+ def initialize (reference, name: "reference", calendar: "standard", bc: false)
6
6
  @calendar = calendar
7
7
  @bc = bc
8
8
  case reference
@@ -15,16 +15,22 @@ class TimeStep::Converter
15
15
  end
16
16
  @pair = {}
17
17
  @target = {}
18
- self["reference"] = reference
18
+ self[name] = reference
19
19
  end
20
20
 
21
21
  # Append or reset new target time step for the given name.
22
22
  #
23
- def []= (name, spec)
23
+ def add_timestep (spec, name:)
24
24
  @pair[name] = TimeStep::Pair.new(@reference, spec, calendar: @calendar, bc: @bc)
25
25
  @target[name] = @pair[name].to
26
26
  return @target[name]
27
27
  end
28
+
29
+ # Append or reset new target time step for the given name.
30
+ #
31
+ def []= (name, spec)
32
+ return add_timestep(spec, name: name)
33
+ end
28
34
 
29
35
  # Return target time step of the given name.
30
36
  #
@@ -39,14 +45,41 @@ class TimeStep::Converter
39
45
  @target.delete(name)
40
46
  end
41
47
 
42
- def forward (*indices)
43
- hash = {}
48
+ # Returns the time represented by the given index as DateTime object
49
+ #
50
+ # @param indices [Numeric,Array<Numeric>]
51
+ #
52
+ # @return [DateTime]
53
+ def time_at (*indices)
54
+ return @reference.time_at(*indices)
55
+ end
56
+
57
+ # Converts index refering `from` timestep to index refering `to`timestep.
58
+ #
59
+ def forward (*indices, with_time: false)
60
+ if with_time
61
+ hash = {
62
+ "time" => time_at(*indices)
63
+ }
64
+ else
65
+ hash = {}
66
+ end
44
67
  @pair.each do |name, conv|
45
68
  hash[name] = conv.forward(*indices)
46
69
  end
47
70
  return hash
48
71
  end
49
72
 
73
+ def range (ge: nil, gt: nil, lt: nil, le: nil, with_time: false)
74
+ indices = @reference.range(ge: ge, gt: gt, lt: lt, le: le)
75
+ return forward(*indices, with_time: with_time)
76
+ end
77
+
78
+ def index_at (*times, format: nil, with_time: false)
79
+ indices = @reference.index_at(*times, format: format)
80
+ return forward(*indices, with_time: with_time)
81
+ end
82
+
50
83
  def valid? (*indices)
51
84
  hash = {}
52
85
  @pair.each do |name, conv|
@@ -55,9 +88,6 @@ class TimeStep::Converter
55
88
  return hash
56
89
  end
57
90
 
58
- def time_at (index)
59
- return @from.time_at(index)
60
- end
61
91
 
62
92
  end
63
93
 
@@ -73,7 +73,7 @@ class TimeStep
73
73
  end
74
74
 
75
75
  end
76
-
76
+
77
77
  end
78
78
 
79
79
 
@@ -18,7 +18,6 @@ class TimeStep::Pair
18
18
  # @option calendar [String, TimeStep::Calendar]
19
19
  # @option bc [Boolean]
20
20
  #
21
-
22
21
  def initialize (from, to, calendar: "standard", bc: false)
23
22
 
24
23
  case from
@@ -60,7 +59,9 @@ class TimeStep::Pair
60
59
  end
61
60
 
62
61
  attr_reader :from, :to, :difference
63
-
62
+
63
+ # Returns the value as a string for inspection.
64
+ #
64
65
  def inspect
65
66
  "#<TimeStep::Pair from='#{from.inspect}' to='#{to.inspect}'>"
66
67
  end
@@ -69,14 +70,20 @@ class TimeStep::Pair
69
70
  #
70
71
  # @return [Boolean]
71
72
  def == (other)
72
- return @from == other.from &&
73
- @to == other.to
73
+ return @from == other.from && @to == other.to
74
74
  end
75
75
 
76
+ # Returns the time represented by the given index as DateTime object
77
+ #
78
+ # @param indices [Numeric,Array<Numeric>]
79
+ #
80
+ # @return [DateTime]
76
81
  def time_at (*indices)
77
82
  @from.time_at(*indices)
78
83
  end
79
84
 
85
+ # Converts index refering `from` timestep to index refering `to`timestep.
86
+ #
80
87
  def forward (*indices, &block)
81
88
  if indices.size == 1
82
89
  index = indices.first.to_r
@@ -115,30 +122,17 @@ class TimeStep::Pair
115
122
 
116
123
  alias [] forward
117
124
 
118
- def forward_time (index)
119
- if @numeric_conversion
120
- return @to.time_at((index*@from_interval + @difference).quo(@to_interval))
121
- else
122
- case @from_symbol
123
- when :years, :months
124
- target = @from.time_at(index)
125
- else
126
- target = @from_origin + index*(@from_interval.quo(86400))
127
- end
128
- case @to_symbol
129
- when :years
130
- index = (target.year - @from_origin.year).quo(@to.numeric)
131
- when :months
132
- ms = 12*(target.year - @from_origin.year)
133
- ms += target.month - @from_origin.month
134
- index = ms.quo(@to.numeric)
135
- else
136
- index = (target.ajd - @from_origin.ajd).quo(@to_interval)
137
- end
138
- return @to.time_at(index)
139
- end
125
+ def forward_time (*indices)
126
+ return forward(*indices) {|index| @to.time_at(index) }
140
127
  end
141
128
 
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
+ # Converts index refering `to` timestep to index refering `from` timestep.
135
+ #
142
136
  def inverse (*indices, &block)
143
137
  if indices.size == 1
144
138
  index = indices.first.to_r
@@ -159,11 +153,12 @@ class TimeStep::Pair
159
153
  else
160
154
  value = (target.ajd - @from_origin.ajd).quo(@from_interval)
161
155
  end
162
- if block
163
- return block[value]
164
- else
165
- return value
166
- end
156
+ end
157
+ value = value.to_i if value.denominator == 1
158
+ if block
159
+ return block[value]
160
+ else
161
+ return value
167
162
  end
168
163
  else
169
164
  if block
@@ -174,29 +169,8 @@ class TimeStep::Pair
174
169
  end
175
170
  end
176
171
 
177
- #
178
- def inverse_time (index)
179
- if @numeric_conversion
180
- return @from.time_at((index*@to_interval - @difference).quo(@from_interval))
181
- else
182
- case @to_symbol
183
- when :years, :months
184
- target = @to.time_at(index)
185
- else
186
- target = @to_origin + index*(@to_interval.quo(86400))
187
- end
188
- case @from_symbol
189
- when :years
190
- index = (target.year - @to_origin.year).quo(@from.numeric)
191
- when :months
192
- ms = 12*(target.year - @to_origin.year)
193
- ms += target.month - @to_origin.month
194
- index = ms.quo(@from.numeric)
195
- else
196
- index = (target.ajd - @to_origin.ajd).quo(@from_interval)
197
- end
198
- return @from.time_at(index)
199
- end
172
+ def inverse_time (*indices)
173
+ return inverse(*indices) {|index| @from.time_at(index) }
200
174
  end
201
175
 
202
176
  end
@@ -109,7 +109,7 @@ describe "AllLeap.parse_timestamp" do
109
109
  '05-Mar-2001 09:35:12.5 +09:00',
110
110
  ].each do |string|
111
111
 
112
- d2 = DateTime::AllLeap.parse_timestamp(string)
112
+ d2 = DateTime.parse_timestamp(string, calendar: "allleap")
113
113
 
114
114
  is_asserted_by { d2 == d1 }
115
115
  end
@@ -119,15 +119,15 @@ describe "AllLeap.parse_timestamp" do
119
119
  example 'raise for "2000-02-29"' do
120
120
 
121
121
  # leap day for noleap calendar
122
- is_asserted_by { DateTime::AllLeap.parse_timestamp("2000-2-29").is_a?(DateTime::AllLeap) }
122
+ is_asserted_by { DateTime.parse_timestamp("2000-2-29", calendar: "allleap").is_a?(DateTime::AllLeap) }
123
123
 
124
124
  end
125
125
 
126
126
  example "with bc option" do
127
127
 
128
128
  d1 = DateTime::AllLeap.new(0, 1, 1, 0, 0, 0, 0)
129
- d2 = DateTime::AllLeap.parse_timestamp('BC 0001-1-1 00:00:00')
130
- d3 = DateTime::AllLeap.parse_timestamp('-0001-1-1 00:00:00', bc: true)
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
131
 
132
132
  is_asserted_by { d2 == d1 }
133
133
  is_asserted_by { d3 == d1 }
@@ -137,7 +137,7 @@ describe "AllLeap.parse_timestamp" do
137
137
  example '2000-12-31 24:00:00' do
138
138
 
139
139
  d1 = DateTime::AllLeap.new(2001, 1, 1, 0, 0, 0, 0)
140
- d2 = DateTime::AllLeap.parse_timestamp('2000-12-31 24:00:00')
140
+ d2 = DateTime.parse_timestamp('2000-12-31 24:00:00', calendar: "allleap")
141
141
 
142
142
  is_asserted_by { d2 == d1 }
143
143
 
@@ -118,7 +118,7 @@ describe "Fixed360Day.parse_timestamp" do
118
118
  '05-Mar-2001 09:35:12.5 +09:00',
119
119
  ].each do |string|
120
120
 
121
- d2 = DateTime::Fixed360Day.parse_timestamp(string)
121
+ d2 = DateTime.parse_timestamp(string, calendar: "360_day")
122
122
 
123
123
  is_asserted_by { d2 == d1 }
124
124
  end
@@ -128,7 +128,7 @@ describe "Fixed360Day.parse_timestamp" do
128
128
  example 'raise for "2000-02-29"' do
129
129
 
130
130
  # leap day for noleap calendar
131
- is_asserted_by { DateTime::Fixed360Day.parse_timestamp("2000-2-29").is_a?(DateTime::Fixed360Day) }
131
+ is_asserted_by { DateTime.parse_timestamp("2000-2-29", calendar: "360_day").is_a?(DateTime::Fixed360Day) }
132
132
 
133
133
 
134
134
  end
@@ -136,8 +136,8 @@ describe "Fixed360Day.parse_timestamp" do
136
136
  example "with bc option" do
137
137
 
138
138
  d1 = DateTime::Fixed360Day.new(0, 1, 1, 0, 0, 0, 0)
139
- d2 = DateTime::Fixed360Day.parse_timestamp('BC 0001-1-1 00:00:00')
140
- d3 = DateTime::Fixed360Day.parse_timestamp('-0001-1-1 00:00:00', bc: true)
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
141
 
142
142
  is_asserted_by { d2 == d1 }
143
143
  is_asserted_by { d3 == d1 }
@@ -147,7 +147,7 @@ describe "Fixed360Day.parse_timestamp" do
147
147
  example '2000-12-31 24:00:00' do
148
148
 
149
149
  d1 = DateTime::Fixed360Day.new(2001, 1, 1, 0, 0, 0, 0)
150
- d2 = DateTime::Fixed360Day.parse_timestamp('2000-12-30 24:00:00')
150
+ d2 = DateTime.parse_timestamp('2000-12-30 24:00:00', calendar: "360_day")
151
151
 
152
152
  is_asserted_by { d2 == d1 }
153
153
 
@@ -107,7 +107,7 @@ describe "NoLeap.parse_timestamp" do
107
107
  '05-Mar-2001 09:35:12.5 +09:00',
108
108
  ].each do |string|
109
109
 
110
- d2 = DateTime::NoLeap.parse_timestamp(string)
110
+ d2 = DateTime.parse_timestamp(string, calendar: "noleap")
111
111
 
112
112
  is_asserted_by { d2 == d1 }
113
113
  end
@@ -117,15 +117,15 @@ describe "NoLeap.parse_timestamp" do
117
117
  example 'raise for "2000-02-29"' do
118
118
 
119
119
  # leap day for noleap calendar
120
- expect { DateTime::NoLeap.parse_timestamp("2000-2-29") }.to raise_error(RuntimeError)
120
+ expect { DateTime.parse_timestamp("2000-2-29", calendar: "noleap") }.to raise_error(RuntimeError)
121
121
 
122
122
  end
123
123
 
124
124
  example "with bc option" do
125
125
 
126
126
  d1 = DateTime::NoLeap.new(0, 1, 1, 0, 0, 0, 0)
127
- d2 = DateTime::NoLeap.parse_timestamp('BC 0001-1-1 00:00:00')
128
- d3 = DateTime::NoLeap.parse_timestamp('-0001-1-1 00:00:00', bc: true)
127
+ d2 = DateTime.parse_timestamp('BC 0001-1-1 00:00:00', calendar: "noleap")
128
+ d3 = DateTime.parse_timestamp('-0001-1-1 00:00:00', calendar: "noleap", bc: true)
129
129
 
130
130
  is_asserted_by { d2 == d1 }
131
131
  is_asserted_by { d3 == d1 }
@@ -135,7 +135,7 @@ describe "NoLeap.parse_timestamp" do
135
135
  example '2000-12-31 24:00:00' do
136
136
 
137
137
  d1 = DateTime::NoLeap.new(2001, 1, 1, 0, 0, 0, 0)
138
- d2 = DateTime::NoLeap.parse_timestamp('2000-12-31 24:00:00')
138
+ d2 = DateTime.parse_timestamp('2000-12-31 24:00:00', calendar: "noleap")
139
139
 
140
140
  is_asserted_by { d2 == d1 }
141
141
 
@@ -121,6 +121,53 @@ describe "TimeStep.new" do
121
121
  end
122
122
 
123
123
  end
124
+
125
+ example 'since option with format' do
126
+
127
+ time = "20010203_040506.dat"
128
+ template = "%Y%m%d_%H%M%S.dat"
129
+
130
+ ts = TimeStep.new("3 days", since: time, format: template)
131
+
132
+ is_asserted_by { ts.origin.strftime(template) == time }
133
+ is_asserted_by { ts.numeric == 3 }
134
+ is_asserted_by { ts.symbol == :days }
135
+
136
+ ts = TimeStep.new("3 days", since: time, format: template, calendar: "noleap")
137
+
138
+ is_asserted_by { ts.origin.strftime(template) == time }
139
+ is_asserted_by { ts.numeric == 3 }
140
+ is_asserted_by { ts.symbol == :days }
141
+
142
+ end
143
+
144
+ example 'since option' do
145
+
146
+ time = DateTime.new(2001,2,3,4,5,6,7.quo(24),Date::ITALY)
147
+ ts = TimeStep.new("3 days", since: time)
148
+
149
+ is_asserted_by { ts.origin == time }
150
+ is_asserted_by { ts.numeric == 3 }
151
+ is_asserted_by { ts.symbol == :days }
152
+
153
+ time = DateTime::NoLeap.new(2001,2,3,4,5,6,7.quo(24))
154
+ ts = TimeStep.new("3 days", since: time, calendar: "noleap")
155
+
156
+ is_asserted_by { ts.origin == time }
157
+ is_asserted_by { ts.numeric == 3 }
158
+ is_asserted_by { ts.symbol == :days }
159
+
160
+ end
161
+
162
+ example 'since option with calendar mismatch' do
163
+ time = DateTime.new(2001,2,3,4,5,6,7.quo(24),Date::GREGORIAN)
164
+ expect { TimeStep.new("3 days", since: time) }.to raise_error(RuntimeError)
165
+ expect { TimeStep.new("3 days", since: time, calendar: "noleap") }.to raise_error(RuntimeError)
166
+
167
+ time = DateTime::NoLeap.new(2001,2,3,4,5,6,7.quo(24))
168
+ expect { TimeStep.new("3 days", since: time) }.to raise_error(RuntimeError)
169
+ expect { TimeStep.new("3 days", since: time, calendar: "allleap") }.to raise_error(RuntimeError)
170
+ end
124
171
 
125
172
  end
126
173
 
@@ -281,6 +328,15 @@ describe "TimeStep#index_at" do
281
328
 
282
329
  end
283
330
 
331
+ example 'unix' do
332
+
333
+ unixtime = TimeStep.new("seconds since 1970-01-01 00:00:00")
334
+ time = DateTime.parse("2001-01-01 00:00:00 +09:00")
335
+
336
+ is_asserted_by { unixtime.index_at(time) == 978274800 }
337
+
338
+ end
339
+
284
340
  end
285
341
 
286
342
  describe "TimeStep#days_at" do
@@ -90,7 +90,6 @@ describe "TimeStep::Pair#forward" do
90
90
 
91
91
  is_asserted_by { pair.forward(0) == 978274800 }
92
92
  is_asserted_by { pair.forward_time(0) == DateTime.new(2000,12,31,15,0,0,0) }
93
- is_asserted_by { Time.at(pair.forward(0), in: "+00:00") == ts.origin.to_time }
94
93
 
95
94
  end
96
95
 
@@ -1,6 +1,6 @@
1
1
 
2
2
  Gem::Specification::new do |s|
3
- version = "0.9.3"
3
+ version = "0.9.5"
4
4
 
5
5
  files = Dir.glob("**/*") - [
6
6
  Dir.glob("timesteps-*.gem"),
@@ -12,9 +12,12 @@ Gem::Specification::new do |s|
12
12
  s.name = "timesteps"
13
13
  s.summary = "A library for handling discrete time series in constant increments"
14
14
  s.description = <<-HERE
15
- A library for handling discrete time series in constant increments.
16
- The main purpose of this library is to describe the time axis
17
- when dealing with time series of observational data and climate data.
15
+ A library for time conversion and intercomparison of multiple time series data
16
+ in the case of handling time series data of the type that specifies the time using
17
+ indexes of time steps since origin time. It handles time units notation like
18
+ "hours since 2001-01-01 00:00:00", which is originate from udunits library and
19
+ also is used in CF-convension of NetCDF. The main purpose of this library is to
20
+ describe the time axis when dealing with time series of observational data and climate data.
18
21
  HERE
19
22
  s.version = version
20
23
  s.licenses = ['MIT']
@@ -22,5 +25,5 @@ Gem::Specification::new do |s|
22
25
  s.email = ""
23
26
  s.homepage = 'https://github.com/himotoyoshi/timesteps'
24
27
  s.files = files
25
- s.required_ruby_version = ">= 2.5.1"
28
+ s.required_ruby_version = ">= 2.4.1"
26
29
  end
metadata CHANGED
@@ -1,18 +1,22 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: timesteps
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.9.3
4
+ version: 0.9.5
5
5
  platform: ruby
6
6
  authors:
7
7
  - Hiroki Motoyoshi
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2020-05-04 00:00:00.000000000 Z
11
+ date: 2020-05-08 00:00:00.000000000 Z
12
12
  dependencies: []
13
- description: " A library for handling discrete time series in constant increments.\n
14
- \ The main purpose of this library is to describe the time axis \n when dealing
15
- with time series of observational data and climate data.\n"
13
+ description: " A library for time conversion and intercomparison of multiple time
14
+ series data \n in the case of handling time series data of the type that specifies
15
+ the time using \n indexes of time steps since origin time. It handles time units
16
+ notation like \n \"hours since 2001-01-01 00:00:00\", which is originate from udunits
17
+ library and \n also is used in CF-convension of NetCDF. The main purpose of this
18
+ library is to \n describe the time axis when dealing with time series of observational
19
+ data and climate data.\n"
16
20
  email: ''
17
21
  executables: []
18
22
  extensions: []
@@ -24,14 +28,17 @@ files:
24
28
  - Rakefile
25
29
  - lib/timesteps.rb
26
30
  - lib/timesteps/calendar.rb
31
+ - lib/timesteps/datetime_360day.rb
32
+ - lib/timesteps/datetime_allleap.rb
33
+ - lib/timesteps/datetime_noleap.rb
27
34
  - lib/timesteps/datetimelike.rb
28
35
  - lib/timesteps/format.rb
29
36
  - lib/timesteps/grads.rb
30
37
  - lib/timesteps/parse_timestamp.rb
31
38
  - lib/timesteps/timestep.rb
32
- - lib/timesteps/timestepconverter.rb
33
- - lib/timesteps/timestepdatetimeext.rb
34
- - lib/timesteps/timesteppair.rb
39
+ - lib/timesteps/timestep_converter.rb
40
+ - lib/timesteps/timestep_datetime_ext.rb
41
+ - lib/timesteps/timestep_pair.rb
35
42
  - spec/allleap_spec.rb
36
43
  - spec/fixed360day_spec.rb
37
44
  - spec/noleap_spec.rb
@@ -50,7 +57,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
50
57
  requirements:
51
58
  - - ">="
52
59
  - !ruby/object:Gem::Version
53
- version: 2.5.1
60
+ version: 2.4.1
54
61
  required_rubygems_version: !ruby/object:Gem::Requirement
55
62
  requirements:
56
63
  - - ">="