修改文件时间工具

我看了一下修改文件时间的方式可以用win32file和win32_setfiletime,我这次用的是win32file,其实win32_setfiletime使用起来更简单一些

用到的知识点有
1.读取文件路径
2.触发按钮
3.timec转换为time

from win32file import CreateFile, SetFileTime, GetFileTime, CloseHandle
from win32file import GENERIC_READ, GENERIC_WRITE, OPEN_EXISTING
from win32_setfiletime import setctime, setmtime, setatime
from pywintypes import Time  # 可以忽视这个 Time 报错(运行程序还是没问题的)
import time
import tkinter.messagebox
import random
from tkinter.filedialog import *
import calendar
import tkinter as tk
import tkinter.font as tkFont
from tkinter import ttk
datetime = calendar.datetime.datetime
timedelta = calendar.datetime.timedelta
global getTime,geturl
class Calendar:

    def __init__(s, point=None, position=None):
        # point    提供一个基点,来确定窗口位置
        # position 窗口在点的位置 'ur'-右上, 'ul'-左上, 'll'-左下, 'lr'-右下
        # s.master = tk.Tk()
        s.master = tk.Toplevel()
        s.master.withdraw()
        fwday = calendar.SUNDAY

        year = datetime.now().year
        month = datetime.now().month
        locale = None
        sel_bg = '#ecffc4'
        sel_fg = '#05640e'

        s._date = datetime(year, month, 1)
        s._selection = None  # 设置为未选中日期

        s.G_Frame = ttk.Frame(s.master)

        s._cal = s.__get_calendar(locale, fwday)

        s.__setup_styles()  # 创建自定义样式
        s.__place_widgets()  # pack/grid 小部件
        s.__config_calendar()  # 调整日历列和安装标记
        # 配置画布和正确的绑定,以选择日期。
        s.__setup_selection(sel_bg, sel_fg)

        # 存储项ID,用于稍后插入。
        s._items = [s._calendar.insert('', 'end', values = '') for _ in range(6)]

        # 在当前空日历中插入日期
        s._update()

        s.G_Frame.pack(expand = 1, fill = 'both')
        s.master.overrideredirect(1)
        s.master.update_idletasks()
        width, height = s.master.winfo_reqwidth(), s.master.winfo_reqheight()
        if point and position:
            if position == 'ur':
                x, y = point[0], point[1] - height
            elif position == 'lr':
                x, y = point[0], point[1]
            elif position == 'ul':
                x, y = point[0] - width, point[1] - height
            elif position == 'll':
                x, y = point[0] - width, point[1]
        else:
            x, y = (s.master.winfo_screenwidth() - width) / 2, (s.master.winfo_screenheight() - height) / 2
        s.master.geometry('%dx%d+%d+%d' % (width, height, x, y))  # 窗口位置居中
        s.master.after(300, s._main_judge)
        s.master.deiconify()
        s.master.focus_set()
        s.master.wait_window()  # 这里应该使用wait_window挂起窗口,如果使用mainloop,可能会导致主程序很多错误

    def __get_calendar(s, locale, fwday):
        # 实例化适当的日历类
        if locale is None:
            return calendar.TextCalendar(fwday)
        else:
            return calendar.LocaleTextCalendar(fwday, locale)

    def __setitem__(s, item, value):
        if item in ('year', 'month'):
            raise AttributeError("attribute '%s' is not writeable" % item)
        elif item == 'selectbackground':
            s._canvas['background'] = value
        elif item == 'selectforeground':
            s._canvas.itemconfigure(s._canvas.text, item = value)
        else:
            s.G_Frame.__setitem__(s, item, value)

    def __getitem__(s, item):
        if item in ('year', 'month'):
            return getattr(s._date, item)
        elif item == 'selectbackground':
            return s._canvas['background']
        elif item == 'selectforeground':
            return s._canvas.itemcget(s._canvas.text, 'fill')
        else:
            r = ttk.tclobjs_to_py({item: ttk.Frame.__getitem__(s, item)})
            return r[item]

    def __setup_styles(s):
        # 自定义TTK风格
        style = ttk.Style(s.master)
        arrow_layout = lambda dir: (
            [('Button.focus', {'children': [('Button.%sarrow' % dir, None)]})]
        )
        style.layout('L.TButton', arrow_layout('left'))
        style.layout('R.TButton', arrow_layout('right'))

    def __place_widgets(s):
        # 标头框架及其小部件
        Input_judgment_num = s.master.register(s.Input_judgment)  # 需要将函数包装一下,必要的
        hframe = ttk.Frame(s.G_Frame)
        gframe = ttk.Frame(s.G_Frame)
        bframe = ttk.Frame(s.G_Frame)
        hframe.pack(in_ = s.G_Frame, side = 'top', pady = 5, anchor = 'center')
        gframe.pack(in_ = s.G_Frame, fill = tk.X, pady = 5)
        bframe.pack(in_ = s.G_Frame, side = 'bottom', pady = 5)

        lbtn = ttk.Button(hframe, style = 'L.TButton', command = s._prev_month)
        lbtn.grid(in_ = hframe, column = 0, row = 0, padx = 12)
        rbtn = ttk.Button(hframe, style = 'R.TButton', command = s._next_month)
        rbtn.grid(in_ = hframe, column = 5, row = 0, padx = 12)

        s.CB_year = ttk.Combobox(hframe, width = 5, values = [str(year) for year in
                                                              range(datetime.now().year, datetime.now().year - 11, -1)],
                                 validate = 'key', validatecommand = (Input_judgment_num, '%P'))
        s.CB_year.current(0)
        s.CB_year.grid(in_ = hframe, column = 1, row = 0)
        s.CB_year.bind('<KeyPress>', lambda event: s._update(event, True))
        s.CB_year.bind("<<ComboboxSelected>>", s._update)
        tk.Label(hframe, text = '年', justify = 'left').grid(in_ = hframe, column = 2, row = 0, padx = (0, 5))

        s.CB_month = ttk.Combobox(hframe, width = 3, values = ['%02d' % month for month in range(1, 13)],
                                  state = 'readonly')
        s.CB_month.current(datetime.now().month - 1)
        s.CB_month.grid(in_ = hframe, column = 3, row = 0)
        s.CB_month.bind("<<ComboboxSelected>>", s._update)
        tk.Label(hframe, text = '月', justify = 'left').grid(in_ = hframe, column = 4, row = 0)

        # 日历部件
        s._calendar = ttk.Treeview(gframe, show = '', selectmode = 'none', height = 7)
        s._calendar.pack(expand = 1, fill = 'both', side = 'bottom', padx = 5)

        ttk.Button(bframe, text = "确 定", width = 6, command = lambda: s._exit(True)).grid(row = 0, column = 0,
                                                                                          sticky = 'ns', padx = 20)
        ttk.Button(bframe, text = "取 消", width = 6, command = s._exit).grid(row = 0, column = 1, sticky = 'ne',
                                                                            padx = 20)

        tk.Frame(s.G_Frame, bg = '#565656').place(x = 0, y = 0, relx = 0, rely = 0, relwidth = 1, relheigh = 2 / 200)
        tk.Frame(s.G_Frame, bg = '#565656').place(x = 0, y = 0, relx = 0, rely = 198 / 200, relwidth = 1,
                                                  relheigh = 2 / 200)
        tk.Frame(s.G_Frame, bg = '#565656').place(x = 0, y = 0, relx = 0, rely = 0, relwidth = 2 / 200, relheigh = 1)
        tk.Frame(s.G_Frame, bg = '#565656').place(x = 0, y = 0, relx = 198 / 200, rely = 0, relwidth = 2 / 200,
                                                  relheigh = 1)

    def __config_calendar(s):
        # cols = s._cal.formatweekheader(3).split()
        cols = ['日', '一', '二', '三', '四', '五', '六']
        s._calendar['columns'] = cols
        s._calendar.tag_configure('header', background = 'grey90')
        s._calendar.insert('', 'end', values = cols, tag = 'header')
        # 调整其列宽
        font = tkFont.Font()
        maxwidth = max(font.measure(col) for col in cols)
        for col in cols:
            s._calendar.column(col, width = maxwidth, minwidth = maxwidth,
                               anchor = 'center')

    def __setup_selection(s, sel_bg, sel_fg):
        def __canvas_forget(evt):
            canvas.place_forget()
            s._selection = None

        s._font = tkFont.Font()
        s._canvas = canvas = tk.Canvas(s._calendar, background = sel_bg, borderwidth = 0, highlightthickness = 0)
        canvas.text = canvas.create_text(0, 0, fill = sel_fg, anchor = 'w')

        canvas.bind('<Button-1>', __canvas_forget)
        s._calendar.bind('<Configure>', __canvas_forget)
        s._calendar.bind('<Button-1>', s._pressed)

    def _build_calendar(s):
        year, month = s._date.year, s._date.month

        # update header text (Month, YEAR)
        header = s._cal.formatmonthname(year, month, 0)

        # 更新日历显示的日期
        cal = s._cal.monthdayscalendar(year, month)
        for indx, item in enumerate(s._items):
            week = cal[indx] if indx < len(cal) else []
            fmt_week = [('%02d' % day) if day else '' for day in week]
            s._calendar.item(item, values = fmt_week)

    def _show_select(s, text, bbox):
        """为新的选择配置画布。"""
        x, y, width, height = bbox

        textw = s._font.measure(text)

        canvas = s._canvas
        canvas.configure(width = width, height = height)
        canvas.coords(canvas.text, (width - textw) / 2, height / 2 - 1)
        canvas.itemconfigure(canvas.text, text = text)
        canvas.place(in_ = s._calendar, x = x, y = y)

    def _pressed(s, evt=None, item=None, column=None, widget=None):
        """在日历的某个地方点击。"""
        if not item:
            x, y, widget = evt.x, evt.y, evt.widget
            item = widget.identify_row(y)
            column = widget.identify_column(x)

        if not column or not item in s._items:
            # 在工作日行中单击或仅在列外单击。
            return

        item_values = widget.item(item)['values']
        if not len(item_values):  # 这个月的行是空的。
            return

        text = item_values[int(column[1]) - 1]
        if not text:  # 日期为空
            return

        bbox = widget.bbox(item, column)
        if not bbox:  # 日历尚不可见
            s.master.after(20, lambda: s._pressed(item = item, column = column, widget = widget))
            return

        # 更新,然后显示选择
        text = '%02d' % text
        s._selection = (text, item, column)
        s._show_select(text, bbox)

    def _prev_month(s):
        """更新日历以显示前一个月。"""
        s._canvas.place_forget()
        s._selection = None

        s._date = s._date - timedelta(days = 1)
        s._date = datetime(s._date.year, s._date.month, 1)
        s.CB_year.set(s._date.year)
        s.CB_month.set(s._date.month)
        s._update()

    def _next_month(s):
        """更新日历以显示下一个月。"""
        s._canvas.place_forget()
        s._selection = None

        year, month = s._date.year, s._date.month
        s._date = s._date + timedelta(
            days = calendar.monthrange(year, month)[1] + 1)
        s._date = datetime(s._date.year, s._date.month, 1)
        s.CB_year.set(s._date.year)
        s.CB_month.set(s._date.month)
        s._update()

    def _update(s, event=None, key=None):
        """刷新界面"""
        if key and event.keysym != 'Return': return
        year = int(s.CB_year.get())
        month = int(s.CB_month.get())
        if year == 0 or year > 9999: return
        s._canvas.place_forget()
        s._date = datetime(year, month, 1)
        s._build_calendar()  # 重建日历

        if year == datetime.now().year and month == datetime.now().month:
            day = datetime.now().day
            for _item, day_list in enumerate(s._cal.monthdayscalendar(year, month)):
                if day in day_list:
                    item = 'I00' + str(_item + 2)
                    column = '#' + str(day_list.index(day) + 1)
                    s.master.after(100, lambda: s._pressed(item = item, column = column, widget = s._calendar))

    def _exit(s, confirm=False):
        """退出窗口"""
        if not confirm: s._selection = None
        s.master.destroy()

    def _main_judge(s):
        """判断窗口是否在最顶层"""
        try:
            # s.master 为 TK 窗口
            # if not s.master.focus_displayof(): s._exit()
            # else: s.master.after(10, s._main_judge)

            # s.master 为 toplevel 窗口
            if s.master.focus_displayof() == None or 'toplevel' not in str(s.master.focus_displayof()):
                s._exit()
            else:
                s.master.after(10, s._main_judge)
        except:
            s.master.after(10, s._main_judge)

        # s.master.tk_focusFollowsMouse() # 焦点跟随鼠标

    def selection(s):
        """返回表示当前选定日期的日期时间。"""
        if not s._selection: return None

        year, month = s._date.year, s._date.month
        return str(datetime(year, month, int(s._selection[0])))[:10]

    def Input_judgment(s, content):
        """输入判断"""
        # 如果不加上==""的话,就会发现删不完。总会剩下一个数字
        if content.isdigit() or content == "":
            return True
        else:
            return False



