synchronize_times() must fail with assertion
ftputil.ftp_error.TimeShiftError: time shift (-31514426.37 s) > 1 day
Debugging info: ftputil 2.5, Python 2.7 (win32)
when the client and/or server are in western time zones and the server reports file/dir time as GMT.
After creating a test file, synchronize_times() calls
server_time = self.path.getmtime(helper_file_name)
to get the server-relative time. getmtime() uses the normal functions to develop the time value.
Within parse_unix_time() the code attempts to figure out which year a directory line references, e.g.
line = -rw-r--r-- 1 500 500 0 Jan 12 20:43 _ftputil_sync_
when no year value is present in a listing line like above. If the time value developed by the code assuming "this year" is some impossible *future* time value, then it decides the correct year must be "last year".
The code uses
if st_mtime > time.time() + time_shift + 60.0:
as a check for whether the year is correct. But if the server time is
GMT, and the local client is two or more time zones west of GMT, then
this check will always be true, and the year return will *always* be
last year, and the __assert_valid_time_shift()
rule 1 will always
fail.
As a check, I set the time_shift() value correctly, and then the problem didn't assert.
I got some snapshots while stepping through the code, and for the directory line above.
(Pdb) year, month, day, hour, minute
(2011, 1, 12, 20, 43)
(Pdb) st_mtime, time.asctime(time.localtime(st_mtime))
(1294886580.0, 'Wed Jan 12 20:43:00 2011')
197 -> if st_mtime > time.time() + time_shift + 60.0:
(Pdb) st_mtime, time.time(), time_shift
(1294886580.0, 1294865365.84, 0.0)
198 -> st_mtime = time.mktime( (year-1, month, day,
199 hour, minute, 0, 0, 0, -1) )
(Pdb) st_mtime, time.asctime(time.localtime(st_mtime))
(1263350580.0, 'Tue Jan 12 20:43:00 2010')
^^^^
I've seen mention of these symptoms with ftputil using Google, but don't remember where. I hope this explains the scenario. Maybe I'll have more insight to a solution later.
Many thanks for the detailed report! :-)
(I added some code markup to the description for better readability.)
Replying to ftputiluser:
The code uses
if st_mtime > time.time() + time_shift + 60.0:
as a check for whether the year is correct. But if the server time is GMT, and the local client is two or more time zones west of GMT, then this check will always be true, and the year return will *always* be last year, and the__assert_valid_time_shift()
rule 1 will always fail.The problem is that
synchronize_times
callsgetmtime
which callsparse_unix_time
- butparse_unix_time
uses the very time shift value thatsynchronize_times
is supposed to set in the first place. So the time shift value at the time of the year determination is still 0.0, regardless of the actual time zone difference. This, in turn, makesparse_unix_time
conclude a wrong year.As a check, I set the time_shift() value correctly, and then the problem didn't assert.
This supports my interpretation nicely. :-)
The bug should be fixed in changeset [8b6505b9e736665ca4de9ca763093bfae19177b9](https://git.sr.ht/~sschwarzer/ftputil/commit/8b6505b9e736665ca4de9ca763093bfae19177b9 "Added fix for ticket #55 (thanks to Thomas L. Shinnick). Ticket URL: ..."). It would be great if you could report if the problem is fixed for you.
To help other users finding a solution to similar problems, I changed the title to reflect that the server doesn't have to be in the GMT time zone.
The problem seems to be fixed according to an e-mail by the reporter of this ticket. Thanks!