Modifique la marca de tiempo de creación / acceso / escritura de archivos con Python en Windows

Intenté encontrar una manera fácil de modificar la marca de tiempo de un archivo en windows usando python, pero no había mucha información clara en la web. Después de buscar un rato conseguí una solución. Para acortar la búsqueda de otros, el código sigue aquí.

Puede hacerse más fácil y más hermoso, pero funciona. Lo único que no resolví es el horario de verano: el problema del horario de invierno, es decir, si se da una hora en verano, el resultado difiere en una hora. Tal vez alguien puede agregar una corrección?

from win32file import CreateFile, SetFileTime, GetFileTime, CloseHandle from win32file import GENERIC_READ, GENERIC_WRITE, OPEN_EXISTING from pywintypes import Time import time import sys import os if len(sys.argv)<5: pfile = os.path.basename(sys.argv[0]) print "USAGE:\n\t%s    \n" % pfile print "EXAMPLE:" print '%s "01.01.2000 00:00:00" "01.01.2000 00:00:00" "01.01.2000 00:00:00" file' % (pfile) sys.exit() # get arguments cTime = sys.argv[1] # create mTime = sys.argv[2] # modify aTime = sys.argv[3] # access fName = sys.argv[4] # specify time format format = "%d.%m.%Y %H:%M:%S" offset = 0 # in seconds # create struct_time object cTime_t = time.localtime(time.mktime(time.strptime(cTime,format))+offset) mTime_t = time.localtime(time.mktime(time.strptime(mTime,format))+offset) aTime_t = time.localtime(time.mktime(time.strptime(aTime,format))+offset) # visually check if conversion was ok print print "FileName: %s" % fName print "Create : %s --> %s OK" % (cTime,time.strftime(format,cTime_t)) print "Modify : %s --> %s OK" % (mTime,time.strftime(format,mTime_t)) print "Access : %s --> %s OK" % (aTime,time.strftime(format,aTime_t)) print # change timestamp of file fh = CreateFile(fName, GENERIC_READ | GENERIC_WRITE, 0, None, OPEN_EXISTING, 0, 0) createTime, accessTime, modifyTime = GetFileTime(fh) print "Change Create from",createTime,"to %s" % (time.strftime(format,cTime_t)) print "Change Modify from",modifyTime,"to %s" % (time.strftime(format,mTime_t)) print "Change Access from",accessTime,"to %s" % (time.strftime(format,aTime_t)) print createTime = Time(time.mktime(cTime_t)) accessTime = Time(time.mktime(aTime_t)) modifyTime = Time(time.mktime(mTime_t)) SetFileTime(fh, createTime, accessTime, modifyTime) CloseHandle(fh) # check if all was ok ctime = time.strftime(format,time.localtime(os.path.getctime(fName))) mtime = time.strftime(format,time.localtime(os.path.getmtime(fName))) atime = time.strftime(format,time.localtime(os.path.getatime(fName))) print "CHECK MODIFICATION:" print "FileName: %s" % fName print "Create : %s" % (ctime) print "Modify : %s" % (mtime) print "Access : %s" % (atime) 

Usando os.utime , puedes cambiar el atime, mtime (no ctime).

 >>> import time >>> import os >>> t = time.mktime(time.strptime('16.01.2014 00:00:00', '%d.%m.%Y %H:%M:%S')) >>> t 1389798000.0 >>> os.utime('..\path\to\file', (t,t)) # <--- >>> os.path.getmtime('..\path\to\file') 1389798000.0 

Hay dos lugares donde es posible que desee corregir una diferencia de invierno / verano de una hora. En ambos casos, utilizamos el campo tm_isdst , que time.localtime calcula convenientemente para indicarnos si el horario de verano (DST) estaba vigente para una marca de tiempo en particular.

Corrección de entrada

