Q: finding distance between 2 time's

M

martin

I made this little script (below) to look througt a dir to see if
there are any files newer than .e.g. 1 hour.
I have the loop through the dir working and can retreive file time as
well as present time.
both time variables are in the format returned by time.localtime()

My question:
How do I find the difference between such two time variables, to
calculate the 'age' of the file?

:) Martin

------8<------ Code begin -------------

import os, time

def buildList(directory):
listing = os.listdir(directory)
for x in listing:
x = os.path.join(directory, x)
if os.path.isdir(x):
print ('dir -> %s') % x
if os.path.isfile(x):
tstF = time.localtime(os.path.getmtime(x))
nSize = os.path.getsize(x)
print ('fil -> %s %d @ %s') % (x, nSize, time.asctime
(tstF))
return 0

tstN = time.localtime()
print tstN
print "Time now: %s" % time.asctime(tstN)
buildList('C:\Martin\Work\Work_Eclipse\.metadata')
 
J

jkv

Hi Martin,

What i usally do is to convert the two times to seconds since epoch and
compare the two values in seconds. You can use time.mktime to convert
localtime to seconds since epoch.

I added a few lines to your script, and now it ought to only print files
newer than 3601 seconds (3600 seconds is one hour).
The modification to you script is just some quick code, im pretty sure
on can compress it a bit.

Regards,
Johnny

script:

import os, time

def buildList(directory):
listing = os.listdir(directory)
for x in listing:
x = os.path.join(directory, x)
if os.path.isdir(x):
print ('dir -> %s') % x
if os.path.isfile(x):
current_time = time.localtime()
tstF = time.localtime(os.path.getmtime(x))
#convert the current time to seconds since epoch
current_epoch=time.mktime(current_time)
#convert the timestamp on the file to seconds since epoch
file_epoch = time.mktime(tstF)
nSize = os.path.getsize(x)
time_difference = current_epoch - file_epoch
#if file newer than one hour print a line
if time_difference < 3601:
print ('NEW FILE -> %s %d @ %s') % (x, nSize, time.asctime
(tstF))
return 0

tstN = time.localtime()
print tstN
print "Time now: %s" % time.asctime(tstN)
buildList('/')
 
A

Anders J. Munch

jkv said:
Hi Martin,

What i usally do is to convert the two times to seconds since epoch and
compare the two values in seconds. You can use time.mktime to convert
localtime to seconds since epoch.

There's no need to convert - simply retrieve the times as absolute times to
begin with:

file_age_in_seconds = time.time() - os.path.getmtime(filename)

Only convert to local time for presentation.

- Anders
 
M

martin

Thanks both

The first answer is quite instuctive, the other one might be the one
I'll use in the code, it's nicely compact and clear.

So 2x thanks.

:) Martin
 
S

Steven D'Aprano

I added a few lines to your script, and now it ought to only print files
newer than 3601 seconds (3600 seconds is one hour). ....
#if file newer than one hour print a line
if time_difference < 3601:

That's a potential off-by-one error. That may print files that are older
than one hour. Admittedly, they'll be off by less than one second, but if
you're going to write code, write correct code. The right test is:

if time_difference <= 3600:

(and you may even want to deal with files that have a *negative* time
difference, e.g. they were created apparently in the future).

This is particularly necessary if you use time.time() to generate the
current time, since that returns fractions of a second. But even if you
don't, it's still the right thing to do: it's defensive programming.
Rather than assume that all file systems store timestamps accurate only
to a second, assume that some file system, somewhere, will be accurate to
fractions of a second, and code accordingly.

That way, no matter what the file system does, your code will still do
the right thing, and (in this case) it doesn't even cost you anything.
 
J

jkv

Thanks both

The first answer is quite instuctive, the other one might be the one
I'll use in t
I didn't receive the other answer, could you please forward it to me?
So 2x thanks.
You are welcome.

I took another look at your code, and you can compress it all to a if
"oneliner":
(and thanks to Steven for the <= reminder)

if os.path.isfile(x):
nSize = os.path.getsize(x)
#if oneliner
if time.mktime(time.localtime()) -
time.mktime(time.localtime(os.path.getmtime(x))) <= 3600:
print ('HT fil -> %s %d @ %s') % (x, nSize, time.asctime)
 
J

John Machin

I made this little script (below) to look througt a dir to see if
there are any files newer than .e.g. 1 hour.
I have the loop through the dir working and can retreive file time as
well as present time.
both time variables are in the format returned by time.localtime()

My question:
How do I find the difference between such two time variables, to
calculate the 'age' of the file?

