Question

Existe-t-il un moyen d'utiliser la bibliothèque standard de Python pour déterminer facilement (c'est-à-direun appel de fonction) le dernier jour d'un mois donné ?

Si la bibliothèque standard ne prend pas en charge cela, le package dateutil le prend-il en charge ?

Était-ce utile?

La solution

Je ne l'avais pas remarqué plus tôt lorsque je regardais le documentation pour le module calendrier, mais une méthode appelée plage de mois fournit ces informations :

plage de mois (année, mois)
Renvoie le jour de la semaine du premier jour du mois et le nombre de jours du mois, pour l'année et le mois spécifiés.

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

donc:

calendar.monthrange(year, month)[1]

cela semble être la voie la plus simple à suivre.

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

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

Ma réponse précédente fonctionne toujours, mais est clairement sous-optimal.

Autres conseils

Si vous ne souhaitez pas importer le calendar module, une fonction simple en deux étapes peut également ê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)

Les 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

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

MODIFIER:voir mon autre réponse.Il a une meilleure implémentation que celle-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 du calcul du premier jour du mois suivant.

Ce qui suit n'est pas particulièrement élégant, mais pour déterminer le dernier jour du mois auquel se trouve une date donnée, 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)

C'est en fait assez simple avec dateutil.relativedelta (paquet python-datetutil pour pip). day=31 renverra 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)

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 d'utiliser relativedelta pour avancer 1 mois et 1 jour en arrière pour obtenir le dernier jour du mois souhaité.

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)
from datetime import timedelta
(any_day.replace(day=1) + timedelta(days=32)).replace(day=1) - timedelta(days=1)
>>> 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

si vous souhaitez utiliser une bibliothèque externe, consultez http://crsmithdev.com/arrow/

Vous pouvez alors obtenir le dernier jour du mois avec :

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

Cela renvoie un objet date que vous pouvez ensuite effectuer votre manipulation.

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 le diviser en deux parties :

la première consiste à obtenir le nombre de jours du mois en cours pour lesquels nous utilisons plage de mois dont Blair Conrad a déjà évoqué sa solution :

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

la deuxième consiste à obtenir la dernière date elle-même, ce que nous faisons avec l'aide de remplacer par exemple

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

et lorsque nous les combinons comme mentionné en haut, nous obtenons une solution dynamique.

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)

Pour moi c'est le 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)

Le moyen le plus simple (sans avoir à importer le calendrier) est d'obtenir le premier jour du mois suivant, puis d'en 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

Sortir:

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

PS : Ce code s'exécute plus rapidement que le import calendarapproche;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)

SORTIR:

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

Ce code suppose que vous voulez la date du dernier jour du mois (c'est-à-dire pas seulement la partie JJ, mais la date entière AAAAMMJJ)

Dans Python 3.7, il y a les sans-papiers calendar.monthlen(year, month) fonction:

>>> calendar.monthlen(2002, 1)
31
>>> calendar.monthlen(2008, 2)
29
>>> calendar.monthlen(2100, 2)
28

C'est équivalent à le documenté calendar.monthrange(year, month)[1] appel.

Vous pouvez calculer vous-même la date de fin.la logique simple est de soustraire un jour à la date de début du mois prochain.:)

Alors écrivez 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 renverra la date de fin de ce mois.Passez n’importe quelle date à cette fonction.vous renvoie la date de fin de ce mois.

Voici une autre réponse.Aucun forfait supplémentaire requis.

datetime.date(year + int(month/12), month%12+1, 1)-datetime.timedelta(days=1)

Obtenez le premier jour du mois suivant et soustrayez-en un jour.

Cela ne répond pas à la question principale, mais à une astuce intéressante pour obtenir la dernière jour de la semaine dans un mois, c'est à utiliser calendar.monthcalendar, qui renvoie une matrice de dates, organisées avec lundi comme première colonne jusqu'à dimanche comme 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

La totalité [0:-2] le problème est de raser les chroniques du week-end et de les jeter.Les dates qui se situent en dehors du mois sont indiquées par 0, donc le maximum les ignore effectivement.

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

Utilisez des 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

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)

Si vous souhaitez créer votre propre petite fonction, voici 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 il faut connaître les règles des années bissextiles :

  • tous les quatre ans
  • à l'exception de tous les 100 ans
  • mais encore une fois tous les 400 ans

vous pouvez utiliser relativedeltahttps://dateutil.readthedocs.io/en/stable/relativedelta.html month_end = <your datetime value within the month> + relativedelta(day=31) cela vous donnera le dernier jour.

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

Sortir:

31



Cela imprimera le dernier jour du mois en cours.Dans cet exemple, c'était le 15 mai 2016.Votre sortie peut donc être différente, mais la sortie sera d'autant de jours que le mois en cours.Idéal si vous souhaitez vérifier le dernier jour du mois en exécutant une tâche cron quotidienne.

Donc:

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

Sortir:

False

Sauf si c'est le dernier jour du mois.

Si vous transmettez 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

Dans le code ci-dessous 'get_last_day_of_month(dt)' vous donnera ceci, avec la date au format chaîne comme « AAAA-MM-JJ ».

import datetime

def DateTime( d ):
    return datetime.datetime.strptime( d, '%Y-%m-%d').date()

def RelativeDate( start, num_days ):
    d = DateTime( start )
    return str( d + datetime.timedelta( days = num_days ) )

def get_first_day_of_month( dt ):
    return dt[:-2] + '01'

def get_last_day_of_month( dt ):
    fd = get_first_day_of_month( dt )
    fd_next_month = get_first_day_of_month( RelativeDate( fd, 31 ) )
    return RelativeDate( fd_next_month, -1 )

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 tuple du premier jour du mois suivant et passe à l'année suivante.Le month_end lambda transforme une date (dte) à un tuple, s'applique next_month et crée une nouvelle date.Ensuite, la « fin du mois » correspond simplement au premier jour du mois suivant moins timedelta(days=1).

J'espère que c'est utile pour beaucoup de choses..Essayez-le de cette façon..nous devons avoir besoin d'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],
    }

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)
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top