วันที่ python ของเดือนก่อนหน้า


133

ฉันพยายามหาวันที่ของเดือนก่อนด้วย python นี่คือสิ่งที่ฉันได้ลอง:

str( time.strftime('%Y') ) + str( int(time.strftime('%m'))-1 )

อย่างไรก็ตามวิธีนี้ไม่ดีด้วยเหตุผล 2 ประการประการแรกจะส่งคืน 20122 สำหรับเดือนกุมภาพันธ์ของปี 2012 (แทนที่จะเป็น 201202) และประการที่สองจะส่งคืน 0 แทนที่จะเป็น 12 ในเดือนมกราคม

ฉันได้แก้ไขปัญหานี้ด้วยการทุบตี

echo $(date -d"3 month ago" "+%G%m%d")

ฉันคิดว่าถ้า bash มีวิธีในตัวเพื่อจุดประสงค์นี้ python ที่มีอุปกรณ์ครบครันกว่ามากควรให้สิ่งที่ดีกว่าการบังคับให้เขียนสคริปต์ของตัวเองเพื่อให้บรรลุเป้าหมายนี้ แน่นอนฉันสามารถทำบางสิ่งเช่น:

if int(time.strftime('%m')) == 1:
    return '12'
else:
    if int(time.strftime('%m')) < 10:
        return '0'+str(time.strftime('%m')-1)
    else:
        return str(time.strftime('%m') -1)

ฉันไม่ได้ทดสอบรหัสนี้และฉันไม่ต้องการใช้มันต่อไป (เว้นแต่ฉันจะหาวิธีอื่นไม่ได้: /)

ขอบคุณสำหรับความช่วยเหลือของคุณ!


คำตอบ:


303

datetimeและคลาส datetime.timedelta เป็นเพื่อนของคุณ

  1. พบวันนี้.
  2. ใช้เพื่อค้นหาวันแรกของเดือนนี้
  3. ใช้ timedelta เพื่อสำรองข้อมูลวันเดียวถึงวันสุดท้ายของเดือนก่อนหน้า
  4. พิมพ์สตริง YYYYMM ที่คุณต้องการ

แบบนี้:

 import datetime
 today = datetime.date.today()
 first = today.replace(day=1)
 lastMonth = first - datetime.timedelta(days=1)
 print(lastMonth.strftime("%Y%m"))

201202 ถูกพิมพ์


31
คุณสามารถใช้.replace()วิธีการ:datetime.utcnow().replace(day=1) - timedelta(days=1)
jfs

1
เย็น! ฉันพลาดวิธีการแทนที่
bgporter

คุณยังสามารถเชื่อมต่อ.replace()ฟังก์ชัน ทำครั้งเดียวเพื่อรับเดือนสุดท้ายแล้วทำอีกครั้งเพื่อให้ได้วันที่คุณต้องการ อันดับแรก: d = date.today() แล้วone_month_ago = (d.replace(day=1) - timedelta(days=1)).replace(day=d.day)
Thane Plummer

@JFSebastian คุณถูกต้อง - ขอบคุณที่ชี้ให้เห็น ดูเหมือนจะไม่มีซับเดียวที่หรูหราสำหรับเรื่องนี้เนื่องจาก "เดือน" ไม่ใช่ช่วงเวลาที่คงที่ คุณสามารถทำสิ่งที่น่าเกลียดได้โดยการนำเข้าcalendarและใช้งานcalendar.mdays[d.month-1]และความอัปลักษณ์ที่มากขึ้นในmin()ฟังก์ชันในภาค 2 replaceแต่ดูเหมือนว่าไม่เป็น Pythonic และไม่ได้คำนึงถึงกรณีมุม ฉันได้อัปเดตคำตอบของฉันด้านล่างโดยใช้try - exceptบัญชีสำหรับทุกกรณีแม้ว่าฉันจะเกลียดการใช้ข้อยกเว้นเป็นส่วนหนึ่งของอัลกอริทึมก็ตาม
Thane Plummer

ดูคำตอบของ Ivan และเพิ่ม: min (date.today (). day, last_day_of_previous_month.day)
michel.iamit

