subroutine 3.0.3 → 3.0.5

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: a2dedf592996ae8331d333379af49033a3f5a3e74a4c8dd8d8cf5fbe7c878258
4
- data.tar.gz: ab33d0b731a9f28b52e4661fdcb6626d6eda2f2e8883a8f05ecfa2b529f2961a
3
+ metadata.gz: e7441c613353cda046900b7165d787576d3cb757943496fb7b4ccc65a9f5faf1
4
+ data.tar.gz: b154f7ab48dc32c391be450bc684ee34d59451d6e327d90f463654d53e8f0a55
5
5
  SHA512:
6
- metadata.gz: 26617e51aeb874dbabb64ad62add32903ad734014ed09e4b0c59f81829bb9bbf728726ab4c7690d82ce1280967b59507c689a58464c13216ad46df87b99c0ff5
7
- data.tar.gz: 3a45d5cbac6d68660c875e0c7163b403276b360a7d37efb86199d2b593c04876060e6f83b99cef3e0dd2c144cba2c75c11a2eeb51a17253bfff49cb6657c55c7
6
+ metadata.gz: 9da5a1f35f9888ebc970e23c60e53871258d837767b6baf3597fb216c64eca039171d993f4abc8c02627b678623e47df35defe5a79799a6c166ff7aebc2cb712
7
+ data.tar.gz: 5df7cc84df8ec5b19f60f9101fb66abeee95b578b474d956d378857132a60881a039c55ddecc4b8e6405b1ef9c95fb69f5b3d2d3ffc3fd5cb02bdce0aba8da4d
@@ -4,11 +4,16 @@ require 'date'
4
4
  require 'time'
5
5
  require 'bigdecimal'
6
6
  require 'securerandom'
7
+ require 'active_support'
8
+ require 'active_support/json'
9
+ require 'active_support/core_ext/date_time/acts_like'
10
+ require 'active_support/core_ext/date_time/calculations'
7
11
  require 'active_support/core_ext/object/acts_like'
8
12
  require 'active_support/core_ext/object/blank'
9
13
  require 'active_support/core_ext/object/try'
10
14
  require 'active_support/core_ext/array/wrap'
11
15
  require 'active_support/core_ext/time/acts_like'
16
+ require 'active_support/core_ext/time/calculations'
12
17
 
13
18
  module Subroutine
14
19
  module TypeCaster
@@ -108,7 +113,7 @@ end
108
113
  t ||= value if value.is_a?(::Time)
109
114
  t ||= value if value.try(:acts_like?, :time)
110
115
  t ||= ::Time.parse(String(value))
111
- t.utc.iso8601
116
+ t.utc.iso8601(::ActiveSupport::JSON::Encoding.time_precision)
112
117
  end
113
118
 
114
119
  ::Subroutine::TypeCaster.register :date do |value, _options = {}|
@@ -117,14 +122,19 @@ end
117
122
  ::Date.parse(String(value))
118
123
  end
119
124
 
120
- ::Subroutine::TypeCaster.register :time, :timestamp, :datetime do |value, _options = {}|
125
+ ::Subroutine::TypeCaster.register :time, :timestamp, :datetime do |value, options = {}|
121
126
  next nil unless value.present?
122
127
 
123
- if value.try(:acts_like?, :time)
124
- value
128
+ value = if value.try(:acts_like?, :time)
129
+ value.to_time
125
130
  else
126
131
  ::Time.parse(String(value))
127
132
  end
133
+
134
+ # High precision must be opted into. The original implementation is to set usec:0
135
+ next value if options[:precision] == :high || ::Subroutine.preserve_time_precision?
136
+
137
+ value.change(usec: 0)
128
138
  end
129
139
 
130
140
  ::Subroutine::TypeCaster.register :hash, :object, :hashmap, :dict do |value, _options = {}|
@@ -4,7 +4,7 @@ module Subroutine
4
4
 
5
5
  MAJOR = 3
6
6
  MINOR = 0
7
- PATCH = 3
7
+ PATCH = 5
8
8
  PRE = nil
9
9
 
10
10
  VERSION = [MAJOR, MINOR, PATCH, PRE].compact.join(".")
data/lib/subroutine.rb CHANGED
@@ -3,3 +3,17 @@
3
3
  require "subroutine/version"
4
4
  require "subroutine/fields"
5
5
  require "subroutine/op"
6
+
7
+ module Subroutine
8
+
9
+ def self.preserve_time_precision=(bool)
10
+ @preserve_time_precision = !!bool
11
+ end
12
+
13
+ def self.preserve_time_precision?
14
+ return !!@preserve_time_precision if defined?(@preserve_time_precision)
15
+
16
+ false
17
+ end
18
+
19
+ end
@@ -241,7 +241,7 @@ module Subroutine
241
241
  assert_nil op.date_input
242
242
  end
243
243
 
