Class: Time

Inherits:
Object show all
Defined in:
lib/core/facets/time/set.rb,
lib/core/facets/time/shift.rb,
lib/core/facets/time/stamp.rb,
lib/core/facets/time/trunc.rb,
lib/core/facets/time/change.rb,
lib/core/facets/time/future.rb,
lib/core/facets/time/elapse.rb,
lib/core/facets/time/to_time.rb,
lib/core/facets/time/round_to.rb,
lib/core/facets/time/dst_adjustment.rb,
lib/standard/facets/date.rb

Constant Summary

FORMAT =
{
  :utc      => "%Y-%m-%d %H:%M:%S",
  :utcT     => "%Y-%m-%dT%H:%M:%S",
  :db       => "%Y-%m-%d %H:%M:%S",
  :database => "%Y-%m-%d %H:%M:%S",
  :number   => "%Y%m%d%H%M%S",
  :short    => "%d %b %H:%M",
  :time     => "%H:%M",
  :long     => "%B %d, %Y %H:%M",
  :day1st   => "%d-%m-%Y %H:%M",
  :dmYHM    => "%d-%m-%Y %H:%M",
  :rfc822   => "%a, %d %b %Y %H:%M:%S %z",
  :ruby18   => "%a %b %d %H:%M:%S %z %Y",
  nil       => "%Y-%m-%d %H:%M:%S %z"
}

Class Method Summary collapse

Instance Method Summary collapse

Class Method Details

.elapseObject

Tracks the elapse time of a code block.

e = Time.elapse { sleep 1 }

e.assert > 1

CREDIT: Hal Fulton



11
12
13
14
15
16
# File 'lib/core/facets/time/elapse.rb', line 11

def self.elapse
  raise "Need block" unless block_given?
  t0 = now.to_f
  yield
  now.to_f - t0
end

.local_time(*args) ⇒ Object



356
357
358
# File 'lib/standard/facets/date.rb', line 356

def self.local_time(*args)
  time_with_datetime_fallback(:local, *args)
end

.stamp(*args) ⇒ Object

Produce time stamp for Time.now. See #stamp.

CREDIT: Trans



26
27
28
# File 'lib/core/facets/time/stamp.rb', line 26

def self.stamp(*args)
  now.stamp(*args)
end

.time_with_datetime_fallback(utc_or_local, year, month = 1, day = 1, hour = 0, min = 0, sec = 0, usec = 0) ⇒ Object



366
367
368
369
370
371
# File 'lib/standard/facets/date.rb', line 366

def self.time_with_datetime_fallback(utc_or_local, year, month=1, day=1, hour=0, min=0, sec=0, usec=0)
  ::Time.send(utc_or_local, year, month, day, hour, min, sec, usec)
rescue
  offset = utc_or_local.to_sym == :local ? ::DateTime.local_offset : 0
  ::DateTime.civil(year, month, day, hour, min, sec, offset)
end

.utc_time(*args) ⇒ Object



361
362
363
# File 'lib/standard/facets/date.rb', line 361

def self.utc_time(*args)
  time_with_datetime_fallback(:utc, *args)
end

Instance Method Details

#change(options) ⇒ Object

Returns a new Time where one or more of the elements have been changed according to the options parameter. The time options (hour, minute, sec, usec) reset cascadingly, so if only the hour is passed, then minute, sec, and usec is set to 0. If the hour and minute is passed, then sec and usec is set to 0.

t1 = Time.at(10000)
t1.ctime   #=> "Wed Dec 31 21:46:40 1969"

t2 = t1.change(:hour => 11)
t2.ctime   #=> "Wed Dec 31 11:00:00 1969"


16
17
18
19
20
21
22
23
24
25
26
27
28
# File 'lib/core/facets/time/change.rb', line 16

