Чи є функція Python, щоб визначити, в якій чверті року дата знаходиться?


113

Впевнений, що я міг би це написати сам, але перед тим, як зайнятися винаходом колеса, є функція, яка вже це робить?


22
Запитання ДУЖЕ обґрунтовано, навіть якщо ранні відповіді здаються неприйнятними ("просто питання", "здається досить простим"): два відповіді (включаючи ПЕРЕГЛЯДАНИЙ!) Жахливо баггі, показуючи, що це НЕ все так просто або " просто "...
Алекс Мартеллі

Я впевнений, що він повернеться і виправить це
Надія Алрамлі

Це питання дуже корисне у 2018 році: D
wdfc

Якщо об'єкти DateTime зберігаються в серії панди або Dataframe , існує метод , який повертає відповідний квартал (и): pandas.Series.dt.quarter.
Сумант Лазар

Відповіді:


162

З огляду на екземпляр xз datetime.date , (x.month-1)//3дасть вам чверть (0 за перший квартал, 1 за другий квартал і т.д. - додати 1 , якщо вам потрібно рахувати від 1 замість ;-).


Спочатку дві відповіді, множинні, схвалені та навіть спочатку прийняті (обидві видалені в даний час), були баггі - не роблячи -1до поділу, а ділившись на 4 замість 3. Оскільки .monthйде від 1 до 12, легко перевірити для себе, що таке формула правильно:

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

дає 1 1 1 2 2 2 2 3 3 3 3 4- два чотиримісячні чверті та одномісячний (eep).

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

дає 1 1 1 2 2 2 3 3 3 4 4 4- тепер це не виглядає для вас надзвичайно переважним? -)

Це доводить, що питання, на мою думку, є досить обґрунтованим; я думаю ;-).

Я не вважаю, що модуль дати повинен обов'язково виконувати всі можливі корисні функції календаря, але я знаю, що я підтримую (добре перевірений ;-) datetoolsмодуль для використання моїх (та інших) проектів на роботі, у яких є дуже мало функції для виконання всіх цих календаричних обчислень - деякі складні, деякі прості, але немає підстав робити роботу знову і знову (навіть просту роботу) або ризикувати помилками в таких обчисленнях ;-).


3
Дякую Алекс. Ось чому має бути функція. Подивіться, скільки людей помилилися.
Джейсон Кріста

Я думаю, ви довели свою думку. Не зайве забруднювати всю сторінку повторними коментарями.
Жоао Сільва

1
@ Джейсон, так, саме тому я відхилив ваше запитання, побачивши інші відповіді на помилки (видалені на даний момент), хоча, здається, хтось інший прийняв рішення вважати мою нагороду, ну добре.
Алекс Мартеллі

1
@JG, які "повторні коментарі"? Коли відповіді на помилки були видалені, коментарі з ними пішли, тож я вніс їхній вміст у відповідь - важливо знати, як легко відволікатися чи поспішати та отримувати помилку, яку можна уникнути, навіть у простому обчисленні, і це має наслідки (з точки зору створення та надійного тестування функцій багаторазового використання) для найкращих програм програмування; цей випадок є гарним прикладом (що, на мою думку, підтверджує, що питання було обґрунтованим).
Алекс Мартеллі

7
Можна також використовувати: (m+2)//3замість(m-1)//3 + 1
Бен

49

ЯКЩО ви вже використовуєте pandas, це досить просто.

import datetime as dt
import pandas as pd

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

Якщо у вас є dateстовпець у кадрі даних, ви можете легко створити новий quarterстовпець:

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

Що робити, якщо мій квартальний фінансовий рік розпочнеться у вересні?
Артур Д. Хоуленд

Метод Pandas pandas.Series.dt.quarterє ідеальним рішенням, коли у вас є значення дати в об'єкті Dataframe або Series .
Сумант Лазар

31

Я б запропонував ще одне, мабуть, більш чисте рішення. Якщо X - це datetime.datetime.now()примірник, то чверть дорівнює:

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

ceil повинен бути імпортований з математичного модуля, оскільки до нього не можна отримати доступ безпосередньо.


1
Найкращий поки що. Дякую тонну!
curlyreggie

3
Напевно, слід загорнути це в int ()
Паблохім,

Як і відповідь @garbanzio. Мені потрібно було поставити аргумент місяця через функцію float, щоб змусити це працювати, math.ceil(float(4)/3) = 2.0покиmath.ceil(4/3) = 1.0
Тео Кузеліс,

1
Ігноруй мене, я не усвідомлював, що .зробив після 3-х. math.ceil(4/3.) = 2.0
Тео Кузеліс

11

Для тих, хто намагається отримати квартал фінансового року, який може відрізнятися від календарного року, я написав модуль Python, щоб зробити саме це.

Установка проста. Просто запустіть:

$ pip install fiscalyear

Немає залежностей, і fiscalyear повинні працювати як для Python 2, так і для 3.

Це в основному обгортка навколо вбудованого модуля datetime , тому будь-які datetimeкоманди, з якими ви вже знайомі, працюватимуть. Ось демонстрація:

>>> 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розміщується на GitHub та PyPI . Документацію можна знайти в розділі Прочитати документи . Якщо ви шукаєте будь-які функції, яких він наразі не має, повідомте мене!


4

Ось приклад функції, яка отримує об’єкт datetime.datetime і повертає унікальний рядок для кожного кварталу:

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

А вихід:

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


2

Цей метод працює для будь-якого відображення:

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

Ми щойно створили функцію int->int

month2quarter(9) # returns 3

Цей спосіб також є нерозумним

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

2

Для тих, хто шукає дані за квартал фінансового року, використовуючи панди,

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

довідка: індекс періоду панд


1

Це давнє питання, але все ще гідне обговорення.

Ось моє рішення, використовуючи відмінний модуль 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)

Так first_dayє перший день кварталу і last_dayостанній день кварталу (обчислюється шляхом знаходження першого дня наступної чверті мінус один день).


1

Це дуже просто і працює в 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

хммм, тому розрахунки можуть піти не так, ось краща версія (просто заради неї)

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 в цьому випадку ви можете мати рацію, але іноді читабельність і явний підрахунок і призводить до менших помилок, замість
невідкладного

1
@RussBradberry також бачить видалені відповіді та коментарі до цього, див. Простий розрахунок може бути складним і для хороших програмістів, і складно побачити правильність, окрім тестування його, у моєму рішенні ви можете побачити і бути впевненим, що він спрацює
Anurag Uniyal

1
так, як ви сказали "it is difficult to see correctness except by testing it". Ви повинні писати тести, як і всі хороші розробники. Тести - це те, що допомагає утримати помилки та зловити тих, що ви робите. Розробник ніколи не повинен жертвувати продуктивністю та читабельністю, щоб не допустити помилок. Крім того, це менш читабельно, ніж якби ви просто зробили статичний вислів за допомогою літералів.
Russ Bradberry

не зрозумійте мене (m-1)//3 + 1не так, читається не все, і багато людей знають, що //робить. Мій оригінальний коментар був саме на твердження, "calculations can go wrong"яке мені просто звучить дивно.
Russ Bradberry

@RussBradberry насправді я згоден з вами, моя відповідь була альтернативою, і, зауважуючи, іноді існують альтернативи, я бачив багато коду, де люди намагаються обчислити / вивести щось, що просто може бути жорстко закодовано на карті
Anurag Uniyal

0

Ось багатослівне, але також читабельне рішення, яке буде працювати для екземплярів дати та дати

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

використовуючи словники, ви можете витягнути це

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))
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.