ฉันจะคำนวณวันที่หกเดือนจากวันที่ปัจจุบันโดยใช้โมดูล Python ได้อย่างไร


391

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

เหตุผลที่ผมต้องการสร้างวันที่ 6 เดือนนับจากวันที่ปัจจุบันคือการผลิตวันที่ตรวจสอบ หากผู้ใช้ป้อนข้อมูลเข้าสู่ระบบผู้ใช้จะมีวันที่ตรวจสอบ 6 เดือนนับจากวันที่พวกเขาป้อนข้อมูล


2
คุณจะต้องเจาะจงมากขึ้น: เมื่อหกเดือนมีนาคม 31? และตั้งแต่วันที่ 30 สิงหาคม
kmkaplan

3
ใช่การแก้ไขช่วย: หมายความว่าคุณสามารถใช้งานได้ 6 เดือนถึง 183 วันโดยไม่มีผลกระทบใด ๆ ดังนั้นการเพิ่ม 183 วันในวันนี้จึงเป็นการหลอกลวง
kmkaplan

15
ความคิดเห็นด้านบนทำให้ฉันงี่เง่า แนวคิดของ "การเพิ่มหกเดือน" ค่อนข้างชัดเจน - นำองค์ประกอบเดือนและเพิ่ม6ไปด้วยการสนับสนุนสำหรับการพลิกปี (และขี่จักรยานเดือนกลับไป1) ถ้าเราไปผ่านเดือนธันวาคม สิ่งนี้เกิดขึ้นได้อย่างแท้จริงrelativedeltaและสิ่งที่จริง ๆ แล้วคือสิ่งที่ภาษาการเขียนโปรแกรมทุกภาษาพร้อมสนับสนุนแนวคิดแบบนี้
Kirk Woll

5
@ KirkWoll: ฉันแน่ใจว่ามันค่อนข้างชัดเจน แต่ก็ยังแตกต่างกันสำหรับใครก็ตามที่พูด งูใหญ่: ช่วยให้date(2015, 3, 31) + relativedelta(months = 6) datetime.date(2015, 9, 30)Perl: ช่วยให้DateTime->new(year=>2000, month=>3, day=>31)->add(months=>6) 2000-10-01T00:00:00Php: date_create('2000-03-31', new DateTimeZone('UTC'))->add(new DateInterval('P6M'))ให้ 2000-10-01 เลือกพิษของคุณ
kmkaplan

2
... การเพิ่ม 182 ดูเหมือนจะเป็นประโยชน์มากขึ้นสำหรับการสร้างวันที่ตรวจสอบ : มันทำให้วันในสัปดาห์เหมือนเดิม
Wolf

คำตอบ:


1047

ฉันพบวิธีแก้ปัญหานี้ดี (ใช้ส่วนขยายของ python-dateutil )

from datetime import date
from dateutil.relativedelta import relativedelta

six_months = date.today() + relativedelta(months=+6)

ข้อดีของวิธีการนี้คือการดูแลปัญหาที่เกิดขึ้นกับ 28, 30, 31 วันเป็นต้นซึ่งจะมีประโยชน์มากในการจัดการกฎเกณฑ์ทางธุรกิจและสถานการณ์ (เช่นการสร้างใบแจ้งหนี้เป็นต้น)

$ date(2010,12,31)+relativedelta(months=+1)
  datetime.date(2011, 1, 31)

$ date(2010,12,31)+relativedelta(months=+2)
  datetime.date(2011, 2, 28)

2
+6 เป็นตัวบ่งชี้ว่ามันอาจเป็น -6, ใช้กับวันและปีเหมือนกัน :)
securecurve

5
@sliders_alpha คุณต้องติดตั้งแพ็คเกจ python-dateutil (pip install python-dateutil)
poiuytrez

18
นี่คือทางออกที่ถูกต้อง ถ้า OP ถาม 6 ปีแทนที่จะเป็น 6 เดือนคำตอบที่ได้รับการอนุมัติจะล้มเหลวอย่างน่าสังเวช ดังนั้นเราควรระลึกไว้เสมอว่าคำตอบนั้นมีค่ามากขึ้น
Daniel F

