Obtenez le dernier jour du mois en Python

est-il possible d'utiliser la bibliothèque standard de Python pour déterminer facilement (i.e. un appel de fonction) le dernier jour d'un mois donné?

si la bibliothèque standard ne supporte pas cela, est-ce que le paquet dateutil supporte cela?

453
demandé sur Cristian 2008-09-04 04:54:44

24 réponses

Je ne l'ai pas remarqué plus tôt lorsque je regardais la documentation pour le module de calendrier , mais une méthode appelée monthrange fournit cette information:

monthrange(Année, Mois)

    Retourne la semaine du premier jour du mois et le nombre de jours dans le mois, l'année et le mois.

>>> import calendar
>>> calendar.monthrange(2002,1)
(1, 31)
>>> calendar.monthrange(2008,2)
(4, 29)
>>> calendar.monthrange(2100,2)
(0, 28)

:

calendar.monthrange(year, month)[1]

semble être la façon la plus simple de partir.

Juste pour être clair, monthrange prend en charge les années bissextiles ainsi:

>>> from calendar import monthrange
>>> monthrange(2012, 2)
(2, 29)

Ma réponse précédente fonctionne toujours, mais est clairement insuffisante.

824
répondu Blair Conrad 2017-05-23 12:03:09

si vous ne voulez pas importer le module calendar , une simple fonction en deux étapes peut aussi être:

import datetime

def last_day_of_month(any_day):
    next_month = any_day.replace(day=28) + datetime.timedelta(days=4)  # this will never fail
    return next_month - datetime.timedelta(days=next_month.day)

sorties:

>>> for month in range(1, 13):
...     print last_day_of_month(datetime.date(2012, month, 1))
...
2012-01-31
2012-02-29
2012-03-31
2012-04-30
2012-05-31
2012-06-30
2012-07-31
2012-08-31
2012-09-30
2012-10-31
2012-11-30
2012-12-31
92
répondu Augusto Men 2012-11-26 12:48:40

EDIT: voir la réponse de @Blair Conrad pour une solution plus propre


>>> import datetime
>>> datetime.date (2000, 2, 1) - datetime.timedelta (days = 1)
datetime.date(2000, 1, 31)
>>> 
59
répondu John Millikin 2008-09-05 00:36:04

EDIT: voir mon autre réponse . Il a une meilleure implémentation que celui-ci, que je laisse ici juste au cas où quelqu'un serait intéressé à voir comment on pourrait "lancer sa propre calculatrice".

@John Millikin donne une bonne réponse, avec la complication supplémentaire de calculer le premier jour du mois suivant.

ce qui suit n'est pas particulièrement élégant, mais pour comprendre le dernier jour du mois qu'une date donnée vit dans, vous pouvez essayer:

def last_day_of_month(date):
    if date.month == 12:
        return date.replace(day=31)
    return date.replace(month=date.month+1, day=1) - datetime.timedelta(days=1)

>>> last_day_of_month(datetime.date(2002, 1, 17))
datetime.date(2002, 1, 31)
>>> last_day_of_month(datetime.date(2002, 12, 9))
datetime.date(2002, 12, 31)
>>> last_day_of_month(datetime.date(2008, 2, 14))
datetime.date(2008, 2, 29)
37
répondu Blair Conrad 2008-09-05 19:44:55

c'est en fait assez facile avec dateutil.relativedelta (paquet python-datetutil pour pip). day=31 sera toujours toujours le dernier jour du mois.

exemple:

from datetime import datetime
from dateutil.relativedelta import relativedelta

date_in_feb = datetime.datetime(2013, 2, 21)
print datetime.datetime(2013, 2, 21) + relativedelta(day=31)  # End-of-month
>>> datetime.datetime(2013, 2, 28, 0, 0)
31
répondu Vince Spicer 2015-08-24 12:46:19

en utilisant relativedelta vous obtiendriez la dernière date du mois comme ceci:

from dateutil.relativedelta import relativedelta
last_date_of_month = datetime(mydate.year,mydate.month,1)+relativedelta(months=1,days=-1)

l'idée est d'obtenir le premier jour du mois et utiliser relativedelta pour aller 1 mois en avant et 1 jour en arrière de sorte que vous obtiendriez le dernier jour du mois que vous vouliez.

12
répondu Satish Reddy 2016-06-01 19:44:51

une autre solution serait de faire quelque chose comme ceci:

from datetime import datetime

def last_day_of_month(year, month):
    """ Work out the last day of the month """
    last_days = [31, 30, 29, 28, 27]
    for i in last_days:
        try:
            end = datetime(year, month, i)
        except ValueError:
            continue
        else:
            return end.date()
    return None

et utilisez la fonction comme ceci:

