Existe-t-il une fonction Python pour déterminer dans quel trimestre de l'année se trouve une date?

113

Bien sûr, je pourrais l'écrire moi-même, mais avant de réinventer la roue, y a-t-il une fonction qui le fait déjà?

Jason Christa
la source
22
Question TRÈS justifiée même si les premières réponses semblent un peu dédaigneuses ("juste une question de", "semble assez simple"): deux des réponses (dont une UPVOTED!) Sont horriblement boguées, montrant que ce n'est PAS si simple ou " juste "...
Alex Martelli
Je suis sûr qu'il reviendra et
réglera
Cette question très utile en 2018: D
wdfc
Si les objets datetime sont stockés dans une série Pandas ou dataframe , il existe une méthode qui retourne le trimestre correspondant (s): pandas.Series.dt.quarter.
Sumanth Lazarus

Réponses:

162

Étant donné une instance xde datetime.date , (x.month-1)//3vous donnera le trimestre (0 pour le premier trimestre, 1 pour le deuxième trimestre, etc. - ajoutez 1 si vous devez compter à partir de 1 à la place ;-).


À l'origine, deux réponses, multipliées par vote positif et même acceptées à l'origine (toutes deux actuellement supprimées), étaient boguées - ne faisant pas -1avant la division, et divisant par 4 au lieu de 3. Puisque .monthva de 1 à 12, il est facile de vérifier par vous-même quelle formule est droite:

for m in range(1, 13):
  print m//4 + 1,
print

donne 1 1 1 2 2 2 2 3 3 3 3 4- deux trimestres de quatre mois et un seul mois (eep).

for m in range(1, 13):
  print (m-1)//3 + 1,
print

donne 1 1 1 2 2 2 3 3 3 4 4 4- maintenant cela ne vous semble-t-il pas largement préférable? -)

Cela prouve que la question est bien justifiée, je pense ;-).

Je ne pense pas que le module datetime devrait nécessairement avoir toutes les fonctions de calendrier utiles possibles, mais je sais que je maintiens un datetoolsmodule (bien testé ;-) pour l'utilisation de mes projets (et d'autres) au travail, qui a beaucoup peu fonctions pour effectuer tous ces calculs calendriers - certains sont complexes, d'autres simples, mais il n'y a aucune raison de faire le travail encore et encore (même un travail simple) ou de risquer des bogues dans de tels calculs ;-).

Alex Martelli
la source
3
Merci Alex. C'est pourquoi il devrait y avoir une fonction. Regardez combien de personnes se sont trompées.
Jason Christa
Je pense que vous avez prouvé votre point de vue. Il n'est pas nécessaire de polluer toute la page avec des commentaires répétés.
João Silva
1
@Jason, oui, exactement - c'est pourquoi j'ai voté pour votre question une fois que j'ai vu les autres réponses boguées (actuellement supprimées), même si quelqu'un d'autre semble avoir voté contre pour compter mon vote, ah bien.
Alex Martelli
1
@JG, quels "commentaires répétés"? Comme les réponses boguées ont été supprimées, les commentaires sont partis avec eux, alors j'ai apporté leur contenu dans la réponse - il est important de savoir à quel point il est facile d'être distrait ou pressé et d'obtenir un bug évitable même dans un simple calcul, et cela a des conséquences (en termes de création et de test solide de fonctions réutilisables) pour les meilleures pratiques de programmation; ce cas est un bon exemple (qui, je pense, prouve que la question était justifiée).
Alex Martelli
7
Peut également utiliser: (m+2)//3au lieu de(m-1)//3 + 1
Ben
49

SI vous utilisez déjà pandas, c'est assez simple.

import datetime as dt
import pandas as pd

quarter = pd.Timestamp(dt.date(2016, 2, 29)).quarter
assert quarter == 1

Si vous avez une datecolonne dans un dataframe, vous pouvez facilement créer une nouvelle quartercolonne:

