How to get internal state of DateTime in seconds

How do you get internal state in seconds of DateTime instance?
Or convert it to Time instance?

I want to compare two times with variable precision.
Below is my try to parse time from Common Log Format.

require ‘date’
str1 = ‘20/Nov/2003:08:08:09 +0200’
str2 = ‘20/Nov/2003:08:04:09 +0200’
t1 = DateTime.strptime(str=str1, fmt=’%d/%b/%Y:%H:%M:%S %Z’)
t2 = DateTime.strptime(str=str2, fmt=’%d/%b/%Y:%H:%M:%S %Z’)

#what is difference in minutes between these 2 times?

#example with Time instances
t1 = Time.new
t2 = Time.new + 2*60 #2 minutes later

puts (t1-t2).abs > 60 #diff more than minute

How do you get internal state in seconds of DateTime instance?
Or convert it to Time instance?

I want to compare two times with variable precision.
Below is my try to parse time from Common Log Format.

require ‘date’
str1 = ‘20/Nov/2003:08:08:09 +0200’
str2 = ‘20/Nov/2003:08:04:09 +0200’
t1 = DateTime.strptime(str=str1, fmt=‘%d/%b/%Y:%H:%M:%S %Z’)
t2 = DateTime.strptime(str=str2, fmt=‘%d/%b/%Y:%H:%M:%S %Z’)

#what is difference in minutes between these 2 times?

#example with Time instances
t1 = Time.new
t2 = Time.new + 2*60 #2 minutes later

puts (t1-t2).abs > 60 #diff more than minute

Use to_i if you want it as an integer number of seconds

$ ruby -we ‘puts Time.now.to_i’
=> 1080754316

/Stefan

Quoteing smejmoon@yahoo.com, on Thu, Apr 01, 2004 at 01:44:21AM +0900:

How do you get internal state in seconds of DateTime instance?
Or convert it to Time instance?

There is no method to do this, I proposed it in my email:

‘possible Time & DateTime RCR: reconciling and extending their apis’

please reply to it if you’d like to see such a method added in the future!

I want to compare two times with variable precision.
Below is my try to parse time from Common Log Format.

require ‘date’
str1 = ‘20/Nov/2003:08:08:09 +0200’
str2 = ‘20/Nov/2003:08:04:09 +0200’
t1 = DateTime.strptime(str=str1, fmt=‘%d/%b/%Y:%H:%M:%S %Z’)
t2 = DateTime.strptime(str=str2, fmt=‘%d/%b/%Y:%H:%M:%S %Z’)

#what is difference in minutes between these 2 times?

It’s not clear from the docs, but you can do this:

[ensemble] ~/p/ruby/vcard $ irb18 -r date
irb(main):001:0> t0 = DateTime.now
irb(main):002:0> t0.to_s
=> “2004-03-31T12:57:41-0500”
irb(main):003:0> t1 = DateTime.now
irb(main):004:0> t1.to_s
=> “2004-03-31T12:57:50-0500”
irb(main):005:0> r = t1-t0
=> Rational(192691, 1920000000)
irb(main):007:0> r.to_f * 24 * 60 * 60
=> 8.671095

The difference between two DateTime objects is a Rational, a fraction of days.
Multiply that by the number of seconds/day, and you get the number of seconds
difference.

You could implement Date#to_time() by taking the difference between self, and
Date.civil(1970,1,1), which should give you difference in days, then multiply
by seconds per day, then use Time.at().

Cheers,
Sam

How do you get internal state in seconds of DateTime instance?
Or convert it to Time instance?

I want to compare two times with variable precision.
Below is my try to parse time from Common Log Format.

require ‘date’
str1 = ‘20/Nov/2003:08:08:09 +0200’
str2 = ‘20/Nov/2003:08:04:09 +0200’
fmt=‘%d/%b/%Y:%H:%M:%S %Z’
t1 = DateTime.strptime(str1, fmt)
t2 = DateTime.strptime(str2, fmt)

#what is difference in minutes between these 2 times?

Use to_i if you want it as an integer number of seconds

$ ruby -we ‘puts Time.now.to_i’
=> 1080754316

There is no DateTime#to_i
Right now I do like below and it looks ugly to me.

