class datetime.timedelta 是如何工作的?

0 投票
3 回答
1574 浏览
提问于 2025-04-18 16:09

我正在写一个Python脚本,用来删除文件夹里超过x个月的文件。

我可以很容易地删除超过一年的文件。 我也能处理两个值,x(一个文件)和y(一个月数),如果x的年龄超过y个月,就删除它,前提是它们在同一个日历年里。

我遇到的问题是,当年份从一个变到另一个时,如果文件x的年龄还不到y个月,就不应该删除它。比如说,如果现在是2014年1月,而文件是在2013年12月创建的,那就不应该删除;但如果现在是2014年1月,而文件是在2013年3月修改的,那就应该删除。

我试着根据月份的数字来想出一个解决方案(1月=01,等等),但我搞不定。我发现可以使用datetime.timedelta这个类来表示两个日期之间的差异。我想从头开始编写这个代码,或者至少想看看它是怎么工作的。我在Python文档里找不到关于datetime.timedelta类的代码。我想学习如何解决这个问题,而不是依赖一个我不理解的内置类。有没有人能帮我理解这个?

import os
import time
import math

def main():

    path = '/home/gabriel/Documents/bookmarks/'
    months = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec']

    for root, dirs, files in os.walk(path):
        print "root:", root
        print "dirs:", dirs
        print "files:"

        for f in files:
            mtime = "%s" % time.ctime(os.path.getmtime('%s%s' % (path,f)))
            print "\tlast modified: %s %s" % (mtime, f)
            weekDay, month, day, HMS, year = mtime.split()
            if int(time.strftime("%Y")) - int(year) > 1:
                print "\t... deleting %s" % f
                os.remove('%s%s' % (path,f))
            # elif int(time.strftime("%Y")) - int(year) == 1 & :
            # after the & in the elif expression above is what I cannot figure out. 

            elif abs((months.index(month) + 1)-(int(time.strftime("%m")))) > 4:
                print "\t... deleting %s" % f
                os.remove('%s%s' % (path,f))



main()

3 个回答

0

如果你真的想知道 timedelta 是怎么实现的,可以去找一下 Python 库源代码里的 class timedeltahttp://hg.python.org/cpython/file/tip/Lib/datetime.py

如果这就是你想了解的内容,我建议你修改一下你的提问,把那些不相关的内容(比如源代码和关于删除旧文件的文字)去掉。

0

最简单的方法就是不使用时间差(timedelta)。直接把你的时间戳和现在的时间进行比较就可以了:

tseconds = time.time() - os.path.getmtime(...)

这样你就能得到自上次修改以来经过的时间,单位是秒。因为你讨论的是几个月的时间,我想你并不太在意文件是2013年2月1日修改的,还是1月31日修改的:虽然它们属于不同的月份,但无论如何都应该被删除。

如果你真的想使用时间差(timedelta),可以用那个秒数来构造它:

tdelta = datetime.timedelta(seconds=tseconds)

不过这样做并不会自动给你月份的计算。再说了,你处理的是较大的时间范围,可以假设每个月都有31天,这样就比较安全了。

1

timedelta 是用来表示一段时间的,或者说是两个时间点之间的差距。它的单位包括天、秒和微秒。

在创建 timedelta 时,你还可以使用其他单位,比如周、小时等等。不过,这里面有一些数学运算需要把这些单位统一成简单的、固定的单位。除了这些,它基本上就是一个有单位的数值。

在处理日期和时间时,计算两个日期的差或者把 timedelta 加到日期上其实也很简单。关键是要明白 timedelta 只记录天数,不记录月或年。日期的计算是基于一个整数值,这个值从公元1年1月1日开始,表示的是天数。然后还会对秒、微秒和时区差异进行一些调整。

简单来说,计算日期时其实并不涉及月份。

现在,我们来聊聊如何减去月份。假设一个月是31天,这样做在删除备份的时候可能还行。比如 datetime.now() - timedelta(days=31),这样就完成了,前提是没有时区的问题。

不过,从长远来看,假设每个月都是31天的话,结果会变成372天一年。

所以如果你想减去“真实”的月份,就需要查一下每个月的天数,然后逐个减去。但是你是减去当前月份的天数,还是上一个月的天数呢?从长远来看,这个差别基本上会抵消掉。

撰写回答