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
}
ICAL_DAYS =
{ 
  'SU' => :sunday, 'MO' => :monday, 'TU' => :tuesday, 'WE' => :wednesday, 
  'TH' => :thursday, 'FR' => :friday, 'SA' => :saturday 
}
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



45
46
47
48
49
# File 'lib/ice_cube/time_util.rb', line 45

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



100
101
102
# File 'lib/ice_cube/time_util.rb', line 100

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

.days_in_month_year(month, year) ⇒ Object



116
117
118
# File 'lib/ice_cube/time_util.rb', line 116

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



138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
# File 'lib/ice_cube/time_util.rb', line 138

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



126
127
128
129
130
131
132
133
134
135
# File 'lib/ice_cube/time_util.rb', line 126

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



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

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



121
122
123
# File 'lib/ice_cube/time_util.rb', line 121

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



36
37
38
39
40
41
42
# File 'lib/ice_cube/time_util.rb', line 36

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



52
53
54
55
56
# File 'lib/ice_cube/time_util.rb', line 52

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

.ical_day_to_symbol(str) ⇒ Object



72
73
74
75
76
# File 'lib/ice_cube/time_util.rb', line 72

def self.ical_day_to_symbol(str)
  day = ICAL_DAYS[str]
  raise "No such day: #{str}" if day.nil?
  day
end

.is_leap?(year) ⇒ Boolean

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

Returns:

  • (Boolean)


160
161
162
# File 'lib/ice_cube/time_util.rb', line 160

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

.normalize_weekday(daynum, week_start) ⇒ Object

Convert weekday from base sunday to the schedule’s week start.



86
87
88
# File 'lib/ice_cube/time_util.rb', line 86

def self.normalize_weekday(daynum, week_start)
  (daynum - symbol_to_day(week_start)) % 7
end

.serialize_time(time) ⇒ Object

Serialize a time appropriate for storing



27
28
29
30
31
32
33
# File 'lib/ice_cube/time_util.rb', line 27

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



66
67
68
69
70
# File 'lib/ice_cube/time_util.rb', line 66

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



59
60
61
62
63
# File 'lib/ice_cube/time_util.rb', line 59

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

.week_start(sym) ⇒ Object

Convert a symbol to an ical day (SU, MO)



79
80
81
82
83
# File 'lib/ice_cube/time_util.rb', line 79

def self.week_start(sym)
  raise "No such day: #{sym}" unless DAYS.keys.include?(sym)
  day = sym.to_s.upcase[0..1]
  day
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



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

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