How do I change the file creation date of a Windows file?

Question:

How do I change the file creation date of a Windows file from Python?

Asked By: Claudiu

||

Answers:

Yak shaving for the win.

import pywintypes, win32file, win32con
def changeFileCreationTime(fname, newtime):
    wintime = pywintypes.Time(newtime)
    winfile = win32file.CreateFile(
        fname, win32con.GENERIC_WRITE,
        win32con.FILE_SHARE_READ | win32con.FILE_SHARE_WRITE | win32con.FILE_SHARE_DELETE,
        None, win32con.OPEN_EXISTING,
        win32con.FILE_ATTRIBUTE_NORMAL, None)

    win32file.SetFileTime(winfile, wintime, None, None)

    winfile.close()
Answered By: Claudiu
import os
os.utime(path, (accessed_time, modified_time))

http://docs.python.org/library/os.html

At least it changes the modification time, without using win32 module.

Answered By: Delta

This code works on python 3 without
ValueError: astimezone() cannot be applied to a naive datetime:

wintime = datetime.datetime.utcfromtimestamp(newtime).replace(tzinfo=datetime.timezone.utc)
winfile = win32file.CreateFile(
    fname, win32con.GENERIC_WRITE,
    win32con.FILE_SHARE_READ | win32con.FILE_SHARE_WRITE | win32con.FILE_SHARE_DELETE,
    None, win32con.OPEN_EXISTING,
    win32con.FILE_ATTRIBUTE_NORMAL, None)
win32file.SetFileTime(winfile, wintime)
winfile.close()
Answered By: panda-34

Here’s a more robust version of the accepted answer. It also has the opposing getter function. This addresses created, modified, and accessed datetimes. It handles having the datetimes parameters provided as either datetime.datetime objects, or as “seconds since the epoch” (what the getter returns). Further, it adjusts for Day Light Saving time, which the accepted answer does not. Without that, your times will not be set correctly when you set a winter or summer time during the opposing phase of your actual system time.

The major weakness of this answer is that it is for Windows only (which answers the question posed). In the future, I’ll try to post a cross platform solution.

def isWindows() :
  import platform
  return platform.system() == 'Windows' 

def getFileDateTimes( filePath ):        
    return ( os.path.getctime( filePath ), 
             os.path.getmtime( filePath ), 
             os.path.getatime( filePath ) )

def setFileDateTimes( filePath, datetimes ):
    try :
        import datetime
        import time 
        if isWindows() :
            import win32file, win32con
            ctime = datetimes[0]
            mtime = datetimes[1]
            atime = datetimes[2]
            # handle datetime.datetime parameters
            if isinstance( ctime, datetime.datetime ) :
                ctime = time.mktime( ctime.timetuple() ) 
            if isinstance( mtime, datetime.datetime ) :
                mtime = time.mktime( mtime.timetuple() ) 
            if isinstance( atime, datetime.datetime ) :
                atime = time.mktime( atime.timetuple() )             
            # adjust for day light savings     
            now = time.localtime()
            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)            
            # change time stamps
            winfile = win32file.CreateFile(
                filePath, win32con.GENERIC_WRITE,
                win32con.FILE_SHARE_READ | win32con.FILE_SHARE_WRITE | win32con.FILE_SHARE_DELETE,
                None, win32con.OPEN_EXISTING,
                win32con.FILE_ATTRIBUTE_NORMAL, None)
            win32file.SetFileTime( winfile, ctime, atime, mtime )
            winfile.close()
        else : """MUST FIGURE OUT..."""
    except : pass    
Answered By: BuvinJ

install pywin32 extension first https://sourceforge.net/projects/pywin32/files/pywin32/Build%20221/

import win32file
import pywintypes

# main logic function
def changeFileCreateTime(path, ctime):
    # path: your file path
    # ctime: Unix timestamp

    # open file and get the handle of file
    # API: http://timgolden.me.uk/pywin32-docs/win32file__CreateFile_meth.html
    handle = win32file.CreateFile(
        path,                          # file path
        win32file.GENERIC_WRITE,       # must opened with GENERIC_WRITE access
        0,
        None,
        win32file.OPEN_EXISTING,
        0,
        0
    )

    # create a PyTime object
    # API: http://timgolden.me.uk/pywin32-docs/pywintypes__Time_meth.html
    PyTime = pywintypes.Time(ctime)

    # reset the create time of file
    # API: http://timgolden.me.uk/pywin32-docs/win32file__SetFileTime_meth.html
    win32file.SetFileTime(
        handle,
        PyTime
    )