http://en.wikipedia.org/wiki/Subtraction

This technique in well worth learning, as it can be applied in many
real-world situations, sometimes not even requiring a computer. For
example:

The letter was postmarked on the 18th of May; it was delivered on the
29th of May; how many days was it in transit? You give a $10 note for
an article priced at $6.35; how much change should you get?

HTH,
John
 
J

John Machin

I didn't receive the other answer, could you please forward it to me?> So 2x thanks.

You are welcome.

I took another look at your code, and you can compress it all to a if
"oneliner":
(and thanks to Steven for the <= reminder)

        if os.path.isfile(x):
            nSize = os.path.getsize(x)
            #if oneliner
            if time.mktime(time.localtime()) -
time.mktime(time.localtime(os.path.getmtime(x))) <= 3600:
              print ('HT fil -> %s %d @ %s') % (x, nSize, time.asctime)

There is no virtue in onelinedness if the code is unclear and/or
incorrect.

Problems:
(1) Converting UTC time to local time and back again??
> import time
You are in a maze of twisty little functions, all alike.

So it can pay to do things a step at a time, and leave a note of your
intentions at each step.

(2) Consider grabbing the "current time" once instead of each for each
file

(3) asctime ... you are missing (an_argument)

import os, time, sys

def buildList(directory):
listing = os.listdir(directory)
now_utc_secs = time.time()
for x in os.listdir(directory):
x = os.path.join(directory, x)
if os.path.isdir(x):
print ('dir -> %s') % x
elif os.path.isfile(x):
mtime_utc_secs = os.path.getmtime(x)
if now_utc_secs - mtime_utc_secs <= 3600.0:
nSize = os.path.getsize(x)
mtime_local_tuple = time.localtime(mtime_utc_secs)
mtime_local_text = time.asctime(mtime_local_tuple)
print ('fil -> %s %d @ %s') % (x, nSize,
mtime_local_text)

tstN = time.localtime()
print tstN
print "Time now: %s" % time.asctime(tstN)
buildList(sys.argv[1])

HTH,
John
 
M

martin

That's a potential off-by-one error. That may print files that are older
than one hour. Admittedly, they'll be off by less than one second, but if
you're going to write code, write correct code. The right test is:

    if time_difference <= 3600:

(and you may even want to deal with files that have a *negative* time
difference, e.g. they were created apparently in the future).

This is particularly necessary if you use time.time() to generate the
current time, since that returns fractions of a second. But even if you
don't, it's still the right thing to do: it's defensive programming.
Rather than assume that all file systems store timestamps accurate only
to a second, assume that some file system, somewhere, will be accurate to
fractions of a second, and code accordingly.

That way, no matter what the file system does, your code will still do
the right thing, and (in this case) it doesn't even cost you anything.

Hi Steve thanks for your comment.
But I only need it to re-run some test scripts in case there seems to
be hick-up in our live download of satellite images. It's not critical
within seconds, not even within minutes...
But in principel the potential error could of cause be important - in
other context.

:) M
 
M

martin

I didn't receive the other answer, could you please forward it to me?> So 2x thanks.

You are welcome.

I took another look at your code, and you can compress it all to a if
"oneliner":
(and thanks to Steven for the <= reminder)

        if os.path.isfile(x):
            nSize = os.path.getsize(x)
            #if oneliner
            if time.mktime(time.localtime()) -
time.mktime(time.localtime(os.path.getmtime(x))) <= 3600:
              print ('HT fil -> %s %d @ %s') % (x, nSize, time.asctime)

I encurrage both Clarity and Brevity, but usually in that order.
In other words, I don't mind to split a statement in two (or three)
sub-sentenses, if it increases Clarity. As long as it dosn't so large
that I loose the overview, and as long as it dosn't affect runtime
performance.
 
J

John Machin

Only one problem, wise arse:
TypeError: unsupported operand type(s) for -: 'time.struct_time' and
'time.struct_time'

Like I didn't try that...

The point being that you can subtract them in other ways than by
shoving a - between them and throwing the result at Python. What you
were doing was like saying "I was born in January MCMLXXXIX and it's
now MMIX; how do I work out how old I am?" when you *already* had the
relevant numbers in a easily-subtractable form.
 
C

CTO

  > import time
  You are in a maze of twisty little functions, all alike.

Quote of the week. Perhaps the year. I hope you don't mind
me using it in the future.

Geremy Condra
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,755
Messages
2,569,537
Members
45,020
Latest member
GenesisGai

Latest Threads

Top