244
- def test_time_inputs
244
+ def test_time_inputs__with_seconds_precision
245
245
  op.time_input = nil
246
246
  assert_nil op.time_input
247
247
 
@@ -256,22 +256,153 @@ module Subroutine
256
256
  assert_equal 0, op.time_input.min
257
257
  assert_equal 0, op.time_input.sec
258
258
 
259
+ op.time_input = ::DateTime.new(2022, 12, 22)
260
+ assert_equal ::Time, op.time_input.class
261
+ refute_equal ::DateTime, op.time_input.class
262
+
263
+ assert_equal 0, op.time_input.utc_offset
264
+ assert_equal 2022, op.time_input.year
265
+ assert_equal 12, op.time_input.month
266
+ assert_equal 22, op.time_input.day
267
+ assert_equal 0, op.time_input.hour
268
+ assert_equal 0, op.time_input.min
269
+ assert_equal 0, op.time_input.sec
270
+
259
271
  op.time_input = '2023-05-05T10:00:30.123456Z'
260
272
  assert_equal ::Time, op.time_input.class
261
273
  refute_equal ::DateTime, op.time_input.class
262
274
 
275
+ assert_equal 0, op.time_input.utc_offset
263
276
  assert_equal 2023, op.time_input.year
264
277
  assert_equal 5, op.time_input.month
265
278
  assert_equal 5, op.time_input.day
266
279
  assert_equal 10, op.time_input.hour
267
280
  assert_equal 0, op.time_input.min
268
281
  assert_equal 30, op.time_input.sec
269
- assert_equal 123456, op.time_input.usec
282
+ assert_equal 0, op.time_input.usec
270
283
 
271
- time = Time.at(1678741605.123456)
284
+ op.time_input = '2023-05-05T10:00:30Z'
285
+ assert_equal ::Time, op.time_input.class
286
+ assert_equal 0, op.time_input.utc_offset
287
+ assert_equal 2023, op.time_input.year
288
+ assert_equal 5, op.time_input.month
289
+ assert_equal 5, op.time_input.day
290
+ assert_equal 10, op.time_input.hour
291
+ assert_equal 0, op.time_input.min
292
+ assert_equal 30, op.time_input.sec
293
+ assert_equal 0, op.time_input.usec
294
+
295
+ op.time_input = '2024-11-11T16:42:23.246+0100'
296
+ assert_equal ::Time, op.time_input.class
297
+ assert_equal 3600, op.time_input.utc_offset
298
+ assert_equal 2024, op.time_input.year
299
+ assert_equal 11, op.time_input.month
300
+ assert_equal 11, op.time_input.day
301
+ assert_equal 16, op.time_input.hour
302
+ assert_equal 42, op.time_input.min
303
+ assert_equal 23, op.time_input.sec
304
+ assert_equal 0, op.time_input.usec
305
+
306
+ time = Time.at(1678741605.123456).utc
307
+ op.time_input = time
308
+ refute_equal time, op.time_input
309
+ refute_equal time.object_id, op.time_input.object_id
310
+ assert_equal 2023, op.time_input.year
311
+ assert_equal 3, op.time_input.month
312
+ assert_equal 13, op.time_input.day
313
+ assert_equal 21, op.time_input.hour
314
+ assert_equal 6, op.time_input.min
315
+ assert_equal 45, op.time_input.sec
316
+ assert_equal 0, op.time_input.usec
317
+ end
318
+
319
+ def test_time_inputs__with_preserve_time_precision
320
+ Subroutine.stubs(:preserve_time_precision?).returns(true)
321
+
322
+ time = Time.at(1678741605.123456).utc
272
323
  op.time_input = time