def dateToTime(str)
d = DateTime.strptime(str, fmt=‘%d/%b/%Y:%H:%M:%S %Z’)
t = Time.local(d.year, d.month, d.day, d.hour, d.min, d.sec)
t
end

iff

  • your times are a common format
  • your times are within the ranges allowable by Time

both of which appear to be true why not simply parse the time yourself? this
is plenty clean, especially if it’s in instance method of a LogEntry class or
something:

file: logtm.rb

def logtm s
#{{{
pat =
%r|^\s*(\d\d)/(\w\w\w)/(\d\d\d\d):(\d\d):(\d\d):(\d\d)\s++(\d\d)(\d\d)\s*$|io

s = s.to_s
m = pat.match s
raise ArgumentError, “<#{ s.inspect }>” unless m

parts = m.to_a
raise ArgumentError, “<#{ s.inspect }>” unless parts.size == 9

parts.shift
day, month, year, hour, min, sec, zhour, zmin = parts

months = %w(jan feb mar apr may jun jul aug sep oct nov dec)
i = months.index month.downcase
raise ArgumentError, “<#{ s.inspect }>” unless i
month = i + 1

day, month, year, hour, min, sec, zhour, zmin =
[day, month, year, hour, min, sec, zhour, zmin].map{|x| x.to_i}

utc = Time.utc year, month, day, hour, min, sec, usec = 0

t = utc + ((zhour * 60 * 60) + (zmin * 60))
#}}}
end

str1 = ‘20/Nov/2003:08:08:09 +0200’
str2 = ‘20/Nov/2003:08:04:09 +0200’
t1 = logtm str1
t2 = logtm str2

#what is difference in minutes between these 2 times?
p((t1 - t2).abs / 60.0) # => 4.0

-a

···

On 1 Apr 2004, G’irts Kalnins wrote:

How do you get internal state in seconds of DateTime instance?
Or convert it to Time instance?

I want to compare two times with variable precision.
Below is my try to parse time from Common Log Format.

require ‘date’
str1 = ‘20/Nov/2003:08:08:09 +0200’
str2 = ‘20/Nov/2003:08:04:09 +0200’
fmt=‘%d/%b/%Y:%H:%M:%S %Z’
t1 = DateTime.strptime(str1, fmt)
t2 = DateTime.strptime(str2, fmt)

#what is difference in minutes between these 2 times?

Use to_i if you want it as an integer number of seconds

$ ruby -we ‘puts Time.now.to_i’
=> 1080754316

There is no DateTime#to_i
Right now I do like below and it looks ugly to me.

def dateToTime(str)
d = DateTime.strptime(str, fmt=‘%d/%b/%Y:%H:%M:%S %Z’)
t = Time.local(d.year, d.month, d.day, d.hour, d.min, d.sec)
t
end

EMAIL :: Ara [dot] T [dot] Howard [at] noaa [dot] gov
PHONE :: 303.497.6469
ADDRESS :: E/GC2 325 Broadway, Boulder, CO 80305-3328
URL :: Solar-Terrestrial Physics Data | NCEI
TRY :: for l in ruby perl;do $l -e “print "\x3a\x2d\x29\x0a"”;done
===============================================================================

iff

  • your times are a common format
  • your times are within the ranges allowable by Time

both of which appear to be true why not simply parse the time yourself? this
is plenty clean, especially if it’s in instance method of a LogEntry class or
something:

file: logtm.rb

def logtm s
#{{{
pat =
%r|^\s*(\d\d)/(\w\w\w)/(\d\d\d\d):(\d\d):(\d\d):(\d\d)\s++(\d\d)(\d\d)\s*$|io

s = s.to_s
m = pat.match s
raise ArgumentError, “<#{ s.inspect }>” unless m

parts = m.to_a
raise ArgumentError, “<#{ s.inspect }>” unless parts.size == 9

parts.shift
day, month, year, hour, min, sec, zhour, zmin = parts

months = %w(jan feb mar apr may jun jul aug sep oct nov dec)
i = months.index month.downcase
raise ArgumentError, “<#{ s.inspect }>” unless i
month = i + 1

day, month, year, hour, min, sec, zhour, zmin =
[day, month, year, hour, min, sec, zhour, zmin].map{|x| x.to_i}