3
โปรดทราบว่าrelativedeltaฟังก์ชั่นนี้ยังใช้monthเป็นอาร์กิวเมนต์ซึ่งโดยทั่วไปจะแทนที่ / sets / fix เดือนในวันที่ส่งผ่านซึ่งแตกต่างจากการเพิ่มเดือนมากขึ้น เพียงข้อควรระวังสำหรับคนสงสัยว่าถ้าฟังก์ชั่นที่ถูกทำลายเพราะพวกเขาลืมเสริมsในเดือน
shad0w_wa1k3r

1
ฉันอยากรู้อยากเห็น: ไม่มีใครรู้ว่าทำไมค่าเริ่มต้นนี้ไม่รวมอยู่ด้วย Timedelta ดูเหมือนว่าจะบรรจุด้วยdatetimeโดยค่าเริ่มต้น ที่จริงฉันคิดว่าฉันสามารถผ่าน "เดือน" ไปที่ timedelta
dTanMan

51

นั่นขึ้นอยู่กับว่าคุณหมายถึงอะไร 6 เดือนจากวันที่ปัจจุบัน

  1. ใช้เดือนธรรมชาติ:

    (day, month, year) = (day, (month + 5) % 12 + 1, year + (month + 5)/12)
  2. ใช้คำจำกัดความของนายธนาคาร 6 * 30:

    date += datetime.timedelta(6 * 30)

3
คุณสามารถนิยามในครึ่งปี (183 วัน) บวกกับนิยามที่ 26 สัปดาห์ได้หรือไม่? มันช่วยให้พวกเขามีทั้งหมดในที่เดียว
S.Lott

11
เพียงคำพูดสั้น ๆ : ฉันคิดว่าสำหรับเดือนสูตรจะแทน (เดือน +5)% 12 + 1 b / c สำหรับเดือนมิถุนายนสูตรของคุณให้ 0 ในขณะที่ผลลัพธ์ที่คาดหวังคือ 12 ... แม้จะมีข้อผิดพลาดเล็กน้อยนี้ ใจของฉันคำตอบของคุณคือคำตอบที่ดีที่สุด
PierrOz

3
และเหมือนกันสำหรับปี: ควรเป็นปี + (เดือน + 5) / 12
PierrOz

7
เกิดอะไรขึ้นถ้าวันที่ 31 และเดือนหกเดือนต่อมาไม่สามารถมี 31 วัน (ซึ่งเป็นกรณีสำหรับเดือนส่วนใหญ่ที่มี 31 วัน)?
akv

4
Downvote เนื่องจากโซลูชันแรก(day, month, year) = (day, (month+6)%12, year+(month+6)/12)สามารถใช้งานได้เนื่องจากสร้างวันที่ไม่ถูกต้องเช่น(31, 8, 2015)->(31, 2, 2016)
ohw

37

ด้วย Python 3.x คุณสามารถทำสิ่งนี้ได้:

from datetime import datetime, timedelta
from dateutil.relativedelta import *

date = datetime.now()
print(date)
# 2018-09-24 13:24:04.007620

date = date + relativedelta(months=+6)
print(date)
# 2019-03-24 13:24:04.007620

แต่คุณจะต้องติดตั้งโมดูลpython-dateutil :

pip install python-dateutil

โหวตให้สำหรับpip install ...
นาธาน

from dateutil.relativedelta import relativedeltaผมอยากแนะนำให้ การใช้import *ไม่ชัดเจน
Sam Morgan

19

สำหรับการคำนวณต้นเดือนถึงเดือน:

from datetime import timedelta
from dateutil.relativedelta import relativedelta

end_date = start_date + relativedelta(months=delta_period) + timedelta(days=-delta_period)

18
นี่ไม่ใช่วิธีการแก้ปัญหาสัมพันธ์ที่กล่าวถึงข้างต้นในความคิดเห็น เลื่อนไปเรื่อย ๆ เพื่อแก้ปัญหาด้วย 600+ upvotes
Nostalg.io

15

คุณหมายถึงอะไรโดย "6 เดือน"

2009-02-13 + 6 เดือน == 2009-08-13 หรือมันคือ 2009-02-13 + 6 * 30 วัน?

import mx.DateTime as dt

#6 Months
dt.now()+dt.RelativeDateTime(months=6)
#result is '2009-08-13 16:28:00.84'

#6*30 days
dt.now()+dt.RelativeDateTime(days=30*6)
#result is '2009-08-12 16:30:03.35'

ข้อมูลเพิ่มเติมเกี่ยวกับmx.DateTime


14

ดังนั้นนี่คือตัวอย่างของสิ่งdateutil.relativedeltaที่ฉันพบว่ามีประโยชน์สำหรับการทำซ้ำตลอดปีที่ผ่านมาข้ามเดือนทุกครั้งจนถึงวันที่ปัจจุบัน:

>>> import datetime
>>> from dateutil.relativedelta import relativedelta
>>> today = datetime.datetime.today()
>>> month_count = 0
>>> while month_count < 12:
...  day = today - relativedelta(months=month_count)
...  print day
...  month_count += 1
... 
2010-07-07 10:51:45.187968
2010-06-07 10:51:45.187968
2010-05-07 10:51:45.187968
2010-04-07 10:51:45.187968
2010-03-07 10:51:45.187968
2010-02-07 10:51:45.187968
2010-01-07 10:51:45.187968
2009-12-07 10:51:45.187968
2009-11-07 10:51:45.187968
2009-10-07 10:51:45.187968
2009-09-07 10:51:45.187968
2009-08-07 10:51:45.187968

เช่นเดียวกับคำตอบอื่น ๆ คุณต้องเข้าใจความหมายของคำว่า "6 เดือนนับจากนี้" หากคุณหมายถึง "วันนี้วันที่ของเดือนในเดือนหกปีในอนาคต" สิ่งนี้จะทำ:

datetime.datetime.now() + relativedelta(months=6)

14

โซลูชันนี้ทำงานได้อย่างถูกต้องในเดือนธันวาคมซึ่งคำตอบส่วนใหญ่ในหน้านี้ทำไม่ได้ คุณต้องเปลี่ยนเดือนจากฐาน 1 (เช่น Jan = 1) เป็นฐาน 0 (เช่น Jan = 0) ก่อนใช้โมดูลัส (%) หรือการหารจำนวนเต็ม (//) มิฉะนั้นพฤศจิกายน (11) บวก 1 เดือนจะให้ 12 ซึ่งเมื่อค้นหาส่วนที่เหลือ (12% 12) จะให้ 0

(และอย่าแนะนำ "(เดือน% 12) + 1" หรือตุลาคม + 1 = ธันวาคม!)

def AddMonths(d,x):
    newmonth = ((( d.month - 1) + x ) % 12 ) + 1
    newyear  = int(d.year + ((( d.month - 1) + x ) / 12 ))
    return datetime.date( newyear, newmonth, d.day)

อย่างไรก็ตาม ... นี่ไม่ใช่ปัญหาสำหรับบัญชีเช่น 31 ม.ค. + หนึ่งเดือน ดังนั้นเรากลับไปที่ OP - คุณหมายถึงอะไรโดยการเพิ่มเดือน ทางออกหนึ่งคือการย้อนกลับจนกว่าคุณจะถึงวันที่ถูกต้องเนื่องจากคนส่วนใหญ่จะเข้าใจวันสุดท้ายของมกราคมบวกหนึ่งเดือนเท่ากับวันสุดท้ายของเดือนกุมภาพันธ์ซึ่งจะทำงานในจำนวนลบของเดือนเช่นกัน พิสูจน์:

>>> import datetime
>>> AddMonths(datetime.datetime(2010,8,25),1)
datetime.date(2010, 9, 25)
>>> AddMonths(datetime.datetime(2010,8,25),4)
datetime.date(2010, 12, 25)
>>> AddMonths(datetime.datetime(2010,8,25),5)
datetime.date(2011, 1, 25)
>>> AddMonths(datetime.datetime(2010,8,25),13)
datetime.date(2011, 9, 25)
>>> AddMonths(datetime.datetime(2010,8,25),24)
datetime.date(2012, 8, 25)
>>> AddMonths(datetime.datetime(2010,8,25),-1)
datetime.date(2010, 7, 25)
>>> AddMonths(datetime.datetime(2010,8,25),0)
datetime.date(2010, 8, 25)
>>> AddMonths(datetime.datetime(2010,8,25),-12)
datetime.date(2009, 8, 25)
>>> AddMonths(datetime.datetime(2010,8,25),-8)
datetime.date(2009, 12, 25)
>>> AddMonths(datetime.datetime(2010,8,25),-7)
datetime.date(2010, 1, 25)>>> 

3
แก้ไขปัญหา "31 ม.ค. + หนึ่งเดือน": days_in_month = calendar.monthrange (ปีใหม่ปีใหม่) [1]; newday = min (d.day, days_in_month); (กระแทกวันลงถ้าใหญ่เกินไปเช่น 31 ก.พ.
Curtis Yallop

สิ่งนี้ใช้ได้กับฉันโดยการแปลงปีใหม่เป็นประเภทข้อมูลจำนวนเต็ม def AddMonths (d, x): newmonth = (((d.month - 1) + x)% 12) + 1 ปีใหม่ = d.year + int (( (d.month - 1) + x) / 12) ส่งกลับ datetime.date (ปีใหม่, newmonth, d.day)
Manmeet Singh

12

ฉันรู้ว่านี่เป็นเวลา 6 เดือน แต่คำตอบแสดงใน google สำหรับ "การเพิ่มเดือนลงในไพ ธ อน" ถ้าคุณเพิ่มอีกหนึ่งเดือน:

import calendar

date = datetime.date.today()    //Or your date

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

สิ่งนี้จะนับวันในเดือนปัจจุบันและเพิ่มลงในวันที่ปัจจุบันการใช้ 365/12 จะโฆษณา 1/12 ของปีอาจทำให้เกิดปัญหาในระยะสั้น / ยาวเดือนหากทำซ้ำในวันที่



10

เพียงใช้วิธีการschedupleเพื่อแยกเดือนเพิ่มเดือนของคุณและสร้าง Dateobject ใหม่ หากมีวิธีที่มีอยู่แล้วสำหรับสิ่งนี้ฉันไม่ทราบ

import datetime

def in_the_future(months=1):
    year, month, day = datetime.date.today().timetuple()[:3]
    new_month = month + months
    return datetime.date(year + (new_month / 12), (new_month % 12) or 12, day)

API นั้นค่อนข้างงุ่มง่าม แต่ทำงานเป็นตัวอย่าง จะเห็นได้ชัดว่าจะไม่ทำงานในมุมกรณีเช่น 2008-01-31 + 1 เดือน :)


3
เกิดข้อผิดพลาดในรหัสของคุณ: ควรจะเป็นnew_month % 12 (new_month % 12) or 12มิฉะนั้นถ้าคุณลองในเดือนพฤศจิกายนคุณจะได้รับข้อผิดพลาด :)
Jordan Reiter

อันนี้จริง ๆ แล้วสะอาดกว่าโซลูชันที่ยอมรับ สิ่งนี้ไม่ต้องการการนำเข้าใหม่ใด ๆ เพียงแค่คณิตศาสตร์พื้นฐาน
Simon PA

return datetime.date (ปี + (new_month / / 12), (new_month% 12) หรือ 12 วัน)
paytam

9

แพ็คเกจ Dateutilมีการใช้งานฟังก์ชั่นดังกล่าว แต่ระวังให้ดีว่าสิ่งนี้จะไร้เดียงสาเหมือนอย่างที่คนอื่น ๆ ชี้ไปแล้ว


dateutil น่ากลัว มันสามารถติดตั้งได้ด้วย easy_install เช่นกัน
Soviut

ยอดเยี่ยม ขอบคุณที่บอกว่า ดูเหมือนว่าจะเป็นพระเจ้าที่ส่งมา
ayaz

9

การใช้ไลบรารีมาตรฐานของ Python เช่นไม่มีdateutilหรืออื่น ๆ และแก้ไขปัญหา '31 กุมภาพันธ์':

import datetime
import calendar

def add_months(date, months):
    months_count = date.month + months

    # Calculate the year
    year = date.year + int(months_count / 12)

    # Calculate the month
    month = (months_count % 12)
    if month == 0:
        month = 12

    # Calculate the day
    day = date.day
    last_day_of_month = calendar.monthrange(year, month)[1]
    if day > last_day_of_month:
        day = last_day_of_month

    new_date = datetime.date(year, month, day)
    return new_date

การทดสอบ:

>>>date = datetime.date(2018, 11, 30)

>>>print(date, add_months(date, 3))
(datetime.date(2018, 11, 30), datetime.date(2019, 2, 28))

>>>print(date, add_months(date, 14))
(datetime.date(2018, 12, 31), datetime.date(2020, 2, 29))

สิ่งนี้มีข้อบกพร่อง: หากเดือนเป้าหมายคือเดือนธันวาคมมันจะส่งคืนวันที่ในภายหลังหนึ่งปีหลังจากที่จำเป็น ตัวอย่าง: add_months(datetime.date(2018, 11, 30), 1)ผลตอบแทนdatetime.date(2019, 12, 30)(ปีควรเป็น 2018 ไม่ใช่ 2019) ดังนั้นควรใช้ไลบรารี่ที่ผ่านการทดสอบมาเป็นพิเศษและดีกว่านี้! ถ้าคุณต้องการจริงๆที่จะใช้เฉพาะโมดูลมาตรฐานห้องสมุดดูคำตอบของฉันคำถามที่คล้ายกัน
taleinat

5

ฉันมีวิธีที่ดีกว่าในการแก้ปัญหา '31 กุมภาพันธ์':

def add_months(start_date, months):
    import calendar

    year = start_date.year + (months / 12)
    month = start_date.month + (months % 12)
    day = start_date.day

    if month > 12:
        month = month % 12
        year = year + 1

    days_next = calendar.monthrange(year, month)[1]
    if day > days_next:
        day = days_next

    return start_date.replace(year, month, day)

ฉันคิดว่ามันใช้งานได้กับตัวเลขติดลบ (เพื่อลบเดือน) แต่ฉันไม่ได้ทดสอบสิ่งนี้มากนัก


1
คำตอบนี้มีข้อดีในการแก้ปัญหาอย่างถูกต้องโดยใช้ไลบรารี Python ในตัวเท่านั้น ตรวจสอบ stackoverflow.com/a/4131114/302264 สำหรับคำตอบที่เทียบเท่า แต่กระชับกว่าเล็กน้อย
Eduardo Dobay

3

คลาส QDate ของ PyQt4 มีฟังก์ชั่น addmonths

>>>from PyQt4.QtCore import QDate  
>>>dt = QDate(2009,12,31)  
>>>required = dt.addMonths(6) 

>>>required
PyQt4.QtCore.QDate(2010, 6, 30)

>>>required.toPyDate()
datetime.date(2010, 6, 30)

3

แล้วเรื่องนี้ล่ะ ไม่ได้ใช้ห้องสมุดอื่น ( dateutil) หรือtimedelta? การสร้างคำตอบของvartecฉันทำสิ่งนี้และฉันเชื่อว่ามันใช้งานได้:

import datetime

today = datetime.date.today()
six_months_from_today = datetime.date(today.year + (today.month + 6)/12, (today.month + 6) % 12, today.day)

ฉันลองใช้timedeltaแต่เป็นเพราะมันนับวัน365/2หรือ6*356/12แปลไม่ถึง 6 เดือน แต่ก็เป็น 182 วัน เช่น

day = datetime.date(2015, 3, 10)
print day
>>> 2015-03-10

print (day + datetime.timedelta(6*365/12))
>>> 2015-09-08

ฉันเชื่อว่าเรามักจะคิดว่า 6 เดือนจากวันหนึ่งจะมาถึงในวันเดียวกันของเดือน แต่ 6 เดือนต่อมา (เช่น2015-03-10-> 2015-09-10ไม่2015-09-08 )

ฉันหวังว่าคุณจะพบว่ามีประโยชน์


