binxtils 0.4.2 → 0.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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 15e2f7ef3eacc9bc7a549e93c60b48a4c64f3d3880b7cacb5b70f4a4962752b8
4
- data.tar.gz: aca6cfcec5e692f27810f3930a37b75b345263ffca350a0402b697b72f5bdd47
3
+ metadata.gz: e72c90471da7710071e132edf196d7599c104c825c57c763473dc7b2d76e013b
4
+ data.tar.gz: 8db5ae15b52cbf23d5a2e3a2ca5b5fb1b16a790e3c1c50b9a38f0f4519796c4c
5
5
  SHA512:
6
- metadata.gz: 1615e2f50804ad8556c23c6f8d804eaf1c6c6ac96714a2ecc256d8f054240ba978ee7acfba8b674e44b5eefe8f2da4b7e305d337314fd09d2780271ec04c6e1c
7
- data.tar.gz: e84cbc603fd7762034ae2b86f7f5cbe8540879bc5f1b7101e062eb7212e017625e96fd35a76e1111273dd1ba8e0bb13f2cb5d68ab80153aca70a1fcd48f1d951
6
+ metadata.gz: 0fcf63a17b0886fcb73543e5ddbd363b95237eb257a159451d2a6af6b15ecf45354dcafd17cfd3e359b565459e28ce3ddad4b17d57d02562dc2b87b1ad9296d9
7
+ data.tar.gz: 2ffc0ce173f6d2431b831451f8c40f5668740c732ceb543ed90a584d3fba7f9c4e4c145281b92cee1d4a4b9842a7e2710483cf8eb84c073ce83f4f47122ac958
@@ -16,16 +16,15 @@ module Binxtils
16
16
  # Set time period
17
17
  @period ||= params[:period]
18
18
  if @period == "custom"
19
- if params[:start_time].present?
20
- @start_time = Binxtils::TimeParser.parse(params[:start_time], @timezone)
21
- @end_time = Binxtils::TimeParser.parse(params[:end_time], @timezone) || latest_period_date
19
+ @start_time = Binxtils::TimeParser.parse(params[:start_time], @timezone, parse_error: :nil)
20
+ if @start_time.present?
21
+ @end_time = Binxtils::TimeParser.parse(params[:end_time], @timezone, parse_error: :nil) || latest_period_date
22
22
  @start_time, @end_time = @end_time, @start_time if @start_time > @end_time
23
23
  else
24
24
  set_time_range_from_period
25
25
  end
26
- elsif params[:search_at].present?
26
+ elsif (@search_at = Binxtils::TimeParser.parse(params[:search_at], @timezone, parse_error: :nil))
27
27
  @period = "custom"
28
- @search_at = Binxtils::TimeParser.parse(params[:search_at], @timezone)
29
28
  offset = params[:period].present? ? params[:period].to_i : 10.minutes.to_i
30
29
  @start_time = @search_at - offset
31
30
  @end_time = @search_at + offset
@@ -31,16 +31,16 @@ module Binxtils
31
31
  render_sortable = html_options.key?(:render_sortable) ? html_options[:render_sortable] : !html_options[:skip_sortable]
32
32
  return title unless render_sortable
33
33
 
34
- html_options[:class] = "#{html_options[:class]} sortable-link"
35
- direction = (column == sort_column && sort_direction == "desc") ? "asc" : "desc"
34
+ active = column == sort_column
35
+ direction = (active && sort_direction == "desc") ? "asc" : "desc"
36
+ span_content = ((direction == "asc") ? "\u2193" : "\u2191") if active
36
37
 
37
- if column == sort_column
38
- html_options[:class] += " active"
39
- span_content = (direction == "asc") ? "\u2193" : "\u2191"
40
- end
38
+ link_options = html_options.except(:render_sortable, :skip_sortable)
39
+ .merge(class: [html_options[:class], "sortable-link", ("active" if active)].compact.join(" "))
41
40
 
42
- link_to(sortable_url(column, direction), html_options) do
43
- concat(block_given? ? capture(&block) : title.html_safe)
41
+ # Titles are escaped (not marked html_safe) - pass a block to render HTML
42
+ link_to(sortable_url(column, direction), link_options) do
43
+ concat(block_given? ? capture(&block) : title)
44
44
  concat(content_tag(:span, span_content, class: "sortable-direction"))
45
45
  end
46
46
  end
@@ -13,7 +13,7 @@ module Binxtils
13
13
  def string(val)
14
14
  return nil if val.blank?
15
15
 
16
- val.delete("\u0000").strip.gsub(/\s+/, " ")
16
+ val.to_s.delete("\u0000").strip.gsub(/\s+/, " ")
17
17
  end
18
18
 
19
19
  def present_or_false?(val)
@@ -5,26 +5,48 @@ module Binxtils
5
5
  extend Functionable
6
6
 
7
7
  EARLIEST_YEAR = 1900
8
- LATEST_YEAR = Time.current.year + 100
9
8
 
10
9
  def default_time_zone
11
10
  @default_time_zone ||= ActiveSupport::TimeZone[Rails.application.class.config.time_zone].freeze
12
11
  end
13
12
 
