summaryrefslogtreecommitdiff
path: root/lib/leap_cli/core_ext/time.rb
blob: fef6c5dfd9a90b3d1f4d55eeb3333a03a9928c21 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
#
# The following methods are copied from ActiveSupport's Time extension:
# activesupport/lib/active_support/core_ext/time/calculations.rb
#

class Time

  #
  # Uses Date to provide precise Time calculations for years, months, and days
  # according to the proleptic Gregorian calendar. The options parameter takes
  # a hash with any of these keys: :years, :months, :weeks, :days, :hours,
  # :minutes, :seconds.
  #
  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 since(seconds)
    self + seconds
  rescue
    to_datetime.since(seconds)
  end

  #
  # Returns a new Time where one or more of the elements have been changed
  # according to the options parameter. The time options (:hour, :min, :sec,
  # :usec) reset cascadingly, so if only the hour is passed, then minute, sec,
  # and usec is set to 0. If the hour and minute is passed, then sec and usec
  # is set to 0. The options parameter takes a hash with any of these keys:
  # :year, :month, :day, :hour, :min, :sec, :usec.
  #
  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)
    new_usec  = options.fetch(:usec, (options[:hour] || options[:min] || options[:sec]) ? 0 : Rational(nsec, 1000))

    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
      ::Time.new(new_year, new_month, new_day, new_hour, new_min, new_sec + (new_usec.to_r / 1000000), utc_offset)
    end
  end

end

class Date

  # activesupport/lib/active_support/core_ext/date/calculations.rb
  def advance(options)
    options = options.dup
    d = self
    d = d >> options.delete(:years) * 12 if options[:years]
    d = d >> options.delete(:months)     if options[:months]
    d = d +  options.delete(:weeks) * 7  if options[:weeks]
    d = d +  options.delete(:days)       if options[:days]
    d
  end

end