Class: RiCal::FastDateTime

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

Overview

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.



11
12
13
14
15
# File 'lib/ri_cal/fast_date_time.rb', line 11

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.



5
6
7
# File 'lib/ri_cal/fast_date_time.rb', line 5

def date
  @date
end

#hourObject

Returns the value of attribute hour.



5
6
7
# File 'lib/ri_cal/fast_date_time.rb', line 5

def hour
  @hour
end

#minObject

Returns the value of attribute min.



5
6
7
# File 'lib/ri_cal/fast_date_time.rb', line 5

def min
  @min
end

#offsetObject Also known as: utc_offset_seconds

Returns the value of attribute offset.



5
6
7
# File 'lib/ri_cal/fast_date_time.rb', line 5

def offset
  @offset
end

#secObject

Returns the value of attribute sec.



5
6
7
# File 'lib/ri_cal/fast_date_time.rb', line 5

def sec
  @sec
end

#secs_since_bodObject

Returns the value of attribute secs_since_bod.



5
6
7
# File 'lib/ri_cal/fast_date_time.rb', line 5

def secs_since_bod
  @secs_since_bod
end

Class Method Details

.from_date(date) ⇒ Object



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

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



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

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



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

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



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

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

.parse(val, just_date = false) ⇒ Object



17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
# File 'lib/ri_cal/fast_date_time.rb', line 17

def self.parse(val, just_date = false)
  if match_data = /\A(\d{4})(\d{2})(\d{2})(?:T(\d{2})(\d{2})(\d{2})(?:(Z)|(?:(-|\+)(\d{2})(\d{2})))?)?\z/.match(val.strip)
    year, month, day, hour, minute, second, utc, tzsign, tzhour, tzminute = *match_data[1..-1]
    if just_date
      hour, minute, second, timezone = 0
    elsif hour
      timezone = utc ? 0 : tzsign ? (tzsign == '-' ? -1 : 1) * (tzhour.to_i * 60 + tzminute.to_i) * 60 : 0
    end
    new(year.to_i, month.to_i, day.to_i, hour.to_i, minute.to_i, second.to_i, timezone.to_i)
  elsif just_date
    from_date_time(::DateTime.parse(::DateTime.parse(val).strftime("%Y%m%d")))
  else
    from_date_time(::DateTime.parse(val))
  end
end

Instance Method Details

#<=>(other) ⇒ Object



85
86
87
88
89
90
91
# File 'lib/ri_cal/fast_date_time.rb', line 85

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



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

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



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

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:



161
162
163
164
165
166
167
168
169
170
171
172
# File 'lib/ri_cal/fast_date_time.rb', line 161

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



108
109
110
111
112
113
114
115
116
117
118
# File 'lib/ri_cal/fast_date_time.rb', line 108

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



240
241
242
# File 'lib/ri_cal/fast_date_time.rb', line 240

def cmp_fast_date_time_value(other)
  other <=> self
end

#dayObject



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

def day
  @date.day
end

#days_in_monthObject

def jd

date.jd

end



101
102
103
# File 'lib/ri_cal/fast_date_time.rb', line 101

def days_in_month
  date.days_in_month
end

#hms_to_seconds(hours, minutes, seconds) ⇒ Object



136
137
138
# File 'lib/ri_cal/fast_date_time.rb', line 136

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

#ical_date_strObject



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

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

#ical_strObject



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

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

#iso_weeks_in_year(wkst) ⇒ Object



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

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

#iso_year_and_week_one_start(wkst) ⇒ Object



236
237
238
# File 'lib/ri_cal/fast_date_time.rb', line 236

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

#iso_year_start(wkst) ⇒ Object



232
233
234
# File 'lib/ri_cal/fast_date_time.rb', line 232

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

#monthObject Also known as: mon



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

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)


183
184
185
186
187
188
189
190
191
192
193
194
195
# File 'lib/ri_cal/fast_date_time.rb', line 183

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)


206
207
208
209
210
211
212
213
214
215
216
# File 'lib/ri_cal/fast_date_time.rb', line 206

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



140
141
142
143
144
145
146
147
# File 'lib/ri_cal/fast_date_time.rb', line 140

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



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

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

#to_datetimeObject



77
78
79
# File 'lib/ri_cal/fast_date_time.rb', line 77

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

#to_sObject Also known as: inspect



93
94
95
# File 'lib/ri_cal/fast_date_time.rb', line 93

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



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

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

#wdayObject



73
74
75
# File 'lib/ri_cal/fast_date_time.rb', line 73

def wday
  @date.wday
end

#yearObject



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

def year
  @date.year
end