In Files

Parent

Class Index [+]

Quicksearch

TaskJuggler::TjTime

The TjTime class is based on the original Ruby class Time but provides lots of additional functionality.

Constants

MON_MAX

The number of days per month. Leap years are taken care of separately.

Attributes

time[R]

Public Class Methods

checkTimeZone(zone) click to toggle source

Check if zone is a valid time zone.

     # File lib/TjTime.rb, line 169
169:     def TjTime.checkTimeZone(zone)
170:       return true if zone == 'UTC'
171: 
172:       # Valid time zones must be of the form 'Region/City'
173:       return false unless zone.include?('/')
174: 
175:       # Save curent value of TZ
176:       tz = ENV['TZ']
177:       ENV['TZ'] = zone
178:       newZone = Time.new.zone
179:       # If the time zone is valid, the OS can convert a zone like
180:       # 'America/Denver' into 'MST'. Unknown time zones are either not
181:       # converted or cause a fallback to UTC.
182:       # Since glibc 2.10 Time.new.zone only return the region for illegal
183:       # zones instead of the full zone string like it does on earlier
184:       # versions.
185:       region = zone[0..zone.index('/') - 1]
186:       res = (newZone != zone && newZone != region && newZone != 'UTC')
187:       # Restore TZ if it was set earlier.
188:       if tz
189:         ENV['TZ'] = tz
190:       else
191:         ENV.delete('TZ')
192:       end
193:       res
194:     end
gm(*args) click to toggle source

Creates a time based on given values, interpreted as UTC. See Time.gm() for details.

    # File lib/TjTime.rb, line 53
53:     def TjTime.gm(*args)
54:       TjTime.new(Time.gm(*args))
55:     end
local(*args) click to toggle source

Creates a time based on given values, interpreted as local time. The result is stored as UTC time, though. See Time.local() for details.

    # File lib/TjTime.rb, line 59
59:     def TjTime.local(*args)
60:       TjTime.new(Time.local(*args).gmtime)
61:     end
TjTime(time) → Scenario TjTime(s) → Scenario TjTime(secs) → Scenario click to toggle source

The constructor is overloaded and accepts 3 kinds of arguments. If t is a Time object this is just copied to the @time variable. If it’s a string, it is parsed as a date. Or else it is interpreted as seconds after Epoch.

    # File lib/TjTime.rb, line 36
36:     def initialize(t)
37:       if t.is_a?(Time)
38:         @time = t
39:       elsif t.is_a?(String)
40:         @time = TjTime.parse(t).time
41:       else
42:         @time = Time.at(t)
43:       end
44:     end
now() click to toggle source

Returns the current UTC time as Time object.

    # File lib/TjTime.rb, line 47
47:     def TjTime.now
48:       TjTime.new(Time.now.gmtime)
49:     end
parse(t) click to toggle source
     # File lib/TjTime.rb, line 63
 63:     def TjTime.parse(t)
 64:       year, month, day, time, zone = t.split('-', 5)
 65: 
 66:       # Check the year
 67:       if year
 68:         year = year.to_i
 69:         if year < 1970 || year > 2035
 70:           raise TjException.new, "Year #{year} out of range (1970 - 2035)"
 71:         end
 72:       else
 73:         raise TjException.new, "Year not specified"
 74:       end
 75: 
 76:       # Check the month
 77:       if month
 78:         month = month.to_i
 79:         if month < 1 || month > 12
 80:           raise TjException.new, "Month #{month} out of range (1 - 12)"
 81:         end
 82:       else
 83:         raise TjException.new, "Month not specified"
 84:       end
 85: 
 86:       # Check the day
 87:       if day
 88:         day = day.to_i
 89:         maxDay = [ 0, 31, Date.gregorian_leap?(year) ? 29 : 28, 31, 30, 31,
 90:                    30, 31, 31, 30, 31, 30, 31 ]
 91:         if month < 1 || month > maxDay[month]
 92:           raise TjException.new, "Day #{day} out of range (1 - #{maxDay[month]})"
 93:         end
 94:       else
 95:         raise TjException.new, "Day not specified"
 96:       end
 97: 
 98:       # The time is optional. Will be expanded to 00:00:00.
 99:       if time
