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

AS core_ext refactoring

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