Difference Between Two datetimes

17 views
Skip to first unread message

W. eWatson

unread,
Dec 27, 2009, 11:54:57 PM12/27/09
to
According to one web source, this program:

import datetime
bree = datetime.datetime(1981, 6, 16, 4, 35, 25)
nat = datetime.datetime(1973, 1, 18, 3, 45, 50)

difference = bree - nat
print "There were", difference, "minutes between Nat and Bree"

yields:
There were 3071 days, 0:49:35 minutes between Nat and Bree

That's fine, but I'd like to start with two dates as strings, as
"1961/06/16 04:35:25" and "1973/01/18 03:45:50"

How do I get the strings into a shape that will accommodate a difference?

For example,
t1=datetime.datetime.strptime("2009/01/02 13:01:15","%y/%m/%d %H:%M:%S")
doesn't do it.
ValueError: time data did not match format: data=2009/01/02 13:01:15
fmt=%y/%m/%d %H:%M:%S

Roy Smith

unread,
Dec 28, 2009, 12:11:07 AM12/28/09
to
In article <hh9dmv$f9s$1...@news.eternal-september.org>,
"W. eWatson" <wolft...@invalid.com> wrote:

> t1=datetime.datetime.strptime("2009/01/02 13:01:15","%y/%m/%d %H:%M:%S")
> doesn't do it.
> ValueError: time data did not match format: data=2009/01/02 13:01:15
> fmt=%y/%m/%d %H:%M:%S

The first thing that jumps out at me is that %y is the two-digit year. You
want %Y for 4-digit year.

One thing to keep in mind is that "2009/01/02 13:01:15" is ambiguous
without a time zone. Even if you assume that both timestamps were from the
same location, you need to know what daylight savings rules that location
uses, to do this right.

Ben Finney

unread,
Dec 28, 2009, 12:21:34 AM12/28/09
to
"W. eWatson" <wolft...@invalid.com> writes:

> How do I get the strings into a shape that will accommodate a difference?
>
> For example,
> t1=datetime.datetime.strptime("2009/01/02 13:01:15","%y/%m/%d %H:%M:%S")
> doesn't do it.
> ValueError: time data did not match format: data=2009/01/02 13:01:15
> fmt=%y/%m/%d %H:%M:%S

As the error message indicates, the data input (the string) doesn't
match the specified format.

See the time format specifications at the ‘time.strftime’ documentation
<URL:http://docs.python.org/library/time.html#time.strftime>. Note
especially that ‘%y’ and ‘%Y’ are distinct.