def change(options)
  opts=options; #{}; options.each_pair{ |k,v| opts[k] = v.to_i }
  self.class.send(
    self.utc? ? :utc : :local,
    opts[:year]  || self.year,
    opts[:month] || self.month,
    opts[:day]   || self.day,
    opts[:hour]  || self.hour,
    opts[:min]   || (opts[:hour] ? 0 : self.min),
    opts[:sec]   || ((opts[:hour] || opts[:min]) ? 0 : self.sec),
    opts[:usec]  || ((opts[:hour] || opts[:min] || opts[:sec]) ? 0 : self.usec)
  )
end

#dst_adjustment(time) ⇒ Object

Adjust DST

TODO: Can't seem to get this to pass ActiveSupport tests, even though it is essentially identical to the ActiveSupport code (see Time#since in time/calculations.rb). It handles all but 4 tests.



11
12
13
14
15
16
17
18
19
20
# File 'lib/core/facets/time/dst_adjustment.rb', line 11

def dst_adjustment(time)
  self_dst = self.dst? ? 1 : 0
  time_dst = time.dst? ? 1 : 0
  seconds  = (self - time).abs
  if (seconds >= 86400 && self_dst != time_dst)
    time + ((self_dst - time_dst) * 60 * 60)
  else
    time
  end
end

#future?(other = nil) ⇒ Boolean



9
10
11
# File 'lib/core/facets/time/future.rb', line 9

def future?(other=nil)
  self > (other || ::Time.now)
end

#less(*time_units) ⇒ Object Also known as: ago

Returns a new Time representing the time a number of time-units ago. This is just like #shift, but reverses the direction.

t = Time.utc(2010,10,10,0,0,0)

t.less(4, :days)             #=>  Time.utc(2010,10,6,0,0,0)


79
80
81
82
83
84
85
86
87
88
89
90
91
# File 'lib/core/facets/time/shift.rb', line 79

def less(*time_units)
  time_hash  = Hash===time_units.last ? time_units.pop : {}
  time_units = time_units.flatten

  time_units << :seconds if time_units.size % 2 == 1

  time_hash.each{ |units, number| time_units << number; time_units << units }

  neg_times = []
  time_units.each_slice(2){ |number, units| neg_times << -number; neg_times << units }

  shift(*neg_times)
end

#past?(other = nil) ⇒ Boolean



4
5
6
# File 'lib/core/facets/time/future.rb', line 4

def past?(other=nil)
  self < (other || ::Time.now)
end

#round_to(seconds) ⇒ Object

Round time at the nearest range (in seconds).

t1 = Time.now
t2 = t1.round_to(60*60)
t2.min #=> 0
t2.sec #=> 0

TODO: What about `round(:minute)`?

TODO: Fractional seconds should round the usec.



16
17
18
# File 'lib/core/facets/time/round_to.rb', line 16

def round_to(seconds)
  (self + seconds / 2.0).trunc(seconds)
end

#set(options) ⇒ Object

Like change but does not reset earlier times.

NOTE: It would be better, probably if this were called “change”. and that #change were called “reset”.



8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
# File 'lib/core/facets/time/set.rb', line 8

def set(options)
  opts={}
  options.each_pair do |k,v| 
    k = :min if k.to_s =~ /^min/
    k = :sec if k.to_s =~ /^sec/
    opts[k] = v.to_i 
  end
  self.class.send(
    self.utc? ? :utc : :local,
    opts[:year]  || self.year,
    opts[:month] || self.month,
    opts[:day]   || self.day,
    opts[:hour]  || self.hour,
    opts[:min]   || self.min,
    opts[:sec]   || self.sec,
    opts[:usec]  || self.usec
  )
end

#shift(*time_units) ⇒ Object Also known as: in, hence

Returns a new Time representing the time shifted by the time-units given. Positive number shift the time forward, negative number shift the time backward.

t = Time.utc(2010,10,10,0,0,0)
t.shift( 4, :days)            #=>  Time.utc(2010,10,14,0,0,0)
t.shift(-4, :days)            #=>  Time.utc(2010,10,6,0,0,0)