def modifyFileTime(filePath, createTime, modifyTime, accessTime, offset):
    """
    用来修改任意文件的相关时间属性,时间格式:YYYY-MM-DD HH:MM:SS 例如:2019-02-02 00:01:02
    :param filePath: 文件路径名
    :param createTime: 创建时间
    :param modifyTime: 修改时间
    :param accessTime: 访问时间
    :param offset: 时间偏移的秒数,tuple格式,顺序和参数时间对应
    """
    try:
        format = "%Y-%m-%d %H:%M:%S"  # 时间格式
        cTime_t = timeOffsetAndStruct(createTime, format, offset[0])
        mTime_t = timeOffsetAndStruct(modifyTime, format, offset[1])
        aTime_t = timeOffsetAndStruct(accessTime, format, offset[2])

        fh = CreateFile(filePath, GENERIC_READ | GENERIC_WRITE, 0, None, OPEN_EXISTING, 0, 0)
        createTimes, accessTimes, modifyTimes = GetFileTime(fh)

        createTimes = Time(time.mktime(cTime_t))
        accessTimes = Time(time.mktime(aTime_t))
        modifyTimes = Time(time.mktime(mTime_t))

        SetFileTime(fh, createTimes, accessTimes, modifyTimes)
        CloseHandle(fh)

        timeArray = time.strptime(modifyTime, "%Y-%m-%d %H:%M:%S")
        timeStamp = int(time.mktime(timeArray))
        setmtime(filePath, timeStamp)

        return 0
    except:
        return 1


