lib/timeliness/parser.rb in timeliness-0.2.0 vs lib/timeliness/parser.rb in timeliness-0.3.0
- old
+ new
@@ -5,55 +5,64 @@
class << self
def parse(value, *args)
return value unless value.is_a?(String)
- options = args.last.is_a?(Hash) ? args.pop : {}
- type = args.first
+ type, options = type_and_options_from_args(args)
time_array = _parse(value, type, options)
return nil if time_array.nil?
- override_values_by_type(time_array, type, options) unless type == :datetime
- make_time(time_array[0..6], options[:zone])
+ 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 =~ /zone/
raise MissingTimezoneSupport, "ActiveSupport must be loaded to use timezones other than :utc and :local."
end
- def make_time(time_array, zone=nil)
+ def make_time(time_array, zone_option=nil)
return nil unless fast_date_valid_with_fallback(*time_array[0..2])
- zone ||= Timeliness.default_timezone
- case zone
- when :utc, :local
- time_with_datetime_fallback(zone, *time_array.compact)
- when :current
- Time.zone.local(*time_array)
- else
- Time.use_zone(zone) { Time.zone.local(*time_array) }
- end
+ zone_or_offset = time_array.delete_at(7)
+ zone, offset = zone_and_offset(zone_or_offset) if zone_or_offset
+
+ value = create_time_in_zone(time_array, zone || zone_option)
+ value = time_in_zone(value, zone_option) if zone
+
+ offset ? value + (value.utc_offset - offset) : value
rescue ArgumentError, TypeError
nil
end
def _parse(string, type=nil, options={})
if options[:strict] && type
- set = Formats.send("#{type}_format_set")
+ set = Definitions.send("#{type}_format_set")
set.match(string, options[:format])
else
values = nil
- Formats.format_set(type, string).find {|set| values = set.match(string, options[:format]) }
+ Definitions.format_sets(type, string).find {|set| values = set.match(string, options[:format]) }
values
end
rescue
nil
end
private
- def override_values_by_type(values, type, options)
+ 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.is_a?(Hash)
+ options[:now] = type_or_now
+ end
+ return type, options
+ end
+
+ def default_values_by_type(values, type, options)
case type
when :date
values[3..7] = nil
when :time
values[0..2] = current_date(options)
@@ -83,9 +92,42 @@
when :current
Time.current
else
Time.use_zone(zone) { Time.current }
end
+ end
+
+ def time_in_zone(time, zone=nil)
+ zone ||= Timeliness.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
+
+ def create_time_in_zone(time_array, zone=nil)
+ zone ||= Timeliness.default_timezone
+ case zone
+ when :utc, :local
+ time_with_datetime_fallback(zone, *time_array.compact)
+ when :current
+ Time.zone.local(*time_array)
+ else
+ Time.use_zone(zone) { Time.zone.local(*time_array) }
+ end
+ end
+
+ 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
# Taken from ActiveSupport and simplified
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