More than one unit of time can be given.

t.shift(4, :days, 3, :hours)  #=>  Time.utc(2010,10,14,3,0,0)

The #shift method can also take a hash.

t.shift(:days=>4, :hours=>3)  #=>  Time.utc(2010,10,14,3,0,0)


24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
# File 'lib/core/facets/time/shift.rb', line 24

def shift(*time_units)
  time_hash = Hash===time_units.last ? time_units.pop : {}
  time_units = time_units.flatten
  time_units << :seconds if time_units.size % 2 == 1
  time_hash.each{ |units, number| time_units << number; time_units << units }

  time = self
  time_units.each_slice(2) do |number, units|
    #next time = time.ago(-number, units) if number < 0
    time = (
      case units.to_s.downcase.to_sym
      when :years, :year
        time.set( :year=>(year + number) )
      when :months, :month
        if number > 0
          new_month = ((month + number - 1) % 12) + 1
          y = (number / 12) + (new_month < month ? 1 : 0)
          time.set(:year => (year + y), :month => new_month)
        else
          number = -number
          new_month = ((month - number - 1) % 12) + 1
          y = (number / 12) + (new_month > month ? 1 : 0)
          time.set(:year => (year - y), :month => new_month)
        end
      when :weeks, :week
        time + (number * 604800)
      when :days, :day
        time + (number * 86400)
      when :hours, :hour
        time + (number * 3600)
      when :minutes, :minute, :mins, :min
        time + (number * 60)
      when :seconds, :second, :secs, :sec, nil
        time + number
      else
        raise ArgumentError, "unrecognized time units -- #{units}"
      end
    )
  end
  dst_adjustment(time)
end

#stamp(fmt = nil) ⇒ Object

Create a time stamp.

t = Time.at(10000)
t.stamp(:short)    #=> "31 Dec 21:46"

Supported formats come from the Time::FORMAT constant.

CREDIT: Trans



39
40
41
42
43
44
# File 'lib/core/facets/time/stamp.rb', line 39

def stamp(fmt = nil)
  unless String === fmt
    fmt = FORMAT[fmt]
  end
  strftime(fmt).strip
end

#to_dateObject

Converts a Time object to a Date, dropping hour, minute, and second precision.

my_time = Time.now  # Mon Nov 12 22:59:51 -0500 2007
my_time.to_date     # Mon, 12 Nov 2007

your_time = Time.parse("1/13/2009 1:13:03 P.M.")  # Tue Jan 13 13:13:03 -0500 2009
your_time.to_date                                 # Tue, 13 Jan 2009


384
385
386
# File 'lib/standard/facets/date.rb', line 384

def to_date
  ::Date.new(year, month, day)
end

#to_datetimeObject

Converts a Time instance to a Ruby DateTime instance, preserving UTC offset.

my_time = Time.now    # Mon Nov 12 23:04:21 -0500 2007
my_time.to_datetime   # Mon, 12 Nov 2007 23:04:21 -0500

your_time = Time.parse("1/13/2009 1:13:03 P.M.")  # Tue Jan 13 13:13:03 -0500 2009
your_time.to_datetime                             # Tue, 13 Jan 2009 13:13:03 -0500


406
407
408
# File 'lib/standard/facets/date.rb', line 406

def to_datetime
  ::DateTime.civil(year, month, day, hour, min, sec, Rational(utc_offset, 86400))
end

#to_timeObject

To be able to keep Dates and Times interchangeable on conversions.



8
9
10
# File 'lib/core/facets/time/to_time.rb', line 8

def to_time
  getlocal 
end

#trunc(amount) ⇒ Object

Truncate time at give range (in seconds).

t = Time.now
t = t.trunc(60*60)
t.min #=> 0
t.sec #=> 0


10
11
12
# File 'lib/core/facets/time/trunc.rb', line 10

def trunc(amount)
  self - (self.to_i % amount)
end