วิธีรับวันสุดท้ายของเดือน


632

มีวิธีการใช้ห้องสมุดมาตรฐานของงูใหญ่ในการตรวจสอบ (เช่นการเรียกใช้ฟังก์ชันหนึ่ง) ในวันสุดท้ายของเดือนที่กำหนดหรือไม่?

หากไลบรารีมาตรฐานไม่รองรับแพคเกจ dateutil นี้สนับสนุนหรือไม่

คำตอบ:


1082

ฉันไม่ได้สังเกตสิ่งนี้ก่อนหน้านี้เมื่อฉันดูเอกสารประกอบของcalendarโมดูลแต่วิธีการที่เรียกว่าmonthrangeให้ข้อมูลนี้:

monthrange (ปี, เดือน)
    ส่งคืนวันทำงานของวันแรกของเดือนและจำนวนวันในเดือนสำหรับปีและเดือนที่ระบุ

>>> import calendar
>>> calendar.monthrange(2002,1)
(1, 31)
>>> calendar.monthrange(2008,2)
(4, 29)
>>> calendar.monthrange(2100,2)
(0, 28)

ดังนั้น:

calendar.monthrange(year, month)[1]

ดูเหมือนจะเป็นวิธีที่ง่ายที่สุดที่จะไป

เพื่อความชัดเจนmonthrangeสนับสนุนการกระโดดปีเช่นกัน

>>> from calendar import monthrange
>>> monthrange(2012, 2)
(2, 29)

คำตอบก่อนหน้าของฉันยังใช้งานได้ แต่ไม่ดีพอ


นี่ไม่ใช่คำตอบที่ถูกต้องสำหรับคำถามต้นฉบับ! เกิดอะไรขึ้นถ้าวันสุดท้ายของเดือนเป็นวันเสาร์ / อาทิตย์
Mahdi

8
@mahdi: ถูกต้องหมายเลขที่สองคือ "nr วันในเดือน" == "วันสุดท้าย" โดยไม่คำนึงว่าเป็นวันไหน
RickyA

มันกลับมาผิดวันสำหรับปี 1800 กุมภาพันธ์ ฉันไม่เข้าใจ
sword1st

8
@ sword1st ฉันเห็น28ว่าเป็นคำตอบที่ถูกต้องโดยใช้กฎสำหรับปฏิทินแบบคริสต์ศักราช
Blair Conrad

ฉันไม่สามารถเป็นคนเดียวที่คิดได้ว่าmonthrangeเป็นชื่อที่สับสน คุณจะคิดว่ามันจะกลับมา(first_day, last_day)ไม่ใช่(week_day_of_first_day, number_of_days)
Flimm

146

หากคุณไม่ต้องการที่จะนำเข้าcalendarโมดูลฟังก์ชั่นสองขั้นตอนง่าย ๆ ก็สามารถ:

import datetime

def last_day_of_month(any_day):
    next_month = any_day.replace(day=28) + datetime.timedelta(days=4)  # this will never fail
    return next_month - datetime.timedelta(days=next_month.day)

ขาออก:

>>> for month in range(1, 13):
...     print last_day_of_month(datetime.date(2012, month, 1))
...
2012-01-31
2012-02-29
2012-03-31
2012-04-30
2012-05-31
2012-06-30
2012-07-31
2012-08-31
2012-09-30
2012-10-31
2012-11-30
2012-12-31

81

แก้ไข: ดูคำตอบของ @Blair Conrad สำหรับโซลูชันที่สะอาดกว่า


>>> import datetime
>>> datetime.date(2000, 2, 1) - datetime.timedelta(days=1)
datetime.date(2000, 1, 31)

43
ที่จริงผมจะเรียกทำความสะอาดนี้ยกเว้นสำหรับความจริงที่ว่ามันล้มเหลวในเดือนธันวาคมเมื่อและคุณได้รับtoday.month + 1 == 13 ValueError
ลูกธนู

4
คุณสามารถแก้ปัญหานี้ได้โดยใช้(today.month % 12) + 1ตั้งแต่12 % 12ให้ 0
bluesmoon

สวิตช์ประหยัดเวลากลางวันแปลก ๆ บางอย่างในวันที่ 31 ของเดือน (ฉันคิดว่าไม่มีวันนี้ แต่อนาคตอาจแตกต่างกัน) อาจทำให้วันที่ 31 ของเดือนนั้นมีความยาวเพียง 23 ชั่วโมงดังนั้นการลบหนึ่งวันจะช่วยให้คุณ สิ้นสุดเวลา 23:00 น. ของวันที่ 30 นั่นเป็นกรณีที่แปลกประหลาดอย่างแน่นอน แต่มันแสดงให้เห็นว่าวิธีการนั้นไม่ได้เสียง
Alfe

50

อันที่จริงมันค่อนข้างง่ายด้วยdateutil.relativedelta(package python-datetutil สำหรับ pip)day=31จะกลับวันสุดท้ายของเดือนเสมอ

ตัวอย่าง:

from datetime import datetime
from dateutil.relativedelta import relativedelta

date_in_feb = datetime.datetime(2013, 2, 21)
print datetime.datetime(2013, 2, 21) + relativedelta(day=31)  # End-of-month
>>> datetime.datetime(2013, 2, 28, 0, 0)

7
ผมเองชอบ relativedelta (เดือน + = 1 วินาที = -1) ดูเหมือนว่าชัดเจนมากขึ้นสิ่งที่เกิดขึ้น
BenH

คุณผิด. datetime(2014, 2, 1) + relativedelta(days=31)ให้datetime(2014, 3, 4, 0, 0)...
Emmanuel

9
คุณใช้วัน = แทนวัน =
Vince Spicer

@BenH นั้นขึ้นอยู่กับความหวัง (ฉันไม่แน่ใจว่ามีการระบุไว้) ว่าmonthsจะเพิ่มสิ่งแรกก่อนแล้วจึงsecondsลบออก เนื่องจากพวกเขาถูกส่งผ่านไปเพราะ**kwargsฉันจะไม่พึ่งพาสิ่งนั้นและทำชุดปฏิบัติการแยกต่างหาก: now + relative(months=+1) + relative(day=1) + relative(days=-1)ซึ่งไม่คลุมเครือ
Alfe

last_day = (<datetime_object> + relativedelta(day=31)).day
user12345

44

แก้ไข: ดูคำตอบอื่นของฉันคำตอบอื่นมันมีการนำไปใช้ที่ดีกว่าอันนี้ซึ่งฉันไปที่นี่ในกรณีที่มีคนสนใจที่จะดูว่าเครื่องคิดเลข "ของคุณเอง" จะหมุนอย่างไร

@John Millikin ให้คำตอบที่ดีพร้อมกับความยุ่งยากในการคำนวณวันแรกของเดือนถัดไป

ต่อไปนี้ไม่สวยงามเป็นพิเศษ แต่หากต้องการทราบวันสุดท้ายของเดือนที่มีวันที่ใดก็ตามคุณสามารถลอง:

def last_day_of_month(date):
    if date.month == 12:
        return date.replace(day=31)
    return date.replace(month=date.month+1, day=1) - datetime.timedelta(days=1)

>>> last_day_of_month(datetime.date(2002, 1, 17))
datetime.date(2002, 1, 31)
>>> last_day_of_month(datetime.date(2002, 12, 9))
datetime.date(2002, 12, 31)
>>> last_day_of_month(datetime.date(2008, 2, 14))
datetime.date(2008, 2, 29)

มันฟังดูไร้สาระ แต่ฉันจะได้รับวันแรกของเดือนในทำนองเดียวกันได้อย่างไร
Kishan

10
ใช่หรือไม่เสมอไป
แบลร์คอนราด

ใช่ แต่ฉันสับสนฉันกำลังมองหาบางสิ่งเช่นนี้: start_date = date (datetime.now (). ปี, datetime.now (). เดือน, 1)
Kishan

4
อา. today = datetime.date.today(); start_date = today.replace(day=1). คุณต้องการหลีกเลี่ยงการโทร datetime.now สองครั้งในกรณีที่คุณโทรมาก่อนเที่ยงคืนของวันที่ 31 ธันวาคมแล้วหลังเที่ยงคืน คุณจะได้รับ 2016-01-01 แทนที่จะเป็น 2016-12-01 หรือ 2017-01-01
แบลร์คอนราด

ตรงไปตรงมามากที่จะเข้าใจและส่งคืนอินสแตนซ์วันที่และเวลาซึ่งอาจมีประโยชน์ในหลายกรณี ประโยชน์อีกประการหนึ่งก็คือการทำงานถ้าใส่dateเป็นตัวอย่างของdatetime.date, และนอกจากนี้ยังมีdatetime.datetime pandas.Timestamp
Guilherme Salomé

26

ใช้dateutil.relativedeltaคุณจะได้รับวันสุดท้ายของเดือนเช่นนี้:

from dateutil.relativedelta import relativedelta
last_date_of_month = datetime(mydate.year, mydate.month, 1) + relativedelta(months=1, days=-1)

แนวคิดคือการได้รับวันแรกของเดือนและใช้relativedeltaเพื่อไป 1 เดือนล่วงหน้าและ 1 วันย้อนกลับดังนั้นคุณจะได้รับวันสุดท้ายของเดือนที่คุณต้องการ


13

วิธีแก้ปัญหาอื่นก็คือทำสิ่งนี้:

from datetime import datetime

def last_day_of_month(year, month):
    """ Work out the last day of the month """
    last_days = [31, 30, 29, 28, 27]
    for i in last_days:
        try:
            end = datetime(year, month, i)
        except ValueError:
            continue
        else:
            return end.date()
    return None

และใช้ฟังก์ชั่นเช่นนี้:

>>> 
>>> last_day_of_month(2008, 2)
datetime.date(2008, 2, 29)
>>> last_day_of_month(2009, 2)
datetime.date(2009, 2, 28)
>>> last_day_of_month(2008, 11)
datetime.date(2008, 11, 30)
>>> last_day_of_month(2008, 12)
datetime.date(2008, 12, 31)

5
ซับซ้อนเกินไปแบ่งกฎข้อที่สามของเซนของหลาม
markuz

11
from datetime import timedelta
(any_day.replace(day=1) + timedelta(days=32)).replace(day=1) - timedelta(days=1)

นี่คือสิ่งที่ทำจากข้อบกพร่อง) ลองวันที่ 31 มกราคม
LeartS

@ HeartS: มันใช้งานได้สำหรับฉัน จะเกิดอะไรขึ้นเมื่อคุณลองทำ
Collin Anderson

1
มันได้ผล. any_day คือวันที่ 31 มกราคมเราแทนที่วันด้วย 1 ดังนั้น 1 ม.ค. เพิ่ม 32 วันเราจะได้วันที่ 2 กุมภาพันธ์แทนที่ด้วยวัน = 1 อีกครั้งและเราได้รับ 1 กุมภาพันธ์ลบหนึ่งวันและเราได้รับ 31 มกราคมฉันไม่เห็น ปัญหาคืออะไร คุณได้อะไรวัน
Collin Anderson

9
>>> import datetime
>>> import calendar
>>> date  = datetime.datetime.now()

>>> print date
2015-03-06 01:25:14.939574

>>> print date.replace(day = 1)
2015-03-01 01:25:14.939574

>>> print date.replace(day = calendar.monthrange(date.year, date.month)[1])
2015-03-31 01:25:14.939574

9

หากคุณยินดีที่จะใช้ห้องสมุดภายนอกให้ตรวจสอบhttp://crsmithdev.com/arrow/

คุณสามารถรับวันสุดท้ายของเดือนด้วย:

import arrow
arrow.utcnow().ceil('month').date()

ส่งกลับวัตถุวันที่ซึ่งคุณสามารถทำการจัดการของคุณ


9

เพื่อให้ได้วันสุดท้ายของเดือนเราทำอะไรแบบนี้:

from datetime import date, timedelta
import calendar
last_day = date.today().replace(day=calendar.monthrange(date.today().year, date.today().month)[1])

ตอนนี้เพื่ออธิบายสิ่งที่เรากำลังทำอยู่ที่นี่เราจะแบ่งออกเป็นสองส่วน:

อันดับแรกคือการได้รับจำนวนวันของเดือนปัจจุบันซึ่งเราใช้ช่วงเดือนที่ Blair Conrad ได้กล่าวถึงวิธีแก้ปัญหาของเขาแล้ว:

calendar.monthrange(date.today().year, date.today().month)[1]

ที่สองคือการได้รับวันสุดท้ายซึ่งเราทำด้วยความช่วยเหลือของการแทนที่เช่น

>>> date.today()
datetime.date(2017, 1, 3)
>>> date.today().replace(day=31)
datetime.date(2017, 1, 31)

และเมื่อเรารวมมันเข้ากับที่กล่าวไว้ด้านบนเราจะได้คำตอบแบบไดนามิก


แม้ว่ารหัสนี้อาจช่วยในการแก้ปัญหา แต่ก็ไม่ได้อธิบายว่าทำไมและ / หรือวิธีการตอบคำถาม การให้บริบทเพิ่มเติมนี้จะช่วยเพิ่มมูลค่าทางการศึกษาในระยะยาวอย่างมีนัยสำคัญ โปรดแก้ไขคำตอบของคุณเพื่อเพิ่มคำอธิบายรวมถึงข้อ จำกัด และข้อสมมติฐานที่ใช้
Toby Speight

นี่ดูเหมือนจะตรงไปตรงมาที่สุด .. ถ้าคุณอยากจะให้สองบรรทัดคุณจะได้รับความดีdate.replace(day=day)เพื่อให้ทุกคนรู้ว่าเกิดอะไรขึ้น
Adam Starrh

9

ใน Python 3.7 มีฟังก์ชั่นที่ไม่มีเอกสารcalendar.monthlen(year, month) :

>>> calendar.monthlen(2002, 1)
31
>>> calendar.monthlen(2008, 2)
29
>>> calendar.monthlen(2100, 2)
28

มันจะเทียบเท่ากับเอกสารcalendar.monthrange(year, month)[1]การโทร


1
ดูเหมือนจะไม่ทำงานกับ Python 3.8.1: AttributeError: โมดูล 'calendar' ไม่มี attribute 'monthlen'
jeppoo1

1
@ jeppoo1: ใช่มันถูกทำเครื่องหมายเป็นส่วนตัวในbpo-28292 - คาดว่าจะมีฟังก์ชั่นที่ไม่มีเอกสาร
jfs

5
import datetime

now = datetime.datetime.now()
start_month = datetime.datetime(now.year, now.month, 1)
date_on_next_month = start_month + datetime.timedelta(35)
start_next_month = datetime.datetime(date_on_next_month.year, date_on_next_month.month, 1)
last_day_month = start_next_month - datetime.timedelta(1)

5

ใช้นุ่น!

def isMonthEnd(date):
    return date + pd.offsets.MonthEnd(0) == date

isMonthEnd(datetime(1999, 12, 31))
True
isMonthEnd(pd.Timestamp('1999-12-31'))
True
isMonthEnd(pd.Timestamp(1965, 1, 10))
False

1
คุณสามารถใช้งานได้โดยใช้pd.series.dt.is_month_end ลิงก์
Pablo

1
Pandas datetime object มีวิธีการเฉพาะสำหรับ:now=datetime.datetime.now(); pd_now = pd.to_datetime(now); print(pd_now.days_in_month)
Roei Bahumi

3

สำหรับฉันมันเป็นวิธีที่ง่ายที่สุด:

selected_date = date(some_year, some_month, some_day)

if selected_date.month == 12: # December
     last_day_selected_month = date(selected_date.year, selected_date.month, 31)
else:
     last_day_selected_month = date(selected_date.year, selected_date.month + 1, 1) - timedelta(days=1)

3

วิธีที่ง่ายที่สุด (โดยไม่ต้องนำเข้าปฏิทิน) คือการได้รับวันแรกของเดือนถัดไปจากนั้นลบหนึ่งวัน

import datetime as dt
from dateutil.relativedelta import relativedelta

thisDate = dt.datetime(2017, 11, 17)

last_day_of_the_month = dt.datetime(thisDate.year, (thisDate + relativedelta(months=1)).month, 1) - dt.timedelta(days=1)
print last_day_of_the_month

เอาท์พุท:

datetime.datetime(2017, 11, 30, 0, 0)

PS:รหัสนี้ทำงานได้เร็วขึ้นเมื่อเทียบกับimport calendarวิธีการ; ดูด้านล่าง:

import datetime as dt
import calendar
from dateutil.relativedelta import relativedelta

someDates = [dt.datetime.today() - dt.timedelta(days=x) for x in range(0, 10000)]

start1 = dt.datetime.now()
for thisDate in someDates:
    lastDay = dt.datetime(thisDate.year, (thisDate + relativedelta(months=1)).month, 1) - dt.timedelta(days=1)

print ('Time Spent= ', dt.datetime.now() - start1)


start2 = dt.datetime.now()
for thisDate in someDates:
    lastDay = dt.datetime(thisDate.year, 
                          thisDate.month, 
                          calendar.monthrange(thisDate.year, thisDate.month)[1])

print ('Time Spent= ', dt.datetime.now() - start2)

เอาท์พุท:

Time Spent=  0:00:00.097814
Time Spent=  0:00:00.109791

รหัสนี้อนุมานว่าคุณต้องการวันที่วันสุดท้ายของเดือน (เช่นไม่ใช่แค่ส่วน DD แต่เป็นวันที่ YYYYMMDD ทั้งหมด)


ทำไมคุณจะไม่ต้องการimport calendar?
Adam Venturella

1
เพราะมันเร็วกว่า ฉันได้แก้ไขคำตอบของฉันด้านบนเพื่อรวมสิ่งนี้
Vishal