--
\ “Science doesn't work by vote and it doesn't work by |
`\ authority.” —Richard Dawkins, _Big Mistake_ (The Guardian, |
_o__) 2006-12-27) |
Ben Finney

W. eWatson

unread,
Dec 28, 2009, 1:42:48 AM12/28/09
to
You're right. Y. Works fine. The produces datetime.datetime(2009, 1, 2,
13, 1, 15).
If I now use
t2=datetime.datetime.strptime("2009/01/04 13:01:15","%Y/%m/%d %H:%M:%S")
I get tw as
datetime.datetime(2009, 1, 4, 13, 1, 15)
Then t2-t1 gives,
datetime.timedelta(2)
which is a 2 day difference--I guess. Strange.
Changing
t2=datetime.datetime.strptime("2009/01/04 14:00:30","%Y/%m/%d %H:%M:%S")
and differencing gives me,
datetime.timedelta(2, 3555), which seems to indicate a 2 day and 3555
second difference. Interesting, but I think there must be another way to
do this. Maybe not.

W. eWatson

unread,
Dec 28, 2009, 1:43:47 AM12/28/09
to
Ben Finney wrote:
> "W. eWatson" <wolft...@invalid.com> writes:
>
>> How do I get the strings into a shape that will accommodate a difference?
>>
>> For example,
>> t1=datetime.datetime.strptime("2009/01/02 13:01:15","%y/%m/%d %H:%M:%S")
>> doesn't do it.
>> ValueError: time data did not match format: data=2009/01/02 13:01:15
>> fmt=%y/%m/%d %H:%M:%S
>
> As the error message indicates, the data input (the string) doesn't
> match the specified format.
>
> See the time format specifications at the ‘time.strftime’ documentation
> <URL:http://docs.python.org/library/time.html#time.strftime>. Note
> especially that ‘%y’ and ‘%Y’ are distinct.
>
Yes, see my response to the post above yours.

W. eWatson

unread,
Dec 28, 2009, 1:45:39 AM12/28/09
to
BTW, all times are local to my city. Same time zone.

Lie Ryan

unread,
Dec 28, 2009, 2:14:48 AM12/28/09
to
On 12/28/2009 5:42 PM, W. eWatson wrote:
> You're right. Y. Works fine. The produces datetime.datetime(2009, 1, 2,
> 13, 1, 15).
> If I now use
> t2=datetime.datetime.strptime("2009/01/04 13:01:15","%Y/%m/%d %H:%M:%S")
> I get tw as
> datetime.datetime(2009, 1, 4, 13, 1, 15)
> Then t2-t1 gives,
> datetime.timedelta(2)
> which is a 2 day difference--I guess. Strange.

what's strange about it? the difference between 2009/01/02 13:01:15 and
2009/01/04 13:01:15 is indeed 2 days... Can you elaborate what do you
mean by 'strange'?

> Changing
> t2=datetime.datetime.strptime("2009/01/04 14:00:30","%Y/%m/%d %H:%M:%S")
> and differencing gives me,
> datetime.timedelta(2, 3555), which seems to indicate a 2 day and 3555
> second difference. Interesting, but I think there must be another way to
> do this. Maybe not.

to do... what?

W. eWatson

unread,
Dec 28, 2009, 6:41:28 AM12/28/09
to
Lie Ryan wrote:
> On 12/28/2009 5:42 PM, W. eWatson wrote:
>> You're right. Y. Works fine. The produces datetime.datetime(2009, 1, 2,
>> 13, 1, 15).
>> If I now use
>> t2=datetime.datetime.strptime("2009/01/04 13:01:15","%Y/%m/%d %H:%M:%S")
>> I get tw as
>> datetime.datetime(2009, 1, 4, 13, 1, 15)
>> Then t2-t1 gives,
>> datetime.timedelta(2)
>> which is a 2 day difference--I guess. Strange.
>
> what's strange about it? the difference between 2009/01/02 13:01:15 and
> 2009/01/04 13:01:15 is indeed 2 days... Can you elaborate what do you
> mean by 'strange'?
Easily. In one case, it produces a one argument funcion, and the other
2, possibly even a year if that differs. How does one "unload" this
structure to get the seconds and days?

>
>> Changing
>> t2=datetime.datetime.strptime("2009/01/04 14:00:30","%Y/%m/%d %H:%M:%S")
>> and differencing gives me,
>> datetime.timedelta(2, 3555), which seems to indicate a 2 day and 3555
>> second difference. Interesting, but I think there must be another way to
>> do this. Maybe not.
>
> to do... what?
To find the difference more clearly. Why not just return (0,2,3555)

Ben Finney

unread,
Dec 28, 2009, 7:50:30 AM12/28/09
to
"W. eWatson" <wolft...@invalid.com> writes:

> Lie Ryan wrote:
> > what's strange about it? the difference between 2009/01/02 13:01:15
> > and 2009/01/04 13:01:15 is indeed 2 days... Can you elaborate what
> > do you mean by 'strange'?

> Easily. In one case, it produces a one argument funcion, and the other
> 2, possibly even a year if that differs.

In both cases it produces not a function, but a ‘datetime.timedelta’
object::

>>> import datetime
>>> t1 = datetime.datetime(2009, 1, 2, 13, 1, 15)
>>> t2 = datetime.datetime(2009, 1, 4, 13, 1, 15)
>>> type(t1)
<type 'datetime.datetime'>
>>> type(t2)
<type 'datetime.datetime'>

>>> dt = (t2 - t1)
>>> type(dt)
<type 'datetime.timedelta'>

What you're seeing in the interactive interpreter is a string
representation of the object::

>>> dt
datetime.timedelta(2)

This is no different from what's going on with any other string
representation. The representation is not the value.

> How does one "unload" this structure to get the seconds and days?

It's customary to consult the documentation for questions like that
<URL:http://docs.python.org/library/datetime.html#datetime.timedelta>.

> To find the difference more clearly. Why not just return (0,2,3555)

Because the ‘datetime.timedelta’ type is more flexible than a tuple, and
has named attributes as documented at the above URL::

>>> dt.days
2
>>> dt.seconds
0
>>> dt.microseconds
0

--
\ “If you have the facts on your side, pound the facts. If you |
`\ have the law on your side, pound the law. If you have neither |
_o__) on your side, pound the table.” —anonymous |
Ben Finney