# example
changeFileCreateTime('C:/Users/percy/Desktop/1.txt',1234567789)
Answered By: percy507

Here is a solution that works on Python 3.5 and windows 7. Very easy. I admit it’s sloppy coding… but it works. You’re welcome to clean it up. I just needed a quick soln.

import pywintypes, win32file, win32con, datetime, pytz

def changeFileCreationTime(fname, newtime):
    wintime = pywintypes.Time(newtime)
    winfile = win32file.CreateFile(fname, win32con.GENERIC_WRITE,
                                   win32con.FILE_SHARE_READ | 
                                   win32con.FILE_SHARE_WRITE | 
                                   win32con.FILE_SHARE_DELETE,
                                   None, 
                                   win32con.OPEN_EXISTING,
                                   win32con.FILE_ATTRIBUTE_NORMAL, 
                                   None)

    win32file.SetFileTime(      winfile,  wintime,  wintime,     wintime)
    # None doesnt change args = file,     creation, last access, last write
    # win32file.SetFileTime(None, None, None, None) # does nonething
    winfile.close()

if __name__ == "__main__":
    local_tz = pytz.timezone('Antarctica/South_Pole')
    start_date = local_tz.localize(datetime.datetime(1776,7,4), is_dst=None)
    changeFileCreationTime(r'C:homemade.pr0n', start_date )
Answered By: Kardo Paska

I did not want to bring the whole pywin32 / win32file library solely to set the creation time of a file, so I made the win32-setctime package which does just that.

pip install win32-setctime

And then use it like that:

from win32_setctime import setctime

setctime("my_file.txt", 1561675987.509)

Basically, the function can be reduced to just a few lines without needing any dependency other that the built-in ctypes Python library:

from ctypes import windll, wintypes, byref

# Arbitrary example of a file and a date
filepath = "my_file.txt"
epoch = 1561675987.509

# Convert Unix timestamp to Windows FileTime using some magic numbers
# See documentation: https://support.microsoft.com/en-us/help/167296
timestamp = int((epoch * 10000000) + 116444736000000000)
ctime = wintypes.FILETIME(timestamp & 0xFFFFFFFF, timestamp >> 32)

# Call Win32 API to modify the file creation date
handle = windll.kernel32.CreateFileW(filepath, 256, 0, None, 3, 128, None)
windll.kernel32.SetFileTime(handle, byref(ctime), None, None)
windll.kernel32.CloseHandle(handle)

For advanced management (like error handling), see the source code of win32_setctime.py.

Answered By: Delgan

If you want to put a date instead of an epoch you can grab this code. I used win32-setctime and attrs packages so firstly install:

pip install win32-setctime
pip install attrs

Then you can run my code, remember to update FILEPATH, DATE, MONTH and YEAR.

from datetime import datetime

import attr
from win32_setctime import setctime

FILEPATH = r'C:UsersjakubPycharmProjectsdate_creation_changedoc.docx'
DAY, MONTH, YEAR = (9, 5, 2020)


@attr.s
class TimeCounter:
    """
    Class calculates epochs
    """
    day = attr.ib(converter=str)
    month = attr.ib(converter=str)
    year = attr.ib(converter=str)

    def create_datetime(self):
        date_time_obj = datetime.strptime(r'{}/{}/{}'.format(self.day,
                                                             self.month,
                                                             self.year), '%d/%m/%Y')

        unix_start = datetime(1970, 1, 1)
        return (date_time_obj - unix_start).days

    def count_epoch(self):
        days = self.create_datetime()
        return days * 86400


@attr.s
class DateCreatedChanger:
    """
    Class changes the creation date of the file
    """
    file_path = attr.ib()

    def change_creation_date(self):
        epoch_obj = TimeCounter(day=DAY,
                                month=MONTH,
                                year=YEAR)
        epoch = epoch_obj.count_epoch()
        setctime(self.file_path, epoch)


if __name__ == '__main__':
    changer = DateCreatedChanger(FILEPATH)
    changer.change_creation_date()
Answered By: KubaAdam

My simple and clear filedate module might accommodate your needs.

Advantages:

  • Very simple interface
  • Platform independent
  • Fancy string dates support
  • Date Holder utility

Installation

pip install filedate

Usage

import filedate
Path = "~/Documents/File.txt"

filedate.File(Path).set(
    created = "1st February 2003, 12:30",
    modified = "3:00 PM, 04 May 2009",
    accessed = "08/07/2014 18:30:45"
)
Answered By: kubinka0505

