Module: IceCube::TimeUtil

Extended by:
Deprecated
Defined in:
lib/ice_cube/time_util.rb

Defined Under Namespace

Classes: TimeWrapper

Constant Summary collapse

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

Methods included from Deprecated

deprecated, deprecated_alias

Class Method Details

.beginning_of_date(date, reference = nil) ⇒ Object

Get the beginning of a date



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

def self.beginning_of_date(date, reference=nil)
  args = [date.year, date.month, date.day, 0, 0, 0]
  reference ||= Time.local(*args)
  if reference.respond_to?(:time_zone) && reference.time_zone
    reference.time_zone.local(*args)
  else
    match_zone(Time.new(*args << reference.utc_offset), reference)
  end
end

.day_of_month(value, date) ⇒ Object

Get a day of the month in the month of a given time without overflowing into the next month. Accepts days from positive (start of month forward) or negative (from end of month)



179
180
181
182
183
184
185
# File 'lib/ice_cube/time_util.rb', line 179

def self.day_of_month(value, date)
  if value.to_i > 0
    [value, days_in_month(date)].min
  else
    [1 + days_in_month(date) + value, 1].max
  end
end

.days_in_month(time) ⇒ Object

Get the days in the month for +time



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

def self.days_in_month(time)
  date = Date.new(time.year, time.month, 1)
  ((date >> 1) - date).to_i
end

.days_in_n_months(time, month_distance) ⇒ Object

The number of days in n months



200
201
202
203
# File 'lib/ice_cube/time_util.rb', line 200

def self.days_in_n_months(time, month_distance)
  date = Date.new(time.year, time.month, time.day)
  ((date >> month_distance) - date).to_i
end

.days_in_n_years(time, year_distance) ⇒ Object

Number of days to n years



194
195
196
197
# File 'lib/ice_cube/time_util.rb', line 194

def self.days_in_n_years(time, year_distance)
  date = Date.new(time.year, time.month, time.day)
  ((date >> year_distance * 12) - date).to_i
end

.days_in_next_month(time) ⇒ Object

Get the days in the following month for +time



164
165
166
167
# File 'lib/ice_cube/time_util.rb', line 164

def self.days_in_next_month(time)
  date = Date.new(time.year, time.month, 1) >> 1
  ((date >> 1) - date).to_i
end

.days_in_year(time) ⇒ Object

Number of days in a year



188
189
190
191
# File 'lib/ice_cube/time_util.rb', line 188

def self.days_in_year(time)
  date = Date.new(time.year, 1, 1)
  ((date >> 12) - date).to_i
end

.days_to_next_month(time) ⇒ Object

Count the number of days to the same day of the next month without overflowing shorter months



171
172
173
174
# File 'lib/ice_cube/time_util.rb', line 171

def self.days_to_next_month(time)
  date = Date.new(time.year, time.month, time.day)
  ((date >> 1) - date).to_i
end

.deserialize_time(time_or_hash) ⇒ Object

Deserialize a time serialized with serialize_time



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

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

.dst_change(time) ⇒ Object



205
206
207
208
209
210
# File 'lib/ice_cube/time_util.rb', line 205

def self.dst_change(time)
  one_hour_ago = time - ONE_HOUR
  if time.dst? ^ one_hour_ago.dst?
    (time.utc_offset - one_hour_ago.utc_offset) / ONE_HOUR
  end
end

.end_of_date(date, reference = nil) ⇒ Object

Get the end of a date



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

def self.end_of_date(date, reference=nil)
  args = [date.year, date.month, date.day, 23, 59, 59]
  reference ||= Time.local(*args)
  if reference.respond_to?(:time_zone) && reference.time_zone
    reference.time_zone.local(*args)
  else
    match_zone(Time.new(*args << reference.utc_offset), reference)
  end
end

.ensure_date(date) ⇒ Object

Ensure that this is either nil, or a date



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

def self.ensure_date(date)
  case date
  when Date then date
  else
    return Date.new(date.year, date.month, date.day)
  end
end