def timeOffsetAndStruct(times, format, offset):
    """
    调用 localtime 将输入的时间转换为固定格式
    :param times: 输入的时间
    :param format: 时间格式
    :param offset: 时间偏移的秒数,tuple格式,顺序和参数时间对应
    :return: 秒
    time.strptime(times, format)将timec转换为time
    """
    return time.localtime(time.mktime(time.strptime(times, format)) + offset)

def selectFile():
    global geturl
    filepath = askopenfilename()  # 选择打开什么文件,返回文件名
    print(filepath)
    filename.set(filepath)  # 设置变量filename的值
    geturl = filepath


def cpri():
    global getTime
    Sec = str(random.randint(0,60)).rjust(2,'0')
    getTime = (f"{str(date.get()) } {str(hour.get())}:{str(minute.get())}:{Sec}")
    print(f"{str(date.get()) } {str(hour.get())}:{str(minute.get())}:{Sec}")
def uptiem():
    global geturl,getTime
    # print(f'url:{geturl},time{getTime}')
    cpri()
    try:
        aTime = getTime  # 创建时间
        mTime = getTime
        cTime = getTime
        fName = geturl  # 文件路径,文件存在才能成功(可以写绝对路径,也可以写相对路径)

        offset = (0, 1, 2)  # 偏移的秒数(不知道干啥的)

        # 调用函数修改文件创建时间,并判断是否修改成功
        r = modifyFileTime(fName, cTime, mTime, aTime, offset)
        if r == 0:
            print('修改完成')
            tk.messagebox.showinfo("提示", '修改完成')
        elif r == 1:
            print('修改失败')
            tk.messagebox.showinfo("提示", '修改完成')
    except:
        tk.messagebox.showinfo("提示", '请选取完整的时间和路径')