70

คุณควรใช้dateutil ด้วยเหตุนี้คุณสามารถใช้ relativedelta ซึ่งเป็น timedelta เวอร์ชันปรับปรุง

>>> import datetime 
>>> import dateutil.relativedelta
>>> now = datetime.datetime.now()
>>> print now
2012-03-15 12:33:04.281248
>>> print now + dateutil.relativedelta.relativedelta(months=-1)
2012-02-15 12:33:04.281248

ไม่ทำงานในเดือนแรกของปี: >>> IllegalMonthError: เลขเดือนไม่ดี -1; ต้องเป็น 1-12
mtoloo

@mtoloo dateutil รุ่นอะไรครับ? ฉันไม่มีปัญหานั้น แต่ฉันจะเพิ่มไวยากรณ์ทางเลือก
Dave Butler

1
ฉันชอบอันนี้เพราะในขณะที่ @bgporter มีทางออกที่ดีมาก แต่ของเขาก็ไม่ได้ผลดีเท่าที่จะหาได้ในเดือนหน้า
Daniel F

3
@mtoloo คุณคงพิมพ์ผิดเดือน / เดือน
r_black

2
@r_black ใช่คุณพูดถูก นั่นเป็นความผิดของฉันเอง วิธีแก้ไขที่ระบุนี้ถูกต้องและไม่จำเป็นต้องตรวจสอบเพิ่มเติมสำหรับเดือนแรกของปี
mtoloo

45
from datetime import date, timedelta

first_day_of_current_month = date.today().replace(day=1)
last_day_of_previous_month = first_day_of_current_month - timedelta(days=1)

print "Previous month:", last_day_of_previous_month.month

หรือ:

from datetime import date, timedelta

prev = date.today().replace(day=1) - timedelta(days=1)
print prev.month

ส่วนหนึ่งของวิธีแก้ปัญหา ... หากต้องการค้นหาวันของเดือนที่แล้วให้เพิ่มสิ่งนี้: day_previous_month = min (today.day, last_day_of_previous_month.day) เพื่อไม่ให้เกินจำนวนวัน
michel.iamit

9

อาคารในคำตอบของ bgporter

def prev_month_range(when = None): 
    """Return (previous month's start date, previous month's end date)."""
    if not when:
        # Default to today.
        when = datetime.datetime.today()
    # Find previous month: https://stackoverflow.com/a/9725093/564514
    # Find today.
    first = datetime.date(day=1, month=when.month, year=when.year)
    # Use that to find the first day of this month.
    prev_month_end = first - datetime.timedelta(days=1)
    prev_month_start = datetime.date(day=1, month= prev_month_end.month, year= prev_month_end.year)
    # Return previous month's start and end dates in YY-MM-DD format.
    return (prev_month_start.strftime('%Y-%m-%d'), prev_month_end.strftime('%Y-%m-%d'))

5

มันง่ายมากและง่าย ทำเช่นนี้

from dateutil.relativedelta import relativedelta
from datetime import datetime

today_date = datetime.today()
print "todays date time: %s" %today_date

one_month_ago = today_date - relativedelta(months=1)
print "one month ago date time: %s" % one_month_ago
print "one month ago date: %s" % one_month_ago.date()

นี่คือผลลัพธ์: $ python2.7 main.py

todays date time: 2016-09-06 02:13:01.937121
one month ago date time: 2016-08-06 02:13:01.937121
one month ago date: 2016-08-06

4

สำหรับคนที่มาที่นี่และต้องการรับทั้งวันแรกและวันสุดท้ายของเดือนก่อนหน้า:

from datetime import date, timedelta

last_day_of_prev_month = date.today().replace(day=1) - timedelta(days=1)

start_day_of_prev_month = date.today().replace(day=1) - timedelta(days=last_day_of_prev_month.day)

# For printing results
print("First day of prev month:", start_day_of_prev_month)
print("Last day of prev month:", last_day_of_prev_month)

เอาท์พุท:

First day of prev month: 2019-02-01
Last day of prev month: 2019-02-28