df['quarter'] = df['date'].dt.quarter
chishaku
la source
Et si mon trimestre d'exercice commence en septembre?
Arthur D. Howland
La méthode Pandas pandas.Series.dt.quarterest une solution idéale lorsque vous avez des valeurs datetime dans un objet Dataframe ou Series .
Sumanth Lazarus
31

Je suggérerais une autre solution sans doute plus propre. Si X est une datetime.datetime.now()instance, alors le quart est:

import math
Q=math.ceil(X.month/3.)

ceil doit être importé du module mathématique car il n'est pas accessible directement.

Jonathan Rocher
la source
1
Le meilleur à ce jour. Merci beaucoup!
curlyreggie
3
Devrait
Comme le suggère la réponse @garbanzio. J'avais besoin de passer l'argument du mois via la fonction float pour que cela fonctionne math.ceil(float(4)/3) = 2.0pendantmath.ceil(4/3) = 1.0
Theo Kouzelis
1
Ignorez-moi, je n'ai pas réalisé ce qu'ont fait l' .après le 3. math.ceil(4/3.) = 2.0
Theo Kouzelis
11

Pour tous ceux qui essaient d'obtenir le trimestre de l' année fiscale , qui peut différer de l' année civile , j'ai écrit un module Python pour faire exactement cela.

L'installation est simple. Exécutez simplement:

$ pip install fiscalyear

Il n'y a pas de dépendances et fiscalyeardevrait fonctionner pour Python 2 et 3.

Il s'agit essentiellement d'un wrapper autour du module datetime intégré, donc toutes les datetimecommandes que vous connaissez déjà fonctionneront. Voici une démo:

>>> from fiscalyear import *
>>> a = FiscalDate.today()
>>> a
FiscalDate(2017, 5, 6)
>>> a.fiscal_year
2017
>>> a.quarter
3
>>> b = FiscalYear(2017)
>>> b.start
FiscalDateTime(2016, 10, 1, 0, 0)
>>> b.end
FiscalDateTime(2017, 9, 30, 23, 59, 59)
>>> b.q3
FiscalQuarter(2017, 3)
>>> b.q3.start
FiscalDateTime(2017, 4, 1, 0, 0)
>>> b.q3.end
FiscalDateTime(2017, 6, 30, 23, 59, 59)

fiscalyearest hébergé sur GitHub et PyPI . La documentation peut être trouvée sur Lire les documents . Si vous recherchez des fonctionnalités qu'il n'a pas actuellement, faites le moi savoir!

Adam Stewart
la source
4

Voici un exemple de fonction qui obtient un objet datetime.datetime et renvoie une chaîne unique pour chaque trimestre:

from datetime import datetime, timedelta

def get_quarter(d):
    return "Q%d_%d" % (math.ceil(d.month/3), d.year)

d = datetime.now()
print(d.strftime("%Y-%m-%d"), get_q(d))

d2 = d - timedelta(90)
print(d2.strftime("%Y-%m-%d"), get_q(d2))

d3 = d - timedelta(180 + 365)
print(d3.strftime("%Y-%m-%d"), get_q(d3))

Et le résultat est:

2019-02-14 Q1_2019
2018-11-16 Q4_2018
2017-08-18 Q3_2017
Roei Bahumi
la source
2

si mest le numéro du mois ...

import math
math.ceil(float(m) / 3)
garbanzio
la source
2

Cette méthode fonctionne pour n'importe quel mappage:

month2quarter = {
        1:1,2:1,3:1,
        4:2,5:2,6:2,
        7:3,8:3,9:3,
        10:4,11:4,12:4,
    }.get

Nous venons de générer une fonction int->int

month2quarter(9) # returns 3

Cette méthode est également infaillible

month2quarter(-1) # returns None
month2quarter('July') # returns None
Uri Goren
la source
2

Pour ceux qui recherchent des données trimestrielles de l'exercice, en utilisant des pandas,

import datetime
import pandas as pd
today_date = datetime.date.today()
quarter = pd.PeriodIndex(today_date, freq='Q-MAR').strftime('Q%q')