utc = Time.utc year, month, day, hour, min, sec, usec = 0

t = utc + ((zhour * 60 * 60) + (zmin * 60))
#}}}
end

str1 = ‘20/Nov/2003:08:08:09 +0200’
str2 = ‘20/Nov/2003:08:04:09 +0200’
t1 = logtm str1
t2 = logtm str2

#what is difference in minutes between these 2 times?
p((t1 - t2).abs / 60.0) # => 4.0

-a

Umm I don’t understand how this relates, I can construct Time objects
from strings just fine (parsedate), I want a library to take the time
difference in seconds from two Time or Date objects, and format output
of that into something meaningful, ie %H:%M:%S would result in
“00:04:00” for your example difference. But it should scale all the way
up to differences in Months/Years. It seems like a perfectly useful
library, and I was suprised it hadn’t been written. Yes it’s just
division up to months, and then months cares what the actual start/end
times were, but still it seems like a useful object. Seconds is all
fine and good when your just recording short ranges, but for longer…

Charles Comstock

Charles Comstock wrote:

Umm I don’t understand how this relates, I can construct Time objects
from strings just fine (parsedate), I want a library to take the time
difference in seconds from two Time or Date objects, and format output
of that into something meaningful, ie %H:%M:%S would result in
“00:04:00” for your example difference. But it should scale all the way
up to differences in Months/Years. It seems like a perfectly useful
library, and I was suprised it hadn’t been written. Yes it’s just
division up to months, and then months cares what the actual start/end
times were, but still it seems like a useful object. Seconds is all
fine and good when your just recording short ranges, but for longer…

Personally up to “days” would be good enough for me. I once wrote a
simple method sec2dhms that took seconds and returned [days,hours,
minutes,seconds].

“Month” and even “year” are problematic because they don’t have a single
fixed length.

Hal

i think i would be suprisingly difficult to do this for anything other than
seconds when you consider leap years/seconds and diffs which span multiple
leap years.

consider

span = TimeSpan.new t0, t1

span.years # => 3

t0 + (span.years * YEAR_SEC) # but what if one of those years was a leap year!

ok so you could

span = TimeSpan.new t0, t1

t2 = span.add_years t0

but this will really just use seconds under the hood right?

the hard part is - how t you represent an ‘absolute’ time span in anything
other than one unit (seconds is only one) AND give a methods for breaking this
unit up into chunks (days, years) such that the chunks retain their leapness?
i suppose you could

class TimeSpan
class Year
end
class Day
end
end

and extend Time/Data to use those… but surely this is far more error prone
than using utc and seconds?

-a

···

On Thu, 1 Apr 2004, Charles Comstock wrote:

iff

  • your times are a common format
  • your times are within the ranges allowable by Time

both of which appear to be true why not simply parse the time yourself? this
is plenty clean, especially if it’s in instance method of a LogEntry class or
something:

file: logtm.rb

def logtm s
#{{{
pat =
%r|^\s*(\d\d)/(\w\w\w)/(\d\d\d\d):(\d\d):(\d\d):(\d\d)\s++(\d\d)(\d\d)\s*$|io

s = s.to_s
m = pat.match s
raise ArgumentError, “<#{ s.inspect }>” unless m

parts = m.to_a
raise ArgumentError, “<#{ s.inspect }>” unless parts.size == 9

parts.shift
day, month, year, hour, min, sec, zhour, zmin = parts

months = %w(jan feb mar apr may jun jul aug sep oct nov dec)
i = months.index month.downcase
raise ArgumentError, “<#{ s.inspect }>” unless i
month = i + 1

day, month, year, hour, min, sec, zhour, zmin =
[day, month, year, hour, min, sec, zhour, zmin].map{|x| x.to_i}

utc = Time.utc year, month, day, hour, min, sec, usec = 0

t = utc + ((zhour * 60 * 60) + (zmin * 60))
#}}}
end

str1 = ‘20/Nov/2003:08:08:09 +0200’
str2 = ‘20/Nov/2003:08:04:09 +0200’
t1 = logtm str1
t2 = logtm str2

#what is difference in minutes between these 2 times?
p((t1 - t2).abs / 60.0) # => 4.0

-a

