class DateTime

def self.civil_from_format(utc_or_local, year, month = 1, day = 1, hour = 0, min = 0, sec = 0)

# => Mon, 17 Dec 2012 00:00:00 +0000
DateTime.civil_from_format :local, 2012, 12, 17
# => Sun, 01 Jan 2012 00:00:00 +0300
DateTime.civil_from_format :local, 2012

offset is zero.
Returns DateTime with local offset for given year if format is local else
def self.civil_from_format(utc_or_local, year, month = 1, day = 1, hour = 0, min = 0, sec = 0)
  if utc_or_local.to_sym == :local
    offset = ::Time.local(year, month, day).utc_offset.to_r / 86400
  else
    offset = 0
  end
  civil(year, month, day, hour, min, sec, offset)
end

def <=>(other)

ActiveSupport::TimeWithZone instances can be compared with a DateTime.
Layers additional behavior on DateTime#<=> so that Time and
def <=>(other)
  if other.respond_to? :to_datetime
    super other.to_datetime rescue nil
  else
    super
  end
end

def acts_like_date?

Duck-types as a Date-like class. See Object#acts_like?.
def acts_like_date?
  true
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)

month.
largest to smallest. This order can affect the result around the end of a
Just like Date#advance, increments are applied in order of time units from

:minutes, :seconds.
:months, :weeks, :days, :hours,
The +options+ parameter takes a hash with any of these keys: :years,
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)
  datetime_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?
    datetime_advanced_by_date
  else
    datetime_advanced_by_date.since(seconds_to_advance)
  end
end

def ago(seconds)

Do not use this method in combination with x.months, use months_ago instead!
Returns a new DateTime representing the time a number of seconds ago.
def ago(seconds)
  since(-seconds)
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 %z")
  end
end

def beginning_of_day

Returns a new DateTime representing the start of the day (0:00).
def beginning_of_day
  change(hour: 0)
end

def beginning_of_hour

Returns a new DateTime representing the start of the hour (hh:00:00).
def beginning_of_hour
  change(min: 0)
end

def beginning_of_minute

Returns a new DateTime representing the start of the minute (hh:mm:00).
def beginning_of_minute
  change(sec: 0)
end

def blank?

Returns:
  • (false) -
def blank?
  false
end

def change(options)

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

:min, :sec, :offset, :start.
keys: :year, :month, :day, :hour,
then sec is set to 0. The +options+ parameter takes a hash with any of these
passed, then minute and sec is set to 0. If the hour and minute is passed,
:min, :sec) reset cascadingly, so if only the hour is
according to the +options+ parameter. The time options (:hour,
Returns a new DateTime where one or more of the elements have been changed
def change(options)
  if new_nsec = options[:nsec]
    raise ArgumentError, "Can't change both :nsec and :usec at the same time: #{options.inspect}" if options[:usec]
    new_fraction = Rational(new_nsec, 1000000000)
  else
    new_usec = options.fetch(:usec, (options[:hour] || options[:min] || options[:sec]) ? 0 : Rational(nsec, 1000))
    new_fraction = Rational(new_usec, 1000000)
  end
  raise ArgumentError, "argument out of range" if new_fraction >= 1
  ::DateTime.civil(
    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) + new_fraction,
    options.fetch(:offset, offset),
    options.fetch(:start, start)
  )
end

def current

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

def end_of_day

Returns a new DateTime representing the end of the day (23:59:59).
def end_of_day
  change(hour: 23, min: 59, sec: 59, usec: Rational(999999999, 1000))
end

def end_of_hour

Returns a new DateTime representing the end of the hour (hh:59:59).
def end_of_hour
  change(min: 59, sec: 59, usec: Rational(999999999, 1000))
end

def end_of_minute

Returns a new DateTime representing the end of the minute (hh:mm:59).
def end_of_minute
  change(sec: 59, usec: Rational(999999999, 1000))
end

def formatted_offset(colon = true, alternate_utc_string = nil)

datetime.formatted_offset(false) # => "-0600"
datetime.formatted_offset # => "-06:00"
datetime = DateTime.civil(2000, 1, 1, 0, 0, 0, Rational(-6, 24))

string if the time zone is already UTC.
Returns a formatted string of the offset from UTC, or an alternative
def formatted_offset(colon = true, alternate_utc_string = nil)
  utc? && alternate_utc_string || ActiveSupport::TimeZone.seconds_to_utc_offset(utc_offset, colon)
end

def localtime(utc_offset = nil)

Returns a Time instance of the simultaneous time in the system timezone.
def localtime(utc_offset = nil)
  utc = new_offset(0)
  Time.utc(
    utc.year, utc.month, utc.day,
    utc.hour, utc.min, utc.sec + utc.sec_fraction
  ).getlocal(utc_offset)
end

def middle_of_day

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

def nsec

Returns the fraction of a second as nanoseconds
def nsec
  (sec_fraction * 1_000_000_000).to_i
end

def offset_in_seconds

