Module: Binxtils::TimeZoneParser
- Extended by:
- Functionable
- Defined in:
- lib/binxtils/time_zone_parser.rb
Instance Method Summary collapse
- #full_name(time_zone) ⇒ Object
- #parse(time_zone_str) ⇒ Object
- #parse_from_time_and_offset(time:, offset:) ⇒ Object
- #parse_from_time_string(time_str) ⇒ Object
- #prioritize_zones(zones) ⇒ Object
-
#prioritized_zones_matching_offset(at, offset_seconds) ⇒ Object
Guess possible time zones based on UTC offset at a specific time Returns an array of [timezone_name, city_name] pairs.
-
#time_string_has_zone_info?(time_str) ⇒ Boolean
TODO: This might be overly complicated garbage.
Instance Method Details
#full_name(time_zone) ⇒ Object
35 36 37 38 |
# File 'lib/binxtils/time_zone_parser.rb', line 35 def full_name(time_zone) # TODO: figure out an easier way to get this ActiveSupport::TimeZone::MAPPING.key(time_zone.tzinfo.name) || time_zone.name end |
#parse(time_zone_str) ⇒ Object
7 8 9 10 11 12 13 14 15 |
# File 'lib/binxtils/time_zone_parser.rb', line 7 def parse(time_zone_str) return nil if time_zone_str.blank? return time_zone_str if time_zone_str.is_a?(ActiveSupport::TimeZone) # in case we were given a time_zone obj # tzinfo requires non-whitespaced strings. # if the normal lookup fails, remove parens, then remove spaces and convert to underscores ActiveSupport::TimeZone[time_zone_str] || ActiveSupport::TimeZone[time_zone_str.to_s.gsub(/\(.*?\)/, "").strip.tr("\s", "_")] end |
#parse_from_time_and_offset(time:, offset:) ⇒ Object
28 29 30 31 32 33 |
# File 'lib/binxtils/time_zone_parser.rb', line 28 def parse_from_time_and_offset(time:, offset:) offset_seconds = offset.is_a?(String) ? Time.zone_offset(offset) : offset offset_seconds ||= offset.to_i # Fallback parsing of seconds in a string prioritized_zones_matching_offset(time, offset_seconds).first end |
#parse_from_time_string(time_str) ⇒ Object
17 18 19 20 21 22 23 24 25 26 |
# File 'lib/binxtils/time_zone_parser.rb', line 17 def parse_from_time_string(time_str) return unless time_str.present? && time_string_has_zone_info?(time_str) at = Time.parse(time_str.to_s) offset_seconds = at.utc_offset # Otherwise this returns casablanca. Guess UTC over London return ActiveSupport::TimeZone["UTC"] if offset_seconds == 0 prioritized_zones_matching_offset(at, offset_seconds).first end |
#prioritize_zones(zones) ⇒ Object
85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 |
# File 'lib/binxtils/time_zone_parser.rb', line 85 def prioritize_zones(zones) zones.sort_by do |zone| priority = case zone.tzinfo.name # Major US zones when /New_York/, /Chicago/, /Los_Angeles/ then 1 # Major European zones when /London/, /Paris/, /Berlin/ then 5 # Major Asian zones when /Tokyo/, /Shanghai/, /Singapore/ then 5 # Major cities generally when /Mexico City|Sydney|Hong_Kong|Dubai|Toronto|Vancouver/ then 10 # State/Provincial capitals when /Melbourne|Brisbane|Perth|Montreal|Edmonton/ then 20 # Smaller cities else 100 end [priority, zone] end end |
#prioritized_zones_matching_offset(at, offset_seconds) ⇒ Object
Guess possible time zones based on UTC offset at a specific time Returns an array of [timezone_name, city_name] pairs
68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 |
# File 'lib/binxtils/time_zone_parser.rb', line 68 def prioritized_zones_matching_offset(at, offset_seconds) # Convert seconds to hours for comparison offset_hours = offset_seconds / 3600.0 # Get all time zones possible_zones = ActiveSupport::TimeZone.all.select do |zone| # Calculate the offset at the specific time zone_time = at.in_time_zone(zone) zone_offset = zone_time.utc_offset / 3600.0 zone_offset == offset_hours end # Sort zones by priority/popularity prioritize_zones(possible_zones) end |
#time_string_has_zone_info?(time_str) ⇒ Boolean
TODO: This might be overly complicated garbage
45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 |
# File 'lib/binxtils/time_zone_parser.rb', line 45 def time_string_has_zone_info?(time_str) return false if Binxtils::TimeParser.(time_str) timezone_patterns = [ /[+-]\d{2}:?\d{2}\b/, # +0900, +09:00, -0500, etc /\b(?:UTC|GMT)\b/i, # UTC or GMT /\b[A-Z]{3,4}\b/, # EST, PDT, AEST, etc /[+-]\d{4}\b/, # +0900, -0500 without colon /Z\b/, # UTC (Zulu time) /\[[-+A-Za-z0-9\/]+\]/ # Time zone in brackets [America/New_York] ] # Try parsing to validate it's actually a time string Time.parse(time_str) # Check if any timezone pattern matches timezone_patterns.any? { |pattern| time_str.match?(pattern) } rescue ArgumentError false end |