100:         hour, minute, second = time.split(':')
101: 
102:         # Check hour
103:         if hour
104:           hour = hour.to_i
105:           if hour < 0 || hour > 23
106:             raise TjException.new, "Hour #{hour} out of range (0 - 23)"
107:           end
108:         else
109:           raise TjException.new, "Hour not specified"
110:         end
111: 
112:         if minute
113:           minute = minute.to_i
114:           if minute < 0 || minute > 59
115:             raise TjException.new, "Minute #{minute} out of range (0 - 59)"
116:           end
117:         else
118:           raise TjException.new, "Minute not specified"
119:         end
120: 
121:         # Check sencond. This value is optional and defaults to 0.
122:         if second
123:           second = second.to_i
124:           if second < 0 || second > 59
125:             raise TjException.new, "Second #{second} out of range (0 - 59)"
126:           end
127:         else
128:           second = 0
129:         end
130:       else
131:         hour = minute = second = 0
132:       end
133: 
134:       # The zone is optional and defaults to the current time zone.
135:       if zone
136:         if zone[0] != -- && zone[0] != ++
137:           raise TjException.new, "Time zone adjustment must be prefixed by " +
138:                                  "+ or -, not #{zone[0]}"
139:         end
140:         if zone.length != 5
141:           raise TjException.new, "Time zone adjustment must use (+/-)HHMM format"
142:         end
143: 
144:         date = Time.utc(year, month, day, hour, minute, second)
145:         sign = zone[0] == -- ? 1 : 1
146:         tzHour = zone[1..2].to_i
147:         if tzHour < 0 || tzHour > 12
148:           raise TjException.new, "Time zone adjustment hour out of range " +
149:                                  "(0 - 12) but is #{tzHour}"
150:         end
151:         tzMinute = zone[3..4].to_i
152:         if tzMinute < 0 || tzMinute > 59
153:           raise TjException.new, "Time zone adjustment minute out of range " +
154:                                  "(0 - 59) but is #{tzMinute}"
155:         end
156:         date += sign * (tzHour * 3600 + tzMinute * 60)
157:       else
158:         date = Time.mktime(year, month, day, hour, minute, second)
159:       end
160: 
161:       #puts "--> #{t}"
162:       #puts(">>> #{year}-#{month}-#{day}-#{hour}:#{minute}:#{second}" +
163:       #     "#{zone ? "-#{tzHour}:#{tzMinute}" : ""}")
164:       #puts "=== #{date}"
165:       TjTime.new(date)
166:     end

Public Instance Methods

%(val) click to toggle source

Convert the time to seconds since Epoch and return the module of val.

     # File lib/TjTime.rb, line 224
224:     def %(val)
225:       @time.to_i % val
226:     end
+(secs) click to toggle source

Add secs number of seconds to the time.

     # File lib/TjTime.rb, line 209
209:     def +(secs)
210:       TjTime.new(@time + secs)
211:     end
-(arg) click to toggle source

Substract arg number of seconds or return the number of seconds between arg and this time.

     # File lib/TjTime.rb, line 215
215:     def -(arg)
216:       if arg.is_a?(TjTime)
217:         @time - arg.time
218:       else
219:         TjTime.new(@time - arg)
220:       end
221:     end
<(t) click to toggle source

Return true if time is smaller than t.

     # File lib/TjTime.rb, line 229
229:     def <(t)
230:       @time < t.time
231:     end
<=(t) click to toggle source

Return true if time is smaller or equal than t.

     # File lib/TjTime.rb, line 234
234:     def <=(t)
235:       @time <= t.time
236:     end
<=>(t) click to toggle source

Coparison operator for time with another time t.

     # File lib/TjTime.rb, line 255
255:     def <=>(t)
256:       @time <=> t.time
257:     end
==(t) click to toggle source

Return true if time and t are identical.

     # File lib/TjTime.rb, line 249
249:     def ==(t)
250:       return false if t.nil?
251:       @time == t.time
252:     end
>(t) click to toggle source

Return true if time is larger than t.

     # File lib/TjTime.rb, line 239
239:     def >(t)
240:       @time > t.time
241:     end
>=(t) click to toggle source

