파이썬에서 날짜에서 한 달을 빼는 가장 간단한 방법은 무엇입니까?
timedelta 만 생성자에 월 인수가있는 경우. 그래서 이것을하는 가장 간단한 방법은 무엇입니까?
편집 : 나는 아래에서 지적한 것처럼 이것에 대해 너무 열심히 생각하지 않았습니다. 정말로 내가 원했던 것은 지난 달의 어느 날이든 결국은 년과 달만 잡을 것이기 때문입니다. 따라서 datetime 객체가 주어지면 지난 달에 해당하는 datetime 객체 를 반환하는 가장 간단한 방법은 무엇 입니까?
이 시도:
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)
편집 날짜도 처리하도록 수정 되었습니다.
에 대한 더 간단한 계산을 지적하는 퍼즐의 답을 참조하십시오 d
.
d = min(date.day, calendar.monthrange(y, m)[1])
타사 dateutil
모듈을 사용할 수 있습니다 ( 여기에 PyPI 항목 ).
import datetime
import dateutil.relativedelta
d = datetime.datetime.strptime("2013-03-31", "%Y-%m-%d")
d2 = d - dateutil.relativedelta.relativedelta(months=1)
print d2
산출:
2013-02-28 00:00:00
원래 질문을 "전월의 모든 datetime 객체"로 편집 한 후 해당 월의 1 일에서 1 일을 빼면 매우 쉽게 수행 할 수 있습니다.
from datetime import datetime, timedelta
def a_day_in_previous_month(dt):
return dt.replace(day=1) - timedelta(days=1)
Duncan의 답변 에 대한 변형 (댓글 할만한 평판이 충분하지 않음)은 calendar.monthrange를 사용하여 해당 월의 마지막 날 계산을 극적으로 단순화합니다.
import calendar
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, calendar.monthrange(y, m)[1])
return date.replace(day=d,month=m, year=y)
Python에서 이달의 마지막 날 가져 오기의 월간 정보
timedelta 만 생성자에 월 인수가있는 경우. 그래서 이것을하는 가장 간단한 방법은 무엇입니까?
예를 들어 3 월 30 일 날짜에서 한 달을 빼면 결과가 어떻게됩니까? 이것이 달을 더하거나 빼는 문제입니다. 달은 길이가 다릅니다! 어떤 경우에는 예외가 적절하고 다른 경우에는 "전월의 마지막 날"을 사용해도 괜찮습니다 (하지만 한 달을 뺀 다음 한 달을 더하는 것은 전체적으로 작동하지 않는 것이 아닙니다 !) , 다른 경우에는 날짜 외에 사실에 대한 몇 가지 표시를 유지하고 싶을 것입니다. 예를 들어 "2 월 28 일을 말하고 있지만 2 월 30 일이 존재한다면 정말로 원합니다." 그것은 다시 일을 바로 잡을 수 있습니다 (그리고 후자는 분명히 데이터와 s / thing 다른 것을 포함하는 커스텀 클래스를 필요로합니다).
모든 애플리케이션에 허용되는 실제 솔루션은있을 수 없으며,이 비참한 작업의 의미에 대한 특정 앱의 요구 사항을 알려주지 않았으므로 여기에서 제공 할 수있는 더 많은 도움이 없습니다.
벡터화 된 pandas 솔루션은 매우 간단합니다.
df['date'] - pd.DateOffset(months=1)
원하는 것이 지난 달의 어느 날이든간에 할 수있는 가장 간단한 방법은 현재 날짜에서 일 수를 빼는 것입니다. 그러면 지난 달의 마지막 날이됩니다.
예를 들어, 어떤 날짜로 시작 :
>>> import datetime
>>> today = datetime.date.today()
>>> today
datetime.date(2016, 5, 24)
현재 날짜의 날짜를 빼면 다음을 얻습니다.
>>> last_day_previous_month = today - datetime.timedelta(days=today.day)
>>> last_day_previous_month
datetime.date(2016, 4, 30)
이것은 지난달 어느 날의 단순화 된 필요에 충분합니다.
그러나 이제 당신은 그것을 가지고, 당신은 또한 당신이 시작한 같은 날을 포함하여 그 달의 어느 날이든 얻을 수 있습니다 (즉, 한 달을 빼는 것과 거의 같거나 같음) :
>>> same_day_last_month = last_day_previous_month.replace(day=today.day)
>>> same_day_last_month
datetime.date(2016, 4, 24)
물론, 30 일의 31 일 또는 2 월의 누락 된 날 (윤년을 관리)에주의해야하지만, 그렇게하기도 쉽습니다.
>>> a_date = datetime.date(2016, 3, 31)
>>> last_day_previous_month = a_date - datetime.timedelta(days=a_date.day)
>>> a_date_minus_month = (
... last_day_previous_month.replace(day=a_date.day)
... if a_date.day < last_day_previous_month.day
... else last_day_previous_month
... )
>>> a_date_minus_month
datetime.date(2016, 2, 29)
저는 4 분기가 10 월 1 일에 시작되는 정부 회계 연도에 이것을 사용합니다. 참고 날짜를 분기로 변환하고 실행 취소합니다.
import pandas as pd
df['Date'] = '1/1/2020'
df['Date'] = pd.to_datetime(df['Date']) #returns 2020-01-01
df['NewDate'] = df.Date - pd.DateOffset(months=3) #returns 2019-10-01 <---- answer
# For fun, change it to FY Quarter '2019Q4'
df['NewDate'] = df['NewDate'].dt.year.astype(str) + 'Q' + df['NewDate'].dt.quarter.astype(str)
# Convert '2019Q4' back to 2019-10-01
df['NewDate'] = pd.to_datetime(df.NewDate)
다음은이 를 수행하는 몇 가지 코드 입니다. 직접 시도해 보지 않았습니다 ...
def add_one_month(t):
"""Return a `datetime.date` or `datetime.datetime` (as given) that is
one month earlier.
Note that the resultant day of the month might change if the following
month has fewer days:
>>> add_one_month(datetime.date(2010, 1, 31))
datetime.date(2010, 2, 28)
"""
import datetime
one_day = datetime.timedelta(days=1)
one_month_later = t + one_day
while one_month_later.month == t.month: # advance to start of next month
one_month_later += one_day
target_month = one_month_later.month
while one_month_later.day < t.day: # advance to appropriate day
one_month_later += one_day
if one_month_later.month != target_month: # gone too far
one_month_later -= one_day
break
return one_month_later
def subtract_one_month(t):
"""Return a `datetime.date` or `datetime.datetime` (as given) that is
one month later.
Note that the resultant day of the month might change if the following
month has fewer days:
>>> subtract_one_month(datetime.date(2010, 3, 31))
datetime.date(2010, 2, 28)
"""
import datetime
one_day = datetime.timedelta(days=1)
one_month_earlier = t - one_day
while one_month_earlier.month == t.month or one_month_earlier.day > t.day:
one_month_earlier -= one_day
return one_month_earlier
월이 1-12 인 (년, 월) 튜플이 주어지면 다음을 시도하십시오.
>>> from datetime import datetime
>>> today = datetime.today()
>>> today
datetime.datetime(2010, 8, 6, 10, 15, 21, 310000)
>>> thismonth = today.year, today.month
>>> thismonth
(2010, 8)
>>> lastmonth = lambda (yr,mo): [(y,m+1) for y,m in (divmod((yr*12+mo-2), 12),)][0]
>>> lastmonth(thismonth)
(2010, 7)
>>> lastmonth( (2010,1) )
(2009, 12)
매년 12 개월이 있다고 가정합니다.
def month_sub(year, month, sub_month):
result_month = 0
result_year = 0
if month > (sub_month % 12):
result_month = month - (sub_month % 12)
result_year = year - (sub_month / 12)
else:
result_month = 12 - (sub_month % 12) + month
result_year = year - (sub_month / 12 + 1)
return (result_year, result_month)
>>> month_sub(2015, 7, 1)
(2015, 6)
>>> month_sub(2015, 7, -1)
(2015, 8)
>>> month_sub(2015, 7, 13)
(2014, 6)
>>> month_sub(2015, 7, -14)
(2016, 9)
다음 코드를 사용하여 특정 날짜에서 n 개월을 되돌 렸습니다.
your_date = datetime.strptime(input_date, "%Y-%m-%d") #to convert date(2016-01-01) to timestamp
start_date=your_date #start from current date
#Calculate Month
for i in range(0,n): #n = number of months you need to go back
start_date=start_date.replace(day=1) #1st day of current month
start_date=start_date-timedelta(days=1) #last day of previous month
#Calculate Day
if(start_date.day>your_date.day):
start_date=start_date.replace(day=your_date.day)
print start_date
예 : 입력 날짜 = 28/12/2015 6 개월 전 날짜를 계산합니다.
I) CALCULATE MONTH :이 단계는 시작일을 2015 년 6 월 30 일로 제공합니다.
참고 계산 단계 달 단계 후 필요한 달의 마지막 날을 얻을 것이다.
II)CALCULATE DAY: Condition if(start_date.day>your_date.day) checks whether the day from input_date is present in the required month. This handles condition where input date is 31(or 30) and the required month has less than 31(or 30 in case of feb) days. It handles leap year case as well(For Feb). After this step you will get result as 28/06/2015
If this condition is not satisfied, the start_date remains the last date of the previous month. So if you give 31/12/2015 as input date and want 6 months previous date, it will give you 30/06/2015
You can use below given function to get date before/after X month.
from datetime import date def next_month(given_date, month): yyyy = int(((given_date.year * 12 + given_date.month) + month)/12) mm = int(((given_date.year * 12 + given_date.month) + month)%12) if mm == 0: yyyy -= 1 mm = 12 return given_date.replace(year=yyyy, month=mm) if __name__ == "__main__": today = date.today() print(today) for mm in [-12, -1, 0, 1, 2, 12, 20 ]: next_date = next_month(today, mm) print(next_date)
I think this answer is quite readable:
def month_delta(dt, delta):
year_delta, month = divmod(dt.month + delta, 12)
if month == 0:
# convert a 0 to december
month = 12
if delta < 0:
# if moving backwards, then it's december of last year
year_delta -= 1
year = dt.year + year_delta
return dt.replace(month=month, year=year)
for delta in range(-20, 21):
print(delta, "->", month_delta(datetime(2011, 1, 1), delta))
-20 -> 2009-05-01 00:00:00
-19 -> 2009-06-01 00:00:00
-18 -> 2009-07-01 00:00:00
-17 -> 2009-08-01 00:00:00
-16 -> 2009-09-01 00:00:00
-15 -> 2009-10-01 00:00:00
-14 -> 2009-11-01 00:00:00
-13 -> 2009-12-01 00:00:00
-12 -> 2010-01-01 00:00:00
-11 -> 2010-02-01 00:00:00
-10 -> 2010-03-01 00:00:00
-9 -> 2010-04-01 00:00:00
-8 -> 2010-05-01 00:00:00
-7 -> 2010-06-01 00:00:00
-6 -> 2010-07-01 00:00:00
-5 -> 2010-08-01 00:00:00
-4 -> 2010-09-01 00:00:00
-3 -> 2010-10-01 00:00:00
-2 -> 2010-11-01 00:00:00
-1 -> 2010-12-01 00:00:00
0 -> 2011-01-01 00:00:00
1 -> 2011-02-01 00:00:00
2 -> 2011-03-01 00:00:00
3 -> 2011-04-01 00:00:00
4 -> 2011-05-01 00:00:00
5 -> 2011-06-01 00:00:00
6 -> 2011-07-01 00:00:00
7 -> 2011-08-01 00:00:00
8 -> 2011-09-01 00:00:00
9 -> 2011-10-01 00:00:00
10 -> 2011-11-01 00:00:00
11 -> 2012-12-01 00:00:00
12 -> 2012-01-01 00:00:00
13 -> 2012-02-01 00:00:00
14 -> 2012-03-01 00:00:00
15 -> 2012-04-01 00:00:00
16 -> 2012-05-01 00:00:00
17 -> 2012-06-01 00:00:00
18 -> 2012-07-01 00:00:00
19 -> 2012-08-01 00:00:00
20 -> 2012-09-01 00:00:00
import datetime
date_str = '08/01/2018'
format_str = '%d/%m/%Y'
datetime_obj = datetime.datetime.strptime(date_str, format_str)
datetime_obj.replace(month=datetime_obj.month-1)
Simple solution, no need for special libraries.
'Development Tip' 카테고리의 다른 글
라이브러리가로드되지 않음 : /usr/local/opt/readline/lib/libreadline.6.dylib(LoadError) (0) | 2020.10.17 |
---|---|
임의의 문자열과 임의의 16 진수를 만드는 가장 간단한 방법 (0) | 2020.10.17 |
setState (…) : 마운트되거나 마운트 된 구성 요소 만 업데이트 할 수 있습니다. (0) | 2020.10.16 |
로드는 Ruby의 require와 어떻게 다릅니 까? (0) | 2020.10.16 |
Html.BeginForm ()으로 폼의 이름을 어떻게 지정할 수 있습니까? (0) | 2020.10.16 |