How can I get the ctime and/or mtime of a file in Python including timezone?

3.4k views Asked by At

Based on this related question and answer I asked, it has become obvious that datetime.fromtimestamp(os.path.getctime()) in Python 3.4 doesn't return a timezone-aware datetime object, However, based on some investigation, I've also discovered that OS X 10.9 on an HFS+ filesystem (for example) does seem to maintain the timezones along with ctimes (unless gls is inferring the timezone from my local timezone and daylight-savings time):

$ gls -l --full-time -c

-rw-------  1 myuser staff 538 2015-01-04 17:12:57.000000000 +0100 fileone
-rwxr-xr-x 17 myuser staff 578 2015-05-20 06:41:07.000000000 +0200 filetwo

(I am using the GNU version of ls)

How can I get the timezone from the ctime and insert/combine it into a datetime object?

(I'd also like the same answer for the mtime, I assume it will be similar).

3

There are 3 answers

10
jfs On BEST ANSWER

Both ctime and mtime are available as "seconds since epoch" (values returned by time.time()).

To get the local timezone, you could use tzlocal module:

#!/usr/bin/env python
import os
from datetime import datetime
from tzlocal import get_localzone # $ pip install tzlocal

local_timezone = get_localzone()
aware_dt = datetime.fromtimestamp(os.path.getctime(path), local_timezone)

You might see the timezone info because ls converts the timestamps into corresponding broken-down time with timezone offset using the local timezone.

6
Serge Ballesta On

If you only want to rely on Python Standard Library, you can only use the timezone subclass of tzinfo :

tz = datetime.timezone(datetime.timedelta(seconds=-time.timezone), time.tzname[0]) \
    if (time.daylight == 0 || time.localtime(os.path.getctime(path)).tm_isdst == 0) \
    else datetime.timezone(datetime.timedelta(seconds=-time.altzone), time.tzname[1])
dt = datetime.fromtimestamp(os.path.getctime(path), tz)

Then you could have (in France) :

>>> dt
datetime.datetime(2015, 6, 9, 13, 43, 3, 791255, tzinfo=datetime.timezone(datetime.timedelta(0, 7200), 'Paris, Madrid (heure d\x92été)'))
>>> dt.utctimetuple()
time.struct_time(tm_year=2015, tm_mon=6, tm_mday=9, tm_hour=11, tm_min=43, tm_sec=3, tm_wday=1, tm_yday=160, tm_isdst=0)

Of course, mtime would work exactly the same

You should consult J.F. Sebastian's post for references. Here is an extract :

To get the current UTC offset in a way that workarounds the time.daylight issue and that works even if tm_gmtoff is not available, [this] can be used:

import time
from datetime import datetime

ts = time.time()
utc_offset = (datetime.fromtimestamp(ts) -
              datetime.utcfromtimestamp(ts)).total_seconds()
0
Anjan On

This works for me:

import os, datetime, time

modified_time = os.path.getmtime(file)
mtime_obj = datetime.datetime(*time.localtime(modified_time)[:6])
# (or)
mtime_obj = datetime.datetime.fromtimestamp(modified_time)
print(mtime_obj.strftime('%Y-%m-%d_%H-%M-%S'))

No external packages. Just the standard python libraries. (Python 3.6)