A small solution without dependencies inspired by Delgan’s answer.
It supports unix timestamps up to nano precision (like the values returned by os.stat(...).st_ctime_ns as an example).
Modified, accessed and created timestamps are supported.
Unpassed/noned parameters are being ignored by the Win32 api call (those file properties won’t be changed).
It requires python 3.10 for the multi-type hints used on the parameters. Just remove the hints if you want it to work for older python versions.

from ctypes import wintypes, byref, WinDLL, WinError, get_last_error


def __unix_ts_to_win_filetime(self, timestamp: int | None) -> wintypes.FILETIME:
    if not timestamp:
        return wintypes.FILETIME(0xFFFFFFFF, 0xFFFFFFFF)

    # difference in ticks between 16010101 and 19700101 (leapseconds were introduced in 1972 so we're fine)
    _EPOCH_OFFSET_TICKS = 116444736000000000
    # truncate timestamp to 19 decimals or fill it up with zeroes
    timestamp = int(str(timestamp)[:19].rjust(19, '0'))
    timestamp_in_ticks = int(timestamp / 100)
    # add epoch offset to timestamp ticks
    timestamp_in_ticks += _EPOCH_OFFSET_TICKS
    # convert to wintypes.FILETIME by filling higher (32-bit masked) and lower number (shifted by 32 bits)
    return wintypes.FILETIME(timestamp_in_ticks & 0xFFFFFFFF, timestamp_in_ticks >> 32)

def __set_times_on_file(self, path: str, created_timestamp: int = None, access_timestamp: int = None, modify_timestamp: int = None) -> bool:
    created_timestamp = self.__unix_ts_to_win_filetime(timestamp=created_timestamp)
    access_timestamp = self.__unix_ts_to_win_filetime(timestamp=access_timestamp)
    modify_timestamp = self.__unix_ts_to_win_filetime(timestamp=modify_timestamp)

    # Win32 API call for CreateFileW and SetFileTime
    kernel32 = WinDLL("kernel32", use_last_error=True)
    hndl = kernel32.CreateFileW(path, 256, 0, None, 3, 128, None)
    if hndl == -1:
        print(WinError(get_last_error()))
        return False

    if not wintypes.BOOL(kernel32.SetFileTime(hndl, byref(created_timestamp), byref(access_timestamp), byref(modify_timestamp))):
        print(WinError(get_last_error()))
        return False

    if not wintypes.BOOL(kernel32.CloseHandle(hndl)):
        print(WinError(get_last_error()))
        return False

    return True

Usage example

if __set_times_on_file(path='C:WindowsTempfoo.bar', created_timestamp=1657101345298000000):
    print("file timestamps could be set")
else:
    print("file timestamps could not be set")
Answered By: 0x446

I could not find a straight answer for python exactly, so i am leaving an answer for anyone searching how to modify the dates for a directory (or a file, thanks to the answers in this thread).

import os, win32con, win32file, pywintypes


def changeCreationTime(path, time):

    try:
        wintime = pywintypes.Time(time)
        # File
        if os.path.isfile(path):
            winfile = win32file.CreateFile(path,
                                           win32con.GENERIC_WRITE,
                                           win32con.FILE_SHARE_READ |
                                           win32con.FILE_SHARE_WRITE |
                                           win32con.FILE_SHARE_DELETE,
                                           None,
                                           win32con.OPEN_EXISTING,
                                           win32con.FILE_ATTRIBUTE_NORMAL,
                                           None)
            win32file.SetFileTime(winfile, wintime, wintime, wintime)
            winfile.close()
            print(f'File {path} modified')
        # Directory
        elif os.path.isdir(path):
            windir = win32file.CreateFile(path,
                                          win32con.GENERIC_WRITE,
                                          win32con.FILE_SHARE_WRITE |
                                          win32con.FILE_SHARE_DELETE |
                                          win32con.FILE_SHARE_READ,
                                          None,
                                          win32con.OPEN_EXISTING,
                                          win32con.FILE_FLAG_BACKUP_SEMANTICS,
                                          None)
            win32file.SetFileTime(windir, wintime, wintime, wintime)
            windir.close()
            print(f"Directory {path} modified")
    except BaseException as err:
        print(err)

Example:

# Create a folder named example and a text file named example.txt in C:example
changeCreationTime(r'C:example', 1338587789)
changeCreationTime(r'C:exampleexample.txt', 1338587789)

Answered By: Flame
Categories: questions Tags: , , , ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.