Existe uma função Python para determinar em qual trimestre do ano está uma data?


113

Claro que eu poderia escrever isso sozinho, mas antes de reinventar a roda, há uma função que já faz isso?


22
Pergunta MUITO justificada, embora as primeiras respostas pareçam um pouco desdenhosas ("apenas uma questão de", "parece muito simples"): duas das respostas (incluindo uma REALIZADA!) São terrivelmente bugadas, mostrando que NÃO é tão simples ou " apenas "...
— Alex Martelli

Tenho certeza que ele vai voltar e consertar isso
— Nadia Alramli

Esta pergunta é muito útil em 2018: D
— wdfc

Se os objetos de data e hora são armazenados em uma série Pandas ou trama de dados , há um método que retorna o respectivo trimestre (s): pandas.Series.dt.quarter.
— Sumanth Lazarus

Respostas:


162

Dada uma instância xde datetime.date , (x.month-1)//3fornecerá o trimestre (0 para o primeiro trimestre, 1 para o segundo trimestre, etc. - adicione 1 se precisar contar a partir de 1 ;-).


Originalmente, duas respostas, com votos positivos multiplicados e até mesmo aceitas originalmente (ambas atualmente excluídas), apresentavam erros - não fazendo o -1antes da divisão e dividindo por 4 em vez de 3. Como .monthvai de 1 a 12, é fácil verificar por si mesmo qual é a fórmula certo:

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

dá 1 1 1 2 2 2 2 3 3 3 3 4- dois trimestres de quatro meses e um de um mês (eep).

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

dá 1 1 1 2 2 2 3 3 3 4 4 4- agora isso não parece muito preferível para você? -)

Isso prova que a questão é bem justificada, eu acho ;-).

Não acho que o módulo datetime deva necessariamente ter todas as funções de calendário úteis possíveis, mas sei que mantenho um datetoolsmódulo (bem testado ;-) para o uso de meus (e de outros) projetos no trabalho, que tem muitos poucos funções para realizar todos esses cálculos do calendário - alguns são complexos, outros simples, mas não há razão para fazer o trabalho repetidamente (mesmo o trabalho simples) ou arriscar bugs em tais cálculos ;-).


3
Obrigado Alex. É por isso que deve haver uma função. Veja quantas pessoas erraram.
— Jason Christa

Eu acho que você provou seu ponto. Não é necessário poluir a página inteira com comentários repetidos.
— João Silva

1
@Jason, sim, exatamente - é por isso que votei positivamente em sua pergunta quando vi as outras respostas problemáticas (atualmente excluídas), embora outra pessoa pareça ter votado negativamente para contar meu voto positivo, ah, bem.
— Alex Martelli

1
@JG, quais são os "comentários repetidos"? Como as respostas com erros foram excluídas, os comentários foram embora com eles, então eu trouxe seu conteúdo para a resposta - é importante estar ciente de como é fácil se distrair ou se apressar e obter um bug evitável, mesmo em um cálculo simples, e tem consequências (em termos de fazer e testar solidamente funções reutilizáveis) para as melhores práticas de programação; este caso é um bom exemplo (o que eu acho que prova que a questão era justificada).
— Alex Martelli

7
Também pode usar: em (m+2)//3vez de(m-1)//3 + 1
— Ben

49

SE você já está usando pandas, é bem simples.

import datetime as dt
import pandas as pd

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

Se você tem uma datecoluna em um dataframe, pode facilmente criar uma nova quartercoluna:

df['quarter'] = df['date'].dt.quarter

E se o trimestre do meu ano fiscal começar em setembro?
— Arthur D. Howland

O método Pandas pandas.Series.dt.quarteré uma solução ideal quando você tem valores de data e hora em um objeto Dataframe ou Series .
— Sumanth Lazarus

31

Eu sugeriria outra solução indiscutivelmente mais limpa. Se X for uma datetime.datetime.now()instância, o quarto será:

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