1
day + datetime.timedelta(6*365/12)จะไม่ทำงานเสมอไปเนื่องจากบางปีมี 365 วันและอื่น ๆ มี 366 วัน
3kstc

3

สิ่งนี้ไม่ตอบคำถามเฉพาะ (ใช้ datetimeเท่านั้น) แต่ระบุว่าคนอื่น ๆ pandasปัญหาการใช้งานของโมดูลที่แตกต่างกันที่นี่มีวิธีใช้

import datetime as dt
import pandas as pd

date = dt.date.today() - \
       pd.offsets.DateOffset(months=6)

print(date)

2019-05-04 00:00:00

ซึ่งทำงานได้ตามที่คาดไว้ในปีอธิกสุรทิน

date = dt.datetime(2019,8,29) - \
       pd.offsets.DateOffset(months=6)
print(date)

2019-02-28 00:00:00

2

แก้ไข AddMonths () เพื่อใช้ใน Zope และจัดการหมายเลขวันที่ไม่ถูกต้อง:

def AddMonths(d,x):
    days_of_month = [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31]
    newmonth = ((( d.month() - 1) + x ) % 12 ) + 1
    newyear  = d.year() + ((( d.month() - 1) + x ) // 12 ) 
    if d.day() > days_of_month[newmonth-1]:
      newday = days_of_month[newmonth-1]
    else:
      newday = d.day() 
    return DateTime( newyear, newmonth, newday)

นี่ดูเหมือนจะไม่พิจารณาปีอธิกสุรทิน (29 วันใน feb)
จัดการกับ

2
import time

def add_month(start_time, months):  

        ret = time.strptime(start_time, '%Y-%m-%d')
        t = list(ret)

        t[1] += months

        if t[1] > 12:
            t[0] += 1 + int(months / 12)

            t[1] %= 12

        return int(time.mktime(tuple(t)))

1
import datetime


'''
Created on 2011-03-09

@author: tonydiep
'''

def add_business_months(start_date, months_to_add):
    """
    Add months in the way business people think of months. 
    Jan 31, 2011 + 1 month = Feb 28, 2011 to business people
    Method: Add the number of months, roll back the date until it becomes a valid date
    """
    # determine year
    years_change = months_to_add / 12

    # determine if there is carryover from adding months
    if (start_date.month + (months_to_add % 12) > 12 ):
        years_change = years_change + 1

    new_year = start_date.year + years_change

    # determine month
    work = months_to_add % 12
    if 0 == work:
        new_month = start_date.month
    else:
        new_month = (start_date.month + (work % 12)) % 12

    if 0 == new_month:
        new_month = 12 

    # determine day of the month
    new_day = start_date.day
    if(new_day in [31, 30, 29, 28]):
        #user means end of the month
        new_day = 31


    new_date = None
    while (None == new_date and 27 < new_day):
        try:
            new_date = start_date.replace(year=new_year, month=new_month, day=new_day)
        except:
            new_day = new_day - 1   #wind down until we get to a valid date

    return new_date


if __name__ == '__main__':
    #tests
    dates = [datetime.date(2011, 1, 31),
             datetime.date(2011, 2, 28),
             datetime.date(2011, 3, 28),
             datetime.date(2011, 4, 28),
             datetime.date(2011, 5, 28),
             datetime.date(2011, 6, 28),
             datetime.date(2011, 7, 28),
             datetime.date(2011, 8, 28),
             datetime.date(2011, 9, 28),
             datetime.date(2011, 10, 28),
             datetime.date(2011, 11, 28),
             datetime.date(2011, 12, 28),
             ]
    months = range(1, 24)
    for start_date in dates:
        for m in months:
            end_date = add_business_months(start_date, m)
            print("%s\t%s\t%s" %(start_date, end_date, m))

1

แก้ไขคำตอบของ Johannes Wei ในกรณีที่ 1new_month = 121 สิ่งนี้ทำงานได้อย่างสมบูรณ์แบบสำหรับฉัน เดือนอาจเป็นบวกหรือลบ

def addMonth(d,months=1):
    year, month, day = d.timetuple()[:3]
    new_month = month + months
    return datetime.date(year + ((new_month-1) / 12), (new_month-1) % 12 +1, day)

2
มันไม่ได้ทำงานอย่างสมบูรณ์แบบเมื่อวันในวันที่เริ่มต้นมากกว่าจำนวนวันในเดือนเป้าหมาย ตัวอย่าง: 2001-01-31 บวกหนึ่งเดือนพยายามสร้างวันที่ 2001-02-31
John Machin

1

วิธีการแก้ปัญหาอื่น - หวังว่าบางคนจะชอบ:

def add_months(d, months):
    return d.replace(year=d.year+months//12).replace(month=(d.month+months)%12)

โซลูชันนี้ใช้งานไม่ได้สำหรับ 29,30,31 วันสำหรับทุกกรณีดังนั้นจึงจำเป็นต้องใช้โซลูชันที่มีประสิทธิภาพยิ่งขึ้น (ซึ่งไม่ได้ดีอีกต่อไป :)):

def add_months(d, months):
    for i in range(4):
        day = d.day - i
        try:
            return d.replace(day=day).replace(year=d.year+int(months)//12).replace(month=(d.month+int(months))%12)
        except:
            pass
    raise Exception("should not happen")

1

จากคำตอบนี้ดูparsedatetime ตัวอย่างรหัสดังต่อไปนี้ รายละเอียดเพิ่มเติม: การทดสอบหน่วยที่มีหลายภาษาธรรมชาติ -> ตัวอย่างการแปลง YYYY-MM-DDและชัดเจนparsedatetime แปลงความท้าทาย

#!/usr/bin/env python
# -*- coding: utf-8 -*-
import time, calendar
from datetime import date

# from https://github.com/bear/parsedatetime
import parsedatetime as pdt

def print_todays_date():
    todays_day_of_week = calendar.day_name[date.today().weekday()]
    print "today's date = " + todays_day_of_week + ', ' + \
                              time.strftime('%Y-%m-%d')

def convert_date(natural_language_date):
    cal = pdt.Calendar()
    (struct_time_date, success) = cal.parse(natural_language_date)
    if success:
        formal_date = time.strftime('%Y-%m-%d', struct_time_date)
    else:
        formal_date = '(conversion failed)'
    print '{0:12s} -> {1:10s}'.format(natural_language_date, formal_date)

print_todays_date()
convert_date('6 months')

โค้ดด้านบนสร้างสิ่งต่อไปนี้จากเครื่อง MacOSX:

$ ./parsedatetime_simple.py 
today's date = Wednesday, 2015-05-13
6 months     -> 2015-11-13
$ 

1

นี่คือตัวอย่างที่ช่วยให้ผู้ใช้ตัดสินใจว่าจะคืนวันที่วันใดมากกว่าจำนวนวันในเดือน

def add_months(date, months, endOfMonthBehaviour='RoundUp'):
    assert endOfMonthBehaviour in ['RoundDown', 'RoundIn', 'RoundOut', 'RoundUp'], \
        'Unknown end of month behaviour'
    year = date.year + (date.month + months - 1) / 12
    month = (date.month + months - 1) % 12 + 1
    day = date.day
    last = monthrange(year, month)[1]
    if day > last:
        if endOfMonthBehaviour == 'RoundDown' or \
            endOfMonthBehaviour == 'RoundOut' and months < 0 or \
            endOfMonthBehaviour == 'RoundIn' and months > 0:
            day = last
        elif endOfMonthBehaviour == 'RoundUp' or \
            endOfMonthBehaviour == 'RoundOut' and months > 0 or \
            endOfMonthBehaviour == 'RoundIn' and months < 0:
            # we don't need to worry about incrementing the year
            # because there will never be a day in December > 31
            month += 1
            day = 1
    return datetime.date(year, month, day)


>>> from calendar import monthrange
>>> import datetime
>>> add_months(datetime.datetime(2016, 1, 31), 1)
datetime.date(2016, 3, 1)
>>> add_months(datetime.datetime(2016, 1, 31), -2)
datetime.date(2015, 12, 1)
>>> add_months(datetime.datetime(2016, 1, 31), -2, 'RoundDown')
datetime.date(2015, 11, 30)

1

เนื่องจากตัวแปร datetime ของคุณเรียกว่าวันที่:

date=datetime.datetime(year=date.year+int((date.month+6)/12),
                       month=(date.month+6)%13 + (1 if (date.month + 
                       months>12) else 0), day=date.day)

1

ฟังก์ชั่นทั่วไปเพื่อรับวันที่ถัดไปหลังจาก / ก่อน x เดือน

จากวันที่นำเข้าวันที่และเวลา

def after_month (Given_date เดือน):
    yyyy = int (((Given_date.year * 12 + given_date.month) + เดือน) / 12)
    mm = int (((Given_date.year * 12 + given_date.month) + เดือน)% 12)

    ถ้า mm == 0:
        yyyy - = 1
        mm = 12
    return Given_date.replace (ปี = yyyy, เดือน = mm)


ถ้า __name__ == "__main__":
    today = date.today ()
    พิมพ์ (วันนี้)

    สำหรับ mm ใน [-12, -1, 0, 1, 2, 12, 20]:
        next_date = after_month (วันนี้, มม.)
        พิมพ์ (next_date)

นี่เป็นคำตอบที่ชัดเจนที่สุด ง่ายและมีประสิทธิภาพโดยไม่มีปัญหาการปัดเศษ
jprobichaud

1

คำแนะนำด่วนคือArrow

ลูกศรติดตั้ง pip

>>> import arrow

>>> arrow.now().date()
datetime.date(2019, 6, 28)
>>> arrow.now().shift(months=6).date()
datetime.date(2019, 12, 28)

0

ใช้โมดูล python datetime เพื่อเพิ่ม timedelta หกเดือนใน datetime.today ()

http://docs.python.org/library/datetime.html

คุณจะแน่นอนจะต้องแก้ปัญหาที่เกิดขึ้นโดยโยฮันเนWeiß--สิ่งที่ทำคุณหมายถึงโดย 6 เดือน?


1
timedelta ไม่รองรับหลายเดือนดังนั้นจึงไม่ต้องตอบคำถามที่เป็นไปได้ "ประมาณกี่วันในรอบ 6 เดือน" รหัสของ Eef จะกำหนดวันที่ตรวจทานดังนั้นฉันขอแนะนำให้คุณพิจารณาตั้ง timedelta โดยใช้วัน (6 * 30) หากช่วงเวลาแสดงถึงการเข้าถึงผลิตภัณฑ์ / บริการของลูกค้าอาจต้องมีคำจำกัดความ / คำจำกัดความทางธุรกิจ
คาร์ล

0

นี่คือสิ่งที่ฉันมาด้วย มันย้ายจำนวนเดือนและปีที่ถูกต้อง แต่ไม่สนใจวัน (ซึ่งเป็นสิ่งที่ฉันต้องการในสถานการณ์ของฉัน)

import datetime

month_dt = 4
today = datetime.date.today()
y,m = today.year, today.month
m += month_dt-1
year_dt = m//12
new_month = m%12
new_date = datetime.date(y+year_dt, new_month+1, 1)

0

ฉันใช้ฟังก์ชั่นนี้เพื่อเปลี่ยนปีและเดือน แต่เก็บวัน:

def replace_month_year(date1, year2, month2):
    try:
        date2 = date1.replace(month = month2, year = year2)
    except:
        date2 = datetime.date(year2, month2 + 1, 1) - datetime.timedelta(days=1)
    return date2

คุณควรเขียน:

new_year = my_date.year + (my_date.month + 6) / 12
new_month = (my_date.month + 6) % 12
new_date = replace_month_year(my_date, new_year, new_month)

0

ฉันคิดว่าการทำสิ่งนี้จะปลอดภัยกว่าการเพิ่มวันด้วยตนเอง:

import datetime
today = datetime.date.today()

def addMonths(dt, months = 0):
    new_month = months + dt.month
    year_inc = 0
    if new_month>12:
        year_inc +=1
        new_month -=12
    return dt.replace(month = new_month, year = dt.year+year_inc)

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