дата пітона попереднього місяця


131

Я намагаюся отримати дату попереднього місяця з python. Ось що я спробував:

str( time.strftime('%Y') ) + str( int(time.strftime('%m'))-1 )

Однак цей спосіб поганий з двох причин: по-перше, він повертає 20122 року за лютий 2012 року (замість 201202), а по-друге, він поверне 0 замість 12 січня.

Я вирішив цю проблему в баш

echo $(date -d"3 month ago" "+%G%m%d")

Я думаю, що якщо для bash є вбудований спосіб для цієї мети, то пітон, набагато більш оснащений, повинен забезпечити щось краще, ніж змушувати писати власний сценарій для досягнення цієї мети. Звичайно, я міг би зробити щось на кшталт:

if int(time.strftime('%m')) == 1:
    return '12'
else:
    if int(time.strftime('%m')) < 10:
        return '0'+str(time.strftime('%m')-1)
    else:
        return str(time.strftime('%m') -1)

Я не перевіряв цей код, і я не хочу його використовувати в будь-якому випадку (якщо тільки я не можу знайти інший спосіб: /)

Спасибі за вашу допомогу!


Відповіді:


299

datetime і class datetime.timedelta - ваш друг.

  1. знайдіть сьогодні.
  2. використовуйте це, щоб знайти перший день цього місяця.
  3. використовувати timedelta для резервного копіювання одного дня до останнього дня попереднього місяця.
  4. надрукуйте рядок YYYYMM, яку ви шукаєте.

Подобається це:

 import datetime
 today = datetime.date.today()
 first = today.replace(day=1)
 lastMonth = first - datetime.timedelta(days=1)
 print(lastMonth.strftime("%Y%m"))

201202 друкується.


31
ви можете скористатися .replace()методом:datetime.utcnow().replace(day=1) - timedelta(days=1)
jfs

1
Класно! Я пропустив метод заміни.
bgporter

Ви також можете ланцюг .replace()функції. Зробіть це один раз, щоб отримати останній місяць, а потім зробіть це знову, щоб отримати бажаний день. Спочатку: d = date.today() потімone_month_ago = (d.replace(day=1) - timedelta(days=1)).replace(day=d.day)
Thane Plummer

@JFSebastian Ви маєте рацію - дякую, що вказали на це. Здається, не існує елегантного однолінійного для цього, оскільки "місяць" не є постійним періодом часу. Ви можете зробити щось потворне, імпортуючи calendarта використовуючи, calendar.mdays[d.month-1]і більше неподобства у min()функції у другому replace, але це здається непітонічним і не враховує кутових випадків. Я оновив свою відповідь нижче, використовуючи, try - exceptякі облікові записи для всіх випадків, хоча я ненавиджу винятки як частину алгоритму.
Thane Plummer

дивіться відповідь Івана, і додайте: хв (дата.today (). день, останній день_обіг_превізора_місяця.день)
michel.iamit

70

Вам слід скористатись датою . З цим ви можете використовувати Reladelta, це вдосконалена версія timedelta.

>>> import datetime 
>>> import dateutil.relativedelta
>>> now = datetime.datetime.now()
>>> print now
2012-03-15 12:33:04.281248
>>> print now + dateutil.relativedelta.relativedelta(months=-1)
2012-02-15 12:33:04.281248

Він не працює перший місяць року: >>> IllegalMonthError: неправильний номер місяця -1; повинно бути 1-12
mtoloo

@mtoloo Яка версія dateutil? У мене цього питання немає, але я додам альтернативний синтаксис
Дейв Батлер

1
Я вважаю за краще це, оскільки, хоча у @bgporter є дуже приємне рішення, його не так добре, щоб шукати наступного місяця.
Даніель Ф

3
@mtoloo Ви, ймовірно, неправильно вводили місяці / місяць
r_black

2
@r_black Так, ти маєш рацію. Це була моя вина. Наведене тут рішення є правильним і не потрібно більше перевіряти протягом першого місяця року.
mtoloo

45
from datetime import date, timedelta

first_day_of_current_month = date.today().replace(day=1)
last_day_of_previous_month = first_day_of_current_month - timedelta(days=1)

print "Previous month:", last_day_of_previous_month.month

Або:

from datetime import date, timedelta

prev = date.today().replace(day=1) - timedelta(days=1)
print prev.month

частину рішення ... щоб знайти день минулого місяця, додайте щось подібне: day_previous_month = min (today.day, last_day_of_previous_month.day), щоб уникнути перевищення кількості днів.
michel.iamit

9

Спираючись на відповідь bgporter .

