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!


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é.


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

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

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

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

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

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

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


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

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.


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')
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.