Umm I don’t understand how this relates, I can construct Time objects from
strings just fine (parsedate), I want a library to take the time difference
in seconds from two Time or Date objects, and format output of that into
something meaningful, ie %H:%M:%S would result in “00:04:00” for your
example difference. But it should scale all the way up to differences in
Months/Years. It seems like a perfectly useful library, and I was suprised
it hadn’t been written. Yes it’s just division up to months, and then
months cares what the actual start/end times were, but still it seems like a
useful object. Seconds is all fine and good when your just recording short
ranges, but for longer…

EMAIL :: Ara [dot] T [dot] Howard [at] noaa [dot] gov
PHONE :: 303.497.6469
ADDRESS :: E/GC2 325 Broadway, Boulder, CO 80305-3328
URL :: Solar-Terrestrial Physics Data | NCEI
TRY :: for l in ruby perl;do $l -e “print "\x3a\x2d\x29\x0a"”;done
===============================================================================

Ara.T.Howard wrote:

iff

  • your times are a common format
  • your times are within the ranges allowable by Time

both of which appear to be true why not simply parse the time yourself? this
is plenty clean, especially if it’s in instance method of a LogEntry class or
something:

file: logtm.rb

def logtm s
#{{{
pat =
%r|^\s*(\d\d)/(\w\w\w)/(\d\d\d\d):(\d\d):(\d\d):(\d\d)\s++(\d\d)(\d\d)\s*$|io

s = s.to_s
m = pat.match s
raise ArgumentError, “<#{ s.inspect }>” unless m

parts = m.to_a
raise ArgumentError, “<#{ s.inspect }>” unless parts.size == 9

parts.shift
day, month, year, hour, min, sec, zhour, zmin = parts

months = %w(jan feb mar apr may jun jul aug sep oct nov dec)
i = months.index month.downcase
raise ArgumentError, “<#{ s.inspect }>” unless i
month = i + 1

day, month, year, hour, min, sec, zhour, zmin =
[day, month, year, hour, min, sec, zhour, zmin].map{|x| x.to_i}

utc = Time.utc year, month, day, hour, min, sec, usec = 0

t = utc + ((zhour * 60 * 60) + (zmin * 60))
#}}}
end

str1 = ‘20/Nov/2003:08:08:09 +0200’
str2 = ‘20/Nov/2003:08:04:09 +0200’
t1 = logtm str1
t2 = logtm str2

#what is difference in minutes between these 2 times?
p((t1 - t2).abs / 60.0) # => 4.0

-a

Umm I don’t understand how this relates, I can construct Time objects from
strings just fine (parsedate), I want a library to take the time difference
in seconds from two Time or Date objects, and format output of that into
something meaningful, ie %H:%M:%S would result in “00:04:00” for your
example difference. But it should scale all the way up to differences in
Months/Years. It seems like a perfectly useful library, and I was suprised
it hadn’t been written. Yes it’s just division up to months, and then
months cares what the actual start/end times were, but still it seems like a
useful object. Seconds is all fine and good when your just recording short
ranges, but for longer…

i think i would be suprisingly difficult to do this for anything other than
seconds when you consider leap years/seconds and diffs which span multiple
leap years.

consider

span = TimeSpan.new t0, t1

span.years # => 3

t0 + (span.years * YEAR_SEC) # but what if one of those years was a leap year!

ok so you could

span = TimeSpan.new t0, t1

t2 = span.add_years t0

but this will really just use seconds under the hood right?

the hard part is - how t you represent an ‘absolute’ time span in anything
other than one unit (seconds is only one) AND give a methods for breaking this
unit up into chunks (days, years) such that the chunks retain their leapness?
i suppose you could

class TimeSpan
class Year
end
class Day
end
end

and extend Time/Data to use those… but surely this is far more error prone
than using utc and seconds?

-a

Utc doesn’t start out at a completely zeroed out date, so you
automatically get a starting value, therfore you can’t format nicely
just using utc, strftime and the difference in seconds. I mean it is
possible that something similar could be used but I’m not sure the best
approach there. At the very least it would seem like a nice TimeSpan
object that at least allowed manipulation of
weeks/days/hours/minutes/seconds/milliseconds as well as some sort of
string format method would be a nice thing to have in the standard library.

Charles Comstock

···

On Thu, 1 Apr 2004, Charles Comstock wrote: