module Timeliness::Parser
Public Class Methods
_parse(string, type=nil, options={})
click to toggle source
# File lib/timeliness/parser.rb, line 38 def _parse(string, type=nil, options={}) if options[:strict] && type Definitions.send("#{type}_format_set").match(string, options[:format]) else values = nil Definitions.format_sets(type, string).find {|set| values = set.match(string, options[:format]) } values end rescue nil end
make_time(time_array, zone_option=nil)
click to toggle source
# File lib/timeliness/parser.rb, line 24 def make_time(time_array, zone_option=nil) return nil unless fast_date_valid_with_fallback(*time_array[0..2]) zone, offset = zone_and_offset(time_array[7]) if time_array[7] value = create_time_in_zone(time_array[0..6].compact, zone || zone_option) value = shift_time_to_zone(value, zone_option) if zone return nil unless value offset ? value + (value.utc_offset - offset) : value rescue ArgumentError, TypeError nil end
parse(value, *args)
click to toggle source
# File lib/timeliness/parser.rb, line 7 def parse(value, *args) return value if acts_like_temporal?(value) return nil unless parseable?(value) type, options = type_and_options_from_args(args) time_array = _parse(value, type, options) return nil if time_array.nil? default_values_by_type(time_array, type, options) unless type == :datetime make_time(time_array[0..7], options[:zone]) rescue NoMethodError => ex raise ex unless ex.message =~ /undefined method `(zone|use_zone|current)' for Time:Class/ raise MissingTimezoneSupport, "ActiveSupport timezone support must be loaded to use timezones other than :utc and :local." end
Private Class Methods
acts_like_temporal?(value)
click to toggle source
# File lib/timeliness/parser.rb, line 56 def acts_like_temporal?(value) value.is_a?(Time) || value.is_a?(Date) || value.respond_to?(:acts_like_date?) || value.respond_to?(:acts_like_time?) end
create_time_in_zone(time_array, zone=nil)
click to toggle source
# File lib/timeliness/parser.rb, line 119 def create_time_in_zone(time_array, zone=nil) zone ||= Timeliness.configuration.default_timezone case zone when :utc, :local time_with_datetime_fallback(zone, *time_array) when :current Time.zone.local(*time_array) else Time.use_zone(zone) { Time.zone.local(*time_array) } end end
current_date(options)
click to toggle source
# File lib/timeliness/parser.rb, line 85 def current_date(options) now = if options[:now] options[:now] elsif options[:zone] current_time_in_zone(options[:zone]) else evaluate_date_for_time_type end now.is_a?(Array) ? now[0..2] : [now.year, now.month, now.day] end
current_time_in_zone(zone)
click to toggle source
# File lib/timeliness/parser.rb, line 96 def current_time_in_zone(zone) case zone when :utc, :local Time.now.send("get#{zone}") when :current Time.current else Time.use_zone(zone) { Time.current } end end
default_values_by_type(values, type, options)
click to toggle source
# File lib/timeliness/parser.rb, line 71 def default_values_by_type(values, type, options) case type when :date values[3..7] = nil when :time values[0..2] = current_date(options) when nil dummy_date = current_date(options) values[0] ||= dummy_date[0] values[1] ||= dummy_date[1] unless values.values_at(0,2).all? values[2] ||= dummy_date[2] end end
evaluate_date_for_time_type()
click to toggle source
# File lib/timeliness/parser.rb, line 155 def evaluate_date_for_time_type date_for_time_type = Timeliness.configuration.date_for_time_type case date_for_time_type when Array date_for_time_type when Proc v = date_for_time_type.call [v.year, v.month, v.day] end end
fast_date_valid_with_fallback(year, month, day)
click to toggle source
Enforce strict date part validity which the Time class does not. Only does full date check if month and day are possibly invalid.
# File lib/timeliness/parser.rb, line 151 def fast_date_valid_with_fallback(year, month, day) month && month < 13 && (day < 29 || Date.valid_civil?(year, month, day)) end
parseable?(value)
click to toggle source
# File lib/timeliness/parser.rb, line 52 def parseable?(value) value.is_a?(String) end
shift_time_to_zone(time, zone=nil)
click to toggle source
# File lib/timeliness/parser.rb, line 107 def shift_time_to_zone(time, zone=nil) zone ||= Timeliness.configuration.default_timezone case zone when :utc, :local time.send("get#{zone}") when :current time.in_time_zone else Time.use_zone(zone) { time.in_time_zone } end end
time_with_datetime_fallback(utc_or_local, year, month=1, day=1, hour=0, min=0, sec=0, usec=0)
click to toggle source
Taken from ActiveSupport and simplified
# File lib/timeliness/parser.rb, line 141 def time_with_datetime_fallback(utc_or_local, year, month=1, day=1, hour=0, min=0, sec=0, usec=0) return nil if hour > 23 || min > 59 || sec > 59 ::Time.send(utc_or_local, year, month, day, hour, min, sec, usec) rescue offset = utc_or_local == :local ? (::Time.local(2007).utc_offset.to_r/86400) : 0 ::DateTime.civil(year, month, day, hour, min, sec, offset) end
type_and_options_from_args(args)
click to toggle source
# File lib/timeliness/parser.rb, line 60 def type_and_options_from_args(args) options = args.last.is_a?(Hash) ? args.pop : {} type_or_now = args.first if type_or_now.is_a?(Symbol) type = type_or_now elsif type_or_now options[:now] = type_or_now end return type, options end
zone_and_offset(parsed_value)
click to toggle source
# File lib/timeliness/parser.rb, line 131 def zone_and_offset(parsed_value) if parsed_value.is_a?(String) zone = Definitions.timezone_mapping[parsed_value] || parsed_value else offset = parsed_value end return zone, offset end