class Time

def ===(other)

Overriding case equality method so that it returns true for ActiveSupport::TimeWithZone instances
def ===(other)
  super || (self == Time && other.is_a?(ActiveSupport::TimeWithZone))
end

def _dump(*args)

def _dump(*args)
  obj = dup
  obj.instance_variable_set('@_zone', zone)
  obj.send :_dump_without_zone, *args
end

def _load(marshaled_time)

def _load(marshaled_time)
  time = _load_without_zone(marshaled_time)
  time.instance_eval do
    if zone = defined?(@_zone) && remove_instance_variable('@_zone')
      ary = to_a
      ary[0] += subsec if ary[0] == sec
      ary[-1] = zone
      utc? ? Time.utc(*ary) : Time.local(*ary)
    else
      self
    end
  end
end

def acts_like_time?

Duck-types as a Time-like class. See Object#acts_like?.
def acts_like_time?
  true
end

def advance(options)

Time.new(2015, 8, 1, 14, 35, 0).advance(weeks: 1) # => 2015-08-08 14:35:00 -0700
Time.new(2015, 8, 1, 14, 35, 0).advance(days: 1) # => 2015-08-02 14:35:00 -0700
Time.new(2015, 8, 1, 14, 35, 0).advance(hours: 1) # => 2015-08-01 15:35:00 -0700
Time.new(2015, 8, 1, 14, 35, 0).advance(minutes: 1) # => 2015-08-01 14:36:00 -0700
Time.new(2015, 8, 1, 14, 35, 0).advance(seconds: 1) # => 2015-08-01 14:35:01 -0700

:seconds.
:weeks, :days, :hours, :minutes,
takes a hash with any of these keys: :years, :months,
according to the proleptic Gregorian calendar. The +options+ parameter
Uses Date to provide precise Time calculations for years, months, and days
def advance(options)
  unless options[:weeks].nil?
    options[:weeks], partial_weeks = options[:weeks].divmod(1)
    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.fetch(:hours, 0) + 24 * partial_days
  end
  d = to_date.advance(options)
  d = d.gregorian if d.julian?
  time_advanced_by_date = change(:year => d.year, :month => d.month, :day => d.day)
  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

def ago(seconds)

Returns a new Time representing the time a number of seconds ago, this is basically a wrapper around the Numeric extension
def ago(seconds)
  since(-seconds)
end

def all_day

Returns a Range representing the whole day of the current time.
def all_day
  beginning_of_day..end_of_day
end

def as_json(options = nil) #:nodoc:

