4

I am trying to get a file's last modified time using Python 3.8 in Cygwin.

So if I do stat .profile I get:

  File: .profile
  Size: 1236            Blocks: 4          IO Block: 65536  regular file
Device: 46e61a95h/1189485205d   Inode: 8162774324632653  Links: 1
Access: (0755/-rwxr-xr-x)  Uid: (197609/   pepol)   Gid: (197609/   pepol)
Access: 2020-09-14 15:16:04.773101900 +0700
Modify: 2020-09-14 15:15:21.977809000 +0700
Change: 2020-09-14 15:16:04.055602500 +0700
 Birth: 2020-09-14 15:16:04.052652900 +0700

But if I try getting the file's timestamp using Python:

from pathlib import Path
from datetime import datetime

p1 = Path(".profile")
p1st = p1.stat()
dts = datetime.fromtimestamp(p1st.st_mtime)
print(str(dts))

I got this 'naive' (timezoneless) instead:

2020-09-14 09:15:21.977809

Now here's where I get confused:

  • As shown in the stat output, my timezone is UTC+07:00
  • My country does NOT have DST
  • Windows' timezone is properly set
  • 15:15:21.977809000 +0700 is equivalent to 08:15:21.977809000 +0000

Why is the timestamp as fetched by pathlib.Path().stat() is 1 hour ahead of what the UTC timestamp should be? What timezone is it actually using?

pepoluan
  • 6,132
  • 4
  • 46
  • 76
  • Which Python do you use, cygwin's or Windows'? In cygwin, does `echo $TZ` show the correct time zone? Side-note: the timestamps returned by `pathlib.Path().stat()` are POSIX timestamps, so you could use `datetime.fromtimestamp(p1st.st_mtime, tz=timezone.utc)` to get UTC straight away. – FObersteiner Sep 14 '20 at 09:40
  • @MrFuppes holy bejeebus, that might be it! I checked with `which` and it's pointing to Windows' Python! `echo $TZ` already shows the correct time zone, btw. And thanks for the tips! – pepoluan Sep 14 '20 at 10:04
  • @MrFuppes update: setting `tz=timezone.utc` properly returns the UTC timestamp, yay! If you can post your tip up there as an answer, I'll gladly mark it as the solution. – pepoluan Sep 14 '20 at 10:06
  • related : https://stackoverflow.com/q/63713891/10197418 – FObersteiner Sep 15 '20 at 06:28

1 Answers1

3

Make sure that in cygwin, you use Cygwin's Python. You can check which Python version cygwin uses with $which python3. That should return e.g. /usr/bin/python3.

  • if you use a Windows Python installation from within Cygwin, it won't be able to determine the machines' time zone (OS setting) correctly (the Windows Python is configured to do that on Windows, not in a Unix environment and vice versa).

Side note, since the timestamps returned by pathlib.Path().stat() are POSIX timestamps, so you could use e.g. datetime.fromtimestamp(p1st.st_mtime, tz=timezone.utc) to get UTC straight away.

FObersteiner
  • 22,500
  • 8
  • 42
  • 72
  • How do you know that the datetime recorded by the OS when a file is saved is UTC or local time? Obviously a POSIX timestamp is just a number (float or int). A file could also be saved on one OS and then copied/moved to another... so can you explain how you know you're dealing with UTC (as it is timezone-naive)? Wouldn't this imply that every way of saving a file in every possible OS took the trouble to stamp with a UTC value? – mike rodent Jun 16 '23 at 17:38
  • 1
    @mikerodent [Unix time](https://en.wikipedia.org/wiki/Unix_time) refers to UTC (1970-01-01 00:00 UTC is the epoch). So it's not naive in that sense. You can convert it to some datetime structure, including the time zone that the OS is configured to use, then display that to a user e.g. in a file manager. All that only works correctly of course if the OS that sets up / modifies the file sets the correct Unix time. – FObersteiner Jun 16 '23 at 18:47
  • Yes I know what Unix time is. I've since found at least one link suggesting that not all OSs store `st_mtime` as a UTC value. See here: https://stackoverflow.com/a/76492554/595305. Given that a file can have been saved in any OS, every `datetime` derived from `st_mtime` should be a timezone-naive `datetime`. – mike rodent Jun 16 '23 at 19:01
  • 1
    @mikerodent as I said, the suggestion in my answer above only works if the file's timestamps are correct. Btw. it's not only the OS; programs might also modify those file attributes. I don't see how naive datetime should help in this case. Python's naive datetime object for instance still needs *some* reference, otherwise, it will be equally wrong. – FObersteiner Jun 17 '23 at 07:38
  • Sorry, I can't understand your reasoning there. I especially don't understand your last sentence. If you have a timezone-aware `datetime` you are giving the impression that that points to a specific moment in time, in the history of the universe. The reality is that a POSIX timestamp can always, **always**, be up to 23 hours inaccurate. Unless you have definite knowledge of the timezone it was created for/in. – mike rodent Jun 17 '23 at 07:57
  • @mikerodent I fear this goes both ways. So let's not get lost in the argument here. Do you think there is anything ***plain wrong*** with the answer above? If so, I'll look into that, I don't want to spread misinformation (we have AI for that). If not, my suggestion is let's leave it at that. – FObersteiner Jun 17 '23 at 15:06