Có một hàm Python nào để xác định ngày tháng của năm không?


113

Chắc chắn tôi có thể tự viết cái này, nhưng trước khi tôi bắt đầu phát minh lại bánh xe, có một chức năng nào đó đã thực hiện điều này không?


22
Câu hỏi RẤT được đảm bảo mặc dù các câu trả lời ban đầu có vẻ hơi khó hiểu ("chỉ là vấn đề", "có vẻ khá đơn giản"): hai trong số các câu trả lời (bao gồm cả một câu trả lời ĐÃ CẬP NHẬT!) Bị lỗi khủng khiếp, cho thấy nó KHÔNG đơn giản như vậy hoặc " just "...
Alex Martelli 10/09/09

Tôi chắc chắn anh ấy sẽ quay lại và sửa lỗi này
Nadia Alramli. 10/09/09

Đây câu hỏi rất hữu ích vào năm 2018: D
wdfc

Nếu các đối tượng datetime được lưu trữ trong một Pandas Series hoặc Dataframe , có một phương pháp mà trả về quý tương ứng (s): pandas.Series.dt.quarter.
Sumanth Lazarus

Câu trả lời:


161

Với một phiên xbản datetime.date , (x.month-1)//3sẽ cung cấp cho bạn quý (0 cho quý đầu tiên, 1 cho quý thứ hai, v.v. - thêm 1 nếu bạn cần đếm từ 1 thay thế ;-).


Ban đầu, hai câu trả lời, nhân với số phiếu ủng hộ và thậm chí được chấp nhận ban đầu (cả hai hiện đã bị xóa), đều có lỗi - không thực hiện -1phép chia trước và chia cho 4 thay vì 3. Vì từ .month1 đến 12, thật dễ dàng để tự kiểm tra công thức là gì đúng:

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

cho 1 1 1 2 2 2 2 3 3 3 3 4- hai quý bốn tháng và một quý một tháng (eep).

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

cho 1 1 1 2 2 2 3 3 3 4 4 4- bây giờ cái này trông có vẻ thích hợp hơn với bạn sao? -)

Điều này chứng tỏ rằng câu hỏi được bảo đảm tốt, tôi nghĩ ;-).

Tôi không nghĩ rằng mô-đun datetime nhất thiết phải có mọi chức năng lịch có thể hữu ích, nhưng tôi biết tôi duy trì một datetoolsmô-đun (đã được kiểm tra kỹ lưỡng ;-) để sử dụng cho các dự án của tôi (và của những người khác) tại nơi làm việc, có nhiều các chức năng để thực hiện tất cả các tính toán lịch sử này - một số phức tạp, một số đơn giản, nhưng không có lý do gì để thực hiện công việc lặp đi lặp lại (thậm chí là công việc đơn giản) hoặc có lỗi trong các tính toán như vậy ;-).


3
Cảm ơn Alex. Đây là lý do tại sao nên có một chức năng. Nhìn xem có bao nhiêu người đã sai.
Jason Christa 10/09/09

Tôi nghĩ rằng bạn đã chứng minh quan điểm của mình. Không cần thiết phải gây ô nhiễm toàn bộ trang với các bình luận lặp lại.
João Silva

1
@Jason, vâng, chính xác - đó là lý do tại sao tôi ủng hộ câu hỏi của bạn khi tôi nhìn thấy các câu trả lời lỗi khác (hiện đã bị xóa), mặc dù có người khác dường như đã bỏ phiếu để tính lượt ủng hộ của tôi, à tốt.
Alex Martelli 10/09/09

1
@JG, "bình luận lặp lại" là gì? Khi các câu trả lời có lỗi bị xóa, các nhận xét sẽ biến mất cùng với chúng, vì vậy tôi đã đưa nội dung của chúng vào câu trả lời - điều quan trọng là phải biết rằng bạn dễ bị phân tâm hoặc vội vàng và mắc phải một lỗi có thể tránh được ngay cả trong một phép tính đơn giản, và nó có hậu quả (về việc tạo và kiểm tra vững chắc các chức năng có thể tái sử dụng) đối với các phương pháp lập trình tốt nhất; trường hợp này là một ví dụ điển hình (mà tôi nghĩ chứng tỏ câu hỏi đã được bảo đảm).
Alex Martelli 10/09/09

7
Cũng có thể sử dụng: (m+2)//3thay vì(m-1)//3 + 1
Ben

49

NẾU bạn đang sử dụng pandas, nó khá đơn giản.

import datetime as dt
import pandas as pd

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

Nếu bạn có một datecột trong khung dữ liệu, bạn có thể dễ dàng tạo một quartercột mới :

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

Điều gì sẽ xảy ra nếu quý năm tài chính của tôi bắt đầu vào tháng 9?
Arthur D. Howland

Phương pháp Pandas pandas.Series.dt.quarterlà một giải pháp lý tưởng khi bạn có các giá trị ngày giờ trong đối tượng Dataframe hoặc Series .
Sumanth Lazarus

31

