Claro que podría escribir esto yo mismo, pero antes de reinventar la rueda, ¿hay alguna función que ya lo haga?
Dada una instancia x
de datetime.date , (x.month-1)//3
le 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 -1
anterior a la división y dividían por 4 en lugar de 3. Dado que .month
va 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 datetools
mó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 ;-).
(m+2)//3
lugar de(m-1)//3 + 1
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 date
columna en un marco de datos, puede crear fácilmente una nueva quarter
columna:
df['quarter'] = df['date'].dt.quarter
pandas.Series.dt.quarter
es una solución ideal cuando tiene valores de fecha y hora en un objeto Dataframe o Series .
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.
math.ceil(float(4)/3) = 2.0
mientrasmath.ceil(4/3) = 1.0
.
después del 3. math.ceil(4/3.) = 2.0
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 fiscalyear
deberí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 datetime
comando 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)
fiscalyear
está 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!
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
si m
es el número del mes ...
import math
math.ceil(float(m) / 3)
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
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
É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_day
es el primer día del trimestre, y last_day
es el último día del trimestre (calculado encontrando el primer día del siguiente trimestre menos un día).
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)
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]
"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.
(m-1)//3 + 1
tampoco 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.
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
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))
pandas.Series.dt.quarter
.