.ensure_time(time, date_eod = false) ⇒ Object

Ensure that this is either nil, or a time



40
41
42
43
44
45
46
47
48
49
50
# File 'lib/ice_cube/time_util.rb', line 40

def self.ensure_time(time, date_eod = false)
  case time
  when DateTime
    warn "IceCube: DateTime support is deprecated (please use Time)"
    Time.local(time.year, time.month, time.day, time.hour, time.min, time.sec)
  when Date
    date_eod ? end_of_date(time) : time.to_time
  else
    time
  end
end

.match_zone(time, reference) ⇒ Object



24
25
26
27
28
29
30
31
32
33
34
35
36
37
# File 'lib/ice_cube/time_util.rb', line 24

def self.match_zone(time, reference)
  return unless time = ensure_time(time)
  if reference.respond_to? :time_zone
    time.in_time_zone(reference.time_zone)
  else
    if reference.utc?
      time.utc
    elsif reference.zone
      time.getlocal
    else
      time.getlocal(reference.utc_offset)
    end
  end
end

.normalize_wday(wday, week_start) ⇒ Object

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



143
144
145
# File 'lib/ice_cube/time_util.rb', line 143

def self.normalize_wday(wday, week_start)
  (wday - sym_to_wday(week_start)) % 7
end

.now(reference = Time.now) ⇒ Object

Provides a Time.now without the usec, in the reference zone or utc offset



20
21
22
# File 'lib/ice_cube/time_util.rb', line 20

def self.now(reference=Time.now)
  match_zone(Time.at(Time.now.to_i), reference)
end

.restore_deserialized_offset(time, orig_offset_str) ⇒ Object

Check the deserialized time offset string against actual local time offset to try and preserve the original offset for plain Ruby Time. If the offset is the same as local we can assume the same original zone and keep it. If it was serialized with a different offset than local TZ it will lose the zone and not support DST.



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

def self.restore_deserialized_offset(time, orig_offset_str)
  return time if time.respond_to?(:time_zone) ||
                 time.getlocal(orig_offset_str).utc_offset == time.utc_offset
  warn 'IceCube: parsed Time from nonlocal TZ. Use ActiveSupport to fix DST'
  time.localtime(orig_offset_str)
end

.serialize_time(time) ⇒ Object

Serialize a time appropriate for storing



62
63
64
65
66
67
68
# File 'lib/ice_cube/time_util.rb', line 62

def self.serialize_time(time)
  if time.respond_to?(:time_zone)
    {:time => time.utc, :zone => time.time_zone.name}
  elsif time.is_a?(Time)
    time
  end
end

.sym_to_month(sym) ⇒ Object

Convert a symbol to a numeric month



114
115
116
117
118
119
120
# File 'lib/ice_cube/time_util.rb', line 114

def self.sym_to_month(sym)
  return wday = sym if (1..12).include? sym
  MONTHS.fetch(sym) do |k|
    raise ArgumentError, "Expecting Fixnum or Symbol value for month. " \
                         "No such month: #{k.inspect}"
  end
end

.sym_to_wday(sym) ⇒ Object

Convert a symbol to a wday number



124
125
126
127
128
129
130
# File 'lib/ice_cube/time_util.rb', line 124

def self.sym_to_wday(sym)
  return sym if (0..6).include? sym
  DAYS.fetch(sym) do |k|
    raise ArgumentError, "Expecting Fixnum or Symbol value for weekday. " \
                         "No such weekday: #{k.inspect}"
  end
end

.wday_to_sym(wday) ⇒ Object

Convert wday number to day symbol



134
135
136
137
138
139
140
# File 'lib/ice_cube/time_util.rb', line 134

def self.wday_to_sym(wday)
  return sym = wday if DAYS.keys.include? wday
  DAYS.invert.fetch(wday) do |i|
    raise ArgumentError, "Expecting Fixnum value for weekday. " \
                         "No such wday number: #{i.inspect}"
  end
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



150
151
152
153
154
155
# File 'lib/ice_cube/time_util.rb', line 150

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