if __name__ == '__main__':
    root = Tk()
    filename = StringVar()
    root.title("timeup")
    root.attributes("-alpha",0.9)
    root.minsize(375,65)
    root.maxsize(375,65)
    # frm = ttk.Frame(root, padding = 10)
    # frm.grid()
    width, height = root.winfo_reqwidth() + 170,100  # 窗口大小
    x, y = (root.winfo_screenwidth() - width) / 2, (root.winfo_screenheight() - height) / 2
    root.geometry('%dx%d+%d+%d' % (width, height, x, y))  # 窗口位置居中
    # root.iconbitmap("favicon.ico")


    date_str = tk.StringVar()
    date = ttk.Entry(root, textvariable = date_str, width = 10,state='disabled')
    date.grid(row = 2, column = 1)


    """选择日期模块"""
    # Calendar((x, y), 'ur').selection() 获取日期,x,y为点坐标
    date_str_gain = lambda: [
        date_str.set(date)
        for date in [Calendar((x, y), 'ur').selection()]
        if date]
    ttk.Button(root, text = '日  期', command = date_str_gain).grid(row = 2, column = 0)

    """选择时间模块"""
    values_h = ["00", "01", "02", "03", "04", "05", "06", "07", "08", "09", 10, 11, 12, 13, 14, 15, 16, 17, 18, 19,
                20, 21, 22, 23]
    values_m = ["00", "01", "02", "03", "04", "05", "06", "07", "08", "09", 10, 11, 12, 13, 14, 15, 16, 17, 18, 19,
                20, 21, 22, 23, 24, 25, 26, 27, 28,
                29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53,
                54,55, 56, 57, 58, 59]

    hour = ttk.Combobox(
        master = root,  # 父容器
        height = 15,  # 高度,下拉显示的条目数量
        width = 3,  # 宽度
        state = "readonly",  # 设置状态 normal(可选可输入)、readonly(只可选)、 disabled
        cursor = "arrow",  # 鼠标移动时样式 arrow, circle, cross, plus...
        # font = ("", 20),  # 字体
        values = values_h,  # 设置下拉框的选项
    )
    hour.grid(row = 2, column = 3)
    ttk.Label(root, text = "时").grid(row = 2, column = 4)
    minute = ttk.Combobox(
        master = root,  # 父容器

        height = 15,  # 高度,下拉显示的条目数量
        width = 3,  # 宽度
        state = "readonly",  # 设置状态 normal(可选可输入)、readonly(只可选)、 disabled
        cursor = "arrow",  # 鼠标移动时样式 arrow, circle, cross, plus...
        # font = ("", 20),  # 字体
        values = values_m,  # 设置下拉框的选项
    )
    minute.grid(row = 2, column = 5, padx = 0, pady = 0)
    ttk.Label(root, text = "分").grid(row = 2, column = 6, padx = 0, pady = 0)


    '''
    选择文件模块
    '''
    # 构建“选择文件”这一行的标签、输入框以及启动按钮,同时我们希望当用户选择图片之后能够显示原图的基本信息
    # ttk.Label(root, text = '选择文件').grid(row = 4, column = 0, padx = 5, pady = 5)
    # lf  = LabelFrame(root,text='disable')
    ttk.Entry(root,textvariable = filename ,state=tk.DISABLED, width = 30).grid(row = 4, column = 1,columnspan = 6,sticky = 'e')
    ttk.Button(root, text = '打开文件', command = selectFile).grid(row = 4, column = 0, padx = 5, pady = 5)
    # ttk.Button(root, text = "确认时间", command = cpri).grid
    # ttk.Button(root, text = "退出", command = root.destroy).grid(row = 5,column = 0)
    tk.Button(root, text = "修改", command = uptiem,height = 2,width = 5).grid(row = 2,column =7,rowspan = 3 , padx='4px', pady='5px')



    # 需要自己配置
    # cTime = "2019-12-13 21:51:02"  # 创建时间
    # mTime = "2019-02-02 00:01:03"  # 修改时间
    # aTime = "2019-02-02 00:01:04"  # 访问时间
    # fName = r"log/2023-03-08/23-29-25.txt"  # 文件路径,文件存在才能成功(可以写绝对路径,也可以写相对路径)
    # offset = (0, 1, 2)  # 偏移的秒数(不知道干啥的)

    root.mainloop()
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 213,992评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,212评论 3 388
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 159,535评论 0 349
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,197评论 1 287
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,310评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,383评论 1 292
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,409评论 3 412
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,191评论 0 269
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,621评论 1 306
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,910评论 2 328
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,084评论 1 342
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,763评论 4 337
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,403评论 3 322
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,083评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,318评论 1 267
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,946评论 2 365
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,967评论 2 351

推荐阅读更多精彩内容