def prev_month_range(when = None): 
    """Return (previous month's start date, previous month's end date)."""
    if not when:
        # Default to today.
        when = datetime.datetime.today()
    # Find previous month: https://stackoverflow.com/a/9725093/564514
    # Find today.
    first = datetime.date(day=1, month=when.month, year=when.year)
    # Use that to find the first day of this month.
    prev_month_end = first - datetime.timedelta(days=1)
    prev_month_start = datetime.date(day=1, month= prev_month_end.month, year= prev_month_end.year)
    # Return previous month's start and end dates in YY-MM-DD format.
    return (prev_month_start.strftime('%Y-%m-%d'), prev_month_end.strftime('%Y-%m-%d'))

5

Це дуже легко і просто. Зробити це

from dateutil.relativedelta import relativedelta
from datetime import datetime

today_date = datetime.today()
print "todays date time: %s" %today_date

one_month_ago = today_date - relativedelta(months=1)
print "one month ago date time: %s" % one_month_ago
print "one month ago date: %s" % one_month_ago.date()

Ось вихід: $ python2.7 main.py

todays date time: 2016-09-06 02:13:01.937121
one month ago date time: 2016-08-06 02:13:01.937121
one month ago date: 2016-08-06

4

Для того, хто потрапив сюди і хотів отримати перший і останній день попереднього місяця:

from datetime import date, timedelta

last_day_of_prev_month = date.today().replace(day=1) - timedelta(days=1)

start_day_of_prev_month = date.today().replace(day=1) - timedelta(days=last_day_of_prev_month.day)

# For printing results
print("First day of prev month:", start_day_of_prev_month)
print("Last day of prev month:", last_day_of_prev_month)

Вихід:

First day of prev month: 2019-02-01
Last day of prev month: 2019-02-28

Якщо ви хочете отримати початок і кінець місяця (і більше), перегляньте Calendarмодуль: stackabuse.com/introduction-to-the-python-calendar-module
toast38coza

Якщо ми хочемо почати та закінчити другий попередній місяць?
геймер

3
def prev_month(date=datetime.datetime.today()):
    if date.month == 1:
        return date.replace(month=12,year=date.year-1)
    else:
        try:
            return date.replace(month=date.month-1)
        except ValueError:
            return prev_month(date=date.replace(day=date.day-1))

Перерви 31 березня
Майк

1

Просто для розваги, чисто математичний відповідь, використовуючи divmod. Досить невмілий через множення може зробити так само просту перевірку кількості місяця (якщо дорівнює 12, рік збільшення тощо)

year = today.year
month = today.month

nm = list(divmod(year * 12 + month + 1, 12))
if nm[1] == 0:
    nm[1] = 12
    nm[0] -= 1
pm = list(divmod(year * 12 + month - 1, 12))
if pm[1] == 0:
    pm[1] = 12
    pm[0] -= 1

next_month = nm
previous_month = pm

1

Маючи маятник, що має дуже повну бібліотеку, у нас є subtractметод (а не "subStract"):

import pendulum
today = pendulum.datetime.today()  # 2020, january
lastmonth = today.subtract(months=1)
lastmonth.strftime('%Y%m')
# '201912'

Ми бачимо, що вона справляється зі стрибками років.

Зворотний еквівалент дорівнює add.

https://pendulum.eustace.io/docs/#addition-and-subtraction


0

Відштовхуючись від коментаря @JF Себастьяна, ви можете зв'язати replace()функцію, щоб повернутися на один "місяць". Оскільки місяць не є постійним періодом часу, це рішення намагається повернутися до тієї ж дати попереднього місяця, що, звичайно, працює не всі місяці. У такому випадку цей алгоритм за замовчуванням відповідає останньому дню попереднього місяця.

from datetime import datetime, timedelta

d = datetime(2012, 3, 31) # A problem date as an example

# last day of last month
one_month_ago = (d.replace(day=1) - timedelta(days=1))
try:
    # try to go back to same day last month
    one_month_ago = one_month_ago.replace(day=d.day)
except ValueError:
    pass
print("one_month_ago: {0}".format(one_month_ago))

Вихід:

one_month_ago: 2012-02-29 00:00:00

0

Якщо ви хочете переглянути літери ASCII у файлі типу EXE у середовищі LINUX / UNIX, спробуйте "od -c 'ім'я файлу" | більше "

Ви, ймовірно, отримаєте багато невпізнаваних елементів, але вони будуть представлені всі, і відображатимуться HEX-представлення, а ASCII-еквівалентні символи (якщо потрібно) будуть слідувати рядку шістнадцяткових кодів. Спробуйте його на складеному фрагменті коду, який ви знаєте. Ви можете побачити речі, які ви впізнаєте.


Чи можете ви відредагувати це, щоб пояснити, як він відповідає на запитання.
AdrianHHH

0

Існує бібліотека високого рівня, dateparserяка може визначити минулу дату природного мовою та повернути відповідний datetimeоб’єкт Python

from dateparser import parse
parse('4 months ago')
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.