>>> 
>>> last_day_of_month(2008, 2)
datetime.date(2008, 2, 29)
>>> last_day_of_month(2009, 2)
datetime.date(2009, 2, 28)
>>> last_day_of_month(2008, 11)
datetime.date(2008, 11, 30)
>>> last_day_of_month(2008, 12)
datetime.date(2008, 12, 31)
11
répondu Ulf Gjerdingen 2016-06-01 20:04:48
from datetime import timedelta
(any_day.replace(day=1) + timedelta(days=32)).replace(day=1) - timedelta(days=1)
9
répondu Collin Anderson 2014-09-03 12:44:07
>>> import datetime
>>> import calendar
>>> date  = datetime.datetime.now()

>>> print date
2015-03-06 01:25:14.939574

>>> print date.replace(day = 1)
2015-03-01 01:25:14.939574

>>> print date.replace(day = calendar.monthrange(date.year, date.month)[1])
2015-03-31 01:25:14.939574
8
répondu Vatsal 2015-03-05 20:02:18
import datetime

now = datetime.datetime.now()
start_month = datetime.datetime(now.year, now.month, 1)
date_on_next_month = start_month + datetime.timedelta(35)
start_next_month = datetime.datetime(date_on_next_month.year, date_on_next_month.month, 1)
last_day_month = start_next_month - datetime.timedelta(1)
5
répondu Анатолий Панин 2013-06-16 16:57:32

si vous êtes prêt à utiliser une bibliothèque externe, consultez http://crsmithdev.com/arrow /

U peut alors obtenir le dernier jour du mois:

import arrow
arrow.utcnow().ceil('month').date()

renvoie un objet date que vous pouvez ensuite manipuler.

5
répondu Blake 2016-11-27 10:01:06

pour obtenir la dernière date du mois nous faisons quelque chose comme ceci:

from datetime import date, timedelta
import calendar
last_day = date.today().replace(day=calendar.monthrange(date.today().year, date.today().month)[1])

Maintenant, pour expliquer ce que nous faisons ici, nous allons diviser en deux parties:

la première est d'obtenir le nombre de jours du mois en cours pour lequel nous utilisons monthrange que Blair Conrad a déjà mentionné sa solution:

calendar.monthrange(date.today().year, date.today().month)[1]

deuxième est d'obtenir la dernière date elle-même que nous faisons avec l'aide de remplacer E. g

>>> date.today()
datetime.date(2017, 1, 3)
>>> date.today().replace(day=31)
datetime.date(2017, 1, 31)

et quand nous les combiner comme mentionné sur le dessus, nous obtenons une solution dynamique.

4
répondu Siddharth K 2017-01-03 09:54:54

pour moi, c'est la manière la plus simple:

selected_date = date(some_year, some_month, some_day)

if selected_date.month == 12: # December
     last_day_selected_month = date(selected_date.year, selected_date.month, 31)
else:
     last_day_selected_month = date(selected_date.year, selected_date.month + 1, 1) - timedelta(days=1)
3
répondu KravAn 2014-07-30 15:29:08

la façon La plus simple (sans avoir à importer l'agenda), est d'obtenir le premier jour du mois suivant, puis de soustraire un jour.

import datetime as dt
from dateutil.relativedelta import relativedelta

thisDate = dt.datetime(2017, 11, 17)

last_day_of_the_month = dt.datetime(thisDate.year, (thisDate + relativedelta(months=1)).month, 1) - dt.timedelta(days=1)
print last_day_of_the_month

sortie:

datetime.datetime(2017, 11, 30, 0, 0)

PS: ce code court plus vite que l'approche import calendar ; voir ci-dessous:

import datetime as dt
import calendar
from dateutil.relativedelta import relativedelta

someDates = [dt.datetime.today() - dt.timedelta(days=x) for x in range(0, 10000)]

start1 = dt.datetime.now()
for thisDate in someDates:
    lastDay = dt.datetime(thisDate.year, (thisDate + relativedelta(months=1)).month, 1) - dt.timedelta(days=1)

print ('Time Spent= ', dt.datetime.now() - start1)


start2 = dt.datetime.now()
for thisDate in someDates:
    lastDay = dt.datetime(thisDate.year, 
                          thisDate.month, 
                          calendar.monthrange(thisDate.year, thisDate.month)[1])

print ('Time Spent= ', dt.datetime.now() - start2)

sortie:

Time Spent=  0:00:00.097814
Time Spent=  0:00:00.109791

ce code suppose que vous voulez date du dernier jour du mois (c.-à-d. pas seulement la partie JJ, mais la date AAAA entière)

3
répondu Vishal 2017-11-28 19:39:53

vous pouvez calculer la date de fin vous-même. la simple logique est de soustraire un jour de la date_debut du mois prochain. :)

donc écrire une méthode personnalisée,

import datetime

def end_date_of_a_month(date):


    start_date_of_this_month = date.replace(day=1)

    month = start_date_of_this_month.month
    year = start_date_of_this_month.year
    if month == 12:
        month = 1
        year += 1
    else:
        month += 1
    next_month_start_date = start_date_of_this_month.replace(month=month, year=year)

    this_month_end_date = next_month_start_date - datetime.timedelta(days=1)
    return this_month_end_date

appel,

end_date_of_a_month(datetime.datetime.now().date())