Return true if time is larger or equal than t.

     # File lib/TjTime.rb, line 244
244:     def >=(t)
245:       @time >= t.time
246:     end
align(clock) click to toggle source

Align the date to a time grid. The grid distance is determined by clock.

     # File lib/TjTime.rb, line 197
197:     def align(clock)
198:       TjTime.new((@time.to_i / clock) * clock)
199:     end
beginOfHour() click to toggle source

Normalize time to the beginning of the current hour.

     # File lib/TjTime.rb, line 270
270:     def beginOfHour
271:       t = @time.localtime.to_a
272:       t[0, 2] = Array.new(2, 0)
273:       t.slice!(6, 4)
274:       t.reverse!
275:       TjTime.new(Time.local(*t))
276:     end
beginOfMonth() click to toggle source

Normalize time to the beginning of the current month.

     # File lib/TjTime.rb, line 303
303:     def beginOfMonth
304:       t = @time.localtime.to_a
305:       t[0, 3] = Array.new(3, 0)
306:       t[3] = 1
307:       t.slice!(6, 4)
308:       t.reverse!
309:       TjTime.new(Time.local(*t))
310:     end
beginOfQuarter() click to toggle source

Normalize time to the beginning of the current quarter.

     # File lib/TjTime.rb, line 313
313:     def beginOfQuarter
314:       t = @time.localtime.to_a
315:       t[0, 3] = Array.new(3, 0)
316:       t[3] = 1
317:       t[4] = ((t[4] - 1) % 3) + 1
318:       t.slice!(6, 4)
319:       t.reverse!
320:       TjTime.new(Time.local(*t))
321:     end
beginOfWeek(startMonday) click to toggle source

Normalize time to the beginning of the current week. startMonday determines whether the week should start on Monday or Sunday.

     # File lib/TjTime.rb, line 289
289:     def beginOfWeek(startMonday)
290:       t = @time.to_a
291:       # Set time to noon, 12:00:00
292:       t[0, 3] = [ 0, 0, 12 ]
293:       weekday = t[6]
294:       t.slice!(6, 4)
295:       t.reverse!
296:       # Substract the number of days determined by the weekday t[6] and set time
297:       # to midnight of that day.
298:       (TjTime.new(Time.local(*t)) -
299:        (weekday - (startMonday ? 1 : 0)) * 60 * 60 * 24).midnight
300:     end
beginOfYear() click to toggle source

Normalize time to the beginning of the current year.

     # File lib/TjTime.rb, line 324
324:     def beginOfYear
325:       t = @time.localtime.to_a
326:       t[0, 3] = Array.new(3, 0)
327:       t[3, 2] = Array.new(2, 1)
328:       t.slice!(6, 4)
329:       t.reverse!
330:       TjTime.new(Time.local(*t))
331:     end
daysTo(date) click to toggle source

Return the number of days between this time and date. The result is always rounded up.

     # File lib/TjTime.rb, line 415
415:     def daysTo(date)
416:       countIntervals(date, :sameTimeNextDay)
417:     end
hoursLater(hours) click to toggle source

Return a new time that is hours later than time.

     # File lib/TjTime.rb, line 334
334:     def hoursLater(hours)
335:       TjTime.new(@time + hours * 3600)
336:     end
hoursTo(date) click to toggle source

Return the number of hours between this time and date. The result is always rounded up.

     # File lib/TjTime.rb, line 408
408:     def hoursTo(date)
409:       t1, t2 = order(date)
410:       ((t2 - t1) / 3600).ceil
411:     end
method_missing(func, *args) click to toggle source

Pass any unknown function directoy to the @time variable.

     # File lib/TjTime.rb, line 504
504:     def method_missing(func, *args)
505:       @time.method(func).call(*args)
506:     end
midnight() click to toggle source

Normalize time to the beginning of the current day.

     # File lib/TjTime.rb, line 279
279:     def midnight
280:       t = @time.localtime.to_a
281:       t[0, 3] = Array.new(3, 0)
282:       t.slice!(6, 4)
283:       t.reverse!
284:       TjTime.new(Time.local(*t))
285:     end
monthAndYear() click to toggle source

