Coba ini:
def monthdelta(date, delta):
m, y = (date.month+delta) % 12, date.year + ((date.month)+delta-1) // 12
if not m: m = 12
d = min(date.day, [31,
29 if y%4==0 and not y%400==0 else 28,31,30,31,30,31,31,30,31,30,31][m-1])
return date.replace(day=d,month=m, year=y)
>>> for m in range(-12, 12):
print(monthdelta(datetime.now(), m))
2009-08-06 16:12:27.823000
2009-09-06 16:12:27.855000
2009-10-06 16:12:27.870000
2009-11-06 16:12:27.870000
2009-12-06 16:12:27.870000
2010-01-06 16:12:27.870000
2010-02-06 16:12:27.870000
2010-03-06 16:12:27.886000
2010-04-06 16:12:27.886000
2010-05-06 16:12:27.886000
2010-06-06 16:12:27.886000
2010-07-06 16:12:27.886000
2010-08-06 16:12:27.901000
2010-09-06 16:12:27.901000
2010-10-06 16:12:27.901000
2010-11-06 16:12:27.901000
2010-12-06 16:12:27.901000
2011-01-06 16:12:27.917000
2011-02-06 16:12:27.917000
2011-03-06 16:12:27.917000
2011-04-06 16:12:27.917000
2011-05-06 16:12:27.917000
2011-06-06 16:12:27.933000
2011-07-06 16:12:27.933000
>>> monthdelta(datetime(2010,3,30), -1)
datetime.datetime(2010, 2, 28, 0, 0)
>>> monthdelta(datetime(2008,3,30), -1)
datetime.datetime(2008, 2, 29, 0, 0)
Edit Dikoreksi untuk menangani hari itu juga.
Sunting Lihat juga jawaban dari kebingungan yang menunjukkan perhitungan yang lebih sederhana untuk d
:
d = min(date.day, calendar.monthrange(y, m)[1])
((date.month+delta-1) % 12)+1
bekerja dan berartiif not m: m = 12
bisa dihapusdt - timedelta(days=dt.day)
Seperti yang diutarakan semula meskipun kedengarannya mereka ingin dapat mengurangi jumlah bulan yang sewenang-wenang dan itu sedikit lebih sulit.29 if y%4==0 and (not y%100==0 or y%400 == 0) else 28
. misal, 1600 adalah tahun kabisat sedangkan 1700 bukanAnda dapat menggunakan
dateutil
modul pihak ketiga (entri PyPI di sini ).keluaran:
sumber
month
danmonths
di dateutil. Kurangi dengan parammonth
tidak bekerja tetapimonths
berhasilIn [23]: created_datetime__lt - relativedelta(months=1) Out[23]: datetime.datetime(2016, 11, 29, 0, 0, tzinfo=<StaticTzInfo 'Etc/GMT-8'>) In [24]: created_datetime__lt - relativedelta(month=1) Out[24]: datetime.datetime(2016, 1, 29, 0, 0, tzinfo=<StaticTzInfo 'Etc/GMT-8'>)
months
akan membuat perbedaan dalam 1 bulan. Menggunakanmonth
akan menyetel bulan ke 1 (mis. Januari), terlepas dari bulan input.Setelah pertanyaan asli diedit ke "objek datetime mana pun di bulan sebelumnya", Anda dapat melakukannya dengan mudah dengan mengurangi 1 hari dari hari pertama bulan itu.
sumber
dt.replace(day=1) - timedelta(1)
dt - timedelta(days=dt.day)
Variasi pada jawaban Duncan (saya tidak memiliki reputasi yang cukup untuk berkomentar), yang menggunakan calendar.monthrange untuk menyederhanakan penghitungan hari terakhir bulan secara dramatis:
Info tentang rentang bulan dari Dapatkan Hari Terakhir Bulan Ini dengan Python
sumber
Solusi panda yang di-vectorisasi sangat sederhana:
df['date'] - pd.DateOffset(months=1)
sumber
pandas
. Terima kasih!Apa yang Anda inginkan hasilnya jika Anda mengurangi satu bulan dari, misalnya, tanggal 30 Maret? Itulah masalahnya dengan menambah atau mengurangi bulan: bulan memiliki panjang yang berbeda! Dalam beberapa aplikasi, pengecualian sesuai dalam kasus seperti itu, dalam kasus lain "hari terakhir bulan sebelumnya" boleh digunakan (tapi itu benar-benar aritmatika yang gila, saat mengurangi satu bulan kemudian menambahkan satu bulan secara keseluruhan bukan berarti tidak ada operasi!) , di tempat lain, tetapi Anda ingin menambahkan beberapa indikasi tentang fakta sebagai tambahan tanggal, misalnya, "Saya mengatakan 28 Feb tapi saya benar-benar ingin 30 Feb jika ada", sehingga menambahkan atau mengurangi bulan lain untuk yang dapat mengatur segalanya dengan benar (dan yang terakhir jelas membutuhkan kelas khusus yang menyimpan data plus s / thing lainnya).
Tidak ada solusi nyata yang dapat ditoleransi untuk semua aplikasi, dan Anda belum memberi tahu kami apa kebutuhan spesifik aplikasi Anda untuk semantik operasi yang buruk ini, jadi tidak banyak lagi bantuan yang dapat kami berikan di sini.
sumber
datetime
modules mengasumsikan bahwa satu hari adalah tepat 24 jam (tanpa detik kabisat)Saya pikir cara sederhananya adalah menggunakan DateOffset dari Pandas seperti ini:
Hasilnya akan menjadi objek datetime
sumber
Jika Anda hanya menginginkan hari apa saja dalam sebulan terakhir, hal paling sederhana yang dapat Anda lakukan adalah mengurangi jumlah hari dari tanggal sekarang, yang akan memberi Anda hari terakhir bulan sebelumnya.
Misalnya, dimulai dengan tanggal berapa pun:
Mengurangkan hari dari tanggal saat ini yang kita dapatkan:
Ini cukup untuk kebutuhan Anda yang disederhanakan setiap hari dalam sebulan terakhir.
Tetapi sekarang setelah Anda memilikinya, Anda juga bisa mendapatkan hari apa pun dalam sebulan, termasuk hari yang sama saat Anda memulai (yaitu kurang lebih sama dengan mengurangi satu bulan):
Tentu saja, Anda perlu berhati-hati dengan tanggal 31 pada bulan 30 hari atau hari-hari yang hilang dari Februari (dan menjaga tahun kabisat), tetapi itu juga mudah dilakukan:
sumber
Saya menggunakan ini untuk tahun fiskal pemerintah di mana Q4 dimulai 1 Oktober. Perhatikan bahwa saya mengubah tanggal menjadi empat dan membatalkannya juga.
sumber
Berikut adalah beberapa kode untuk melakukannya. Belum mencobanya sendiri ...
sumber
Diberikan tupel (tahun, bulan), di mana bulan berjalan dari 1-12, coba ini:
Diasumsikan ada 12 bulan dalam setiap tahun.
sumber
sumber
Saya menggunakan kode berikut untuk kembali n Bulan dari Tanggal tertentu:
Misalnya: masukan tanggal = 28/12/2015 Hitung 6 bulan tanggal sebelumnya.
I) HITUNG BULAN: Langkah ini akan memberi Anda start_date sebagai 30/06/2015.
Perhatikan bahwa setelah langkah menghitung bulan Anda akan mendapatkan hari terakhir dari bulan yang diperlukan.
II) HITUNG HARI: Kondisi jika (start_date.day> your_date.day) memeriksa apakah hari dari input_date ada di bulan yang diperlukan. Ini menangani kondisi di mana tanggal input adalah 31 (atau 30) dan bulan yang diperlukan memiliki kurang dari 31 (atau 30 dalam kasus feb) hari. Ini menangani kasus tahun kabisat juga (Untuk Feb). Setelah langkah ini Anda akan mendapatkan hasil sebagai 28/06/2015
Jika kondisi ini tidak terpenuhi, start_date tetap menjadi tanggal terakhir bulan sebelumnya. Jadi jika Anda memberikan 31/12/2015 sebagai tanggal input dan menginginkan tanggal 6 bulan sebelumnya, maka Anda akan diberi 30/06/2015
sumber
Anda dapat menggunakan fungsi yang diberikan di bawah ini untuk mendapatkan tanggal sebelum / sesudah X bulan.
sumber
Saya rasa jawaban ini cukup mudah dibaca:
sumber
Satu kapal?
previous_month_date = (current_date - datetime.timedelta(days=current_date.day+1)).replace(day=current_date.day)
sumber
Cara termudah yang baru saja saya coba
sumber
Beberapa waktu lalu saya menemukan algoritma berikut yang bekerja sangat baik untuk menambah dan mengurangi bulan pada a
date
ataudatetime
.PERHATIAN : Ini akan gagal jika
day
tidak tersedia di bulan baru. Saya menggunakan ini pada objek tanggal di manaday == 1
selalu.Python 3.x:
Untuk Python 2.7 ubah
//12
menjadi hanya/12
karena pembagian integer tersirat.Saya baru-baru ini menggunakan ini dalam file default ketika skrip mulai mendapatkan global yang berguna ini:
sumber
Solusi sederhana, tidak perlu perpustakaan khusus.
sumber
Anda bisa melakukannya dalam dua baris seperti ini:
ingat impor
sumber