Python имеет дело с датами и временем - PullRequest
4 голосов
/ 31 марта 2010

Я ищу решение для следующего:

Учитывая сегодняшнюю дату, выясните, какой месяц был раньше. Таким образом, 2 должно вернуться на сегодня, так как это уже март, третий месяц года. 12 должно вернуться на январь.

Затем, исходя из этого, мне нужно иметь возможность перебирать каталог и находить все файлы, созданные в этом месяце.

Бонусные баллы будут включать в себя поиск самого последнего файла, созданного за предыдущий месяц.

Ответы [ 5 ]

3 голосов
/ 31 марта 2010

Простейший, где adate - это экземпляр datetime.date:

def previousmonth(adate):
    m = adate.month - 1
    return m if m else 12

В большинстве файловых систем Unix нет реального способа определить, когда был создан файл, поскольку они просто не хранят эту информацию. Может быть, вы хотите «последнее время изменения инода» (может быть создание, может быть другое изменение инода):

import os, datetime
def cmonth(filename):
    ts = os.stat(filename).st_ctime
    return datetime.date.fromtimestamp(ts).month

Конечно, это может означать, что месяц в любом году - вы уверены, что в обоих вопросах вам не нужен год , а также месяц? Это будет атрибут .year.

В любом случае, придерживаясь только месяца, согласно вашему вопросу, для одного каталога (который является буквой вашего вопроса), чтобы получить все файлы, которые вы можете использовать os.listdir (для дерева, корни которого в каталоге, который вы используйте os.walk вместо). Затем сохранить только те из них, для которых в последнем месяце произошли последние изменения inode:

def fileswithcmonth(dirname, whatmonth):
    results = []
    for f in os.listdir(dirname):
        fullname = os.path.join(dirname, f)
        if whatmonth == cmonth(fullname):
            results.append(fullname)
    return results

Вы можете кодировать это как понимание списка, но там слишком много кода, чтобы listcomp был элегантным и лаконичным.

Чтобы получить «самое последнее» время, вы можете либо повторить вызов os.stat (медленнее, но, вероятно, проще), либо изменить cmonth, чтобы также вернуть отметку времени. По простому маршруту:

def filetimestamp(fullname):
    return os.stat(fullname).st_ctime

Теперь «самый последний файл», содержащий список files полных имен файлов (то есть, включая путь), равен

max(files, key=filetimestamp)

Конечно, есть много степеней свободы в том, как вы сложите все это вместе, в зависимости от ваших точных спецификаций - учитывая, что спецификации не кажутся обязательно точными или полными, я решил показать строительные блоки вы можете легко настроить и собрать все под свои нужды, а не полноценное решение, которое, скорее всего, решит проблему, несколько отличную от вашей реальной; -).

Редактировать : поскольку ОП пояснил, что им нужны и год, и месяц, давайте посмотрим, какие изменения потребуются, используя кортежи ym для (year, month) вместо чистого месяца:

def previousym(adate):
    y = adate.year
    m = adate.month - 1
    return (y, m) if m else (y - 1, 12)

import os, datetime
def cym(filename):
    ts = os.stat(filename).st_ctime
    dt datetime.date.fromtimestamp(ts)
    return cym.year, cym.month

def fileswithcym(dirname, whatym):
    results = []
    for f in os.listdir(dirname):
        fullname = os.path.join(dirname, f)
        # if you need to avoid subdirs, uncomment the following line
        # if not os.path.isfile(fullname): continue
        if whatym == cym(fullname):
            results.append(fullname)
    return results

Ничего глубокого или сложного, как вы можете видеть (я также добавил комментарии, чтобы показать, как пропускать подкаталоги, если вас это беспокоит). И, между прочим, если вам на самом деле нужно пройтись по поддереву, а не просто по каталогу, это изменение тоже довольно локализовано:

def fileswithcymintree(treeroot_dirname, whatym):
    results = []
    for dp, dirs, files in os.walk(treeroot_dirname):
        for f in files:
            fullname = os.path.join(dp, f)
            if whatym == cym(fullname):
                results.append(fullname)
    return results
2 голосов
/ 31 марта 2010

Довольно легко найти предыдущий месяц - см., Например, ответ Алекса Мартелли - но найти последний созданный файл в этом месяце немного сложнее:

from datetime import date
import os

def filesLastMonth(directory):
    """
    Given a directory, returns a tuple containing
    1. A list with all files made in the previous month (disregards year...)
    2. The file most recently created in the previous month
    """
    def fileCreationTime(filePath):
        return os.path.getctime(filePath)
    today = date.today()
    lastMonth = today.month-1 if today.month != 1 else 12
    # gets each item in the directory that was created last month
    createdLastMonth = [item for item in os.listdir(directory) if
                        date.fromtimestamp(os.path.getctime(item)).month == lastMonth]
    # and this is the most recent of the above
    mostRecentlyLastMonth = max(createdLastMonth, key=fileCreationTime)
    return (createdLastMonth, mostRecentlyLastMonth)

Вы можете использовать os.path.getctime в Windows , чтобы получить время создания пути, но это не работает в Unix - время создания в этом случае не сохраняется (вы просто получите время последнего изменения).

1 голос
/ 31 марта 2010

Здесь задают несколько частей ...

  • Вы можете получить текущий месяц, используя datetime следующим образом: datetime.datetime.now().month.Оттуда вы можете просто вычесть один и превратить 0 в 12. Python datetime doc: http://docs.python.org/library/datetime.html

  • Далее вы можете перебрать папку на диске, используя os.walk Python os.walk doc: http://docs.python.org/library/os.html#os.walk

  • Наконец, вы можете проверить время создания / изменения файла, используя os.stat Python os.stat doc: http://docs.python.org/library/os.html#os.stat

0 голосов
/ 01 апреля 2010

Манипулирование датами выполняется тривиально с помощью библиотеки, подобной python-dateutil от Labix.

Вы хотите сделать что-то вроде этого:

In [8]: from dateutil.relativedelta import relativedelta

In [9]: from datetime import date

In [10]: d = date(2010,2,12)

In [11]: print (d-relativedelta(months=1)).month
1

In [12]: print (date(2010,1,4)-relativedelta(months=1)).month
12
0 голосов
/ 31 марта 2010

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

Первое число за предыдущий месяц с даты

def first_of( today )
    yr_mn = today.year*12 + (today.month-1) - 1
    return datetime.date( year= yr_mn//12, month= yr_mn%12+1, day=1 )

Затем вы можете использовать это с os.walk, чтобы найти нужные файлы.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...