Return the abbreviated month name and the full year. E. g. ‘Feb 1972’.

     # File lib/TjTime.rb, line 481
481:     def monthAndYear
482:       @time.strftime('%b %Y')
483:     end
monthsTo(date) click to toggle source

Return the number of months between this time and date. The result is always rounded up.

     # File lib/TjTime.rb, line 427
427:     def monthsTo(date)
428:       countIntervals(date, :sameTimeNextMonth)
429:     end
nextDayOfWeek(dow) click to toggle source

Return the start of the next dow day of week after date. dow must be 0 for Sundays, 1 for Mondays and 6 for Saturdays. If date is a Tuesday and dow is 5 (Friday) the date of next Friday 0:00 will be returned. If date is a Tuesday and dow is 2 (Tuesday) the date of the next Tuesday will be returned.

     # File lib/TjTime.rb, line 495
495:     def nextDayOfWeek(dow)
496:       raise "Day of week must be 0 - 6." unless dow >= 0 && dow <= 6
497:       d = midnight.sameTimeNextDay
498:       currentDoW = d.strftime('%w').to_i
499:       1.upto((dow + 7 - currentDoW) % 7) { |i| d = d.sameTimeNextDay }
500:       d
501:     end
quarterName() click to toggle source

Return the number of the quarter prefixed by a ‘Q’.

     # File lib/TjTime.rb, line 470
470:     def quarterName
471:       "Q#{(@time.mon / 3) + 1}"
472:     end
quartersTo(date) click to toggle source

Return the number of quarters between this time and date. The result is always rounded up.

     # File lib/TjTime.rb, line 433
433:     def quartersTo(date)
434:       countIntervals(date, :sameTimeNextQuarter)
435:     end
sameTimeNextDay() click to toggle source

Return a new time that is 1 day later than time but at the same time of day.

     # File lib/TjTime.rb, line 345
345:     def sameTimeNextDay
346:       delta = [ 0, 1, 1 ]
347:       localT1 = @time.localtime.to_a
348:       delta.each do |d|
349:         t = @time + (24 + d) * 60 * 60
350:         localT2 = t.localtime.to_a
351:         return TjTime.new(t) if localT1[0, 3] == localT2[0, 3]
352:       end
353:       raise "Algorithm is broken for #{@time}"
354:     end
sameTimeNextHour() click to toggle source

Return a new time that is 1 hour later than time.

     # File lib/TjTime.rb, line 339
339:     def sameTimeNextHour
340:       hoursLater(1)
341:     end
sameTimeNextMonth() click to toggle source

Return a new time that is 1 month later than time but at the same time of day.

     # File lib/TjTime.rb, line 371
371:     def sameTimeNextMonth
372:       sec, min, hour, day, month, year = @time.localtime.to_a
373:       monMax = month == 2 && leapYear?(year) ? 29 : MON_MAX[month]
374:       month += 1
375:       if month > 12
376:         month = 1
377:         year += 1
378:       end
379:       day = monMax if day >= monMax
380:       TjTime.new(Time.mktime(year, month, day, hour, min, sec, 0))
381:     end
sameTimeNextQuarter() click to toggle source

Return a new time that is 1 quarter later than time but at the same time of day.

     # File lib/TjTime.rb, line 385
385:     def sameTimeNextQuarter
386:       t = @time.localtime.to_a
387:       if (t[4] += 3) > 12
388:         t[4] -= 12
389:         t[5] += 1
390:       end
391:       t.slice!(6, 4)
392:       t.reverse!
393:       TjTime.new(Time.local(*t))
394:     end
sameTimeNextWeek() click to toggle source

Return a new time that is 1 week later than time but at the same time of day.

     # File lib/TjTime.rb, line 358
358:     def sameTimeNextWeek
359:       delta = [ 0, 1, 1 ]
360:       localT1 = @time.localtime.to_a
361:       delta.each do |d|
362:         t = @time + (7 * 24 + d) * 60 * 60
363:         localT2 = t.localtime.to_a
364:         return TjTime.new(t) if localT1[0, 3] == localT2[0, 3]
365:       end
366:       raise "Algorithm is broken for #{@time}"
367:     end
sameTimeNextYear() click to toggle source