Tôi sẽ đề xuất một giải pháp khác được cho là sạch hơn. Nếu X là một datetime.datetime.now()ví dụ, thì phần tư là:

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

ceil phải được nhập từ mô-đun toán học vì nó không thể được truy cập trực tiếp.


1
Tốt nhất cho đến nay. Cảm ơn rất nhiều!
curlyreggie

3
Có lẽ nên bọc điều này trong một int ()
Pablojim

Giống như câu trả lời @garbanzio gợi ý. Tôi cần thiết để đưa đối số tháng thông qua chức năng phao để có được điều này để làm việc math.ceil(float(4)/3) = 2.0trong khimath.ceil(4/3) = 1.0
Theo Kouzelis

1
Bỏ qua cho tôi, tôi không nhận ra những gì .sau khi 3 đã làm.math.ceil(4/3.) = 2.0
Theo Kouzelis,

11

Đối với bất kỳ ai đang cố gắng lấy quý của năm tài chính , có thể khác với năm dương lịch , tôi đã viết một mô-đun Python để thực hiện điều này.

Cài đặt rất đơn giản. Chỉ cần chạy:

$ pip install fiscalyear

Không có phụ thuộc và fiscalyearsẽ hoạt động cho cả Python 2 và 3.

Về cơ bản, nó là một trình bao bọc xung quanh mô-đun datetime tích hợp , vì vậy bất kỳ datetimelệnh nào bạn đã quen thuộc đều sẽ hoạt động. Đây là bản demo:

>>> 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 được lưu trữ trên GitHubPyPI . Tài liệu có thể được tìm thấy tại Đọc tài liệu . Nếu bạn đang tìm kiếm bất kỳ tính năng nào mà nó hiện không có, hãy cho tôi biết!


4

Dưới đây là một ví dụ về một hàm nhận một đối tượng datetime.datetime và trả về một chuỗi duy nhất cho mỗi phần tư:

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

Và đầu ra là:

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


2

Phương pháp này hoạt động cho bất kỳ ánh xạ nào:

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

Chúng tôi vừa tạo một hàm int->int

month2quarter(9) # returns 3

Phương pháp này cũng chống đánh lừa

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

2

Đối với những người đang tìm kiếm dữ liệu quý năm tài chính, sử dụng gấu trúc,

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

tham khảo: chỉ số thời kỳ gấu trúc


1

Đây là một câu hỏi cũ nhưng vẫn đáng được thảo luận.

Đây là giải pháp của tôi, sử dụng mô-đun dateutil tuyệt vời .

  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)

Vì vậy, first_daylà ngày đầu tiên của quý này, và last_daylà ngày cuối cùng của quý (tính bằng cách tìm ngày đầu tiên của quý tiếp theo, trừ đi một ngày).


1

Điều này rất đơn giản và hoạt động trong 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 vì vậy các phép tính có thể bị sai, đây là phiên bản tốt hơn (chỉ vì lợi ích của nó)

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 trong trường hợp này có thể là bạn đúng, nhưng đôi khi tính dễ đọc và được tính rõ ràng và dẫn đến ít lỗi hơn, thay vì một phép tính ngắn gọn
Anurag Uniyal

1
@RussBradberry cũng thấy các câu trả lời và nhận xét đã bị xóa trên đó, hãy xem một phép tính đơn giản cũng có thể khó đối với các lập trình viên giỏi và rất khó để thấy tính đúng đắn ngoại trừ việc thử nghiệm nó, trong giải pháp của tôi, bạn có thể thấy và chắc chắn rằng nó sẽ hoạt động
Anurag Uniyal

1
đúng như bạn đã nói "it is difficult to see correctness except by testing it". Bạn nên viết thử nghiệm, giống như tất cả các nhà phát triển giỏi. Các bài kiểm tra là thứ giúp bạn tránh mắc sai lầm và nắm bắt được những lỗi bạn làm. Một nhà phát triển không bao giờ được hy sinh hiệu suất và khả năng đọc để tránh cho họ mắc sai lầm. Ngoài ra, điều này khó đọc hơn nếu bạn chỉ tạo một mệnh lệnh tĩnh bằng cách sử dụng các ký tự.
Russ Bradberry

Đừng hiểu lầm tôi (m-1)//3 + 1cũng không phải là tất cả những gì có thể đọc được, không nhiều người biết những gì //làm. Nhận xét ban đầu của tôi chỉ là về tuyên bố "calculations can go wrong"nghe có vẻ kỳ lạ đối với tôi.
Russ Bradberry

@RussBradberry thực sự tôi đồng ý với bạn câu trả lời của tôi là như một sự thay thế và để reming đôi khi có những lựa chọn thay thế tôi đã thấy nhiều mã nơi mọi người đang cố gắng tính toán / suy ra một cái gì đó mà chỉ có thể được hardcoded trong bản đồ
Anurag Uniyal

0

Đây là một giải pháp dài dòng nhưng cũng có thể đọc được sẽ hoạt động cho các phiên bản datetime và date

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

sử dụng từ điển, bạn có thể thực hiện điều này bằng cách

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))
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.