class Time
DATE_FORMATS = {
:db => '%Y-%m-%d %H:%M:%S',
:number => '%Y%m%d%H%M%S',
:nsec => '%Y%m%d%H%M%S%9N',
:time => '%H:%M',
:short => '%d %b %H:%M',
:long => '%B %d, %Y %H:%M',
:long_ordinal => lambda { |time|
day_format = MotionSupport::Inflector.ordinalize(time.day)
time.strftime("%B #{day_format}, %Y %H:%M")
},
:rfc822 => lambda { |time|
offset_format = time.formatted_offset(false)
time.strftime("%a, %d %b %Y %H:%M:%S #{offset_format}")
},
:iso8601 => '%Y-%m-%dT%H:%M:%SZ'
}
# Accepts a iso8601 time string and returns a new instance of Time
def self.iso8601(time_string)
format_string = "yyyy-MM-dd'T'HH:mm:ss"
# Fractional Seconds
format_string += '.SSS' if time_string.include?('.')
# Zulu (standard) or with a timezone
format_string += time_string.include?('Z') ? "'Z'" : 'ZZZZZ'
cached_date_formatter(format_string).dateFromString(time_string)
end
# Returns an iso8601-compliant string
# This method is aliased to xmlschema.
def iso8601
utc.strftime DATE_FORMATS[:iso8601]
end
alias_method :xmlschema, :iso8601
# Converts to a formatted string. See DATE_FORMATS for builtin formats.
#
# This method is aliased to to_s.
#
# time = Time.now # => Thu Jan 18 06:10:17 CST 2007
#
# time.to_formatted_s(:time) # => "06:10"
# time.to_s(:time) # => "06:10"
#
# time.to_formatted_s(:db) # => "2007-01-18 06:10:17"
# time.to_formatted_s(:number) # => "20070118061017"
# time.to_formatted_s(:short) # => "18 Jan 06:10"
# time.to_formatted_s(:long) # => "January 18, 2007 06:10"
# time.to_formatted_s(:long_ordinal) # => "January 18th, 2007 06:10"
# time.to_formatted_s(:rfc822) # => "Thu, 18 Jan 2007 06:10:17 -0600"
#
# == Adding your own time formats to +to_formatted_s+
# You can add your own formats to the Time::DATE_FORMATS hash.
# Use the format name as the hash key and either a strftime string
# or Proc instance that takes a time argument as the value.
#
# # config/initializers/time_formats.rb
# Time::DATE_FORMATS[:month_and_year] = '%B %Y'
# Time::DATE_FORMATS[:short_ordinal] = ->(time) { time.strftime("%B #{time.day.ordinalize}") }
def to_formatted_s(format = :default)
return iso8601 if format == :iso8601
formatter = DATE_FORMATS[format]
return to_default_s unless formatter
return formatter.call(self).to_s if formatter.respond_to?(:call)
strftime(formatter)
end
alias_method :to_default_s, :to_s
alias_method :to_s, :to_formatted_s
private
def self.cached_date_formatter(dateFormat)
Thread.current[:date_formatters] ||= {}
Thread.current[:date_formatters][dateFormat] ||=
NSDateFormatter.alloc.init.tap do |formatter|
formatter.dateFormat = dateFormat
formatter.timeZone = NSTimeZone.timeZoneWithAbbreviation 'UTC'
end
end
private_class_method :cached_date_formatter
end