Get [year month day] of difference between two dates - python

import datetime
difference = (datetime.date(2020, 1, 15) - datetime.date(1987, 7, 15))
'''This gives return as days but I want this as [year, month, day] format. The result must be accurate. '''

run
pip install python-dateutil
try the below code
from datetime import datetime
from dateutil import relativedelta
date1 = datetime(2020, 1, 15)
date2 = datetime(1987, 7, 15)
diff = relativedelta.relativedelta(date1, date2)
years = diff.years
months = diff.months
days = diff.days
print('{},{},{} '.format(years, months, days))

Related

Converting a list of weeks to a dates in Python

I'm trying to convert this list of weeks in a year to dates in Python and then into a Pandas column but having weird results:
import datetime
from dateutil.relativedelta import relativedelta
week = [25,31]
year = 2021
dates = []
for i in week:
date = datetime.date(year, 1, 1) + relativedelta(weeks=+i)
dates.append(date)
print(dates)
The printout of the dates looks like this:
[datetime.date(2021, 6, 25), datetime.date(2021, 8, 6)]
i need it to look like this [ 2021-06-25, 2021-08-06]
Any ideas?
import datetime
from dateutil.relativedelta import relativedelta
dates = []
for i in week:
date = datetime.date(year, 1, 1) + relativedelta(weeks=+i)
dates.append(date)
df['date'] = pd.to_datetime(dates)

Get end of next month [duplicate]

This question already has answers here:
How to get the last day of the month?
(44 answers)
Closed last month.
There is a date like this:
Timestamp('2020-10-17 00:00:00')
How can I get the end of next month?
The output should be like this:
Timestamp('2020-11-30 00:00:00')
I tried rrule but it does not work correctly.
My code:
import pandas as pd
from datetime import date
from dateutil.rrule import rrule, MONTHLY
start_date = date(2020, 9, 17)
end_date = date(2020, 10, 31)
for d in rrule(MONTHLY, dtstart=start_date, until=end_date):
t = pd.Timestamp(d)
print(t)
The output:
2020-09-17 00:00:00
2020-10-17 00:00:00
I am going to get end of month.
in my case, change first day of next 2 month.
and then minus 1 day.
i also use this in java.
sample code
import pandas as pd
t = pd.Timestamp('2020-10-17 00:00:00')
t = t.replace(day=1)
answer = t + pd.DateOffset(months=2) + pd.DateOffset(days=-1)
In addition to the other's answers, you can also use calender module to get the last day of next month, as follows:
import pandas as pd
from datetime import date
import calendar
def get_nextmonth(d):
nextmonth_lastday = calendar.monthrange(d.year, d.month+1)[1] # this return first and last day of the given month, such as (0, 30)
return date(d.year, d.month+1, nextmonth_lastday)
start_date = date(2020, 9, 17)
print(get_nextmonth(start_date))
# 2020-10-31
Dateutil also works:
I set the days to 1, go two months further, and go one day back.
#pip install python-dateutil
from datetime import date
from dateutil.relativedelta import relativedelta
DAY = relativedelta(days=+1)
MONTH = relativedelta(months=+1)
first_date = date(2020, 10, 17).replace(day=1)
print(first_date + 2 * MONTH - DAY)
Output:
2020-11-30
Use pandas vectored way which is fast for large amounts of data.
import pandas as pd
ts = pd.Timestamp(2022, 1, 15)
ts + pd.offsets.DateOffset(months=1) + pd.offsets.MonthEnd(0) -->
Out: Timestamp('2022-02-28 00:00:00')
ts = pd.Timestamp(2022, 1, 31)
ts + pd.offsets.DateOffset(months=1) + pd.offsets.MonthEnd(0) --> putting 0 to get same month last date though it was last date
Out: Timestamp('2022-02-28 00:00:00')
ts = pd.Timestamp(2022, 1, 31)
ts + pd.offsets.DateOffset(months=1) + pd.offsets.MonthEnd()
Out: Timestamp('2022-03-31 00:00:00')
With beautiful-date, you could do:
from beautiful_date import D, months, day, days
last_day_of_the_month = D.today() + 1 * months + 1 * day - 1 * days
This takes the current day (D.today()), goes to the next month (+ 1 * months), goes to the first day of the next month (+ 1 * day), and goes one day back, i.e. last day of the current month (- 1 * days)
And you can easily convert it to datetime:
last_day_of_the_month[0:0]
I would do like this:
from datetime import date,timedelta
start_date = date(2020, 9, 17)
last_day_month=date(start_date.year,start_date.month+1,1)-timedelta(days=1)
You could do it like this:
import pandas as pd
from datetime import datetime, date
date = date(2020, 10, 17)
last_day_of_next_month = pd.Timestamp(datetime.datetime(date.year, ((date.month+2) % 12), 1) - datetime.timedelta(days=1))
Basically, this just created a new date at the first day of the month after next and subtracts one day to get the last day of the next month.
EDIT:
This can be done more cleanly by using pandas DateOffsets as mentioned in the comments and by another answer:
import pandas as pd
from datetime import date
date = date(2020, 10, 17)
last_day_of_next_month = pd.Timestamp(date) + pd.offsets.DateOffset(months=1) + pd.offsets.MonthEnd(0)