หากคุณต้องการเริ่มต้นและสิ้นเดือน (และอื่น ๆ ) ดูที่Calendarโมดูล: stackabuse.com/introduction-to-the-python-calendar-module
toast38coza

ถ้าเราต้องการให้เดือนที่ 2 ก่อนหน้าเริ่มต้นและสิ้นสุด?
gamer

3
def prev_month(date=datetime.datetime.today()):
    if date.month == 1:
        return date.replace(month=12,year=date.year-1)
    else:
        try:
            return date.replace(month=date.month-1)
        except ValueError:
            return prev_month(date=date.replace(day=date.day-1))

พักวันที่ 31 มีนาคม
ไมค์

1

เพื่อความสนุกสนานคำตอบทางคณิตศาสตร์ที่แท้จริงโดยใช้ divmod ค่อนข้างไม่ฉลาดเนื่องจากการคูณสามารถทำได้เช่นกันตรวจสอบจำนวนเดือน (ถ้าเท่ากับ 12 เพิ่มปี ฯลฯ )

year = today.year
month = today.month

nm = list(divmod(year * 12 + month + 1, 12))
if nm[1] == 0:
    nm[1] = 12
    nm[0] -= 1
pm = list(divmod(year * 12 + month - 1, 12))
if pm[1] == 0:
    pm[1] = 12
    pm[0] -= 1

next_month = nm
previous_month = pm

1

ด้วยลูกตุ้มห้องสมุดที่สมบูรณ์มากเรามีsubtractวิธีการ (และไม่ได้เป็น "ลบคุณ"):

import pendulum
today = pendulum.datetime.today()  # 2020, january
lastmonth = today.subtract(months=1)
lastmonth.strftime('%Y%m')
# '201912'

เราเห็นว่ามันรับมือกับการกระโดดข้ามปี

addเทียบเท่ากลับเป็น

https://pendulum.eustace.io/docs/#addition-and-subtraction


1

มีไลบรารีระดับสูงdateparserที่สามารถกำหนดวันที่ในอดีตที่กำหนดให้เป็นภาษาธรรมชาติและส่งคืนdatetimeวัตถุPython ที่เกี่ยวข้อง

from dateparser import parse
parse('4 months ago')

0

จากความคิดเห็นของ @JF Sebastian คุณสามารถเชื่อมต่อreplace()ฟังก์ชันเพื่อย้อนกลับไปหนึ่ง "เดือน" ได้ เนื่องจากเดือนไม่ใช่ช่วงเวลาคงที่วิธีแก้ปัญหานี้จึงพยายามย้อนกลับไปยังวันที่เดิมของเดือนก่อนหน้าซึ่งแน่นอนว่าไม่ได้ผลในทุกเดือน ในกรณีนี้อัลกอริทึมนี้จะมีค่าเริ่มต้นเป็นวันสุดท้ายของเดือนก่อนหน้า

from datetime import datetime, timedelta

d = datetime(2012, 3, 31) # A problem date as an example

# last day of last month
one_month_ago = (d.replace(day=1) - timedelta(days=1))
try:
    # try to go back to same day last month
    one_month_ago = one_month_ago.replace(day=d.day)
except ValueError:
    pass
print("one_month_ago: {0}".format(one_month_ago))

เอาท์พุท:

one_month_ago: 2012-02-29 00:00:00

0

ถ้าคุณต้องการดูตัวอักษร ASCII ในไฟล์ประเภท EXE ใน LINUX / UNIX Environment ให้ลอง "od -c 'filename' | more"

คุณอาจจะได้รับรายการที่ไม่สามารถจดจำได้มากมาย แต่จะมีการนำเสนอทั้งหมดและการแสดง HEX จะปรากฏขึ้นและอักขระที่เทียบเท่า ASCII (หากเหมาะสม) จะเป็นไปตามบรรทัดของรหัสฐานสิบหก ลองใช้โค้ดที่คอมไพล์แล้วที่คุณรู้จัก คุณอาจเห็นสิ่งต่างๆในนั้นที่คุณจำได้


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