# How to get internal state of DateTime in seconds

**URL:** <https://rubytalk.org/t/how-to-get-internal-state-of-datetime-in-seconds/10835>\
**Category:** ruby-talk\
**Created:** [31 March 2004 16:44 UTC](https://rubytalk.org/t/how-to-get-internal-state-of-datetime-in-seconds/10835 "2004-03-31T16:44:21Z")\
**Posts on this page:** 9\
**Page:** 1

<div class="post-metadata">

**Author:** ![Smejmoon](https://avatars.discourse-cdn.com/v4/letter/s/cc9497/32.png) [@Smejmoon](https://rubytalk.org/u/Smejmoon)\
**Post date:** [31 March 2004 16:44 UTC](https://rubytalk.org/t/how-to-get-internal-state-of-datetime-in-seconds/10835/1 "2004-03-31T16:44:21Z")

</div>

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

---

<div class="post-metadata">

**Author:** ![Stefan\_Lidman](https://avatars.discourse-cdn.com/v4/letter/s/b3f665/32.png) [@Stefan\_Lidman](https://rubytalk.org/u/Stefan_Lidman)\
**Post date:** [31 March 2004 17:34 UTC](https://rubytalk.org/t/how-to-get-internal-state-of-datetime-in-seconds/10835/2 "2004-03-31T17:34:22Z")

</div>

> 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

---

<div class="post-metadata">

**Author:** ![Sam\_Roberts1](https://avatars.discourse-cdn.com/v4/letter/s/ed8c4c/32.png) [@Sam\_Roberts1](https://rubytalk.org/u/Sam_Roberts1)\
**Post date:** [31 March 2004 18:08 UTC](https://rubytalk.org/t/how-to-get-internal-state-of-datetime-in-seconds/10835/3 "2004-03-31T18:08:00Z")

</div>

Quoteing [smejmoon@yahoo.com](mailto: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

---

<div class="post-metadata">

**Author:** ![Smejmoon](https://avatars.discourse-cdn.com/v4/letter/s/cc9497/32.png) [@Smejmoon](https://rubytalk.org/u/Smejmoon)\
**Post date:** [1 April 2004 13:39 UTC](https://rubytalk.org/t/how-to-get-internal-state-of-datetime-in-seconds/10835/4 "2004-04-01T13:39:22Z")

</div>

> > 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

---

<div class="post-metadata">

**Author:** ![Ara.T.Howard](https://avatars.discourse-cdn.com/v4/letter/a/a8b319/32.png) [@Ara.T.Howard](https://rubytalk.org/u/Ara.T.Howard)\
**Post date:** [1 April 2004 15:14 UTC](https://rubytalk.org/t/how-to-get-internal-state-of-datetime-in-seconds/10835/5 "2004-04-01T15:14:33Z")

</div>

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](http://www.ngdc.noaa.gov/stp/)  
> > TRY :: for l in ruby perl;do $l -e “print "\x3a\x2d\x29\x0a"”;done  
> > ===============================================================================

---

<div class="post-metadata">

**Author:** ![Charles\_Comstock](https://avatars.discourse-cdn.com/v4/letter/c/91b2a8/32.png) [@Charles\_Comstock](https://rubytalk.org/u/Charles_Comstock)\
**Post date:** [1 April 2004 16:49 UTC](https://rubytalk.org/t/how-to-get-internal-state-of-datetime-in-seconds/10835/6 "2004-04-01T16:49:27Z")

</div>

> 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

---

<div class="post-metadata">

**Author:** ![HAL\_9000](https://avatars.discourse-cdn.com/v4/letter/h/90ced4/32.png) [@HAL\_9000](https://rubytalk.org/u/HAL_9000)\
**Post date:** [1 April 2004 17:24 UTC](https://rubytalk.org/t/how-to-get-internal-state-of-datetime-in-seconds/10835/7 "2004-04-01T17:24:24Z")

</div>

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

---

<div class="post-metadata">

**Author:** ![Ara.T.Howard](https://avatars.discourse-cdn.com/v4/letter/a/a8b319/32.png) [@Ara.T.Howard](https://rubytalk.org/u/Ara.T.Howard)\
**Post date:** [1 April 2004 18:14 UTC](https://rubytalk.org/t/how-to-get-internal-state-of-datetime-in-seconds/10835/8 "2004-04-01T18:14:27Z")

</div>

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](http://www.ngdc.noaa.gov/stp/)  
> > TRY :: for l in ruby perl;do $l -e “print "\x3a\x2d\x29\x0a"”;done  
> > ===============================================================================

---

<div class="post-metadata">

**Author:** ![Charles\_Comstock](https://avatars.discourse-cdn.com/v4/letter/c/91b2a8/32.png) [@Charles\_Comstock](https://rubytalk.org/u/Charles_Comstock)\
**Post date:** [1 April 2004 18:59 UTC](https://rubytalk.org/t/how-to-get-internal-state-of-datetime-in-seconds/10835/9 "2004-04-01T18:59:23Z")

</div>

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:
