tanggal python bulan sebelumnya

132

Saya mencoba mendapatkan tanggal bulan sebelumnya dengan python. Inilah yang saya coba:

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

Namun, cara ini buruk karena 2 alasan: Pertama mengembalikan 20122 untuk Februari 2012 (bukan 201202) dan kedua akan mengembalikan 0 bukannya 12 pada Januari.

Saya telah memecahkan masalah ini di bash with

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

Saya pikir jika bash memiliki cara bawaan untuk tujuan ini, maka python, yang jauh lebih lengkap, harus menyediakan sesuatu yang lebih baik daripada memaksa menulis skrip sendiri untuk mencapai tujuan ini. Tentu saja saya bisa melakukan sesuatu seperti:

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)

Saya belum menguji kode ini dan toh saya tidak ingin menggunakannya (kecuali saya tidak dapat menemukan cara lain: /)

Terima kasih atas bantuan Anda!

philippe
sumber

Jawaban:

300

kelas datetime dan datetime.timedelta adalah teman Anda.

  1. temukan hari ini.
  2. gunakan itu untuk menemukan hari pertama bulan ini.
  3. gunakan timedelta untuk mencadangkan satu hari, ke hari terakhir bulan sebelumnya.
  4. cetak string YYYYMM yang Anda cari.

Seperti ini:

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

201202 dicetak.

bgporter
sumber
31
Anda dapat menggunakan .replace()metode:datetime.utcnow().replace(day=1) - timedelta(days=1)
jfs
1
Keren! Saya melewatkan metode ganti.
bgporter
Anda juga dapat mengaitkan .replace()fungsi. Lakukan sekali untuk mendapatkan bulan lalu, lalu lakukan lagi untuk mendapatkan hari yang Anda inginkan. Pertama: d = date.today() laluone_month_ago = (d.replace(day=1) - timedelta(days=1)).replace(day=d.day)
Thane Plummer
@ JSFSebastian Anda benar - terima kasih telah menunjukkannya. Tampaknya tidak ada satu kalimat yang elegan untuk ini karena "bulan" bukan periode waktu yang konstan. Anda dapat melakukan sesuatu yang buruk dengan mengimpor calendardan menggunakan calendar.mdays[d.month-1]dan lebih banyak kejelekan dalam min()fungsi di ke-2 replace, tetapi tampaknya tidak Pythonic dan tidak memperhitungkan kasus sudut. Saya telah memperbarui jawaban saya di bawah ini menggunakan try - exceptakun mana untuk semua kasus, meskipun saya benci menggunakan pengecualian sebagai bagian dari suatu algoritma.
Thane Plummer
lihat jawaban Ivan, dan tambahkan: min (date.today (). hari, last_day_of_previous_month.day)
michel.iamit
70

Anda harus menggunakan dateutil . Dengan itu, Anda dapat menggunakan relativedelta, ini merupakan versi yang ditingkatkan dari 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
Dave Butler
sumber
Ini tidak berfungsi untuk bulan pertama tahun ini: >>> IllegalMonthError: bad month number -1; harus 1-12
mtoloo
@ mtoloo Versi dateutil apa? Saya tidak mengalami masalah itu, tetapi saya akan menambahkan beberapa sintaks alternatif
Dave Butler
1
Saya lebih suka yang ini karena sementara @bgporter memiliki solusi yang sangat bagus, yang satu ini tidak bekerja dengan baik untuk mencari bulan depan.
Daniel F
3
@ mtoloo Anda mungkin salah ketik bulan / bulan
r_black
2
@r_black Ya Anda benar. Itu salah saya. Solusi yang diberikan di sini benar dan tidak diperlukan pemeriksaan lebih lanjut untuk bulan pertama tahun ini.
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

Atau:

from datetime import date, timedelta

prev = date.today().replace(day=1) - timedelta(days=1)
print prev.month
Ivan
sumber
bagian dari solusi ... untuk menemukan hari bulan lalu, tambahkan sesuatu seperti ini: day_previous_month = min (today.day, last_day_of_previous_month.day) untuk menghindari melebihi jumlah hari.
michel.iamit
9

Membangun jawaban 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'))
paragbaxi
sumber
5

Sangat mudah dan sederhana. Melakukan hal ini

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

Berikut ini hasilnya: $ 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
Mahfuz
sumber
4

Untuk seseorang yang datang ke sini dan ingin mendapatkan hari pertama dan terakhir di bulan sebelumnya:

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)

Keluaran:

First day of prev month: 2019-02-01
Last day of prev month: 2019-02-28
Robin Carlo Catacutan
sumber
Jika Anda ingin mendapatkan awal dan akhir bulan (dan lebih banyak lagi), silakan lihat Calendarmodul: stackabuse.com/introduction-to-the-python-calendar-module
toast38coza
Jika kita ingin awal dan akhir bulan ke-2 sebelumnya?
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))
steve
sumber
Istirahat pada tanggal 31 Maret
Mike
1

Hanya untuk bersenang-senang, jawaban matematika murni menggunakan divmod. Cukup tidak efisien karena penggandaan, bisa juga melakukan pemeriksaan sederhana pada jumlah bulan (jika sama dengan 12, tambah tahun, dll)

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
Tiberiu Ichim
sumber
1

Dengan pustaka Pendulum yang sangat lengkap, kami memiliki subtractmetode (dan bukan "subStract"):

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

Kami melihat bahwa itu menangani tahun melompat.

Setara kebalikannya adalah add.

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

Ehvince
sumber
0

Membangun komentar dari @JF Sebastian, Anda dapat rantai replace()fungsi untuk kembali satu "bulan". Karena sebulan bukan periode waktu yang konstan, solusi ini mencoba untuk kembali ke tanggal yang sama dengan bulan sebelumnya, yang tentu saja tidak berfungsi untuk semua bulan. Dalam kasus seperti itu, algoritma ini default ke hari terakhir bulan sebelumnya.

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

Keluaran:

one_month_ago: 2012-02-29 00:00:00
Thane Plummer
sumber
0

Jika Anda ingin melihat huruf ASCII dalam file tipe EXE di Lingkungan LINUX / UNIX, coba "od -c 'filename' | more"

Anda mungkin akan mendapatkan banyak item yang tidak dapat dikenali, tetapi semuanya akan disajikan, dan representasi HEX akan ditampilkan, dan karakter yang setara ASCII (jika sesuai) akan mengikuti garis kode hex. Cobalah di bagian kode yang dikompilasi yang Anda tahu. Anda mungkin melihat hal-hal di dalamnya yang Anda kenali.

Rick
sumber
Bisakah Anda mengedit ini untuk menjelaskan bagaimana ia menjawab pertanyaan.
AdrianHHH
0

Ada pustaka tingkat tinggi dateparseryang dapat menentukan tanggal terakhir yang diberikan bahasa alami, dan mengembalikan datetimeobjek Python yang sesuai

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