@Vishal คุณมีแนวคิดที่ถูกต้อง แต่บรรทัดต่อไปนี้ไม่ใช่: `` `dt.datetime (thisDate.year, (thisDate + relativedelta (เดือน = 1)). เดือน, 1) - dt.timedelta (วัน = 1) ' `` โดยเฉพาะอย่างยิ่งหากสิ้นเดือนนี้ ลอง `` `last_date_of_month = \ first_date_of_month + relativedelta (เดือน = 1) - relativedelta (วัน = 1)` `` แทน
XValidated

3

นี่คือคำตอบอื่น ไม่จำเป็นต้องมีแพ็คเกจเพิ่มเติม

datetime.date(year + int(month/12), month%12+1, 1)-datetime.timedelta(days=1)

รับวันแรกของเดือนถัดไปและลบวันออก


2

คุณสามารถคำนวณวันที่สิ้นสุดเองได้ ตรรกะง่ายๆคือการลบวันจาก start_date ของเดือนถัดไป :)

ดังนั้นจงเขียนวิธีการที่กำหนดเอง

import datetime

def end_date_of_a_month(date):


    start_date_of_this_month = date.replace(day=1)

    month = start_date_of_this_month.month
    year = start_date_of_this_month.year
    if month == 12:
        month = 1
        year += 1
    else:
        month += 1
    next_month_start_date = start_date_of_this_month.replace(month=month, year=year)

    this_month_end_date = next_month_start_date - datetime.timedelta(days=1)
    return this_month_end_date

โทร

end_date_of_a_month(datetime.datetime.now().date())

มันจะกลับวันที่สิ้นสุดของเดือนนี้ ผ่านวันที่ไปยังฟังก์ชันนี้ ส่งคืนวันที่สิ้นสุดของเดือนนั้นให้คุณ



1

นี่เป็นทางออกที่ง่ายที่สุดสำหรับฉันในการใช้ไลบรารีดาต้าไทม์มาตรฐาน:

import datetime

def get_month_end(dt):
    first_of_month = datetime.datetime(dt.year, dt.month, 1)
    next_month_date = first_of_month + datetime.timedelta(days=32)
    new_dt = datetime.datetime(next_month_date.year, next_month_date.month, 1)
    return new_dt - datetime.timedelta(days=1)

0

นี่ไม่ได้ตอบคำถามหลัก แต่เคล็ดลับที่ดีอย่างหนึ่งในการได้รับวันทำงานสุดท้ายในเดือนนั้นคือการใช้calendar.monthcalendarซึ่งส่งกลับเมทริกซ์ของวันที่ซึ่งจัดระเบียบกับวันจันทร์เป็นคอลัมน์แรกจนถึงวันอาทิตย์สุดท้าย

# Some random date.
some_date = datetime.date(2012, 5, 23)

# Get last weekday
last_weekday = np.asarray(calendar.monthcalendar(some_date.year, some_date.month))[:,0:-2].ravel().max()

print last_weekday
31

[0:-2]สิ่งทั้งหมดคือการกำจัดคอลัมน์วันหยุดสุดสัปดาห์และโยนพวกเขาออกไป วันที่ที่อยู่นอกเดือนนั้นจะถูกระบุด้วย 0 ดังนั้นค่าสูงสุดจะไม่สนใจพวกมัน

การใช้numpy.ravelไม่จำเป็นอย่างเคร่งครัด แต่ฉันเกลียดการพึ่งพาประชุมเพียงอย่างเดียวซึ่งnumpy.ndarray.maxจะทำให้แบนราบอาร์เรย์หากไม่ได้บอกให้แกนใดทำการคำนวณ


0
import calendar
from time import gmtime, strftime
calendar.monthrange(int(strftime("%Y", gmtime())), int(strftime("%m", gmtime())))[1]

เอาท์พุท:

31



นี่จะพิมพ์วันสุดท้ายของเดือนปัจจุบันใด ๆ ในตัวอย่างนี้มันคือ 15 พฤษภาคม 2016 ดังนั้นผลลัพธ์ของคุณอาจแตกต่างกันอย่างไรก็ตามผลลัพธ์จะเป็นจำนวนวันที่เดือนปัจจุบันเป็น ดีมากถ้าคุณต้องการตรวจสอบวันสุดท้ายของเดือนด้วยการทำงาน cron รายวัน

ดังนั้น:

import calendar
from time import gmtime, strftime
lastDay = calendar.monthrange(int(strftime("%Y", gmtime())), int(strftime("%m", gmtime())))[1]
today = strftime("%d", gmtime())
lastDay == today

เอาท์พุท:

False

เว้นแต่จะเป็นวันสุดท้ายของเดือน


0

ฉันชอบวิธีนี้

import datetime
import calendar

date=datetime.datetime.now()
month_end_date=datetime.datetime(date.year,date.month,1) + datetime.timedelta(days=calendar.monthrange(date.year,date.month)[1] - 1)

0

หากคุณต้องการสร้างฟังก์ชั่นเล็ก ๆ ของคุณเองนี่เป็นจุดเริ่มต้นที่ดี:

def eomday(year, month):
    """returns the number of days in a given month"""
    days_per_month = [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31]
    d = days_per_month[month - 1]
    if month == 2 and (year % 4 == 0 and year % 100 != 0 or year % 400 == 0):
        d = 29
    return d

สำหรับสิ่งนี้คุณต้องรู้กฎสำหรับปีอธิกสุรทิน:

  • ทุกปีที่สี่
  • ยกเว้นทุก ๆ 100 ปี
  • แต่อีกทุก 400 ปี

1
แน่นอน แต่ไลบรารีระบบมีข้อมูลนี้อยู่แล้วและควรมีการเปลี่ยนแปลงกฎโดยพระราชกฤษฎีกาการปรับปรุงห้องสมุดเป็นปัญหาของบุคคลอื่น
Jasen

เป็นไปได้ แต่ไม่น่าเป็นไปได้สูงและแม้ว่า - จะกัดคุณในเวลาประมาณ 2,000 ปี ... en.wikipedia.org/wiki/Gregorian_calendar#Accuracy
คณิตศาสตร์

กฎเหล่านี้ใช้งานไม่ได้ใน 500 ปีที่ผ่านมาฉันไม่มีความมั่นใจว่าพวกเขาจะยืนเป็นพัน ๆ ปีสู่อนาคต
Jasen

0

หากคุณผ่านช่วงวันที่คุณสามารถใช้สิ่งนี้:

def last_day_of_month(any_days):
    res = []
    for any_day in any_days:
        nday = any_day.days_in_month -any_day.day
        res.append(any_day + timedelta(days=nday))
    return res

0

ในรหัสด้านล่าง'get_last_day_of_month (dt)'จะให้สิ่งนี้กับคุณโดยมีวันที่ในรูปแบบสตริงเช่น 'YYYY-MM-DD'

import datetime

def DateTime( d ):
    return datetime.datetime.strptime( d, '%Y-%m-%d').date()

def RelativeDate( start, num_days ):
    d = DateTime( start )
    return str( d + datetime.timedelta( days = num_days ) )

def get_first_day_of_month( dt ):
    return dt[:-2] + '01'

def get_last_day_of_month( dt ):
    fd = get_first_day_of_month( dt )
    fd_next_month = get_first_day_of_month( RelativeDate( fd, 31 ) )
    return RelativeDate( fd_next_month, -1 )

0

วิธีที่ง่ายที่สุดคือการใช้datetimeและคณิตศาสตร์วันที่เช่นลบวันจากวันแรกของเดือนถัดไป:

import datetime

def last_day_of_month(d: datetime.date) -> datetime.date:
    return (
        datetime.date(d.year + d.month//12, d.month % 12 + 1, 1) -
        datetime.timedelta(days=1)
    )

อีกวิธีหนึ่งคุณสามารถใช้calendar.monthrange()เพื่อรับจำนวนวันในหนึ่งเดือน (คำนึงถึงปีอธิกสุรทิน) และอัปเดตวันที่ตามลำดับ:

import calendar, datetime

def last_day_of_month(d: datetime.date) -> datetime.date:
    return d.replace(day=calendar.monthrange(d.year, d.month)[1])

มาตรฐานด่วนแสดงให้เห็นว่ารุ่นแรกเร็วขึ้นอย่างเห็นได้ชัด:

In [14]: today = datetime.date.today()

In [15]: %timeit last_day_of_month_dt(today)
918 ns ± 3.54 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each)

In [16]: %timeit last_day_of_month_calendar(today)
1.4 µs ± 17.3 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each)

0

นี่คือรุ่นยาว (เข้าใจง่าย) แต่ดูแลปีอธิกสุรทิน

ไชโย

def last_day_month(year, month):
    leap_year_flag = 0
    end_dates = {
        1: 31,
        2: 28,
        3: 31,
        4: 30,
        5: 31,
        6: 30,
        7: 31,
        8: 31,
        9: 30,
        10: 31,
        11: 30,
        12: 31
    }

    # Checking for regular leap year    
    if year % 4 == 0:
        leap_year_flag = 1
    else:
        leap_year_flag = 0

    # Checking for century leap year    
    if year % 100 == 0:
        if year % 400 == 0:
            leap_year_flag = 1
        else:
            leap_year_flag = 0
    else:
        pass

    # return end date of the year-month
    if leap_year_flag == 1 and month == 2:
        return 29
    elif leap_year_flag == 1 and month != 2:
        return end_dates[month]
    else:
        return end_dates[month]

คุณสามารถลบelse: passและกำจัดได้ if year % 400 == 0: leap_year_flag = 1ด้วยการแก้ไขเล็กน้อย
canbax

-1

นี่คือวิธีแก้ปัญหาโดยใช้ lambdas python:

next_month = lambda y, m, d: (y, m + 1, 1) if m + 1 < 13 else ( y+1 , 1, 1)
month_end  = lambda dte: date( *next_month( *dte.timetuple()[:3] ) ) - timedelta(days=1)

next_monthแลมบ์ดาพบว่าการเป็นตัวแทน tuple ของวันแรกของเดือนถัดไปและม้วนไปในปีถัดไป month_endแลมบ์ดาแปลงวันที่ ( dte) เพื่อ tuple ที่ใช้next_monthและสร้างวันที่ใหม่ แล้ว "สิ้นเดือน" timedelta(days=1)เป็นเพียงเดือนถัดไปเป็นครั้งแรกในวันลบ

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