Si está configurando una marca de tiempo de invierno durante el verano, o viceversa, se apagará una hora cuando llegue la temporada correspondiente, a menos que compense antes de llamar a SetFileTime :

 now = time.localtime() createTime = Time(time.mktime(cTime_t) + 3600 * (now.tm_isdst - cTime_t.tm_isdst)) accessTime = Time(time.mktime(aTime_t) + 3600 * (now.tm_isdst - aTime_t.tm_isdst)) modifyTime = Time(time.mktime(mTime_t) + 3600 * (now.tm_isdst - mTime_t.tm_isdst)) SetFileTime(fh, createTime, accessTime, modifyTime) 

Corrección de salida

Para hacer que los informes de Python coincidan con el Explorador de Windows, aplicamos la corrección antes de llamar a strftime :

 # check if all was ok now = time.localtime() ctime = os.path.getctime(fName) mtime = os.path.getmtime(fName) atime = os.path.getatime(fName) ctime += 3600 * (now.tm_isdst - time.localtime(ctime).tm_isdst) mtime += 3600 * (now.tm_isdst - time.localtime(mtime).tm_isdst) atime += 3600 * (now.tm_isdst - time.localtime(atime).tm_isdst) ctime = time.strftime(format,time.localtime(ctime)) mtime = time.strftime(format,time.localtime(mtime)) atime = time.strftime(format,time.localtime(atime)) 

Ambas correcciones

Tenga cuidado, si aplica ambos, su salida de Python parecerá de nuevo no coincidir con su entrada. Esto puede ser deseable (ver más abajo), pero si te molesta:

  • Elija solo Corrección de entrada si prefiere las marcas de tiempo que se vean a la derecha de su época del año.
  • Elija solo Corrección de salida si está acostumbrado a verlos saltar una hora dos veces al año, ya que el horario de verano entra en vigor y luego desaparece.

¿Por qué es tan inconsistente el horario de verano?

Python y Windows han elegido diferentes métodos para convertir las marcas de tiempo entre UTC y la zona horaria local:

  • Python utiliza el código DST que estaba vigente en la marca de tiempo. De esta manera, la marca de tiempo tiene una representación consistente durante todo el año.

  • Windows usa el código DST vigente en este momento. De esta manera, todas las marcas de tiempo mostradas tienen el mismo código implícito.

Esto es evidente si usa ‘% Z’ para incluir la zona horaria en la cadena convertida (PST frente a PDT, por ejemplo), pero como la mayoría de las aplicaciones (incluido el Explorador de Windows) no lo hacen, puede manifestarse una inconsistencia aparente de una hora.

Ejemplo

Cuando se imprimen con códigos de tiempo explícitos, queda claro que los sellos en cada columna realmente representan el mismo instante en el tiempo:

 File #1 (January) File #2 (June) 2000-01-30 20:00:00 UTC 2000-06-22 20:00:00 UTC observed in January in California: 2000-01-30 12:00:00 PST 2000-06-30 13:00:00 PDT [Python] 2000-01-30 12:00:00 PST 2000-06-30 12:00:00 PST [Windows] observed in June in California: 2000-01-30 12:00:00 PST 2000-06-30 13:00:00 PDT [Python] 2000-01-30 13:00:00 PDT 2000-06-30 13:00:00 PDT [Windows] observed in June in New York: 2000-01-30 15:00:00 EST 2000-06-30 16:00:00 EDT [Python] 2000-01-30 16:00:00 EDT 2000-06-30 16:00:00 EDT [Windows] 

Sería bueno si pudiéramos pedirle a strftime que respete el campo tm_isdst, para que coincida con el Explorador de Windows y la mayoría de las otras aplicaciones que muestran las marcas de tiempo de los archivos, pero al menos hay una solución simple para realizar el cálculo nosotros mismos.

 def adjustForDST (seconds): now = time.localtime() correction = 60*60 * (now.tm_isdst - time.localtime(seconds).tm_isdst) return seconds + correction time.strftime(format, time.localtime(adjustforDST(mtime))) 

Fuentes:

http://bytes.com/topic/python/answers/655606-python-2-5-1-broken-os-stat-module http://search.cpan.org/~shay/Win32-UTCFileTime-1.58/ lib / Win32 / UTCFileTime.pm

Si el enlace cpan se rompe nuevamente con una nueva revisión, encuéntrelo de esta manera:

https://www.google.com/search?q=UTCFileTime.pm