¿Existe una función de Python para determinar en qué trimestre del año se encuentra una fecha?

113

Claro que podría escribir esto yo mismo, pero antes de reinventar la rueda, ¿hay alguna función que ya lo haga?

Jason Christa
fuente
22
Pregunta MUY justificada a pesar de que las primeras respuestas parecen un poco desdeñosas ("solo es cuestión de", "parece bastante simple"): dos de las respuestas (¡incluida una MEJORADA!) Tienen errores horribles, lo que demuestra que NO es tan simple o " simplemente "...
Alex Martelli
Estoy segura de que volverá y arreglará esto
Nadia Alramli
Esta pregunta es muy útil en 2018: D
wdfc
Si los objetos de fecha y hora se almacenan en una serie pandas o trama de datos , hay un método que devuelve el trimestre respectivo (s): pandas.Series.dt.quarter.
Sumanth Lazarus

Respuestas:

161

Dada una instancia xde datetime.date , (x.month-1)//3le dará el trimestre (0 para el primer trimestre, 1 para el segundo trimestre, etc.) agregue 1 si necesita contar desde 1 en su lugar ;-).


Originalmente, dos respuestas, multiplicadas por votos positivos e incluso aceptadas originalmente (ambas actualmente eliminadas), tenían errores: no hacían lo -1anterior a la división y dividían por 4 en lugar de 3. Dado que .monthva del 1 al 12, es fácil comprobar por sí mismo qué fórmula es Derecha:

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

da 1 1 1 2 2 2 2 3 3 3 3 4- dos trimestres de cuatro meses y uno de un solo mes (eep).

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

da 1 1 1 2 2 2 3 3 3 4 4 4- ¿no te parece mucho mejor esto? -)

Esto demuestra que la pregunta está bien justificada, creo ;-).

No creo que el módulo de fecha y hora deba tener necesariamente todas las funciones calendáricas útiles posibles, pero sé que mantengo un datetoolsmódulo (bien probado ;-) para el uso de mis proyectos (y de otros) en el trabajo, que tiene muchos pequeños funciones para realizar todos estos cálculos calendáricos: algunos son complejos, otros simples, pero no hay razón para hacer el trabajo una y otra vez (incluso un trabajo simple) o arriesgarse a errores en dichos cálculos ;-).

Alex Martelli
fuente
3
Gracias Alex. Por eso debería haber una función. Mira cuánta gente se equivocó.
Jason Christa
Creo que demostró su punto. No es necesario contaminar toda la página con comentarios repetidos.
João Silva
1
@Jason, sí, exactamente, es por eso que voté a favor de tu pregunta una vez que vi las otras respuestas con errores (actualmente eliminadas), aunque alguien más parece haber votado en contra para contar mi voto a favor, bueno.
Alex Martelli
1
@JG, ¿qué "comentarios repetidos"? Cuando se eliminaron las respuestas con errores, los comentarios desaparecieron con ellos, por lo que incluí su contenido en la respuesta: es importante ser consciente de lo fácil que es distraerse o apresurarse y obtener un error evitable incluso en un simple cálculo. y tiene consecuencias (en términos de hacer y probar sólidamente funciones reutilizables) para las mejores prácticas de programación; este caso es un buen ejemplo (que creo que prueba que la pregunta estaba justificada).
Alex Martelli
7
También se puede usar: en (m+2)//3lugar de(m-1)//3 + 1
Ben
49

SI ya lo está utilizando pandas, es bastante simple.

import datetime as dt
import pandas as pd

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

Si tiene una datecolumna en un marco de datos, puede crear fácilmente una nueva quartercolumna:

df['quarter'] = df['date'].dt.quarter
chishaku
fuente
¿Qué pasa si el trimestre de mi año fiscal comienza en septiembre?
Arthur D. Howland
El método Pandas pandas.Series.dt.quarteres una solución ideal cuando tiene valores de fecha y hora en un objeto Dataframe o Series .
Sumanth Lazarus
31