:nodoc:
def as_json(options = nil) #:nodoc:
  if ActiveSupport::JSON::Encoding.use_standard_json_time_format
    xmlschema(ActiveSupport::JSON::Encoding.time_precision)
  else
    %(#{strftime("%Y/%m/%d %H:%M:%S")} #{formatted_offset(false)})
  end
end

def at_with_coercion(*args)

instances can be used when called with a single argument
Layers additional behavior on Time.at so that ActiveSupport::TimeWithZone and DateTime
def at_with_coercion(*args)
  return at_without_coercion(*args) if args.size != 1
  # Time.at can be called with a time or numerical value
  time_or_number = args.first
  if time_or_number.is_a?(ActiveSupport::TimeWithZone) || time_or_number.is_a?(DateTime)
    at_without_coercion(time_or_number.to_f).getlocal
  else
    at_without_coercion(time_or_number)
  end
end

def beginning_of_day

Returns a new Time representing the start of the day (0:00)
def beginning_of_day
  #(self - seconds_since_midnight).change(usec: 0)
  change(:hour => 0)
end

def beginning_of_hour

Returns a new Time representing the start of the hour (x:00)
def beginning_of_hour
  change(:min => 0)
end

def beginning_of_minute

Returns a new Time representing the start of the minute (x:xx:00)
def beginning_of_minute
  change(:sec => 0)
end

def change(options)

Time.new(2012, 8, 29, 22, 35, 0).change(year: 1981, hour: 0) # => Time.new(1981, 8, 29, 0, 0, 0)
Time.new(2012, 8, 29, 22, 35, 0).change(year: 1981, day: 1) # => Time.new(1981, 8, 1, 22, 35, 0)
Time.new(2012, 8, 29, 22, 35, 0).change(day: 1) # => Time.new(2012, 8, 1, 22, 35, 0)

:nsec. Path either :usec or :nsec, not both.
:day, :hour, :min, :sec, :usec
parameter takes a hash with any of these keys: :year, :month,
and minute is passed, then sec, usec and nsec is set to 0. The +options+
the hour is passed, then minute, sec, usec and nsec is set to 0. If the hour
:sec, :usec, :nsec) reset cascadingly, so if only
to the +options+ parameter. The time options (:hour, :min,
Returns a new Time where one or more of the elements have been changed according
def change(options)
  new_year  = options.fetch(:year, year)
  new_month = options.fetch(:month, month)
  new_day   = options.fetch(:day, day)
  new_hour  = options.fetch(:hour, hour)
  new_min   = options.fetch(:min, options[:hour] ? 0 : min)
  new_sec   = options.fetch(:sec, (options[:hour] || options[:min]) ? 0 : sec)
  if new_nsec = options[:nsec]
    raise ArgumentError, "Can't change both :nsec and :usec at the same time: #{options.inspect}" if options[:usec]
    new_usec = Rational(new_nsec, 1000)
  else
    new_usec  = options.fetch(:usec, (options[:hour] || options[:min] || options[:sec]) ? 0 : Rational(nsec, 1000))
  end
  if utc?
    ::Time.utc(new_year, new_month, new_day, new_hour, new_min, new_sec, new_usec)
  elsif zone
    ::Time.local(new_year, new_month, new_day, new_hour, new_min, new_sec, new_usec)
  else
    raise ArgumentError, 'argument out of range' if new_usec >= 1000000
    ::Time.new(new_year, new_month, new_day, new_hour, new_min, new_sec + (new_usec.to_r / 1000000), utc_offset)
  end
end

def compare_with_coercion(other)

can be chronologically compared with a Time
Layers additional behavior on Time#<=> so that DateTime and ActiveSupport::TimeWithZone instances
def compare_with_coercion(other)
  # we're avoiding Time#to_datetime cause it's expensive
  if other.is_a?(Time)
    compare_without_coercion(other.to_time)
  else
    to_datetime <=> other
  end
end

def current

Returns Time.zone.now when Time.zone or config.time_zone are set, otherwise just returns Time.now.
def current
  ::Time.zone ? ::Time.zone.now : ::Time.now
end

def days_in_month(month, year = now.year)

If no year is specified, it will use the current year.
Return the number of days in the given month.
def days_in_month(month, year = now.year)
  if month == 2 && ::Date.gregorian_leap?(year)
    29
  else
    COMMON_YEAR_DAYS_IN_MONTH[month]
  end
end

def end_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 => Rational(999999999, 1000)
  )
end

def end_of_hour

Returns a new Time representing the end of the hour, x:59:59.999999 (.999999999 in ruby1.9)
def end_of_hour
  change(
    :min => 59,
    :sec => 59,
    :usec => Rational(999999999, 1000)
  )
end

def end_of_minute

Returns a new Time representing the end of the minute, x:xx:59.999999 (.999999999 in ruby1.9)
def end_of_minute
  change(
    :sec => 59,
    :usec => Rational(999999999, 1000)
  )
end

def eql_with_coercion(other)

can be eql? to an equivalent Time
Layers additional behavior on Time#eql? so that ActiveSupport::TimeWithZone instances
def eql_with_coercion(other)
  # if other is an ActiveSupport::TimeWithZone, coerce a Time instance from it so we can do eql? comparison
  other = other.comparable_time if other.respond_to?(:comparable_time)
  eql_without_coercion(other)
end

def find_zone(time_zone)

def find_zone(time_zone)
  find_zone!(time_zone) rescue nil
end

def find_zone!(time_zone)