How to get a specific date from the previous month given the current date in python?

I want to get the 20th of previous month, given the current_date()
I am trying to use time.strftime but not able to subtract the value from it.
timestr = time.strftime("%Y-(%m-1)%d")
This is giving me error. The expected output is 2019-03-20 if my current_date is in April. Not sure how to go about it.
I read the posts from SO and most of them address getting the first day / last day of the month. Any help would be appreciated.
from datetime import date, timedelta
today = date.today()
last_day_prev_month = today - timedelta(days=today.day)
twenty_prev_month = last_day_prev_month.replace(day=20)
print(twenty_prev_month) # 2019-03-20
Use datetime.replace
import datetime
current_date = datetime.date.today()
new_date = current_date.replace(
month = current_date.month - 1,
day = 20
)
print(new_date)
#2019-03-20
Edit
That won't work for Jan so this is a workaround:
import datetime
current_date = datetime.date(2019, 2, 17)
month = current_date.month - 1
year = current_date.year
if not month:
month, year = 12, year - 1
new_date = datetime.date(year=year, month=month, day=20)
I imagine it is the way dates are parsed. It is my understanding that with your code it is looking for
2019-(03-1)20 or 2019-(12-1)15, etc..
Because the %y is not a variable, but a message about how the date is to be expected within a string of text, and other characters are what should be expected, but not processed (like "-")
This seems entirely not what you are going for. I would just parse the date like normal and then reformat it to be a month earlier:
import datetime
time = datetime.datetime.today()
print(time)
timestr = time.strftime("%Y-%m-%d")
year, month, day = timestr.split("-")
print("{}-{}-{}".format(year, int(month)-1, day))
This would be easier with timedelta objects, but sadly there isn't one for months, because they are of various lengths.
To be more robust if a new year is involved:
import datetime
time = datetime.datetime.today()
print(time)
timestr = time.strftime("%Y-%m-%d")
year, month, day = timestr.split("-")
if month in [1, "01", "1"]: # I don't remember how January is represented
print("{}-{}-{}".format(int(year) - 1, 12, day)) # use December of last year
else:
print("{}-{}-{}".format(year, int(month)-1, day))
This will help:
from datetime import date, timedelta
dt = date.today() - timedelta(30)// timedelta(days No.)
print('Current Date :',date.today())
print(dt)
It is not possible to do math inside a string passed to time.strftime, but you can do something similar to what you're asking very easily using the time module
in Python 3
# Last month
t = time.gmtime()
print(f"{t.tm_year}-{t.tm_mon-1}-20")
or in Python 2
print("{0}-{1}-{2}".format(t.tm_year, t.tm_mon -1, 20))
If you have fewer constraints, you can just use the datetime module instead.
You could use datetime, dateutil or arrow to find the 20th day of the previous month. See examples below.
Using datetime:
from datetime import date
d = date.today()
month, year = (d.month-1, d.year) if d.month != 1 else (12, d.year-1)
last_month = d.replace(day=20, month=month, year=year)
print(last_month)
Using datetime and timedelta:
from datetime import date
from datetime import timedelta
d = date.today()
last_month = (d - timedelta(days=d.day)).replace(day=20)
print(last_month)
Using datetime and dateutil:
from datetime import date
from dateutil.relativedelta import relativedelta # pip install python-dateutil
d = date.today()
last_month = d.replace(day=20) - relativedelta(months=1)
print(last_month)
Using arrow:
import arrow # pip install arrow
d = arrow.now()
last_month = d.shift(months=-1).replace(day=20).datetime.date()
print(last_month)

Subtract a month from a date in Python? [duplicate]

This question already has answers here:
Return datetime object of previous month
(23 answers)
Closed 6 years ago.
I need to get the first day of last month from any date.
I know that I can use monthdelta(datetime(2010,3,30), -1) to get last month, but it doesn't return the first day.
This can be done by first calculating the first day of current month ( or any given date ), then subtracting it with datetime.timedelta(days=1) which gives you the last day of previous month.
For demonstration, here is a sample code:
import datetime
def get_lastday(current):
_first_day = current.replace(day=1)
prev_month_lastday = _first_day - datetime.timedelta(days=1)
return prev_month_lastday.replace(day=1)
Try like this. With using datetime and datetutil.
(if datetutil not available for you install pip install python-dateutil)
In [1]: from datetime import datetime
In [2]: import dateutil.relativedelta
In [3]: today_date = datetime.now().date()
In [4]: today_date
Out[1]: datetime.date(2016, 7, 5)
In [5]: last_month = today_date - dateutil.relativedelta.relativedelta(months=1)
In [6]: last_mont_first_date = last_month.replace(day=1)
In [7]: last_mont_first_date
Out[2]: datetime.date(2016, 6, 1)
Input:
datetime.date(2016, 7, 5)
Output
datetime.date(2016, 6, 1)
Try this :
from datetime import date
d = date.today()
d.replace(
year=d.year if d.month > 1 else d.year - 1,
month=d.month - 1 if d.month > 1 else 12,
day=1
)