il retournera la date de fin de ce mois. Passez n'importe quelle date à cette fonction. renvoie la date de fin du mois.

2
répondu Vipul Vishnu av 2016-09-02 08:47:11

cela ne répond pas à la question principale, mais une belle astuce pour obtenir le dernier en semaine dans un mois est d'utiliser calendar.monthcalendar , qui renvoie une matrice de dates, organisé avec le lundi comme la première colonne à travers le dimanche comme la dernière.

# Some random date.
some_date = datetime.date(2012, 5, 23)

# Get last weekday
last_weekday = np.asarray(calendar.monthcalendar(some_date.year, some_date.month))[:,0:-2].ravel().max()

print last_weekday
31

tout le truc [0:-2] c'est de raser les colonnes de week-end et de les jeter. Les Dates qui tombent en dehors du mois sont indiquées par 0, de sorte que le max les ignore effectivement.

l'utilisation de numpy.ravel n'est pas strictement nécessaire, mais je déteste compter sur la simple convention que numpy.ndarray.max aplatira le tableau si on ne dit pas sur quel axe calculer.

1
répondu ely 2012-11-14 20:06:26

utilisez pandas!

def isMonthEnd(date):
    return date + pd.offsets.MonthEnd(0) == date

isMonthEnd(datetime(1999, 12, 31))
True
isMonthEnd(pd.Timestamp('1999-12-31'))
True
isMonthEnd(pd.Timestamp(1965, 1, 10))
False
1
répondu Steve Schulist 2015-07-24 19:59:53

je préfère cette façon

import datetime
import calendar

date=datetime.datetime.now()
month_end_date=datetime.datetime(date.year,date.month,1) + datetime.timedelta(days=calendar.monthrange(date.year,date.month)[1] - 1)
1
répondu MikA 2016-08-25 09:48:05
import calendar
from time import gmtime, strftime
calendar.monthrange(int(strftime("%Y", gmtime())), int(strftime("%m", gmtime())))[1]

sortie:

31





Ceci imprimera le dernier jour du mois en cours. Dans cet exemple, c'était le 15 Mai 2016. Si votre sortie peut être différent, mais le résultat sera d'autant de jours que le mois en cours. Grand si vous voulez vérifier le dernier jour du mois en exécutant un travail cron quotidien.

So:

import calendar
from time import gmtime, strftime
lastDay = calendar.monthrange(int(strftime("%Y", gmtime())), int(strftime("%m", gmtime())))[1]
today = strftime("%d", gmtime())
lastDay == today

sortie:

False

Si c'EST le dernier jour du mois.

0
répondu Audstanley 2016-05-16 04:51:56

Si vous voulez faire votre propre petite fonction, c'est un bon point de départ:

def eomday(year, month):
    """returns the number of days in a given month"""
    days_per_month = [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31]
    d = days_per_month[month - 1]
    if month == 2 and (year % 4 == 0 and year % 100 != 0 or year % 400 == 0):
        d = 29
    return d

Pour cela, vous devez connaître les règles pour les années bissextiles:

  • tous les quatre ans
  • à l'exception de tous les 100 ans
  • mais à nouveau tous les 400 ans
0
répondu mathause 2017-09-04 08:26:45

Si vous passez dans une plage de dates, vous pouvez utiliser ceci:

def last_day_of_month(any_days):
    res = []
    for any_day in any_days:
        nday = any_day.days_in_month -any_day.day
        res.append(any_day + timedelta(days=nday))
    return res
0
répondu JLord 2018-03-12 16:23:30

Voici une solution basée sur Python lambdas:

next_month = lambda y, m, d: (y, m + 1, 1) if m + 1 < 13 else ( y+1 , 1, 1)
month_end  = lambda dte: date( *next_month( *dte.timetuple()[:3] ) ) - timedelta(days=1)

le next_month lambda trouve la représentation de tuple du premier jour du mois suivant, et se renverse à l'année suivante. La month_end lambda transforme une date ( dte ) en un tuple, applique next_month et crée une nouvelle date. Alors la" fin du mois "n'est que le premier jour du mois suivant moins timedelta(days=1) .

-1
répondu Johannes Blaschke 2018-04-07 22:52:09

j'espère que c'est très utile..Essayez sur cette voie..nous devons importer un paquet

import time
from datetime import datetime, date
from datetime import timedelta
from dateutil import relativedelta

  start_date = fields.Date(
        string='Start Date', 
        required=True,
        ) 

    end_date = fields.Date(
        string='End Date', 
        required=True,
        )

    _defaults = {
        'start_date': lambda *a: time.strftime('%Y-%m-01'),
        'end_date': lambda *a: str(datetime.now() + relativedelta.relativedelta(months=+1, day=1, days=-1))[:10],
    }
-2
répondu Vinoth Jo 2017-09-27 12:23:03

j'ai une solution simple:

import datetime   
datetime.date(2012,2, 1).replace(day=1,month=datetime.date(2012,2,1).month+1)-timedelta(days=1)
datetime.date(2012, 2, 29)
-7
répondu francois 2012-08-21 23:09:57