14
- def parse(time_str = nil, time_zone_str = nil, in_time_zone: false)
13
+ # parse_error: :raise raises unparseable input errors, :nil swallows them
14
+ def parse(time_str = nil, time_zone_str = nil, in_time_zone: false, parse_error: :raise)
15
+ parse!(time_str, time_zone_str, in_time_zone:)
16
+ rescue ArgumentError
17
+ raise unless parse_error == :nil
18
+ nil
19
+ end
20
+
21
+ def looks_like_timestamp?(time_str)
22
+ time_str.is_a?(Integer) || time_str.is_a?(Float) || time_str.to_s.strip.match(/^\d+\z/) # it's only numbers
23
+ end
24
+
25
+ # Accepts a time object, rounds to minutes
26
+ def round(time, unit = "minute")
27
+ if unit == "second"
28
+ time.change(usec: 0, sec: 0)
29
+ else # Default is minute, nothing is built to manage anything else
30
+ time.change(min: 0, usec: 0, sec: 0)
31
+ end
32
+ end
33
+
34
+ #
35
+ # private below here
36
+ #
37
+
38
+ def parse!(time_str = nil, time_zone_str = nil, in_time_zone: false)
15
39
  return nil unless time_str.present?
16
40
  return time_str if time_str.is_a?(Time)
17
41
 
18
42
  if looks_like_timestamp?(time_str)
19
- return parse("#{time_str}-01-01") if time_str.to_s.length == 4 # Looks like year, valid 8601 format
43
+ return parse!("#{time_str}-01-01") if time_str.to_s.length == 4 # Looks like year, valid 8601 format
20
44
 
21
45
  # otherwise it's a timestamp
22
46
  time = Time.at(time_str.to_i)
23
47
  else
24
48
  time_zone = Binxtils::TimeZoneParser.parse(time_zone_str)
25
- Time.zone = time_zone
26
- time = Time.zone.parse(time_str.to_s) # Assign in time zone
27
- Time.zone = default_time_zone
49
+ time = (time_zone || Time.zone).parse(time_str.to_s) # Assign in time zone
28
50
  end
29
51
  # Return in time_zone or not
30
52
  in_time_zone ? time_in_zone(time, time_str:, time_zone:, time_zone_str:) : time
@@ -32,8 +54,8 @@ module Binxtils
32
54
  # Try to parse some other, unexpected formats -
33
55
  paychex_formatted = %r{(?<month>\d+)/(?<day>\d+)/(?<year>\d+) (?<hour>\d\d):(?<minute>\d\d) (?<ampm>\w\w)}.match(time_str)
34
56
  ie11_formatted = %r{(?<month>\d+)/(?<day>\d+)/(?<year>\d+)}.match(time_str)
35
- just_date = %r{(?<year>\d{4})[^\d|\w](?<month>\d\d?)}.match(time_str)
36
- just_date_backward = %r{(?<month>\d\d?)[^\d|\w](?<year>\d{4})}.match(time_str)
57
+ just_date = %r{(?<year>\d{4})\D(?<month>\d\d?)}.match(time_str)
58
+ just_date_backward = %r{(?<month>\d\d?)\D(?<year>\d{4})}.match(time_str)
37
59
 
38
60
  # Get the successful matching regex group, and then reformat it in an expected way
39
61
  regex_match = [paychex_formatted, ie11_formatted, just_date, just_date_backward].compact.first
@@ -44,8 +66,10 @@ module Binxtils
44
66
  .compact
45
67
  .join("-")
46
68
 
47
- # If we end up with an unreasonable year, throw an error
48
- raise e unless new_str.split("-").first.to_i.between?(EARLIEST_YEAR, LATEST_YEAR)
69
+ # If we end up with an unreasonable year or month, throw an error
70
+ # (an invalid month would otherwise recurse forever, re-matching and re-appending the day)
71
+ raise e unless new_str.split("-").first.to_i.between?(EARLIEST_YEAR, Time.current.year + 100)
72
+ raise e unless regex_match["month"].to_i.between?(1, 12)
49
73
 
50
74
  # Add the day, if there isn't one
51
75
  new_str += "-01" unless regex_match.names.include?("day")
@@ -54,26 +78,9 @@ module Binxtils
54
78
  new_str += " #{regex_match["hour"]}:#{regex_match["minute"]}#{regex_match["ampm"]}"
55
79
  end
56
80
  # Run it through Binxtils::TimeParser again
57
- parse(new_str, time_zone_str, in_time_zone:)
58
- end
59
-
60
- def looks_like_timestamp?(time_str)
61
- time_str.is_a?(Integer) || time_str.is_a?(Float) || time_str.to_s.strip.match(/^\d+\z/) # it's only numbers
62
- end
63
-
64
- # Accepts a time object, rounds to minutes
65
- def round(time, unit = "minute")
66
- if unit == "second"
67
- time.change(usec: 0, sec: 0)
68
- else # Default is minute, nothing is built to manage anything else
69
- time.change(min: 0, usec: 0, sec: 0)
70
- end
81
+ parse!(new_str, time_zone_str, in_time_zone:)
71
82
  end
72
83
 
73
- #
74
- # private below here
75
- #
76
-
77
84
  def time_in_zone(time, time_zone_str:, time_str: nil, time_zone: nil)
78
85
  time_zone ||= if time_zone_str.present?
79
86
  Binxtils::TimeZoneParser.parse(time_zone_str)
@@ -85,6 +92,6 @@ module Binxtils
85
92
  time.in_time_zone(time_zone || ActiveSupport::TimeZone["UTC"])
86
93
  end
87
94
 
88
- conceal :time_in_zone
95
+ conceal :time_in_zone, :parse!
89
96
  end
90
97
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Binxtils
4
- VERSION = "0.4.2"
4
+ VERSION = "0.5"
5
5
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: binxtils
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.4.2
4
+ version: '0.5'
5
5
  platform: ruby
6
6
  authors:
7
7
  - Bike Index