Return a new time that is 1 year later than time but at the same time of day.

     # File lib/TjTime.rb, line 398
398:     def sameTimeNextYear
399:       t = @time.localtime.to_a
400:       t[5] += 1
401:       t.slice!(6, 4)
402:       t.reverse!
403:       TjTime.new(Time.local(*t))
404:     end
secondsOfDay(tz = nil) click to toggle source

Returns the total number of seconds of the day. The time is assumed to be in the time zone specified by tz.

     # File lib/TjTime.rb, line 203
203:     def secondsOfDay(tz = nil)
204:       # TODO: Add timezone support
205:       (@time.to_i + @time.gmt_offset) % (60 * 60 * 24)
206:     end
shortMonthName() click to toggle source

Return the abbreviated month name.

     # File lib/TjTime.rb, line 465
465:     def shortMonthName
466:       @time.strftime('%b')
467:     end
to_ary() click to toggle source
     # File lib/TjTime.rb, line 459
459:     def to_ary
460:       to_s
461:     end
to_i() click to toggle source

Return the seconds since Epoch.

     # File lib/TjTime.rb, line 455
455:     def to_i
456:       @time.to_i
457:     end
to_s(format = nil) click to toggle source

This function is just a wrapper around Time.strftime(). In case @time is nil, it returns ‘unkown’.

     # File lib/TjTime.rb, line 445
445:     def to_s(format = nil)
446:       return 'unknown' if @time.nil?
447:       if format.nil?
448:         format = '%Y-%m-%d-%H:%M' + (@time.sec == 0 ? '' : ':%S') + '-%z'
449:       end
450:       # Always report values in local timezone
451:       @time.dup.localtime.strftime(format)
452:     end
upto(endDate, step = 1) click to toggle source

Iterator that executes the block until time has reached endDate increasing time by step on each iteration.

     # File lib/TjTime.rb, line 261
261:     def upto(endDate, step = 1)
262:       t = @time
263:       while t < endDate.time
264:         yield(TjTime.new(t))
265:         t += step
266:       end
267:     end
week(weekStartsMonday) click to toggle source

Return the week number. weekStartsMonday specifies wheter the counting should be for weeks starting Mondays or Sundays.

     # File lib/TjTime.rb, line 476
476:     def week(weekStartsMonday)
477:       @time.strftime(weekStartsMonday ? '%W' : '%U')
478:     end
weekdayAndDate() click to toggle source

Return the abbreviated weekday and the full date. E. g. ‘Sat 2007-11-03’.

     # File lib/TjTime.rb, line 486
486:     def weekdayAndDate
487:       @time.strftime('%A %Y-%m-%d')
488:     end
weeksTo(date) click to toggle source

Return the number of weeks between this time and date. The result is always rounded up.

     # File lib/TjTime.rb, line 421
421:     def weeksTo(date)
422:       countIntervals(date, :sameTimeNextWeek)
423:     end
yearsTo(date) click to toggle source

Return the number of years between this time and date. The result is always rounded up.

     # File lib/TjTime.rb, line 439
439:     def yearsTo(date)
440:       countIntervals(date, :sameTimeNextYear)
441:     end

Private Instance Methods

countIntervals(date, stepFunc) click to toggle source
     # File lib/TjTime.rb, line 521
521:     def countIntervals(date, stepFunc)
522:       i = 0
523:       t1, t2 = order(date)
524:       while t1 < t2
525:         t1 = t1.send(stepFunc)
526:         i += 1
527:       end
528:       i
529:     end
leapYear?(year) click to toggle source
     # File lib/TjTime.rb, line 531
531:     def leapYear?(year)
532:       case
533:       when year % 400 == 0
534:         true
535:       when year % 100 == 0
536:         false
537:       else
538:         year % 4 == 0
539:       end
540:     end
order(date) click to toggle source
     # File lib/TjTime.rb, line 510
510:     def order(date)
511:       if date.time < @time
512:         t1 = date
513:         t2 = self
514:       else
515:         t1 = self
516:         t2 = date
517:       end
518:       [ t1, t2 ]
519:     end

Disabled; run with --debug to generate this.

[Validate]

Generated with the Darkfish Rdoc Generator 1.1.6.