Module: IceCube::TimeUtil

Defined in:
lib/ice_cube/time_util.rb

Defined Under Namespace

Classes: TimeWrapper

Constant Summary collapse

LEAP_YEAR_MONTH_DAYS =
[31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31]
COMMON_YEAR_MONTH_DAYS =
[31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31]
DAYS =
{
  :sunday => 0, :monday => 1, :tuesday => 2, :wednesday => 3,
  :thursday => 4, :friday => 5, :saturday => 6
}
MONTHS =
{
  :january => 1, :february => 2, :march => 3, :april => 4, :may => 5,
  :june => 6, :july => 7, :august => 8, :september => 9, :october => 10,
  :november => 11, :december => 12
}

Class Method Summary collapse

Class Method Details

.beginning_of_date(date) ⇒ Object

Get the beginning of a date



40
41
42
43
44
# File 'lib/ice_cube/time_util.rb', line 40

def self.beginning_of_date(date)
  date.respond_to?(:beginning_of_day) ?
    date.beginning_of_day :
    Time.local(date.year, date.month, date.day, 0, 0, 0)
end

.days_in_month(time) ⇒ Object

Get the days in the month for +time



77
78
79
# File 'lib/ice_cube/time_util.rb', line 77

def self.days_in_month(time)
  days_in_month_year(time.month, time.year)
end

.days_in_month_year(month, year) ⇒ Object



93
94
95
# File 'lib/ice_cube/time_util.rb', line 93

def self.days_in_month_year(month, year)
  is_leap?(year) ? LEAP_YEAR_MONTH_DAYS[month - 1] : COMMON_YEAR_MONTH_DAYS[month - 1]
end

.days_in_n_months(time, month_distance) ⇒ Object

The number of days in n months



115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
# File 'lib/ice_cube/time_util.rb', line 115

def self.days_in_n_months(time, month_distance)
  # move to a safe spot in the month to make this computation
  desired_day = time.day
  time -= IceCube::ONE_DAY * (time.day - 27) if time.day >= 28
  # move n months ahead
  sum = 0
  wrapper = TimeWrapper.new(time)
  month_distance.times do
    dim = days_in_month(wrapper.to_time)
    sum += dim
    wrapper.add(:day, dim)
  end
  # now we can move to the desired day
  dim = days_in_month(wrapper.to_time)
  if desired_day > dim
    sum -= desired_day - dim
  end
  sum
end

.days_in_n_years(time, year_distance) ⇒ Object

Number of days to n years



103
104
105
106
107
108
109
110
111
112
# File 'lib/ice_cube/time_util.rb', line 103

def self.days_in_n_years(time, year_distance)
  sum = 0
  wrapper = TimeWrapper.new(time)
  year_distance.times do
    diy = days_in_year(wrapper.to_time)
    sum += diy
    wrapper.add(:day, diy)
  end
  sum
end

.days_in_next_month(time) ⇒ Object



81
82
83
84
85
86
87
88
89
90
91
# File 'lib/ice_cube/time_util.rb', line 81

def self.days_in_next_month(time)
  # Get the next month
  year = time.year
  month = time.month + 1
  if month > 12
    month %= 12
    year += 1
  end
  # And then determine
  days_in_month_year(month, year)
end

.days_in_year(time) ⇒ Object

Number of days in a year



98
99
100
# File 'lib/ice_cube/time_util.rb', line 98

def self.days_in_year(time)
  is_leap?(time.year) ? 366 : 365
end

.deserialize_time(time_or_hash) ⇒ Object

Deserialize a time serialized with serialize_time



31
32
33
34
35
36
37
# File 'lib/ice_cube/time_util.rb', line 31

def self.deserialize_time(time_or_hash)
  if time_or_hash.is_a?(Time)
    time_or_hash
  elsif time_or_hash.is_a?(Hash)
    time_or_hash[:time].in_time_zone(time_or_hash[:zone])
  end
end

.end_of_date(date) ⇒ Object

Get the end of a date



47
48
49
50
51
# File 'lib/ice_cube/time_util.rb', line 47

def self.end_of_date(date)
  date.respond_to?(:end_of_day) ?
    date.end_of_day :
    Time.local(date.year, date.month, date.day, 23, 59, 59)
end

.is_leap?(year) ⇒ Boolean

Given a year, return a boolean indicating whether it is a leap year or not

Returns:

  • (Boolean)


137
138
139
# File 'lib/ice_cube/time_util.rb', line 137

def self.is_leap?(year)
  (year % 4 == 0 && year % 100 != 0) || (year % 400 == 0)
end

.serialize_time(time) ⇒ Object

Serialize a time appropriate for storing



22
23
24
25
26
27
28
# File 'lib/ice_cube/time_util.rb', line 22

def self.serialize_time(time)
  if defined?(:ActiveSupport) && const_defined?(:ActiveSupport) && time.is_a?(ActiveSupport::TimeWithZone)
    { :time => time.utc, :zone => time.time_zone.name }
  elsif time.is_a?(Time)
    time
  end
end

.symbol_to_day(sym) ⇒ Object

Convert a symbol to a numeric day



61
62
63
64
65
# File 'lib/ice_cube/time_util.rb', line 61

def self.symbol_to_day(sym)
  day = DAYS[sym]
  raise "No such day: #{sym}" unless day
  day
end

.symbol_to_month(sym) ⇒ Object

Convert a symbol to a numeric month



54
55
56
57
58
# File 'lib/ice_cube/time_util.rb', line 54

def self.symbol_to_month(sym)
  month = MONTHS[sym]
  raise "No such month: #{sym}" unless month
  month
end

.which_occurrence_in_month(time, wday) ⇒ Object

Return the count of the number of times wday appears in the month, and which of those time falls on



69
70
71
72
73
74
# File 'lib/ice_cube/time_util.rb', line 69

def self.which_occurrence_in_month(time, wday)
  first_occurrence = ((7 - Time.utc(time.year, time.month, 1).wday) + time.wday) % 7 + 1
  this_weekday_in_month_count = ((days_in_month(time) - first_occurrence + 1) / 7.0).ceil
  nth_occurrence_of_weekday = (time.mday - first_occurrence) / 7 + 1
  [nth_occurrence_of_weekday, this_weekday_in_month_count]
end