提交 1946d7b9 编写于 作者: A Alexey Gaziev

AS core_ext refactoring

上级 242f4d1e
......@@ -16,7 +16,7 @@ def from(position)
# %w( a b c d ).to(10) # => %w( a b c d )
# %w().to(0) # => %w()
def to(position)
self.first position + 1
first position + 1
end
# Equal to <tt>self[1]</tt>.
......
......@@ -46,7 +46,7 @@ def to_sentence(options = {})
def to_formatted_s(format = :default)
case format
when :db
if respond_to?(:empty?) && self.empty?
if respond_to?(:empty?) && empty?
"null"
else
collect { |element| element.id }.join(",")
......
......@@ -71,7 +71,7 @@ def #{sym}=(obj)
end
EOS
end
self.send("#{sym}=", yield) if block_given?
send("#{sym}=", yield) if block_given?
end
end
......
......@@ -5,7 +5,15 @@
require 'active_support/core_ext/time/zones'
class Date
DAYS_INTO_WEEK = { :monday => 0, :tuesday => 1, :wednesday => 2, :thursday => 3, :friday => 4, :saturday => 5, :sunday => 6 }
DAYS_INTO_WEEK = {
:monday => 0,
:tuesday => 1,
:wednesday => 2,
:thursday => 3,
:friday => 4,
:saturday => 5,
:sunday => 6
}
class << self
# Returns a new Date representing the date 1 day ago (i.e. yesterday's date).
......@@ -31,7 +39,7 @@ def past?
# Returns true if the Date object's date is today.
def today?
self.to_date == ::Date.current # we need the to_date because of DateTime
to_date == ::Date.current # we need the to_date because of DateTime
end
# Returns true if the Date object's date lies in the future.
......@@ -105,9 +113,9 @@ def advance(options)
# Date.new(2007, 5, 12).change(:year => 2005, :month => 1) # => Date.new(2005, 1, 12)
def change(options)
::Date.new(
options[:year] || self.year,
options[:month] || self.month,
options[:day] || self.day
options.fetch(:year, year),
options.fetch(:month, month),
options.fetch(:day, day)
)
end
......@@ -166,7 +174,7 @@ def monday
def end_of_week(start_day = :monday)
days_to_end = 6 - days_to_week_start(start_day)
result = self + days_to_end.days
self.acts_like?(:time) ? result.end_of_day : result
acts_like?(:time) ? result.end_of_day : result
end
alias :at_end_of_week :end_of_week
......@@ -180,7 +188,7 @@ def sunday
# week. Default is +:monday+. +DateTime+ objects have their time set to 0:00.
def prev_week(day = :monday)
result = (self - 7).beginning_of_week + DAYS_INTO_WEEK[day]
self.acts_like?(:time) ? result.change(:hour => 0) : result
acts_like?(:time) ? result.change(:hour => 0) : result
end
alias :last_week :prev_week
......@@ -193,43 +201,57 @@ def prev_week(day = :monday)
# Returns a new Date/DateTime representing the start of the given day in next week (default is :monday).
def next_week(day = :monday)
result = (self + 7).beginning_of_week + DAYS_INTO_WEEK[day]
self.acts_like?(:time) ? result.change(:hour => 0) : result
acts_like?(:time) ? result.change(:hour => 0) : result
end
# Returns a new ; DateTime objects will have time set to 0:00DateTime representing the start of the month (1st of the month; DateTime objects will have time set to 0:00)
def beginning_of_month
self.acts_like?(:time) ? change(:day => 1, :hour => 0) : change(:day => 1)
acts_like?(:time) ? change(:day => 1, :hour => 0) : change(:day => 1)
end
alias :at_beginning_of_month :beginning_of_month
# Returns a new Date/DateTime representing the end of the month (last day of the month; DateTime objects will have time set to 0:00)
def end_of_month
last_day = ::Time.days_in_month( self.month, self.year )
self.acts_like?(:time) ? change(:day => last_day, :hour => 23, :min => 59, :sec => 59) : change(:day => last_day)
last_day = ::Time.days_in_month(month, year)
if acts_like?(:time)
change(:day => last_day, :hour => 23, :min => 59, :sec => 59)
else
change(:day => last_day)
end
end
alias :at_end_of_month :end_of_month
# Returns a new Date/DateTime representing the start of the quarter (1st of january, april, july, october; DateTime objects will have time set to 0:00)
def beginning_of_quarter
beginning_of_month.change(:month => [10, 7, 4, 1].detect { |m| m <= self.month })
first_quarter_month = [10, 7, 4, 1].detect { |m| m <= month }
beginning_of_month.change(:month => first_quarter_month)
end
alias :at_beginning_of_quarter :beginning_of_quarter
# Returns a new Date/DateTime representing the end of the quarter (last day of march, june, september, december; DateTime objects will have time set to 23:59:59)
def end_of_quarter
beginning_of_month.change(:month => [3, 6, 9, 12].detect { |m| m >= self.month }).end_of_month
last_quarter_month = [3, 6, 9, 12].detect { |m| m >= month }
beginning_of_month.change(:month => last_quarter_month).end_of_month
end
alias :at_end_of_quarter :end_of_quarter
# Returns a new Date/DateTime representing the start of the year (1st of january; DateTime objects will have time set to 0:00)
def beginning_of_year
self.acts_like?(:time) ? change(:month => 1, :day => 1, :hour => 0) : change(:month => 1, :day => 1)
if acts_like?(:time)
change(:month => 1, :day => 1, :hour => 0)
else
change(:month => 1, :day => 1)
end
end
alias :at_beginning_of_year :beginning_of_year
# Returns a new Time representing the end of the year (31st of december; DateTime objects will have time set to 23:59:59)
def end_of_year
self.acts_like?(:time) ? change(:month => 12, :day => 31, :hour => 23, :min => 59, :sec => 59) : change(:month => 12, :day => 31)
if acts_like?(:time)
change(:month => 12, :day => 31, :hour => 23, :min => 59, :sec => 59)
else
change(:month => 12, :day => 31)
end
end
alias :at_end_of_year :end_of_year
......
......@@ -9,7 +9,10 @@ class Date
:long => "%B %e, %Y",
:db => "%Y-%m-%d",
:number => "%Y%m%d",
:long_ordinal => lambda { |date| date.strftime("%B #{ActiveSupport::Inflector.ordinalize(date.day)}, %Y") }, # => "April 25th, 2007"
:long_ordinal => lambda { |date|
day_format = ActiveSupport::Inflector.ordinalize(date.day)
date.strftime("%B #{day_format}, %Y") # => "April 25th, 2007"
},
:rfc822 => "%e %b %Y"
}
......
......@@ -4,8 +4,8 @@ class DateTime
class << self
# *DEPRECATED*: Use +DateTime.civil_from_format+ directly.
def local_offset
ActiveSupport::Deprecation.warn 'DateTime.local_offset is deprecated. ' \
'Use DateTime.civil_from_format directly.', caller
ActiveSupport::Deprecation.warn 'DateTime.local_offset is deprecated. Use DateTime.civil_from_format directly.', caller
::Time.local(2012).utc_offset.to_r / 86400
end
......@@ -35,14 +35,14 @@ def seconds_since_midnight
# minute is passed, then sec is set to 0.
def change(options)
::DateTime.civil(
options[:year] || year,
options[:month] || month,
options[:day] || day,
options[:hour] || hour,
options[:min] || (options[:hour] ? 0 : min),
options[:sec] || ((options[:hour] || options[:min]) ? 0 : sec),
options[:offset] || offset,
options[:start] || start
options.fetch(:year, year),
options.fetch(:month, month),
options.fetch(:day, day),
options.fetch(:hour, hour),
options.fetch(:min, options[:hour] ? 0 : min),
options.fetch(:sec, (options[:hour] || options[:min]) ? 0 : sec),
options.fetch(:offset, offset),
options.fetch(:start, start)
)
end
......@@ -53,8 +53,16 @@ def change(options)
def advance(options)
d = to_date.advance(options)
datetime_advanced_by_date = change(:year => d.year, :month => d.month, :day => d.day)
seconds_to_advance = (options[:seconds] || 0) + (options[:minutes] || 0) * 60 + (options[:hours] || 0) * 3600
seconds_to_advance == 0 ? datetime_advanced_by_date : datetime_advanced_by_date.since(seconds_to_advance)
seconds_to_advance = \
options.fetch(:seconds, 0) +
options.fetch(:minutes, 0) * 60 +
options.fetch(:hours, 0) * 3600
if seconds_to_advance.zero?
datetime_advanced_by_date
else
datetime_advanced_by_date.since seconds_to_advance
end
end
# Returns a new DateTime representing the time a number of seconds ago
......@@ -108,4 +116,5 @@ def utc_offset
def <=>(other)
super other.to_datetime
end
end
......@@ -62,8 +62,11 @@ class Range #:nodoc:
# Optimize range sum to use arithmetic progression if a block is not given and
# we have a range of numeric values.
def sum(identity = 0)
return super if block_given? || !(first.instance_of?(Integer) && last.instance_of?(Integer))
actual_last = exclude_end? ? (last - 1) : last
(actual_last - first + 1) * (actual_last + first) / 2
if block_given? || !(first.instance_of?(Integer) && last.instance_of?(Integer))
super
else
actual_last = exclude_end? ? (last - 1) : last
(actual_last - first + 1) * (actual_last + first) / 2
end
end
end
......@@ -56,8 +56,8 @@ def silence(temporary_level = Logger::ERROR)
alias :old_datetime_format= :datetime_format=
# Logging date-time format (string passed to +strftime+). Ignored if the formatter
# does not respond to datetime_format=.
def datetime_format=(datetime_format)
formatter.datetime_format = datetime_format if formatter.respond_to?(:datetime_format=)
def datetime_format=(format)
formatter.datetime_format = format if formatter.respond_to?(:datetime_format=)
end
alias :old_datetime_format :datetime_format
......
......@@ -4,7 +4,7 @@ class Object
#
# characters = ["Konata", "Kagami", "Tsukasa"]
# "Konata".in?(characters) # => true
#
#
# character = "Konata"
# character.in?("Konata", "Kagami", "Tsukasa") # => true
#
......@@ -18,7 +18,7 @@ def in?(*args)
if another_object.respond_to? :include?
another_object.include? self
else
raise ArgumentError.new("The single parameter passed to #in? must respond to #include?")
raise ArgumentError.new 'The single parameter passed to #in? must respond to #include?'
end
end
end
......
......@@ -4,21 +4,33 @@
class String
# Form can be either :utc (default) or :local.
def to_time(form = :utc)
return nil if self.blank?
d = ::Date._parse(self, false).values_at(:year, :mon, :mday, :hour, :min, :sec, :sec_fraction, :offset).map { |arg| arg || 0 }
d[6] *= 1000000
::Time.send("#{form}_time", *d[0..6]) - d[7]
unless blank?
date_values = ::Date._parse(self, false).
values_at(:year, :mon, :mday, :hour, :min, :sec, :sec_fraction, :offset).
map! { |arg| arg || 0 }
date_values[6] *= 1000000
offset = date_values.pop
::Time.send("#{form}_time", *date_values) - offset
end
end
def to_date
return nil if self.blank?
::Date.new(*::Date._parse(self, false).values_at(:year, :mon, :mday))
unless blank?
date_values = ::Date._parse(self, false).values_at(:year, :mon, :mday)
::Date.new(*date_values)
end
end
def to_datetime
return nil if self.blank?
d = ::Date._parse(self, false).values_at(:year, :mon, :mday, :hour, :min, :sec, :zone, :sec_fraction).map { |arg| arg || 0 }
d[5] += d.pop
::DateTime.civil(*d)
unless blank?
date_values = ::Date._parse(self, false).
values_at(:year, :mon, :mday, :hour, :min, :sec, :zone, :sec_fraction).
map! { |arg| arg || 0 }
date_values[5] += date_values.pop
::DateTime.civil(*date_values)
end
end
end
......@@ -35,13 +35,17 @@ def squish!
#
# "And they found that many people were sleeping better.".truncate(25, :omission => "... (continued)")
# # => "And they f... (continued)"
def truncate(length, options = {})
return self.dup unless self.length > length
def truncate(truncate_at, options = {})
return dup unless length > truncate_at
options[:omission] ||= "..."
length_with_room_for_omission = length - options[:omission].length
stop = options[:separator] ?
(rindex(options[:separator], length_with_room_for_omission) || length_with_room_for_omission) : length_with_room_for_omission
length_with_room_for_omission = truncate_at - options[:omission].length
stop = \
if options[:separator]
rindex(options[:separator], length_with_room_for_omission) || length_with_room_for_omission
else
length_with_room_for_omission
end
self[0...stop] + options[:omission]
end
......
......@@ -92,7 +92,10 @@ def html_safe?
module ActiveSupport #:nodoc:
class SafeBuffer < String
UNSAFE_STRING_METHODS = ["capitalize", "chomp", "chop", "delete", "downcase", "gsub", "lstrip", "next", "reverse", "rstrip", "slice", "squeeze", "strip", "sub", "succ", "swapcase", "tr", "tr_s", "upcase", "prepend"].freeze
UNSAFE_STRING_METHODS = %w(
capitalize chomp chop delete downcase gsub lstrip next reverse rstrip
slice squeeze strip sub succ swapcase tr tr_s upcase prepend
)
alias_method :original_concat, :concat
private :original_concat
......@@ -104,14 +107,16 @@ def initialize
end
def [](*args)
return super if args.size < 2
if html_safe?
new_safe_buffer = super
new_safe_buffer.instance_eval { @html_safe = true }
new_safe_buffer
if args.size < 2
super
else
to_str[*args]
if html_safe?
new_safe_buffer = super
new_safe_buffer.instance_eval { @html_safe = true }
new_safe_buffer
else
to_str[*args]
end
end
end
......
......@@ -3,7 +3,15 @@
class Time
COMMON_YEAR_DAYS_IN_MONTH = [nil, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31]
DAYS_INTO_WEEK = { :monday => 0, :tuesday => 1, :wednesday => 2, :thursday => 3, :friday => 4, :saturday => 5, :sunday => 6 }
DAYS_INTO_WEEK = {
:monday => 0,
:tuesday => 1,
:wednesday => 2,
:thursday => 3,
:friday => 4,
:saturday => 5,
:sunday => 6
}
class << self
# Overriding case equality method so that it returns true for ActiveSupport::TimeWithZone instances
......@@ -23,8 +31,13 @@ def days_in_month(month, year = now.year)
# otherwise returns a DateTime.
def time_with_datetime_fallback(utc_or_local, year, month=1, day=1, hour=0, min=0, sec=0, usec=0)
time = ::Time.send(utc_or_local, year, month, day, hour, min, sec, usec)
# This check is needed because Time.utc(y) returns a time object in the 2000s for 0 <= y <= 138.
time.year == year ? time : ::DateTime.civil_from_format(utc_or_local, year, month, day, hour, min, sec)
if time.year == year
time
else
::DateTime.civil_from_format(utc_or_local, year, month, day, hour, min, sec)
end
rescue
::DateTime.civil_from_format(utc_or_local, year, month, day, hour, min, sec)
end
......@@ -71,13 +84,13 @@ def seconds_since_midnight
def change(options)
::Time.send(
utc? ? :utc_time : :local_time,
options[:year] || year,
options[:month] || month,
options[:day] || day,
options[:hour] || hour,
options[:min] || (options[:hour] ? 0 : min),
options[:sec] || ((options[:hour] || options[:min]) ? 0 : sec),
options[:usec] || ((options[:hour] || options[:min] || options[:sec]) ? 0 : Rational(nsec, 1000))
options.fetch(:year, year),
options.fetch(:month, month),
options.fetch(:day, day),
options.fetch(:hour, hour),
options.fetch(:min, options[:hour] ? 0 : min),
options.fetch(:sec, (options[:hour] || options[:min]) ? 0 : sec),
options.fetch(:usec, (options[:hour] || options[:min] || options[:sec]) ? 0 : Rational(nsec, 1000))
)
end
......@@ -88,18 +101,26 @@ def change(options)
def advance(options)
unless options[:weeks].nil?
options[:weeks], partial_weeks = options[:weeks].divmod(1)
options[:days] = (options[:days] || 0) + 7 * partial_weeks
options[:days] = options.fetch(:days, 0) + 7 * partial_weeks
end
unless options[:days].nil?
options[:days], partial_days = options[:days].divmod(1)
options[:hours] = (options[:hours] || 0) + 24 * partial_days
options[:hours] = options.fetch(:hours, 0) + 24 * partial_days
end
d = to_date.advance(options)
time_advanced_by_date = change(:year => d.year, :month => d.month, :day => d.day)
seconds_to_advance = (options[:seconds] || 0) + (options[:minutes] || 0) * 60 + (options[:hours] || 0) * 3600
seconds_to_advance == 0 ? time_advanced_by_date : time_advanced_by_date.since(seconds_to_advance)
seconds_to_advance = \
options.fetch(:seconds, 0) +
options.fetch(:minutes, 0) * 60 +
options.fetch(:hours, 0) * 3600
if seconds_to_advance.zero?
time_advanced_by_date
else
time_advanced_by_date.since(seconds_to_advance)
end
end
# Returns a new Time representing the time a number of seconds ago, this is basically a wrapper around the Numeric extension
......@@ -167,6 +188,7 @@ def days_to_week_start(start_day = :monday)
start_day_number = DAYS_INTO_WEEK[start_day]
current_day_number = wday != 0 ? wday - 1 : 6
days_span = current_day_number - start_day_number
days_span >= 0 ? days_span : 7 + days_span
end
......@@ -198,13 +220,19 @@ def sunday
# Returns a new Time representing the start of the given day in the previous week (default is :monday).
def prev_week(day = :monday)
ago(1.week).beginning_of_week.since(DAYS_INTO_WEEK[day].day).change(:hour => 0)
ago(1.week).
beginning_of_week.
since(DAYS_INTO_WEEK[day].day).
change(:hour => 0)
end
alias_method :last_week, :prev_week
# Returns a new Time representing the start of the given day in next week (default is :monday).
def next_week(day = :monday)
since(1.week).beginning_of_week.since(DAYS_INTO_WEEK[day].day).change(:hour => 0)
since(1.week).
beginning_of_week.
since(DAYS_INTO_WEEK[day].day).
change(:hour => 0)
end
# Returns a new Time representing the start of the day (0:00)
......@@ -218,7 +246,12 @@ def beginning_of_day
# Returns a new Time representing the end of the day, 23:59:59.999999 (.999999999 in ruby1.9)
def end_of_day
change(:hour => 23, :min => 59, :sec => 59, :usec => 999999.999)
change(
:hour => 23,
:min => 59,
:sec => 59,
:usec => 999999.999
)
end
# Returns a new Time representing the start of the month (1st of the month, 0:00)
......@@ -232,19 +265,27 @@ def beginning_of_month
def end_of_month
#self - ((self.mday-1).days + self.seconds_since_midnight)
last_day = ::Time.days_in_month(month, year)
change(:day => last_day, :hour => 23, :min => 59, :sec => 59, :usec => 999999.999)
change(
:day => last_day,
:hour => 23,
:min => 59,
:sec => 59,
:usec => 999999.999
)
end
alias :at_end_of_month :end_of_month
# Returns a new Time representing the start of the quarter (1st of january, april, july, october, 0:00)
def beginning_of_quarter
beginning_of_month.change(:month => [10, 7, 4, 1].detect { |m| m <= month })
first_quarter_month = [10, 7, 4, 1].detect { |m| m <= month }
beginning_of_month.change(:month => first_quarter_month)
end
alias :at_beginning_of_quarter :beginning_of_quarter
# Returns a new Time representing the end of the quarter (end of the last day of march, june, september, december)
def end_of_quarter
beginning_of_month.change(:month => [3, 6, 9, 12].detect { |m| m >= month }).end_of_month
last_quarter_month = [3, 6, 9, 12].detect { |m| m >= month }
beginning_of_month.change(:month => last_quarter_month).end_of_month
end
alias :at_end_of_quarter :end_of_quarter
......@@ -256,7 +297,14 @@ def beginning_of_year
# Returns a new Time representing the end of the year (end of the 31st of december)
def end_of_year
change(:month => 12, :day => 31, :hour => 23, :min => 59, :sec => 59, :usec => 999999.999)
change(
:month => 12,
:day => 31,
:hour => 23,
:min => 59,
:sec => 59,
:usec => 999999.999
)
end
alias :at_end_of_year :end_of_year
......@@ -329,7 +377,11 @@ def minus_with_coercion(other)
# can be chronologically compared with a Time
def compare_with_coercion(other)
# we're avoiding Time#to_datetime cause it's expensive
other.is_a?(Time) ? compare_without_coercion(other.to_time) : to_datetime <=> other
if other.is_a?(Time)
compare_without_coercion(other.to_time)
else
to_datetime <=> other
end
end
alias_method :compare_without_coercion, :<=>
alias_method :<=>, :compare_with_coercion
......@@ -343,4 +395,5 @@ def eql_with_coercion(other)
end
alias_method :eql_without_coercion, :eql?
alias_method :eql?, :eql_with_coercion
end
......@@ -8,8 +8,14 @@ class Time
:time => "%H:%M",
:short => "%d %b %H:%M",
:long => "%B %d, %Y %H:%M",
:long_ordinal => lambda { |time| time.strftime("%B #{ActiveSupport::Inflector.ordinalize(time.day)}, %Y %H:%M") },
:rfc822 => lambda { |time| time.strftime("%a, %d %b %Y %H:%M:%S #{time.formatted_offset(false)}") }
:long_ordinal => lambda { |time|
day_format = ActiveSupport::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}")
}
}
# Converts to a formatted string. See DATE_FORMATS for builtin formats.
......
......@@ -51,13 +51,21 @@ def use_zone(time_zone)
# Returns a TimeZone instance or nil, or raises an ArgumentError for invalid timezones.
def find_zone!(time_zone)
return time_zone if time_zone.nil? || time_zone.is_a?(ActiveSupport::TimeZone)
# lookup timezone based on identifier (unless we've been passed a TZInfo::Timezone)
unless time_zone.respond_to?(:period_for_local)
time_zone = ActiveSupport::TimeZone[time_zone] || TZInfo::Timezone.get(time_zone)
if !time_zone || time_zone.is_a?(ActiveSupport::TimeZone)
time_zone
else
# lookup timezone based on identifier (unless we've been passed a TZInfo::Timezone)
unless time_zone.respond_to?(:period_for_local)
time_zone = ActiveSupport::TimeZone[time_zone] || TZInfo::Timezone.get(time_zone)
end
# Return if a TimeZone instance, or wrap in a TimeZone instance if a TZInfo::Timezone
if time_zone.is_a?(ActiveSupport::TimeZone)
time_zone
else
ActiveSupport::TimeZone.create(time_zone.name, nil, time_zone)
end
end
# Return if a TimeZone instance, or wrap in a TimeZone instance if a TZInfo::Timezone
time_zone.is_a?(ActiveSupport::TimeZone) ? time_zone : ActiveSupport::TimeZone.create(time_zone.name, nil, time_zone)
rescue TZInfo::InvalidTimezoneIdentifier
raise ArgumentError, "Invalid Timezone: #{time_zone}"
end
......@@ -80,8 +88,10 @@ def find_zone(time_zone)
#
# Time.utc(2000).in_time_zone('Alaska') # => Fri, 31 Dec 1999 15:00:00 AKST -09:00
def in_time_zone(zone = ::Time.zone)
return self unless zone
ActiveSupport::TimeWithZone.new(utc? ? self : getutc, ::Time.find_zone!(zone))
if zone
ActiveSupport::TimeWithZone.new(utc? ? self : getutc, ::Time.find_zone!(zone))
else
self
end
end
end
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册