date python du mois précédent

132

J'essaye d'obtenir la date du mois précédent avec python. Voici ce que j'ai essayé:

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

Cependant, cette méthode est mauvaise pour 2 raisons: d'abord, elle renvoie 20122 pour le février de 2012 (au lieu de 201202) et deuxièmement, elle renvoie 0 au lieu de 12 en janvier.

J'ai résolu ce problème en bash avec

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

Je pense que si bash a un moyen intégré à cet effet, alors python, beaucoup plus équipé, devrait fournir quelque chose de mieux que de forcer l'écriture de son propre script pour atteindre cet objectif. Bien sûr, je pourrais faire quelque chose comme:

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)

Je n'ai pas testé ce code et je ne veux pas l'utiliser de toute façon (sauf si je ne trouve pas d'autre moyen: /)

Merci de votre aide!

Philippe
la source

Réponses:

300

datetime et les classes datetime.timedelta sont votre ami.

  1. trouver aujourd'hui.
  2. utilisez-le pour trouver le premier jour de ce mois.
  3. utilisez timedelta pour sauvegarder un seul jour, jusqu'au dernier jour du mois précédent.
  4. imprimez la chaîne AAAAMM que vous recherchez.

Comme ça:

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

201202 est imprimé.

bgporter
la source
31
vous pouvez utiliser la .replace()méthode:datetime.utcnow().replace(day=1) - timedelta(days=1)
jfs
1
Cool! J'ai raté la méthode de remplacement.
bgporter
Vous pouvez également chaîner la .replace()fonction. Faites-le une fois pour obtenir le dernier mois, puis recommencez pour obtenir le jour que vous voulez. Premièrement: d = date.today() puisone_month_ago = (d.replace(day=1) - timedelta(days=1)).replace(day=d.day)
Thane Plummer
@JFSebastian Vous avez raison - merci de l'avoir signalé. Il ne semble pas y avoir de one-liner élégant pour cela, car un «mois» n'est pas une période de temps constante. Vous pouvez faire quelque chose de laid en important calendaret en utilisant calendar.mdays[d.month-1]et plus de laideur dans une min()fonction dans le 2nd replace, mais cela semble non pythonique et ne tient pas compte des cas de coin. J'ai mis à jour ma réponse ci-dessous en utilisant try - exceptquels comptes pour tous les cas, bien que je déteste utiliser des exceptions dans le cadre d'un algorithme.
Thane Plummer
voir la réponse d'Ivan, et ajouter: min (date.today (). day, last_day_of_previous_month.day)
michel.iamit
70

Vous devez utiliser dateutil . Avec cela, vous pouvez utiliser relativedelta, c'est une version améliorée de 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
Dave Butler
la source
Cela ne fonctionne pas pour le premier mois de l'année: >>> IllegalMonthError: mauvais mois numéro -1; doit être 1-12
mtoloo
@mtoloo Quelle version de dateutil? Je n'ai pas ce problème, mais j'ajouterai une syntaxe alternative
Dave Butler
1
Je préfère celle-ci car bien que @bgporter ait une très bonne solution, la sienne ne fonctionne pas aussi bien pour la recherche du mois prochain.
Daniel F
3
@mtoloo Vous avez probablement mal tapé mois / mois
r_black
2
@r_black Oui, vous avez raison. C'était ma faute. La solution donnée ici est correcte et aucune autre vérification n'est nécessaire pour le premier mois de l'année.
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

Ou:

from datetime import date, timedelta

prev = date.today().replace(day=1) - timedelta(days=1)
print prev.month
Ivan
la source
une partie de la solution ... pour trouver le jour du mois dernier, ajoutez quelque chose comme ceci: day_previous_month = min (today.day, last_day_of_previous_month.day) pour éviter de dépasser le nombre de jours.
michel.iamit
9

S'appuyant sur la réponse de 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'))
paragbaxi
la source
5

C'est très facile et simple. Faire ça

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()

Voici la sortie: $ 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
Mahfuz
la source
4

Pour quelqu'un qui est arrivé ici et qui cherche à obtenir à la fois le premier et le dernier jour du mois précédent:

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)

Production:

First day of prev month: 2019-02-01
Last day of prev month: 2019-02-28
Robin Carlo Catacutan
la source
Si vous voulez connaître le début et la fin d'un mois (et plus), jetez un œil au Calendarmodule: stackabuse.com/introduction-to-the-python-calendar-module
toast38coza
Si nous voulons le début et la fin du deuxième mois précédent?
gamer
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))
Steve
la source
Pauses le 31 mars
Mike
1

Juste pour le plaisir, une réponse mathématique pure en utilisant divmod. Assez inefficace à cause de la multiplication, pourrait tout aussi bien faire un simple contrôle sur le nombre de mois (s'il est égal à 12, augmenter l'année, etc.)

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
Tiberiu Ichim
la source
1

Avec la librairie Pendulum très complète, nous avons la subtractméthode (et non "soustract"):

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

On voit qu'il gère des années sautantes.

L'équivalent inverse est add.

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

Ehvince
la source
0

En vous basant sur le commentaire de @JF Sebastian, vous pouvez enchaîner la replace()fonction pour remonter d'un "mois". Puisqu'un mois n'est pas une période de temps constante, cette solution essaie de revenir à la même date le mois précédent, ce qui bien sûr ne fonctionne pas pour tous les mois. Dans un tel cas, cet algorithme utilise par défaut le dernier jour du mois précédent.

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))

Production:

one_month_ago: 2012-02-29 00:00:00
Thane Plummer
la source
0

Si vous voulez regarder les lettres ASCII dans un fichier de type EXE dans un environnement LINUX / UNIX, essayez "od -c 'filename' | plus"

Vous obtiendrez probablement beaucoup d'éléments méconnaissables, mais ils seront tous présentés, et les représentations HEX seront affichées, et les caractères équivalents ASCII (le cas échéant) suivront la ligne de codes hexadécimaux. Essayez-le sur un morceau de code compilé que vous connaissez. Vous pourriez y voir des choses que vous reconnaissez.

Meule
la source
Pouvez-vous s'il vous plaît modifier ceci pour expliquer comment il répond à la question.
AdrianHHH
0

Il existe une bibliothèque de haut niveau dateparserqui peut déterminer la date passée en langage naturel et renvoyer l' datetimeobjet Python correspondant

from dateparser import parse
parse('4 months ago')
wesinat0r
la source