def offset_in_seconds
  (offset * 86400).to_i
end

def readable_inspect

Overrides the default inspect method with a human readable one, e.g., "Mon, 21 Feb 2005 14:30:00 +0000".
def readable_inspect
  to_fs(:rfc822)
end

def seconds_since_midnight

DateTime.new(2012, 8, 29, 23, 59, 59).seconds_since_midnight # => 86399
DateTime.new(2012, 8, 29, 12, 34, 56).seconds_since_midnight # => 45296
DateTime.new(2012, 8, 29, 0, 0, 0).seconds_since_midnight # => 0

Returns the number of seconds since 00:00:00.
def seconds_since_midnight
  sec + (min * 60) + (hour * 3600)
end

def seconds_since_unix_epoch

def seconds_since_unix_epoch
  (jd - 2440588) * 86400 - offset_in_seconds + seconds_since_midnight
end

def seconds_until_end_of_day

DateTime.new(2012, 8, 29, 23, 59, 59).seconds_until_end_of_day # => 0
DateTime.new(2012, 8, 29, 12, 34, 56).seconds_until_end_of_day # => 41103
DateTime.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)

months_since instead!
instance time. Do not use this method in combination with x.months, use
Returns a new DateTime representing the time a number of seconds since the
def since(seconds)
  self + Rational(seconds, 86400)
end

def subsec

DateTime.new(2012, 8, 29, 0, 0, 0.5).subsec # => (1/2)

Returns the fraction of a second as a +Rational+
def subsec
  sec_fraction
end

def to_f

Converts +self+ to a floating-point number of seconds, including fractional microseconds, since the Unix epoch.
def to_f
  seconds_since_unix_epoch.to_f + sec_fraction
end

def to_fs(format = :default)

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

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

datetime.to_fs(:iso8601) # => "2007-12-04T00:00:00+00:00"
datetime.to_fs(:rfc822) # => "Tue, 04 Dec 2007 00:00:00 +0000"
datetime.to_fs(:long_ordinal) # => "December 4th, 2007 00:00"
datetime.to_fs(:long) # => "December 04, 2007 00:00"
datetime.to_fs(:short) # => "04 Dec 00:00"
datetime.to_fs(:number) # => "20071204000000"
datetime.to_formatted_s(:db) # => "2007-12-04 00:00:00"
datetime.to_fs(:db) # => "2007-12-04 00:00:00"

datetime = DateTime.civil(2007, 12, 4, 0, 0, 0, 0) # => Tue, 04 Dec 2007 00:00:00 +0000
=== Examples

This method is aliased to to_formatted_s.

Convert to a formatted string. See Time::DATE_FORMATS for predefined formats.
def to_fs(format = :default)
  if formatter = ::Time::DATE_FORMATS[format]
    formatter.respond_to?(:call) ? formatter.call(self).to_s : strftime(formatter)
  else
    to_default_s
  end
end

def to_i

Converts +self+ to an integer number of seconds since the Unix epoch.
def to_i
  seconds_since_unix_epoch.to_i
end

def to_s(format = NOT_SET) # :nodoc:

:nodoc:
:nodoc:
def to_s(format = NOT_SET) # :nodoc:
  if formatter = ::Time::DATE_FORMATS[format]
    ActiveSupport::Deprecation.warn(
      "DateTime#to_s(#{format.inspect}) is deprecated. Please use DateTime#to_fs(#{format.inspect}) instead."
    )
    formatter.respond_to?(:call) ? formatter.call(self).to_s : strftime(formatter)
  elsif format == NOT_SET
    to_default_s
  else
    ActiveSupport::Deprecation.warn(
      "DateTime#to_s(#{format.inspect}) is deprecated. Please use DateTime#to_fs(#{format.inspect}) instead."
    )
    to_default_s
  end
end

def to_time

on the setting of +ActiveSupport.to_time_preserves_timezone+.
in the local system timezone depending on the setting of
as +self+ or an instance of +Time+ representing the same time
Either return an instance of +Time+ with the same UTC offset
def to_time
  preserve_timezone ? getlocal(utc_offset) : getlocal
end

def usec

Returns the fraction of a second as microseconds
def usec
  (sec_fraction * 1_000_000).to_i
end

def utc

DateTime.civil(2005, 2, 21, 10, 11, 12, Rational(-6, 24)).utc # => Mon, 21 Feb 2005 16:11:12 UTC
DateTime.civil(2005, 2, 21, 10, 11, 12, Rational(-6, 24)) # => Mon, 21 Feb 2005 10:11:12 -0600

Returns a Time instance of the simultaneous time in the UTC timezone.
def utc
  utc = new_offset(0)
  Time.utc(
    utc.year, utc.month, utc.day,
    utc.hour, utc.min, utc.sec + utc.sec_fraction
  )
end

def utc?

Returns +true+ if offset == 0.
def utc?
  offset == 0
end

def utc_offset

Returns the offset value in seconds.
def utc_offset
  (offset * 86400).to_i
end