Roy Smith

unread,
Dec 28, 2009, 9:12:25 AM12/28/09
to
In article <hh9k6g$pkq$3...@news.eternal-september.org>,
"W. eWatson" <wolft...@invalid.com> wrote:

> BTW, all times are local to my city. Same time zone.

Yes, but how much time has elapsed between "2009/0/04 13:01:15" and
"2009/06/04 13:01:15"? Even if I tell you that both timestamps were done
in the same city, you don't have enough information.

Hint #1: The answer in Sydney, Bangalore, and New York are all different.

Hint #2: Two of those cities are in temperate zones, and one is in the
tropics.

Hint #3: If you don't pay attention to this, you will be bitten twice a
year.

Roy Smith

unread,
Dec 28, 2009, 9:13:52 AM12/28/09
to
In article <roy-2455BD.0...@news.panix.com>,
Roy Smith <r...@panix.com> wrote:

> Yes, but how much time has elapsed between "2009/0/04 13:01:15"

Typo. Should be "2009/01/04 13:01:15".

Lie Ryan

unread,
Dec 28, 2009, 10:39:42 AM12/28/09
to
On 12/29/2009 1:12 AM, Roy Smith wrote:
> Hint #3: If you don't pay attention to this, you will be bitten twice a
> year.

Not really. Some areas don't have DST and the answer to that is always
exactly 5 months.

W. eWatson

unread,
Dec 28, 2009, 11:20:28 AM12/28/09
to
Sort of the opposite of a stopped clock. It's right twice a day. How
does one solve the DST problem?

D'Arcy J.M. Cain

unread,
Dec 28, 2009, 12:37:49 PM12/28/09
to W. eWatson, pytho...@python.org
On Mon, 28 Dec 2009 08:20:28 -0800
"W. eWatson" <wolft...@invalid.com> wrote:
> Sort of the opposite of a stopped clock. It's right twice a day. How
> does one solve the DST problem?

Depends on which DST problem you have. There is more than one solution
depending on what the problem is. Store and compare in UTC and display
in local time is one solution but it may not be yours.