How to iterate over a timespan after days, hours, weeks and months?

How do I iterate over a timespan after days, hours, weeks or months?
Something like:
for date in foo(from_date, to_date, delta=HOURS):
print date
Where foo is a function, returning an iterator. I've been looking at the calendar module, but that only works for one specific year or month, not between dates.
Use dateutil and its rrule implementation, like so:
from dateutil import rrule
from datetime import datetime, timedelta
now = datetime.now()
hundredDaysLater = now + timedelta(days=100)
for dt in rrule.rrule(rrule.MONTHLY, dtstart=now, until=hundredDaysLater):
print dt
Output is
2008-09-30 23:29:54
2008-10-30 23:29:54
2008-11-30 23:29:54
2008-12-30 23:29:54
Replace MONTHLY with any of YEARLY, MONTHLY, WEEKLY, DAILY, HOURLY, MINUTELY, or SECONDLY. Replace dtstart and until with whatever datetime object you want.
This recipe has the advantage for working in all cases, including MONTHLY. Only caveat I could find is that if you pass a day number that doesn't exist for all months, it skips those months.
I don't think there is a method in Python library, but you can easily create one yourself using datetime module:
from datetime import date, datetime, timedelta
def datespan(startDate, endDate, delta=timedelta(days=1)):
currentDate = startDate
while currentDate < endDate:
yield currentDate
currentDate += delta
Then you could use it like this:
>>> for day in datespan(date(2007, 3, 30), date(2007, 4, 3),
>>> delta=timedelta(days=1)):
>>> print day
2007-03-30
2007-03-31
2007-04-01
2007-04-02
Or, if you wish to make your delta smaller:
>>> for timestamp in datespan(datetime(2007, 3, 30, 15, 30),
>>> datetime(2007, 3, 30, 18, 35),
>>> delta=timedelta(hours=1)):
>>> print timestamp
2007-03-30 15:30:00
2007-03-30 16:30:00
2007-03-30 17:30:00
2007-03-30 18:30:00
I achieved this using pandas and datetime libraries as follows. It was much more convenient for me.
import pandas as pd
from datetime import datetime
DATE_TIME_FORMAT = '%Y-%m-%d %H:%M:%S'
start_datetime = datetime.strptime('2018-05-18 00:00:00', DATE_TIME_FORMAT)
end_datetime = datetime.strptime('2018-05-23 13:00:00', DATE_TIME_FORMAT)
timedelta_index = pd.date_range(start=start_datetime, end=end_datetime, freq='H').to_series()
for index, value in timedelta_index.iteritems():
dt = index.to_pydatetime()
print(dt)
For iterating over months you need a different recipe, since timedeltas can't express "one month".
from datetime import date
def jump_by_month(start_date, end_date, month_step=1):
current_date = start_date
while current_date < end_date:
yield current_date
carry, new_month = divmod(current_date.month - 1 + month_step, 12)
new_month += 1
current_date = current_date.replace(year=current_date.year + carry,
month=new_month)
(NB: you have to subtract 1 from the month for the modulus operation then add it back to new_month, since months in datetime.dates start at 1.)
Month iteration approach:
def months_between(date_start, date_end):
months = []
# Make sure start_date is smaller than end_date
if date_start > date_end:
tmp = date_start
date_start = date_end
date_end = tmp
tmp_date = date_start
while tmp_date.month <= date_end.month or tmp_date.year < date_end.year:
months.append(tmp_date) # Here you could do for example: months.append(datetime.datetime.strftime(tmp_date, "%b '%y"))
if tmp_date.month == 12: # New year
tmp_date = datetime.date(tmp_date.year + 1, 1, 1)
else:
tmp_date = datetime.date(tmp_date.year, tmp_date.month + 1, 1)
return months
More code but it will do fine dealing with long periods of time checking that the given dates are in order...
Also can use the module arrow
https://arrow.readthedocs.io/en/latest/guide.html#ranges-spans
>>> start = datetime(2013, 5, 5, 12, 30)
>>> end = datetime(2013, 5, 5, 17, 15)
>>> for r in arrow.Arrow.range('hour', start, end):
... print(repr(r))
...
<Arrow [2013-05-05T12:30:00+00:00]>
<Arrow [2013-05-05T13:30:00+00:00]>
<Arrow [2013-05-05T14:30:00+00:00]>
<Arrow [2013-05-05T15:30:00+00:00]>
<Arrow [2013-05-05T16:30:00+00:00]>
This library provides a handy calendar tool: mxDateTime, that should be enough :)
You should modify this line to make this work correctly:
current_date = current_date.replace(year=current_date.year + carry,month=new_month,day=1)
;)

Categories