#
#--
# Copyright (c) 2005-2008, John Mettraux, jmettraux@gmail.com
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
# THE SOFTWARE.
#++
#
#
# "hecho en Costa Rica"
#
# john.mettraux@openwfe.org
#
require 'date'
#require 'parsedate'
module Rufus
#TIME_FORMAT = "%Y-%m-%d %H:%M:%S"
#
# Returns the current time as an ISO date string
#
def Rufus.now
to_iso8601_date(Time.new())
end
#
# As the name implies.
#
def Rufus.to_iso8601_date (date)
if date.kind_of? Float
date = to_datetime(Time.at(date))
elsif date.kind_of? Time
date = to_datetime(date)
elsif not date.kind_of? Date
date = DateTime.parse(date)
end
s = date.to_s # this is costly
s[10] = " "
s
end
#
# the old method we used to generate our ISO datetime strings
#
def Rufus.time_to_iso8601_date (time)
s = time.getutc().strftime(TIME_FORMAT)
o = time.utc_offset / 3600
o = o.to_s + "00"
o = "0" + o if o.length < 4
o = "+" + o unless o[0..1] == '-'
s + " " + o.to_s
end
#
# Returns a Ruby time
#
def Rufus.to_ruby_time (iso_date)
DateTime.parse(iso_date)
end
#def Rufus.parse_date (date)
#end
#
# equivalent to java.lang.System.currentTimeMillis()
#
def Rufus.current_time_millis
(Time.new.to_f * 1000).to_i
end
#
# Turns a string like '1m10s' into a float like '70.0', more formally,
# turns a time duration expressed as a string into a Float instance
# (millisecond count).
#
# w -> week
# d -> day
# h -> hour
# m -> minute
# s -> second
# M -> month
# y -> year
# 'nada' -> millisecond
#
# Some examples :
#
# Rufus.parse_time_string "500" # => 0.5
# Rufus.parse_time_string "1000" # => 1.0
# Rufus.parse_time_string "1h" # => 3600.0
# Rufus.parse_time_string "1h10s" # => 3610.0
# Rufus.parse_time_string "1w2d" # => 777600.0
#
def Rufus.parse_time_string (string)
string = string.strip
index = -1
result = 0.0
number = ""
loop do
index = index + 1
if index >= string.length
if number.length > 0
result = result + (Float(number) / 1000.0)
end
break
end
c = string[index, 1]
# TODO : investigate something better than this is_digit?
if is_digit?(c)
number = number + c
next
end
value = Integer(number)
number = ""
multiplier = DURATIONS[c]
raise "unknown time char '#{c}'" \
if not multiplier
result = result + (value * multiplier)
end
result
end
#
# returns true if the character c is a digit
#
def Rufus.is_digit? (c)
return false if not c.kind_of?(String)
return false if c.length > 1
(c >= "0" and c <= "9")
end
#
# conversion methods between Date[Time] and Time
#
# Ruby Cookbook 1st edition p.111
# http://www.oreilly.com/catalog/rubyckbk/
# a must
#
#
# converts a Time instance to a DateTime one
#
def Rufus.to_datetime (time)
s = time.sec + Rational(time.usec, 10**6)
o = Rational(time.utc_offset, 3600 * 24)
begin
DateTime.new(
time.year,
time.month,
time.day,
time.hour,
time.min,
s,
o)
rescue Exception => e
#puts
#puts OpenWFE::exception_to_s(e)
#puts
#puts \
# "\n Date.new() problem. Params :"+
# "\n....y:#{time.year} M:#{time.month} d:#{time.day} "+
# "h:#{time.hour} m:#{time.min} s:#{s} o:#{o}"
DateTime.new(
time.year,
time.month,
time.day,
time.hour,
time.min,
time.sec,
time.utc_offset)
end
end
def Rufus.to_gm_time (dtime)
to_ttime(dtime.new_offset, :gm)
end
def Rufus.to_local_time (dtime)
to_ttime(dtime.new_offset(DateTime.now.offset-offset), :local)
end
def Rufus.to_ttime (d, method)
usec = (d.sec_fraction * 3600 * 24 * (10**6)).to_i
Time.send(method, d.year, d.month, d.day, d.hour, d.min, d.sec, usec)
end
#
# Turns a number of seconds into a a time string
#
# Rufus.to_time_string 0 # => '0s'
# Rufus.to_time_string 60 # => '1m'
# Rufus.to_time_string 3661 # => '1h1m1s'
# Rufus.to_time_string 7 * 24 * 3600 # => '1w'
# Rufus.to_time_string 30 * 24 * 3600 + 1 # => "4w2d1s"
#
# It goes from seconds to the year. Months are not counted (as they
# are of variable length). Weeks are counted.
#
# For 30 days months to be counted, the second parameter of this
# method can be set to true.
#
# Rufus.to_time_string 30 * 24 * 3600 + 1, true # => "1M1s"
#
# If a Float value is passed, milliseconds will be displayed without
# 'marker'
#
# Rufus.to_time_string 0.051 #=>"51"
# Rufus.to_time_string 7.051 #=>"7s51"
# Rufus.to_time_string 0.120 + 30 * 24 * 3600 + 1 #=>"4w2d1s120"
#
# (this behaviour mirrors the one found for parse_time_string()).
#
def Rufus.to_time_string (seconds, months=false)
return '0s' if seconds <= 0
ms = nil
if seconds.is_a?(Float)
ms = (seconds % 1 * 1000).to_i
seconds = seconds.to_i
end
durations = months ? DURATIONS2w : DURATIONS2
s = durations.inject([ seconds, "" ]) { |r, d|
#puts "result : " + r.inspect
#puts "duration : " + d.inspect
sec, str = r
s, d = d
count = sec / d
rest = sec % d
str << "#{count}#{s}" if count > 0
[ rest, str ]
}[1]
"#{s}#{ms}"
end
protected
DURATIONS = {
"y" => 365 * 24 * 3600,
"M" => 30 * 24 * 3600,
"w" => 7 * 24 * 3600,
"d" => 24 * 3600,
"h" => 3600,
"m" => 60,
"s" => 1
}
DURATIONS2w = [
[ "y", DURATIONS["y"] ],
[ "M", DURATIONS["M"] ],
[ "w", DURATIONS["w"] ],
[ "d", DURATIONS["d"] ],
[ "h", DURATIONS["h"] ],
[ "m", DURATIONS["m"] ],
[ "s", DURATIONS["s"] ]
]
DURATIONS2 = DURATIONS2w.dup
DURATIONS2.delete_at 1
end