ceil deve ser importado do módulo matemático, pois não pode ser acessado diretamente.


1
O melhor até agora. Muito obrigado!
— curlyreggie de

3
Provavelmente deve envolver isso em um int ()
— Pablojim

Como a resposta de @garbanzio sugere. Eu precisava colocar o argumento do mês por meio da função float para fazer isso funcionar math.ceil(float(4)/3) = 2.0enquantomath.ceil(4/3) = 1.0
— Theo Kouzelis

1
Ignore-me, não percebi o que o .depois do 3 fez. math.ceil(4/3.) = 2.0
— Theo Kouzelis

11

Para quem está tentando obter o trimestre do ano fiscal , que pode ser diferente do ano civil , escrevi um módulo Python para fazer exatamente isso.

A instalação é simples. Apenas corra:

$ pip install fiscalyear

Não há dependências e fiscalyeardeve funcionar tanto no Python 2 quanto no 3.

É basicamente um invólucro em torno do módulo datetime integrado , portanto, todos os datetimecomandos com os quais você já está familiarizado funcionarão. Aqui está uma demonstração:

>>> 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á hospedado no GitHub e PyPI . A documentação pode ser encontrada em Read the Docs . Se você estiver procurando por algum recurso que ele não tenha atualmente, me avise!


4

Aqui está um exemplo de uma função que obtém um objeto datetime.datetime e retorna uma string exclusiva 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))

E o resultado é:

2019-02-14 Q1_2019
2018-11-16 Q4_2018
2017-08-18 Q3_2017

2

se mé o número do mês ...

import math
math.ceil(float(m) / 3)

2

Este método funciona para qualquer mapeamento:

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 gerar uma função int->int

month2quarter(9) # returns 3

Este método também é infalível

month2quarter(-1) # returns None
month2quarter('July') # returns None

2

Para aqueles que procuram dados trimestrais do ano financeiro, usando o pandas,

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

referência: índice do período dos pandas


1

Esta é uma questão antiga, mas ainda digna de discussão.

Aqui está minha solução, usando o 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)

Assim first_dayé o primeiro dia do trimestre e last_dayé o último dia do trimestre (calculado encontrando o primeiro dia do próximo trimestre, menos um dia).


1

Isso é muito simples e funciona em 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)

0

hmmm então os cálculos podem dar errado, aqui está uma versão melhor (apenas por causa dela)

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]

@RussBradberry neste caso pode estar certo, mas às vezes a legibilidade e o fato de ser explícito contam e levam a menos erros, em vez de um cálculo conciso
— Anurag Uniyal

1
@RussBradberry também veja respostas deletadas e comentários sobre isso, veja um cálculo simples pode ser complicado para bons programadores também e é difícil ver a correção exceto testando-o, na minha solução você pode ver e ter certeza de que funcionará
— Anurag Uniyal

1
exatamente como você disse "it is difficult to see correctness except by testing it". Você deve escrever testes, como todos os bons desenvolvedores deveriam. Os testes ajudam a evitar que você cometa erros e a detectar os erros cometidos. Um desenvolvedor nunca deve sacrificar o desempenho e a legibilidade para evitar cometer erros. Além disso, isso é menos legível do que se você simplesmente fizesse um dicionário estático usando literais.
— Russ Bradberry

Não me interpretem mal (m-1)//3 + 1também não é tão legível, muitas pessoas não sabem o que //significa. Meu comentário original foi apenas sobre a afirmação "calculations can go wrong"que soa estranho para mim.
— Russ Bradberry

@RussBradberry na verdade, eu concordo com você, minha resposta foi como uma alternativa e às vezes há alternativas. Eu vi muito código onde as pessoas estão tentando calcular / deduzir algo que pode ser codificado em um mapa
— Anurag Uniyal

0

Aqui está uma solução detalhada, mas também legível, que funcionará para instâncias de data e 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

0

usando dicionários, você pode fazer isso

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))
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.