--
D'Arcy J.M. Cain <da...@druid.net> | Democracy is three wolves
http://www.druid.net/darcy/ | and a sheep voting on
+1 416 425 1212 (DoD#0082) (eNTP) | what's for dinner.

W. eWatson

unread,
Dec 28, 2009, 1:12:45 PM12/28/09
to
D'Arcy J.M. Cain wrote:
> On Mon, 28 Dec 2009 08:20:28 -0800
> "W. eWatson" <wolft...@invalid.com> wrote:
>> Sort of the opposite of a stopped clock. It's right twice a day. How
>> does one solve the DST problem?
>
> Depends on which DST problem you have. There is more than one solution
> depending on what the problem is. Store and compare in UTC and display
> in local time is one solution but it may not be yours.
>
Actually, UTC is quite relevant here. I would guess there is some way to
use datetime for UTC?

W. eWatson

unread,
Dec 28, 2009, 1:54:46 PM12/28/09
to
Well, it just seems weird to me. <g>. I'm modestly familiar with
objects, but this seems like doing the following.

Suppose we have a module called trigonometry, trig for short. It
contains lots of trig functions, and sort of uses the same concepts as
datetime. Bear with me on that. Here's my imagined interpretive session:

>> import trig
>> c=trig.sin(90.0) # arg is in degrees
>> print c
trig.cos(1.0)
>> type(c)
<type 'trig'>
>> value = c.value
>> print value
1.0
I'd call that weird. Maybe in this case it is ... <g>

W. eWatson

unread,
Dec 28, 2009, 4:51:31 PM12/28/09
to
This is quirky.

>>> t1=datetime.datetime.strptime("20091205_221100","%Y%m%d_%H%M%S")
>>> t1
datetime.datetime(2009, 12, 5, 22, 11)
>>> type(t1)
<type 'datetime.datetime'>
>>>
t1: 2009-12-05 22:11:00 <type 'datetime.datetime'>

but in the program:
import datetime

t1=datetime.datetime.strptime("20091205_221100","%Y%m%d_%H%M%S")
print "t1: ",t1, type(t1)

produces
t1: 2009-12-05 22:11:00 <type 'datetime.datetime'>

Where did the hyphens and colons come from?

Peter Otten

unread,
Dec 28, 2009, 5:22:09 PM12/28/09
to
W. eWatson wrote:

print some_object

first converts some_object to a string invoking str(some_object) which in
turn calls the some_object.__str__() method. The resulting string is then
written to stdout. Quoting the documentation:

datetime.__str__()
For a datetime instance d, str(d) is equivalent to d.isoformat(' ').

datetime.isoformat([sep])
Return a string representing the date and time in ISO 8601 format,
YYYY-MM-DDTHH:MM:SS.mmmmmm or, if microsecond is 0, YYYY-MM-DDTHH:MM:SS

Peter

W. eWatson

unread,
Dec 28, 2009, 5:42:21 PM12/28/09
to
So as long as I don't print it, it's datetime.datetime and I can make
calculations or perform operations on it as though it is not a string,
but a datetime object?

Steven D'Aprano

unread,
Dec 28, 2009, 5:45:00 PM12/28/09
to
On Mon, 28 Dec 2009 23:50:30 +1100, Ben Finney wrote:

>> How does one "unload" this structure to get the seconds and days?
>
> It's customary to consult the documentation for questions like that
> <URL:http://docs.python.org/library/datetime.html#datetime.timedelta>.

No no no, it's customary to annoy everyone on the list by asking the
question *without* consulting the documentation, and then to be told to
Read The Fine Manual.

To be serious for a moment, if you're in the interactive interpreter, you
can get some useful information by calling help(datetime.timedelta).

--
Steven

Peter Otten

unread,
Dec 28, 2009, 5:57:31 PM12/28/09
to
W. eWatson wrote:

Not "as though", it *is* a datetime object. And it knows how to show as
something meaningful to the user when printed

These are very basic concepts that apply to all Python objects. I suggest
that you take a moment to go through the tutorial before you continue with
your efforts.

Peter

Steven D'Aprano

unread,
Dec 28, 2009, 6:05:13 PM12/28/09
to
On Mon, 28 Dec 2009 10:54:46 -0800, W. eWatson wrote:

> Ben Finney wrote:
>> "W. eWatson" <wolft...@invalid.com> writes:
>>
>>> Lie Ryan wrote:
>>>> what's strange about it? the difference between 2009/01/02 13:01:15
>>>> and 2009/01/04 13:01:15 is indeed 2 days... Can you elaborate what do
>>>> you mean by 'strange'?
>>
>>> Easily. In one case, it produces a one argument funcion, and the other
>>> 2, possibly even a year if that differs.

[...]


> Well, it just seems weird to me. <g>. I'm modestly familiar with
> objects, but this seems like doing the following.
>
> Suppose we have a module called trigonometry, trig for short. It
> contains lots of trig functions, and sort of uses the same concepts as
> datetime. Bear with me on that. Here's my imagined interpretive session:
>
> >> import trig
> >> c=trig.sin(90.0) # arg is in degrees
> >> print c
> trig.cos(1.0)
> >> type(c)
> <type 'trig'>
> >> value = c.value
> >> print value
> 1.0
> I'd call that weird. Maybe in this case it is ... <g>


No, that's an invalid analogy, because trig functions are defined to
return unitless numbers and so there is no point in distinguishing
between the 1.0 you get from the sine of 90 degrees and the 1.0 you get
from halving 2.0. They are the same thing.

But time is different. Not only do times have a unit, but we also
distinguish between two different concepts: times as points on a
calendar, as well as differences between such times.

A calendar time of 1000 seconds is not the same as a time difference of
1000 seconds: 1000 seconds is 'Thu Jan 1 10:16:40 1970' according to the
POSIX standard, Windows may pick a different moment for zero. But a time
difference doesn't correspond to any specific moment in time at all, and
represents a distance between two points on the calendar -- a duration.

Hence Python provides timedelta objects for working with time
differences, and datetime objects for working with calendar times.

Of course, one might have chosen to take a different approach, and use
(say) raw ints only for working with dates no matter whether they
represent an absolute time or a relative time. Then the programmer would
be responsible for interpreting 1000 as either 10:16:40 Jan 1 1970 or a
duration of 16 minutes 40 seconds, whichever is appropriate. That's a
legitimate design choice too, but not the one Python uses.

--
Steven

Steven D'Aprano

unread,
Dec 28, 2009, 6:27:28 PM12/28/09
to
On Mon, 28 Dec 2009 14:42:21 -0800, W. eWatson wrote:

> So as long as I don't print it, it's datetime.datetime and I can make
> calculations or perform operations on it as though it is not a string,
> but a datetime object?

No, it remains a datetime object regardless of whether you print it or
not. Printing doesn't turn the object into a string, it leaves the object
as-is and produces an additional string suitable for printing.

This is no different from any other object: if you print a dict, or a
int, or a list, the object doesn't turn into a string. When you say
"print x", Python has no idea what information is appropriate to display
for some arbitrary object x. So it asks x what is appropriate, by calling
the __str__ method. That way Python only needs to know how to print one
data type: strings.

--
Steven

Steven D'Aprano

unread,
Dec 28, 2009, 6:36:35 PM12/28/09
to
On Mon, 28 Dec 2009 23:22:09 +0100, Peter Otten wrote:

> print some_object
>
> first converts some_object to a string invoking str(some_object) which
> in turn calls the some_object.__str__() method. The resulting string is
> then written to stdout.

In fairness to the OP, that's a misleading way of describing it. Python
doesn't convert objects in the standard senses of "convert lead into
gold" or "convert to <insert name of religion here>". some_object.__str__
returns an independent string object while leaving some_object alone.

But I'm sure you knew that already -- it's only the OP who was confused.


--
Steven

W. eWatson

unread,
Dec 28, 2009, 8:20:28 PM12/28/09
to
Yes, thanks. I'm starting to catch on to the idea there are tools like
dir, help, doc sources, and ___dcc__ that can help. It doesn't seem to
be standard practice to more or less teach the environment that Python
is in. If they do, it's jumbled around. Most books start with Python
itself and skirt the issues of the environment and interaction. Oddly,
today I found a source that gets right into these concepts. It may have
something to do with MIT. Here's a link to one of the three section of
the reference
<http://docs.google.com/leaf?id=0B2oiI2reHOh4ZTFkY2ZmYzktZTVkZS00M2E1LTgwNDUtYWRjZTE1Nzc2ZDYz&sort=name&layout=list&pid=0B2oiI2reHOh4ZGVmNjk3MjgtZmY5YS00ZWQxLThkNWMtZmJkMmU1MWM1OTcx&cindex=2>.


BTW, I had looked at some Python doc that seems to be apart from the
reference above. So I'm not entirely remiss on this. I do look first.
However, on the other hand, regarding the reference, 29 pages is a bit
steep for any document.

Ben Finney

unread,
Dec 28, 2009, 8:28:47 PM12/28/09
to
"W. eWatson" <wolft...@invalid.com> writes:

> It doesn't seem to be standard practice to more or less teach the
> environment that Python is in. If they do, it's jumbled around. Most
> books start with Python itself and skirt the issues of the environment
> and interaction.

There are no Python documentation police enforcing standards on
documentation, so I don't know why you'd expect any consistency between
non-official documents.

The official documentation, though, contains an excellent tutorial
<URL:http://docs.python.org/tutorial/>.

As has been suggested to you several times already: Please work through
the entire tutorial, executing every exercise and experimenting until
you understand it, then progressing to the next one. Once you've done
that, you will have a much better grasp of Python and can save a lot of
time in discussions like this.

--
\ “I'm having amnesia and déjà vu at the same time. I feel like |
`\ I've forgotten this before sometime.” —Steven Wright |
_o__) |
Ben Finney

Steve Holden

unread,
Dec 29, 2009, 8:46:19 AM12/29/09
to pytho...@python.org

It's nothing to do with whether you print it or not. When you print it,
an equivalent string is produced, and the string is what gets printed.
This is necessary, because humans only understand character-based output.

>>> type(x)
<type 'float'>
>>> print x
82.2
>>> type(x)
<type 'float'>

The type of something is unchanged by printing it. The print statement
merely calls methods of the object to produce strings that it can print.

>>> x.__str__()
'82.2'
>>> x.__repr__()
'82.200000000000003'
>>>

People talk loosely about "converting an object to a string", but that
doesn't mean transmogrifying the object to something else, it means
producing an equivalent value of some other type which can be used
instead of the original object for some specific purpose. In this case,
printing.

regards
Steve
--
Steve Holden +1 571 484 6266 +1 800 494 3119
PyCon is coming! Atlanta, Feb 2010 http://us.pycon.org/
Holden Web LLC http://www.holdenweb.com/
UPCOMING EVENTS: http://holdenweb.eventbrite.com/

M.-A. Lemburg

unread,
Dec 29, 2009, 10:21:22 AM12/29/09
to W. eWatson, pytho...@python.org
W. eWatson wrote:
> According to one web source, this program:
>
> import datetime
> bree = datetime.datetime(1981, 6, 16, 4, 35, 25)
> nat = datetime.datetime(1973, 1, 18, 3, 45, 50)
>
> difference = bree - nat
> print "There were", difference, "minutes between Nat and Bree"
>
> yields:
> There were 3071 days, 0:49:35 minutes between Nat and Bree
>
> That's fine, but I'd like to start with two dates as strings, as
> "1961/06/16 04:35:25" and "1973/01/18 03:45:50"

>
> How do I get the strings into a shape that will accommodate a difference?
>
> For example,
> t1=datetime.datetime.strptime("2009/01/02 13:01:15","%y/%m/%d %H:%M:%S")
> doesn't do it.
> ValueError: time data did not match format: data=2009/01/02 13:01:15
> fmt=%y/%m/%d %H:%M:%S

Here's how you'd do this with mxDateTime:

http://www.egenix.com/products/python/mxBase/mxDateTime/

>>> from mx.DateTime import *
>>> bree = DateTimeFrom("1981/06/16 04:35:25")
>>> nat = DateTimeFrom("1973/01/18 03:45:50")
>>> bree
<mx.DateTime.DateTime object for '1981-06-16 04:35:25.00' at 2b99c7881088>
>>> nat
<mx.DateTime.DateTime object for '1973-01-18 03:45:50.00' at 2b99c6e342f0>

Now, let's look at the date/time difference:

>>> bree - nat
<mx.DateTime.DateTimeDelta object for '3071:00:49:35.00' at 2b99c6e36500>

i.e. 3071 days, 49 minutes, 35 seconds.

If you want a more human readable, relative format use Age():

>>> Age(bree, nat)
<RelativeDateTime instance for '(+0008)-(+04)-(+29) HH:(+49):(+35)' at 0x2b99c6e37ef0>

i.e. 8 years, 4 months, 29 days, 49 minutes, 35 seconds.

--
Marc-Andre Lemburg
eGenix.com

Professional Python Services directly from the Source (#1, Dec 29 2009)
>>> Python/Zope Consulting and Support ... http://www.egenix.com/
>>> mxODBC.Zope.Database.Adapter ... http://zope.egenix.com/
>>> mxODBC, mxDateTime, mxTextTools ... http://python.egenix.com/
________________________________________________________________________

::: Try our new mxODBC.Connect Python Database Interface for free ! ::::


eGenix.com Software, Skills and Services GmbH Pastor-Loeh-Str.48
D-40764 Langenfeld, Germany. CEO Dipl.-Math. Marc-Andre Lemburg
Registered at Amtsgericht Duesseldorf: HRB 46611
http://www.egenix.com/company/contact/

Steve Ferg

unread,
Jan 14, 2010, 1:08:38 PM1/14/10
to

> I'd like to start with two dates as strings, as
> "1961/06/16 04:35:25" and "1973/01/18 03:45:50"
> How do I get the strings into a shape that will accommodate a difference?

Pyfdate http://www.ferg.org/pyfdate/index.html
has a numsplit function that should do the trick:
http://www.ferg.org/pyfdate/tutorial.html#contents_item_14

It splits a string into its numeric parts and return a list containing
the numeric parts converted to ints.

>>> from pyfdate import *
>>> numsplit("2007_10_09")
[2007, 10, 9]
>>> numsplit("2007-10-09T23:45:59")
[2007, 10, 9, 23, 45, 59]
>>> numsplit("2007/10/09 23.45.59")
[2007, 10, 9, 23, 45, 59]


Reply all
Reply to author
Forward
0 new messages