Class: RiCal::FastDateTime

Inherits:
Object show all
Includes:
Comparable
Defined in:
lib/ri_cal/fast_date_time.rb

Overview

  • ©2009 Rick DeNatale

  • All rights reserved. Refer to the file README.txt for the license

FastDateTime mimics the Ruby Standard library DateTime class but avoids the use of Rational Instead of using a Rational for the utc offset, FastDateTime uses an integer seconds value

Constant Summary collapse

SECONDS_IN_A_DAY =
60*60*24

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(year, month, day, hour, min, sec, offset_seconds) ⇒ FastDateTime

Returns a new instance of FastDateTime.



14
15
16
17
18
# File 'lib/ri_cal/fast_date_time.rb', line 14

def initialize(year, month, day, hour, min, sec, offset_seconds)
  @date = Date.civil(year, month, day)
  @secs_since_bod = hms_to_seconds(hour, min, sec)
  @hour, @min, @sec, @offset = hour, min, sec, offset_seconds
end

Instance Attribute Details

#dateObject

Returns the value of attribute date.



8
9
10
# File 'lib/ri_cal/fast_date_time.rb', line 8

def date
  @date
end

#hourObject

Returns the value of attribute hour.



8
9
10
# File 'lib/ri_cal/fast_date_time.rb', line 8

def hour
  @hour
end

#minObject

Returns the value of attribute min.



8
9
10
# File 'lib/ri_cal/fast_date_time.rb', line 8

def min
  @min
end

#offsetObject Also known as: utc_offset_seconds

Returns the value of attribute offset.



8
9
10
# File 'lib/ri_cal/fast_date_time.rb', line 8

def offset
  @offset
end

#secObject

Returns the value of attribute sec.



8
9
10
# File 'lib/ri_cal/fast_date_time.rb', line 8

def sec
  @sec
end

#secs_since_bodObject

Returns the value of attribute secs_since_bod.



8
9
10
# File 'lib/ri_cal/fast_date_time.rb', line 8

def secs_since_bod
  @secs_since_bod
end

Class Method Details

.from_date(date) ⇒ Object



28
29
30
# File 'lib/ri_cal/fast_date_time.rb', line 28

def self.from_date(date)
  new(date.year, date.month, date.day, 0, 0, 0, 0)
end

.from_date_at_end_of_day(date) ⇒ Object



32
33
34
# File 'lib/ri_cal/fast_date_time.rb', line 32

def self.from_date_at_end_of_day(date)
  new(date.year, date.month, date.day, 23, 59, 59, 0)
end

.from_date_time(date_time) ⇒ Object



20
21
22
# File 'lib/ri_cal/fast_date_time.rb', line 20

def self.from_date_time(date_time)
  new(date_time.year, date_time.month, date_time.day, date_time.hour, date_time.min, date_time.sec, (date_time.offset * SECONDS_IN_A_DAY).to_i)
end

.from_time(time) ⇒ Object



24
25
26
# File 'lib/ri_cal/fast_date_time.rb', line 24

def self.from_time(time)
  new(time.year, time.month, time.day, time.hour, time.min, time.sec, (time.utc_offset.offset * SECONDS_IN_A_DAY))
end

Instance Method Details

#<=>(other) ⇒ Object



72
73
74
75
76
77
78
# File 'lib/ri_cal/fast_date_time.rb', line 72

def <=> (other)
  if FastDateTime === other
    [date, secs_since_bod] <=> [other.date, other.secs_since_bod]
  else
    [year, month, day, hour, min, sec] <=> [other.year, other.month, other.day, other.hour, other.min, other.sec]
  end
end

#==(other) ⇒ Object



68
69
70
# File 'lib/ri_cal/fast_date_time.rb', line 68

def ==(other)
  [date, secs_since_bod, offset] == [other.date, other.secs_since_bod, other.offset]
end

#adjust_day_delta(day_delta, new_secs_since_bod) ⇒ Object



136
137
138
139
140
141
142
143
144
145
# File 'lib/ri_cal/fast_date_time.rb', line 136

def adjust_day_delta(day_delta, new_secs_since_bod)
 if new_secs_since_bod == 0
   [day_delta, new_secs_since_bod]
 elsif new_secs_since_bod > 0
   [day_delta + (new_secs_since_bod / SECONDS_IN_A_DAY), new_secs_since_bod % SECONDS_IN_A_DAY]
 else
   [day_delta - (1 + new_secs_since_bod.abs / SECONDS_IN_A_DAY), 
    SECONDS_IN_A_DAY - (new_secs_since_bod.abs % SECONDS_IN_A_DAY)]
 end
end

#advance(options) ⇒ Object

:nodoc:



148
149
150
151
152
153
154
155
156
157
158
159
# File 'lib/ri_cal/fast_date_time.rb', line 148

def advance(options) # :nodoc:
  new_date = @date
  new_offset = options[:offset] || offset
  month_delta = (options[:years] || 0) * 12 + (options[:months] || 0)
  day_delta =   (options[:weeks] || 0) * 7 + (options[:days] || 0)
  sec_delta = hms_to_seconds((options[:hours] || 0), (options[:minutes] || 0), (options[:seconds] || 0))
  day_delta, new_secs_since_bod = *adjust_day_delta(day_delta, secs_since_bod + sec_delta)
  new_hour, new_min, new_sec = *seconds_to_hms(new_secs_since_bod)
  new_date = new_date >> month_delta unless month_delta == 0
  new_date += day_delta unless day_delta == 0
  FastDateTime.new(new_date.year, new_date.month, new_date.day, new_hour, new_min, new_sec, new_offset)
end

#change(options) ⇒ Object

Return a new FastDateTime based on the receiver but with changes specified by the options



95
96
97
98
99
100
101
102
103
104
105
# File 'lib/ri_cal/fast_date_time.rb', line 95

def change(options)
  FastDateTime.new(
  options[:year]  || year,
  options[:month] || month,
  options[:day]   || day,
  options[:hour]  || hour,
  options[:min]   || (options[:hour] ? 0 : min),
  options[:sec]   || ((options[:hour] || options[:min]) ? 0 : sec),
  options[:offset]  || offset
  )
end

#cmp_fast_date_time_value(other) ⇒ Object



227
228
229
# File 'lib/ri_cal/fast_date_time.rb', line 227

def cmp_fast_date_time_value(other)
  other <=> self
end

#dayObject



56
57
58
# File 'lib/ri_cal/fast_date_time.rb', line 56

def day
  @date.day
end

#days_in_monthObject

def jd

date.jd

end



88
89
90
# File 'lib/ri_cal/fast_date_time.rb', line 88

def days_in_month
  date.days_in_month
end

#hms_to_seconds(hours, minutes, seconds) ⇒ Object



123
124
125
# File 'lib/ri_cal/fast_date_time.rb', line 123

def hms_to_seconds(hours, minutes, seconds)
  seconds + 60 *(minutes + (60 * hours))
end

#ical_date_strObject



42
43
44
# File 'lib/ri_cal/fast_date_time.rb', line 42

def ical_date_str
  "%04d%02d%02d" % [year, month, day]
end

#ical_strObject



38
39
40
# File 'lib/ri_cal/fast_date_time.rb', line 38

def ical_str
  "%04d%02d%02dT%02d%02d%02d" % [year, month, day, hour, min, sec]
end

#iso_weeks_in_year(wkst) ⇒ Object



215
216
217
# File 'lib/ri_cal/fast_date_time.rb', line 215

def iso_weeks_in_year(wkst)
  @date.iso_weeks_in_year(wkst)
end

#iso_year_and_week_one_start(wkst) ⇒ Object



223
224
225
# File 'lib/ri_cal/fast_date_time.rb', line 223

def iso_year_and_week_one_start(wkst)
  @date.iso_year_and_week_one_start(wkst)
end

#iso_year_start(wkst) ⇒ Object



219
220
221
# File 'lib/ri_cal/fast_date_time.rb', line 219

def iso_year_start(wkst)
  @date.iso_year_start(wkst)
end

#monthObject Also known as: mon



50
51
52
# File 'lib/ri_cal/fast_date_time.rb', line 50

def month
  @date.month
end

#nth_wday_in_month(n, which_wday) ⇒ Object

e.g. to obtain the 3nd Tuesday of the receivers month use

time.nth_wday_in_month(2, 2)


170
171
172
173
174
175
176
177
178
179
180
181
182
# File 'lib/ri_cal/fast_date_time.rb', line 170

def nth_wday_in_month(n, which_wday)
  first_of_month = change(:day => 1)
  first_in_month = first_of_month.advance(:days => (which_wday - first_of_month.wday))
  first_in_month = first_in_month.advance(:days => 7) if first_in_month.month != first_of_month.month
  if n > 0
    first_in_month.advance(:days => (7*(n - 1)))
  else
    possible = first_in_month.advance(:days => 21)
    possible = possible.advance(:days => 7) while possible.month == first_in_month.month
    last_in_month = possible.advance(:days => - 7)
    (last_in_month.advance(:days => - (7*(n.abs - 1))))
  end
end

#nth_wday_in_year(n, which_wday) ⇒ Object

e.g. to obtain the 2nd Monday of the receivers year use

time.nth_wday_in_year(2, 1)


193
194
195
196
197
198
199
200
201
202
203
# File 'lib/ri_cal/fast_date_time.rb', line 193

def nth_wday_in_year(n, which_wday)
  if n > 0
    first_of_year = change(:month => 1, :day => 1)
    first_in_year = first_of_year.advance(:days => (which_wday - first_of_year.wday + 7) % 7)
    first_in_year.advance(:days => (7*(n - 1)))
  else
    december25 = change(:month => 12, :day => 25)
    last_in_year = december25.advance(:days => (which_wday - december25.wday + 7) % 7)
    last_in_year.advance(:days => (7 * (n + 1)))
  end
end

#seconds_to_hms(total_seconds) ⇒ Object



127
128
129
130
131
132
133
134
# File 'lib/ri_cal/fast_date_time.rb', line 127

def seconds_to_hms(total_seconds)
  sign = total_seconds <=> 0
  remaining = total_seconds.abs
  seconds = sign * (remaining % 60)
  remaining = remaining / 60
  minutes = sign * (remaining % 60)
  [remaining / 60, minutes, seconds]
end

#start_of_week_with_wkst(wkst) ⇒ Object

Return a DateTime which is the beginning of the first day on or before the receiver with the specified wday



208
209
210
211
212
213
# File 'lib/ri_cal/fast_date_time.rb', line 208

def start_of_week_with_wkst(wkst)
  wkst ||= 1
  date = @date
  date -= 1 while date.wday != wkst
  date
end

#to_datetimeObject



64
65
66
# File 'lib/ri_cal/fast_date_time.rb', line 64

def to_datetime
  DateTime.civil(year, month, day, hour, min, sec, RiCal.RationalOffset[utc_offset_seconds])
end

#to_sObject Also known as: inspect



80
81
82
# File 'lib/ri_cal/fast_date_time.rb', line 80

def to_s
  "#{year}/#{month}/#{day} #{hour}:#{min}:#{sec} #{offset}"
end

#utcObject

def new_offset(ofst)

if ofst == offset
  self
else
  advance(:seconds => offset - ofset, :offset => ofst)
end

end



115
116
117
118
119
120
121
# File 'lib/ri_cal/fast_date_time.rb', line 115

def utc
  if offset == 0
    self
  else
    advance(:seconds => -offset, :offset => 0)
  end
end

#wdayObject



60
61
62
# File 'lib/ri_cal/fast_date_time.rb', line 60

def wday
  @date.wday
end

#yearObject



46
47
48
# File 'lib/ri_cal/fast_date_time.rb', line 46

def year
  @date.year
end