273
- assert_equal time, op.time_input
274
- assert_equal time.object_id, op.time_input.object_id
324
+ assert_equal 2023, op.time_input.year
325
+ assert_equal 3, op.time_input.month
326
+ assert_equal 13, op.time_input.day
327
+ assert_equal 21, op.time_input.hour
328
+ assert_equal 6, op.time_input.min
329
+ assert_equal 45, op.time_input.sec
330
+ assert_equal 123456, op.time_input.usec
331
+ end
332
+
333
+ def test_time_inputs__with_high_precision
334
+ op.precise_time_input = nil
335
+ assert_nil op.precise_time_input
336
+
337
+ op.precise_time_input = '2022-12-22'
338
+ assert_equal ::Time, op.precise_time_input.class
339
+ refute_equal ::DateTime, op.precise_time_input.class
340
+
341
+ assert_equal 2022, op.precise_time_input.year
342
+ assert_equal 12, op.precise_time_input.month
343
+ assert_equal 22, op.precise_time_input.day
344
+ assert_equal 0, op.precise_time_input.hour
345
+ assert_equal 0, op.precise_time_input.min
346
+ assert_equal 0, op.precise_time_input.sec
347
+
348
+ op.precise_time_input = ::DateTime.new(2022, 12, 22)
349
+ assert_equal ::Time, op.precise_time_input.class
350
+ refute_equal ::DateTime, op.precise_time_input.class
351
+
352
+ assert_equal 0, op.precise_time_input.utc_offset
353
+ assert_equal 2022, op.precise_time_input.year
354
+ assert_equal 12, op.precise_time_input.month
355
+ assert_equal 22, op.precise_time_input.day
356
+ assert_equal 0, op.precise_time_input.hour
357
+ assert_equal 0, op.precise_time_input.min
358
+ assert_equal 0, op.precise_time_input.sec
359
+
360
+ op.precise_time_input = '2023-05-05T10:00:30.123456Z'
361
+ assert_equal ::Time, op.precise_time_input.class
362
+ refute_equal ::DateTime, op.precise_time_input.class
363
+
364
+ assert_equal 0, op.precise_time_input.utc_offset
365
+ assert_equal 2023, op.precise_time_input.year
366
+ assert_equal 5, op.precise_time_input.month
367
+ assert_equal 5, op.precise_time_input.day
368
+ assert_equal 10, op.precise_time_input.hour
369
+ assert_equal 0, op.precise_time_input.min
370
+ assert_equal 30, op.precise_time_input.sec
371
+ assert_equal 123456, op.precise_time_input.usec
372
+
373
+ op.precise_time_input = '2023-05-05T10:00:30Z'
374
+ assert_equal ::Time, op.precise_time_input.class
375
+ assert_equal 0, op.precise_time_input.utc_offset
376
+ assert_equal 2023, op.precise_time_input.year
377
+ assert_equal 5, op.precise_time_input.month
378
+ assert_equal 5, op.precise_time_input.day
379
+ assert_equal 10, op.precise_time_input.hour
380
+ assert_equal 0, op.precise_time_input.min
381
+ assert_equal 30, op.precise_time_input.sec
382
+ assert_equal 0, op.precise_time_input.usec
383
+
384
+ op.precise_time_input = '2024-11-11T16:42:23.246+0100'
385
+ assert_equal ::Time, op.precise_time_input.class
386
+ assert_equal 3600, op.precise_time_input.utc_offset
387
+ assert_equal 2024, op.precise_time_input.year
388
+ assert_equal 11, op.precise_time_input.month
389
+ assert_equal 11, op.precise_time_input.day
390
+ assert_equal 16, op.precise_time_input.hour
391
+ assert_equal 42, op.precise_time_input.min
392
+ assert_equal 23, op.precise_time_input.sec
393
+ assert_equal 246000, op.precise_time_input.usec
394
+
395
+ time = Time.at(1678741605.123456).utc
396
+ op.precise_time_input = time
397
+ assert_equal time, op.precise_time_input
398
+ assert_equal time.object_id, op.precise_time_input.object_id
399
+ assert_equal 2023, op.precise_time_input.year
400
+ assert_equal 3, op.precise_time_input.month
401
+ assert_equal 13, op.precise_time_input.day
402
+ assert_equal 21, op.precise_time_input.hour
403
+ assert_equal 6, op.precise_time_input.min
404
+ assert_equal 45, op.precise_time_input.sec
405
+ assert_equal 123456, op.precise_time_input.usec
275
406
  end
276
407
 
277
408
  def test_iso_date_inputs
@@ -293,11 +424,11 @@ module Subroutine
293
424
 
294
425
  op.iso_time_input = '2022-12-22T10:30:24Z'
295
426
  assert_equal ::String, op.iso_time_input.class
296
- assert_equal '2022-12-22T10:30:24Z', op.iso_time_input
427
+ assert_equal '2022-12-22T10:30:24.000Z', op.iso_time_input
297
428
 
298
- op.iso_time_input = Time.parse('2022-12-22T10:30:24Z')
429
+ op.iso_time_input = Time.parse('2022-12-22T10:30:24.123456Z')
299
430
  assert_equal ::String, op.iso_time_input.class
300
- assert_equal '2022-12-22T10:30:24Z', op.iso_time_input
431
+ assert_equal '2022-12-22T10:30:24.123Z', op.iso_time_input
301
432
  end
302
433
 
303
434
  def test_file_inputs
data/test/support/ops.rb CHANGED
@@ -177,6 +177,7 @@ class TypeCastOp < ::Subroutine::Op
177
177
  boolean :boolean_input
178
178
  date :date_input
179
179
  time :time_input, default: -> { Time.now }
180
+ time :precise_time_input, precision: :high
180
181
  iso_date :iso_date_input
181
182
  iso_time :iso_time_input
182
183
  object :object_input
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: subroutine
3
3
  version: !ruby/object:Gem::Version
4
- version: 3.0.3
4
+ version: 3.0.5
5
5
  platform: ruby
6
6
  authors:
7
7
  - Mike Nelson
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2024-11-05 00:00:00.000000000 Z
11
+ date: 2024-11-22 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activemodel