มีฟังก์ชัน Python เพื่อกำหนดวันที่ในไตรมาสของปีหรือไม่?


114

แน่นอนว่าฉันสามารถเขียนสิ่งนี้ด้วยตัวเอง แต่ก่อนที่ฉันจะสร้างวงล้อใหม่มีฟังก์ชันที่ทำสิ่งนี้อยู่แล้วหรือไม่?


23
คำถามได้รับการรับรองอย่างมากแม้ว่าคำตอบในช่วงต้นจะดูไม่น่าสนใจเล็กน้อย ("เป็นเรื่องของ" "ดูเหมือนง่ายมาก"): คำตอบสองข้อ (รวมถึงคำตอบที่อัปเดตแล้ว!) เป็นข้อผิดพลาดที่น่ากลัวแสดงว่ามันไม่ง่ายเลยหรือ " แค่ "...
Alex Martelli

ฉันแน่ใจว่าเขาจะกลับมาแก้ไข
Nadia Alramli

คำถามนี้มีประโยชน์มากในปี 2018: D
wdfc

หากวัตถุ datetime จะถูกเก็บไว้ในซีรีส์นุ่นหรือ Dataframeมีวิธีการซึ่งผลตอบแทนไตรมาสที่เกี่ยวข้อง (s) pandas.Series.dt.quarterA:
Sumanth Lazarus

คำตอบ:


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
ขอบคุณอเล็กซ์ นี่คือเหตุผลที่ควรมีฟังก์ชัน ดูสิว่ามีกี่คนที่เข้าใจผิด
Jason Christa

ฉันคิดว่าคุณพิสูจน์จุดของคุณแล้ว การแสดงความคิดเห็นซ้ำ ๆ ทั้งหน้าไม่จำเป็น
João Silva

1
@ เจสันใช่แล้วนั่นคือเหตุผลที่ฉันโหวตคำถามของคุณเมื่อฉันเห็นคำตอบที่มีข้อบกพร่องอื่น ๆ (ขณะนี้ถูกลบไปแล้ว) แม้ว่าจะมีคนอื่นที่โหวตลดคะแนนเพื่อนับคะแนนโหวตของฉันดี
Alex Martelli

1
@JG "คอมเมนต์ซ้ำ" คืออะไร? เมื่อคำตอบที่ผิดพลาดถูกลบความคิดเห็นก็หายไปด้วยดังนั้นฉันจึงนำเนื้อหาของพวกเขามาเป็นคำตอบ - สิ่งสำคัญคือต้องระวังว่าการเบี่ยงเบนความสนใจหรือรีบร้อนนั้นง่ายเพียงใดและได้รับข้อผิดพลาดที่หลีกเลี่ยงได้แม้ในการคำนวณง่ายๆ และผลที่ตามมา (ในแง่ของการสร้างและทดสอบฟังก์ชันที่ใช้ซ้ำได้อย่างมั่นคง) สำหรับแนวทางปฏิบัติที่ดีที่สุดในการเขียนโปรแกรม กรณีนี้เป็นตัวอย่างที่ดี (ซึ่งฉันคิดว่าพิสูจน์ได้ว่าคำถามนี้ได้รับการรับรอง)
Alex Martelli

7
ยังสามารถใช้: (m+2)//3แทน(m-1)//3 + 1
เบ็น

50

หากคุณใช้งานอยู่แล้ว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

จะเกิดอะไรขึ้นถ้าไตรมาสปีงบประมาณของฉันเริ่มในเดือนกันยายน
Arthur D. Howland

เมธอด Pandas pandas.Series.dt.quarterเป็นโซลูชันที่ดีเมื่อคุณมีค่าวันที่และเวลาในวัตถุDataframeหรือSeries
Sumanth Lazarus

31

ฉันขอแนะนำวิธีแก้ปัญหาอื่นที่สะอาดกว่า ถ้า X เป็นdatetime.datetime.now()อินสแตนซ์ไตรมาสจะเป็น:

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

ต้องนำเข้า ceil จากโมดูลคณิตศาสตร์เนื่องจากไม่สามารถเข้าถึงได้โดยตรง


1
ที่ดีที่สุดจนถึงตอนนี้ ขอบคุณมาก!
Curlyreggie

3
น่าจะรวมไว้ใน int ()
Pablojim

เช่นเดียวกับคำตอบของ @garbanzio แนะนำ ฉันต้องการใส่อาร์กิวเมนต์เดือนผ่านฟังก์ชัน float เพื่อให้มันทำงานได้math.ceil(float(4)/3) = 2.0ในขณะที่math.ceil(4/3) = 1.0
Theo Kouzelis

1
ไม่สนใจฉันฉันไม่รู้ว่า.หลังจากทั้ง 3 คนทำอะไร math.ceil(4/3.) = 2.0
Theo Kouzelis

11

สำหรับใครก็ตามที่พยายามหาไตรมาสของปีงบประมาณซึ่งอาจแตกต่างจากปีปฏิทินฉันเขียนโมดูล Python เพื่อทำสิ่งนี้

การติดตั้งทำได้ง่าย เพียงแค่เรียกใช้:

$ pip install fiscalyear

ไม่มีการอ้างอิงและfiscalyearควรใช้ได้กับทั้ง Python 2 และ 3

มันเป็นพื้นห่อหุ้มรอบตัวในวันที่และเวลาโมดูลใด ๆ ดังนั้น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


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 ในกรณีนี้อาจเป็นคุณที่ถูกต้อง แต่บางครั้งความสามารถในการอ่านและการนับอย่างชัดเจนและนำไปสู่ข้อผิดพลาดน้อยลงแทนที่จะเป็นการคำนวณที่สั้น
Anurag Uniyal

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))
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.