sparkql 1.2.5 → 1.2.6

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,15 +1,15 @@
1
1
  ---
2
2
  !binary "U0hBMQ==":
3
3
  metadata.gz: !binary |-
4
- ODQ4YzQ0YzQ1YmJkMDNlMmUxMmFiZTUyZWY2NTcwNjY0YTM2ZTE3OA==
4
+ MzM0ZTA3ZTIxNjlkMzY5YmFiMGM4MGFkOTA2NWZlNzMzZWQxNTQxMw==
5
5
  data.tar.gz: !binary |-
6
- NTEyZDlkMWVjY2RjZDY2ZTJlMTg3YjNjNTc4NmE2ZDc3ODdhNTAyYQ==
6
+ ZmE5ZTQwZDc1YzI0YTJmZTRjYzMxMGY3ZDZmYmFmNzkxMWRmNTBiMg==
7
7
  SHA512:
8
8
  metadata.gz: !binary |-
9
- MzMwODdhYTQ3NWQwYzlhYjQ5NWM2ZTNkZDlhMzczMWZmMDg1NDliZWMyOWJj
10
- MmQ3MzMwNjBiYjIzMzE3Y2JiNzk2YzQxMzgyM2EzZDM1MTc4OTVkYmM5YTQw
11
- YjQ3NDVjZWVmZjcyZDkxNzE3ZjI5NTFhODU4NWI5ZjZhYWU1YTA=
9
+ Mjc0NjNjNGVkYWE1ZDVlNzIwNTY3ZDNjZmFiZDc2NGI5MmNlNGU5MjYzN2Yy
10
+ NTc1ZTMwYTVmNmM5Nzk2Mjk5OTk2Nzc5ZmYyNTA3Njc2ZmU0NjkzM2I2ZmQx
11
+ YTQxMzIzZjBjNDU0NTc1Y2VmYzMyNGRmZDNmNWFlNTFmYzFiZjg=
12
12
  data.tar.gz: !binary |-
13
- MmE5ODM3ODdmYTY3MGMxN2I2Mjc2MmQ2NjQwNDM0ZTNiYzU4YTkxYjVkNWE3
14
- YThkMmNlZDA3MjI0MWU0MDdkOTVmNzI4NDhkMmMzNTA5ZGYyNTM1ZGM4NDZm
15
- M2M2ZjdmYTBlMTEwODUxN2ZkMDIyYmQyZDFjNjNmNGU5YTU2MGQ=
13
+ MzczODc4ZTAyOTRkNDlhNzZiYTQxYjUyM2FlMTQ0ZmU3NmMyZmY2Y2Q2YmFj
14
+ MTk0ODFmMTFmZmI4MTQ2MzkxOTFiYjkwYmM1NGQ1NzdmZjNiMjZmYjQ4MGJi
15
+ ODY1NmM3NWJhNTFmMzgxY2EwZGU5NWY1ZGVmYTVkZTBjMGZlNmU=
@@ -1,3 +1,7 @@
1
+ v1.2.6, 2019-04-01
2
+ -------------------
3
+ * [IMPROVEMENT] hours(), minutes(), and seconds() functions
4
+
1
5
  v1.2.5, 2018-12-19
2
6
  -------------------
3
7
  * [BUGFIX] Correctly handle arithmetic grouping
data/VERSION CHANGED
@@ -1 +1 @@
1
- 1.2.5
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
- SECONDS_IN_DAY = 60 * 60 * 24
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
@@ -1,6 +1,6 @@
1
1
  #
2
2
  # DO NOT MODIFY!!!!
3
- # This file is automatically generated by Racc 1.4.14
3
+ # This file is automatically generated by Racc 1.4.15
4
4
  # from Racc grammer file "".
5
5
  #
6
6
 
@@ -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.5
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: 2018-12-19 00:00:00.000000000 Z
11
+ date: 2019-04-04 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: georuby