Returns a TimeZone instance or nil, or raises an ArgumentError for invalid timezones.
def find_zone!(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
rescue TZInfo::InvalidTimezoneIdentifier
  raise ArgumentError, "Invalid Timezone: #{time_zone}"
end

def formatted_offset(colon = true, alternate_utc_string = nil)

Time.local(2000).formatted_offset(false) # => "-0600"
Time.local(2000).formatted_offset # => "-06:00"

Returns the UTC offset as an +HH:MM formatted string.
def formatted_offset(colon = true, alternate_utc_string = nil)
  utc? && alternate_utc_string || ActiveSupport::TimeZone.seconds_to_utc_offset(utc_offset, colon)
end

def middle_of_day

Returns a new Time representing the middle of the day (12:00)
def middle_of_day
  change(:hour => 12)
end

def minus_with_coercion(other)

are coerced into values that Time#- will recognize
We're layering on additional behavior so that ActiveSupport::TimeWithZone instances
Time#- can also be used to determine the number of seconds between two Time instances.
def minus_with_coercion(other)
  other = other.comparable_time if other.respond_to?(:comparable_time)
  other.is_a?(DateTime) ? to_f - other.to_f : minus_without_coercion(other)
end

def minus_with_duration(other) #:nodoc:

:nodoc:
def minus_with_duration(other) #:nodoc:
  if ActiveSupport::Duration === other
    other.until(self)
  else
    minus_without_duration(other)
  end
end

def plus_with_duration(other) #:nodoc:

:nodoc:
def plus_with_duration(other) #:nodoc:
  if ActiveSupport::Duration === other
    other.since(self)
  else
    plus_without_duration(other)
  end
end

def seconds_since_midnight

Seconds since midnight: Time.now.seconds_since_midnight
def seconds_since_midnight
  to_i - change(:hour => 0).to_i + (usec / 1.0e+6)
end

def seconds_until_end_of_day

Time.new(2012, 8, 29, 23, 59, 59).seconds_until_end_of_day # => 0
Time.new(2012, 8, 29, 12, 34, 56).seconds_until_end_of_day # => 41103
Time.new(2012, 8, 29, 0, 0, 0).seconds_until_end_of_day # => 86399

Returns the number of seconds until 23:59:59.
def seconds_until_end_of_day
  end_of_day.to_i - to_i
end

def since(seconds)

Returns a new Time representing the time a number of seconds since the instance time
def since(seconds)
  self + seconds
rescue
  to_datetime.since(seconds)
end

def to_formatted_s(format = :default)

Time::DATE_FORMATS[:short_ordinal] = ->(time) { time.strftime("%B #{time.day.ordinalize}") }
Time::DATE_FORMATS[:month_and_year] = '%B %Y'
# config/initializers/time_formats.rb

or Proc instance that takes a time argument as the value.
Use the format name as the hash key and either a strftime string
You can add your own formats to the Time::DATE_FORMATS hash.
== Adding your own time formats to +to_formatted_s+

time.to_formatted_s(:iso8601) # => "2007-01-18T06:10:17-06:00"
time.to_formatted_s(:rfc822) # => "Thu, 18 Jan 2007 06:10:17 -0600"
time.to_formatted_s(:long_ordinal) # => "January 18th, 2007 06:10"
time.to_formatted_s(:long) # => "January 18, 2007 06:10"
time.to_formatted_s(:short) # => "18 Jan 06:10"
time.to_formatted_s(:number) # => "20070118061017"
time.to_formatted_s(:db) # => "2007-01-18 06:10:17"

time.to_s(:time) # => "06:10"
time.to_formatted_s(:time) # => "06:10"

time = Time.now # => Thu Jan 18 06:10:17 CST 2007

This method is aliased to to_s.

Converts to a formatted string. See DATE_FORMATS for built-in formats.
def to_formatted_s(format = :default)
  if formatter = DATE_FORMATS[format]
    formatter.respond_to?(:call) ? formatter.call(self).to_s : strftime(formatter)
  else
    to_default_s
  end
end

def use_zone(time_zone)

Allows override of Time.zone locally inside supplied block; resets Time.zone to existing value when done.
def use_zone(time_zone)
  new_zone = find_zone!(time_zone)
  begin
    old_zone, ::Time.zone = ::Time.zone, new_zone
    yield
  ensure
    ::Time.zone = old_zone
  end
end

def zone

If Time.zone has not been set for the current request, returns the TimeZone specified in config.time_zone.
Returns the TimeZone for the current request, if this has been set (via Time.zone=).
def zone
  Thread.current[:time_zone] || zone_default
end

def zone=(time_zone)

end
end
end
yield
else
Time.use_zone(current_user.time_zone) { yield }
if logged_in?
def set_time_zone

around_filter :set_time_zone
class ApplicationController < ActionController::Base

current_user.time_zone just needs to return a string identifying the user's preferred time zone:
Here's an example of how you might set Time.zone on a per request basis and reset it when the request is done.

* An identifier for a TZInfo::Timezone object (e.g., "America/New_York").
* A TZInfo::Timezone object.
* An identifier for a Rails TimeZone object (e.g., "Eastern Time (US & Canada)", -5.hours).
* A Rails TimeZone object.

This method accepts any of the following:

Sets Time.zone to a TimeZone object for the current request/thread.
def zone=(time_zone)
  Thread.current[:time_zone] = find_zone!(time_zone)
end