reference: index des périodes pandas

Siddaram H
la source
1

C'est une question ancienne mais qui mérite toujours d'être discutée.

Voici ma solution, en utilisant l'excellent module dateutil .

  from dateutil import rrule,relativedelta

   year = this_date.year
   quarters = rrule.rrule(rrule.MONTHLY,
                      bymonth=(1,4,7,10),
                      bysetpos=-1,
                      dtstart=datetime.datetime(year,1,1),
                      count=8)

   first_day = quarters.before(this_date)
   last_day =  (quarters.after(this_date)
                -relativedelta.relativedelta(days=1)

Il en first_dayva de même pour le premier jour du trimestre et last_dayest le dernier jour du trimestre (calculé en trouvant le premier jour du trimestre suivant, moins un jour).

MikeHoss
la source
1

Ceci est très simple et fonctionne en python3:

from datetime import datetime

# Get current date-time.
now = datetime.now()

# Determine which quarter of the year is now. Returns q1, q2, q3 or q4.
quarter_of_the_year = 'q'+str((now.month-1)//3+1)
JavDomGom
la source
0

hmmm donc les calculs peuvent mal tourner, voici une meilleure version (juste pour le plaisir)

first, second, third, fourth=1,2,3,4# you can make strings if you wish :)

quarterMap = {}
quarterMap.update(dict(zip((1,2,3),(first,)*3)))
quarterMap.update(dict(zip((4,5,6),(second,)*3)))
quarterMap.update(dict(zip((7,8,9),(third,)*3)))
quarterMap.update(dict(zip((10,11,12),(fourth,)*3)))

print quarterMap[6]
Anurag Uniyal
la source
@RussBradberry dans ce cas, vous avez peut-être raison, mais parfois la lisibilité et le fait d'être explicite comptent et entraînent moins d'erreurs, au lieu d'un calcul laconique
Anurag Uniyal
1
@RussBradberry voit également des réponses et des commentaires supprimés à ce sujet, voir qu'un simple calcul peut être difficile pour les bons programmeurs aussi et il est difficile de voir l'exactitude sauf en le testant, dans ma solution, vous pouvez voir et être sûr que cela fonctionnera
Anurag Uniyal
1
comme tu l'as dit "it is difficult to see correctness except by testing it". Vous devriez écrire des tests, comme le devraient tous les bons développeurs. Les tests sont ce qui vous aide à ne pas commettre d'erreurs et à attraper celles que vous faites. Un développeur ne doit jamais sacrifier les performances et la lisibilité pour éviter de se tromper. De plus, c'est moins lisible que si vous faisiez simplement un dict statique en utilisant des littéraux.
Russ Bradberry
ne vous méprenez pas, ce (m-1)//3 + 1n'est pas tout à fait lisible non plus, peu de gens savent ce que //fait. Mon commentaire original portait uniquement sur la déclaration "calculations can go wrong"qui me semble étrange.
Russ Bradberry
@RussBradberry en fait, je suis d'accord avec vous, ma réponse était comme une alternative et au reming, il y a parfois des alternatives.J'ai vu beaucoup de code où les gens essaient de calculer / déduire quelque chose qui peut simplement être codé en dur dans une carte
Anurag Uniyal
0

Voici une solution détaillée, mais également lisible, qui fonctionnera pour les instances de date et d'heure

def get_quarter(date):
    for months, quarter in [
        ([1, 2, 3], 1),
        ([4, 5, 6], 2),
        ([7, 8, 9], 3),
        ([10, 11, 12], 4)
    ]:
        if date.month in months:
            return quarter
enflammer
la source
0

en utilisant des dictionnaires, vous pouvez le retirer en

def get_quarter(month):
    quarter_dictionary = {
        "Q1" : [1,2,3],
        "Q2" : [4,5,6],
        "Q3" : [7,8,9],
        "Q4" : [10,11,12]
    }

    for key,values in quarter_dictionary.items():
        for value in values:
            if value == month:
                return key

print(get_quarter(3))
LED
la source