Sugeriría otra solución posiblemente más limpia. Si X es una datetime.datetime.now()instancia, entonces el trimestre es:

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

ceil debe importarse desde el módulo matemático ya que no se puede acceder directamente.

Jonathan Rocher
fuente
1
El mejor hasta ahora. ¡Gracias una tonelada!
curlyreggie
3
Probablemente debería envolver esto en un int ()
Pablojim
Como sugiere la respuesta de @garbanzio. Necesitaba poner el argumento del mes a través de la función flotante para que esto funcione math.ceil(float(4)/3) = 2.0mientrasmath.ceil(4/3) = 1.0
Theo Kouzelis
1
Ignórame, no me di cuenta de lo que hizo el .después del 3. math.ceil(4/3.) = 2.0
Theo Kouzelis
11

Para cualquiera que intente obtener el trimestre del año fiscal , que puede diferir del año calendario , escribí un módulo de Python para hacer precisamente esto.

La instalación es sencilla. Solo corre:

$ pip install fiscalyear

No hay dependencias y fiscalyeardebería funcionar tanto para Python 2 como para 3.

Es básicamente una envoltura del módulo de fecha y hora incorporado , por lo que cualquier datetimecomando con el que ya esté familiarizado funcionará. Aquí hay una demostración:

>>> 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á alojado en GitHub y PyPI . La documentación se puede encontrar en Read the Docs . Si está buscando alguna característica que no tiene actualmente, ¡hágamelo saber!

Adam Stewart
fuente
4

A continuación se muestra un ejemplo de una función que obtiene un objeto datetime.datetime y devuelve una cadena única para cada 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))

Y la salida es:

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

si mes el número del mes ...

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

Este método funciona para cualquier mapeo:

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

Acabamos de generar una función int->int

month2quarter(9) # returns 3

Este método también es infalible

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

Para aquellos que buscan datos trimestrales del año financiero, utilizando pandas,

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

referencia: índice del período de los pandas

Siddaram H
fuente
1

Ésta es una pregunta antigua pero aún digna de discusión.

Aquí está mi solución, usando el excelente módulo 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)

También first_dayes el primer día del trimestre, y last_dayes el último día del trimestre (calculado encontrando el primer día del siguiente trimestre menos un día).

MikeHoss
fuente
1

Esto es muy simple y funciona 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
fuente
0

hmmm, así que los cálculos pueden salir mal, aquí hay una versión mejor (solo por el simple hecho de hacerlo)

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
fuente
@RussBradberry en este caso puede tener razón, pero a veces la legibilidad y ser explícito cuenta y conduce a menos errores, en lugar de un cálculo conciso
Anurag Uniyal
1
@RussBradberry también ve respuestas eliminadas y comentarios sobre eso, ver que un cálculo simple también puede ser complicado para los buenos programadores y es difícil ver la exactitud excepto probándolo, en mi solución puede ver y estar seguro de que funcionará
Anurag Uniyal
1
tal como dijiste "it is difficult to see correctness except by testing it". Deberías escribir pruebas, como deberían hacerlo todos los buenos desarrolladores. Las pruebas son lo que le ayudan a evitar cometer errores y a detectar los que comete. Un desarrollador nunca debe sacrificar el rendimiento y la legibilidad para evitar cometer un error. Además, esto es menos legible que si solo hiciera un dictado estático usando literales.
Russ Bradberry
no me malinterpretes (m-1)//3 + 1tampoco es tan legible, no mucha gente sabe lo que //hace. Mi comentario original fue solo sobre la declaración de "calculations can go wrong"lo que me suena extraño.
Russ Bradberry
@RussBradberry en realidad estoy de acuerdo con usted, mi respuesta fue como una alternativa y para reming, a veces hay alternativas He visto mucho código en el que la gente está tratando de calcular / deducir algo que simplemente se puede codificar en un mapa
Anurag Uniyal
0

Aquí hay una solución detallada, pero también legible, que funcionará para instancias de fecha y hora

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
Igniteflow
fuente
0

usando diccionarios, puede lograr esto

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
fuente