sparkql 1.2.5 → 1.2.6
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 +8 -8
- data/CHANGELOG.md +4 -0
- data/VERSION +1 -1
- data/lib/sparkql/function_resolver.rb +42 -1
- data/lib/sparkql/parser.rb +1 -1
- data/test/unit/function_resolver_test.rb +169 -0
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,15 +1,15 @@
|
|
1
1
|
---
|
2
2
|
!binary "U0hBMQ==":
|
3
3
|
metadata.gz: !binary |-
|
4
|
-
|
4
|
+
MzM0ZTA3ZTIxNjlkMzY5YmFiMGM4MGFkOTA2NWZlNzMzZWQxNTQxMw==
|
5
5
|
data.tar.gz: !binary |-
|
6
|
-
|
6
|
+
ZmE5ZTQwZDc1YzI0YTJmZTRjYzMxMGY3ZDZmYmFmNzkxMWRmNTBiMg==
|
7
7
|
SHA512:
|
8
8
|
metadata.gz: !binary |-
|
9
|
-
|
10
|
-
|
11
|
-
|
9
|
+
Mjc0NjNjNGVkYWE1ZDVlNzIwNTY3ZDNjZmFiZDc2NGI5MmNlNGU5MjYzN2Yy
|
10
|
+
NTc1ZTMwYTVmNmM5Nzk2Mjk5OTk2Nzc5ZmYyNTA3Njc2ZmU0NjkzM2I2ZmQx
|
11
|
+
YTQxMzIzZjBjNDU0NTc1Y2VmYzMyNGRmZDNmNWFlNTFmYzFiZjg=
|
12
12
|
data.tar.gz: !binary |-
|
13
|
-
|
14
|
-
|
15
|
-
|
13
|
+
MzczODc4ZTAyOTRkNDlhNzZiYTQxYjUyM2FlMTQ0ZmU3NmMyZmY2Y2Q2YmFj
|
14
|
+
MTk0ODFmMTFmZmI4MTQ2MzkxOTFiYjkwYmM1NGQ1NzdmZjNiMjZmYjQ4MGJi
|
15
|
+
ODY1NmM3NWJhNTFmMzgxY2EwZGU5NWY1ZGVmYTVkZTBjMGZlNmU=
|
data/CHANGELOG.md
CHANGED
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
1.2.
|
1
|
+
1.2.6
|
@@ -10,7 +10,9 @@ require 'sparkql/geo'
|
|
10
10
|
# Name and argument requirements for the function should match the function declaration in
|
11
11
|
# SUPPORTED_FUNCTIONS which will run validation on the function syntax prior to execution.
|
12
12
|
class Sparkql::FunctionResolver
|
13
|
-
|
13
|
+
SECONDS_IN_MINUTE = 60
|
14
|
+
SECONDS_IN_HOUR = SECONDS_IN_MINUTE * 60
|
15
|
+
SECONDS_IN_DAY = SECONDS_IN_HOUR * 24
|
14
16
|
STRFTIME_DATE_FORMAT = '%Y-%m-%d'
|
15
17
|
STRFTIME_TIME_FORMAT = '%H:%M:%S.%N'
|
16
18
|
VALID_REGEX_FLAGS = ["", "i"]
|
@@ -111,6 +113,18 @@ class Sparkql::FunctionResolver
|
|
111
113
|
:args => [:character],
|
112
114
|
:return_type => :shape
|
113
115
|
},
|
116
|
+
:seconds => {
|
117
|
+
:args => [:integer],
|
118
|
+
:return_type => :datetime
|
119
|
+
},
|
120
|
+
:minutes => {
|
121
|
+
:args => [:integer],
|
122
|
+
:return_type => :datetime
|
123
|
+
},
|
124
|
+
:hours => {
|
125
|
+
:args => [:integer],
|
126
|
+
:return_type => :datetime
|
127
|
+
},
|
114
128
|
:days => {
|
115
129
|
:args => [:integer],
|
116
130
|
:return_type => :datetime
|
@@ -464,6 +478,33 @@ class Sparkql::FunctionResolver
|
|
464
478
|
}
|
465
479
|
end
|
466
480
|
|
481
|
+
# Offset the current timestamp by a number of seconds
|
482
|
+
def seconds(num)
|
483
|
+
t = Time.now + num
|
484
|
+
{
|
485
|
+
:type => :datetime,
|
486
|
+
:value => t.iso8601
|
487
|
+
}
|
488
|
+
end
|
489
|
+
|
490
|
+
# Offset the current timestamp by a number of minutes
|
491
|
+
def minutes(num)
|
492
|
+
t = Time.now + num * SECONDS_IN_MINUTE
|
493
|
+
{
|
494
|
+
:type => :datetime,
|
495
|
+
:value => t.iso8601
|
496
|
+
}
|
497
|
+
end
|
498
|
+
|
499
|
+
# Offset the current timestamp by a number of hours
|
500
|
+
def hours(num)
|
501
|
+
t = Time.now + num * SECONDS_IN_HOUR
|
502
|
+
{
|
503
|
+
:type => :datetime,
|
504
|
+
:value => t.iso8601
|
505
|
+
}
|
506
|
+
end
|
507
|
+
|
467
508
|
# Offset the current timestamp by a number of days
|
468
509
|
def days(num)
|
469
510
|
# date calculated as the offset from midnight tommorrow. Zero will provide values for all times
|
data/lib/sparkql/parser.rb
CHANGED
@@ -279,6 +279,175 @@ class FunctionResolverTest < Test::Unit::TestCase
|
|
279
279
|
assert_equal "ListPrice", value[:args].first[:value]
|
280
280
|
end
|
281
281
|
|
282
|
+
test "seconds()" do
|
283
|
+
dt = Time.new(2019, 4, 1, 8, 30, 20, 0)
|
284
|
+
|
285
|
+
Time.expects(:now).returns(dt).times(3)
|
286
|
+
|
287
|
+
f = FunctionResolver.new('seconds', [{:type=>:integer, :value => 7}])
|
288
|
+
f.validate
|
289
|
+
assert !f.errors?, "Errors #{f.errors.inspect}"
|
290
|
+
value = f.call
|
291
|
+
|
292
|
+
assert_equal :datetime, value[:type]
|
293
|
+
d = DateTime.parse(value[:value])
|
294
|
+
assert_equal dt.year, d.year
|
295
|
+
assert_equal dt.month, d.month
|
296
|
+
assert_equal dt.mday, d.mday
|
297
|
+
assert_equal dt.hour, d.hour
|
298
|
+
assert_equal dt.min, d.min
|
299
|
+
assert_equal dt.sec + 7, d.sec
|
300
|
+
|
301
|
+
f = FunctionResolver.new('seconds', [{:type=>:integer, :value => -21}])
|
302
|
+
f.validate
|
303
|
+
assert !f.errors?, "Errors #{f.errors.inspect}"
|
304
|
+
value = f.call
|
305
|
+
|
306
|
+
assert_equal :datetime, value[:type]
|
307
|
+
d = DateTime.parse(value[:value])
|
308
|
+
assert_equal dt.year, d.year
|
309
|
+
assert_equal dt.month, d.month
|
310
|
+
assert_equal dt.mday, d.mday
|
311
|
+
assert_equal dt.hour, d.hour
|
312
|
+
assert_equal dt.min - 1, d.min
|
313
|
+
assert_equal 29, d.min
|
314
|
+
assert_equal 59, d.sec
|
315
|
+
|
316
|
+
f = FunctionResolver.new('seconds', [{:type=>:integer,
|
317
|
+
:value => -Sparkql::FunctionResolver::SECONDS_IN_DAY}])
|
318
|
+
f.validate
|
319
|
+
assert !f.errors?, "Errors #{f.errors.inspect}"
|
320
|
+
value = f.call
|
321
|
+
|
322
|
+
assert_equal :datetime, value[:type]
|
323
|
+
d = DateTime.parse(value[:value])
|
324
|
+
assert_equal dt.year, d.year
|
325
|
+
assert_equal dt.month - 1, d.month
|
326
|
+
assert_equal 31, d.mday
|
327
|
+
assert_equal dt.hour, d.hour
|
328
|
+
assert_equal dt.min, d.min
|
329
|
+
assert_equal dt.min, d.min
|
330
|
+
assert_equal dt.sec, d.sec
|
331
|
+
end
|
332
|
+
|
333
|
+
test "minutes()" do
|
334
|
+
dt =Time.new(2019, 4, 1, 8, 30, 20, 0)
|
335
|
+
|
336
|
+
Time.expects(:now).returns(dt).times(3)
|
337
|
+
|
338
|
+
f = FunctionResolver.new('minutes', [{:type=>:integer, :value => 7}])
|
339
|
+
f.validate
|
340
|
+
assert !f.errors?, "Errors #{f.errors.inspect}"
|
341
|
+
value = f.call
|
342
|
+
|
343
|
+
assert_equal :datetime, value[:type]
|
344
|
+
d = DateTime.parse(value[:value])
|
345
|
+
assert_equal dt.year, d.year
|
346
|
+
assert_equal dt.month, d.month
|
347
|
+
assert_equal dt.mday, d.mday
|
348
|
+
assert_equal dt.hour, d.hour
|
349
|
+
assert_equal dt.min + 7, d.min
|
350
|
+
assert_equal dt.sec, d.sec
|
351
|
+
|
352
|
+
f = FunctionResolver.new('minutes', [{:type=>:integer, :value => -37}])
|
353
|
+
f.validate
|
354
|
+
assert !f.errors?, "Errors #{f.errors.inspect}"
|
355
|
+
value = f.call
|
356
|
+
|
357
|
+
assert_equal :datetime, value[:type]
|
358
|
+
d = DateTime.parse(value[:value])
|
359
|
+
assert_equal dt.year, d.year
|
360
|
+
assert_equal dt.month, d.month
|
361
|
+
assert_equal dt.mday, d.mday
|
362
|
+
assert_equal dt.hour-1, d.hour
|
363
|
+
assert_equal 53, d.min
|
364
|
+
|
365
|
+
f = FunctionResolver.new('minutes', [{:type=>:integer,
|
366
|
+
:value => -1440}])
|
367
|
+
f.validate
|
368
|
+
assert !f.errors?, "Errors #{f.errors.inspect}"
|
369
|
+
value = f.call
|
370
|
+
|
371
|
+
assert_equal :datetime, value[:type]
|
372
|
+
d = DateTime.parse(value[:value])
|
373
|
+
assert_equal dt.year, d.year
|
374
|
+
assert_equal dt.month - 1, d.month
|
375
|
+
assert_equal 31, d.mday
|
376
|
+
assert_equal dt.hour, d.hour
|
377
|
+
assert_equal dt.min, d.min
|
378
|
+
end
|
379
|
+
|
380
|
+
test "hours(), same day" do
|
381
|
+
dt =Time.new(2019, 4, 1, 8, 30, 20, 0)
|
382
|
+
|
383
|
+
tests = [1, -1, 5, -5, 12]
|
384
|
+
Time.expects(:now).returns(dt).times(tests.count)
|
385
|
+
|
386
|
+
tests.each do |offset|
|
387
|
+
f = FunctionResolver.new('hours', [{:type=>:integer,
|
388
|
+
:value => offset}])
|
389
|
+
f.validate
|
390
|
+
assert !f.errors?, "Errors #{f.errors.inspect}"
|
391
|
+
value = f.call
|
392
|
+
|
393
|
+
assert_equal :datetime, value[:type]
|
394
|
+
d = DateTime.parse(value[:value])
|
395
|
+
assert_equal dt.year, d.year
|
396
|
+
assert_equal dt.month, d.month
|
397
|
+
assert_equal dt.mday, d.mday
|
398
|
+
assert_equal dt.hour + offset, d.hour
|
399
|
+
assert_equal dt.min, d.min
|
400
|
+
assert_equal dt.sec, d.sec
|
401
|
+
end
|
402
|
+
end
|
403
|
+
|
404
|
+
test "hours(), wrap day" do
|
405
|
+
dt =Time.new(2019, 4, 1, 8, 30, 20, 0)
|
406
|
+
Time.expects(:now).returns(dt).times(3)
|
407
|
+
|
408
|
+
# Jump forward a few days, and a few hours.
|
409
|
+
f = FunctionResolver.new('hours', [{:type=>:integer, :value => 52}])
|
410
|
+
f.validate
|
411
|
+
assert !f.errors?, "Errors #{f.errors.inspect}"
|
412
|
+
value = f.call
|
413
|
+
|
414
|
+
assert_equal :datetime, value[:type]
|
415
|
+
d = DateTime.parse(value[:value])
|
416
|
+
assert_equal dt.year, d.year
|
417
|
+
assert_equal dt.month, d.month
|
418
|
+
assert_equal dt.mday + 2, d.mday
|
419
|
+
assert_equal dt.hour + 4, d.hour
|
420
|
+
assert_equal dt.min, d.min
|
421
|
+
|
422
|
+
# Drop back to the previous day, which'll also hit the previous month
|
423
|
+
f = FunctionResolver.new('hours', [{:type=>:integer, :value => -24}])
|
424
|
+
f.validate
|
425
|
+
assert !f.errors?, "Errors #{f.errors.inspect}"
|
426
|
+
value = f.call
|
427
|
+
|
428
|
+
assert_equal :datetime, value[:type]
|
429
|
+
d = DateTime.parse(value[:value])
|
430
|
+
assert_equal dt.year, d.year
|
431
|
+
assert_equal dt.month - 1, d.month
|
432
|
+
assert_equal 31, d.mday
|
433
|
+
assert_equal dt.hour, d.hour
|
434
|
+
assert_equal dt.min, d.min
|
435
|
+
|
436
|
+
# Drop back one full year's worth of hours.
|
437
|
+
f = FunctionResolver.new('hours', [{:type=>:integer, :value => -8760}])
|
438
|
+
f.validate
|
439
|
+
assert !f.errors?, "Errors #{f.errors.inspect}"
|
440
|
+
value = f.call
|
441
|
+
|
442
|
+
assert_equal :datetime, value[:type]
|
443
|
+
d = DateTime.parse(value[:value])
|
444
|
+
assert_equal dt.year - 1, d.year
|
445
|
+
assert_equal dt.month, d.month
|
446
|
+
assert_equal dt.mday, d.mday
|
447
|
+
assert_equal dt.hour, d.hour
|
448
|
+
assert_equal dt.min, d.min
|
449
|
+
end
|
450
|
+
|
282
451
|
test "days()" do
|
283
452
|
d = Date.new(2012,10,20)
|
284
453
|
Date.expects(:today).returns(d)
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: sparkql
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.2.
|
4
|
+
version: 1.2.6
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Wade McEwen
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2019-04-04 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: georuby
|