I was trying a simple date calculation by adding a certain number of days to a datetime.
import datetime
from dateutil.relativedelta import relativedelta
initial = datetime.date(2019, 3, 5)
delta = relativedelta(day=60)
print(f"Initial date: {initial.strftime('%d-%m-%Y')}")
new_dt = initial + delta
print(f"Final date: {new_dt.strftime('%d-%m-%Y')}")
However my output is:
Initial date: 05-03-2019
Final date: 31-03-2019
What is wrong here?
delta = relativedelta(day=60)
new_dt = initial + delta
The day of initial is set (not incremented but set) to 60 but since there are only 31 days in that month it is set to 31.
https://dateutil.readthedocs.io/en/stable/relativedelta.html
If your intention is to increment the date by 60 days use
delta = datetime.timedelta(days=60)
OR
delta = relativedelta(days=60)
instead of
delta = relativedelta(day=60)
Related
I have the date object which is as follows. Date: 2025-11-30. If I add 3 month to it using following code, it will raise an Exception as follows.
code:
def get_next_n_month_forward(date, n):
if date.month + n > 12:
next_month = date.replace(year=date.year + 1,
month=(date.month + n) % 12)
else:
next_month = date.replace(month=(date.month + n))
return next_month
exception:
ValueError: day is out of range for month
As far as I can understand from error it is because february does not have 30th day.
Question: How can I make it set to the last day of the month? !Note: In my case it would be 29th or 28th of February.
You can use timedelta object to increase and decrease dates
from datetime import timedelta
import datetime
d = datetime.datetime.today()
new_d = d + timedelta(days=1)
In order to set the date to the last day of month, you can set the date to the 1st of the next month and then decrease it by 1 day:
from datetime import timedelta
import datetime
day = datetime.datetime.today()
prev_month_last_day = day.replace(day=1) - timedelta(days=1)
Similarly to checking which week is a date I want to check which semi-month period is a date using datetime in python? I know we can use pd.offsets.SemiMonthEnd() but that's not what I am looking for. Is there a function similarly to dt.week that will return the semi-month period the date is in?
I'm not aware if there are such functions, but you can use this code:
from calendar import monthrange
import datetime
today = datetime.date(2020, 6, 3)
# Two-weeks period for a date:
week_number = today.isocalendar()[1]
two_weeks_period_number = week_number // 2 + 1
print('Two-weeks period:', two_weeks_period_number)
# Number of semi-months for a date:
days_in_month = monthrange(today.year, today.month)[1]
semi_months_period_number = 2 * today.month - int((today.day / days_in_month) < .5)
print('Semi-months period:', semi_months_period_number)
Output:
Two-weeks period: 12
Semi-months period: 11
This question already has answers here:
Best way to find the months between two dates
(41 answers)
Closed 8 years ago.
In my django app, I have some date.
I need to count how many months left to this date, using full (rounded) months.
eg: today is 19/02/2015 (february), my "search" date is 04/08/2015. Difference should be 6.
How can I get a proper value?
from datetime import datetime,timedelta
from calendar import monthrange
today = datetime.today()
dt = "04/08/2015"
fut = datetime.strptime(dt, "%d/%m/%Y")
diff = 0
while today <= fut:
today += timedelta(days=monthrange(today.day,today.month)[1])
diff += 1
print(diff)
6
Without importing calender we can increment a count everytime we see a new month:
from datetime import datetime,timedelta
today = datetime.today()
dt = "09/08/2015"
fut = datetime.strptime(dt, "%d/%m/%Y")
diff = 0
while today <= fut:
mon = today.month
today += timedelta(days=1)
if today.month != mon:
diff += 1
print(diff)
6
If you want to make the future day the last day of the month:
from datetime import datetime, timedelta
from calendar import monthrange
today = datetime.today()
dt = "02/08/2015"
fut = datetime.strptime(dt, "%d/%m/%Y")
fut = fut + timedelta(days=monthrange(fut.day,fut.month)[1]-fut.day)
diff = 0
while today < fut:
mon = today.month
today += timedelta(days=1)
if today.month != mon:
diff += 1
print(diff)
This is purposely inaccurate to allow for rounding as required, all we care about are the amount of different months we encounter.
I like the arrow library: http://crsmithdev.com/arrow/
eg.
d1 = arrow.get("19/02/2015", "DD/MM/YYYY")
d2 = arrow.get("04/08/2015", "DD/MM/YYYY")
(d2-d1).days
You are going to have decide how to do your calculation. Divide by 30 or extract the months and subtract those.
d2.month - d1.month
To handle it going over a year:
((d2.year * 100) + d2.month) - ((d1.year * 100) + d1.month)
To calculate the month difference (rounded) I would go this direction:
Get the date objects for the different dates (see datetime package). This is rather easy, since the constructor takes year, month, day
Calculate the difference between the dates "date2 - date1" this automatically gives a timedelta object
Get the difference seconds between the two dates by calling "total_seconds()" on the timedelta object
Dividing the number of seconds by 24*60*60 will give the number of days
Dividing the number of days by 30 or (as you like) 31 will give the number of months. You can round the value as you like.
This should suffice:
d,m,y = date1.split('/')
d1 = datetime.date(y, m, d)
d,m,y = date1.split('/')
d2 = datetime.date(y, m, d)
delta = d2 - d1
days = delta.total_seconds() // (24*60*60)
result = int(days/30.0+0.5)
The nice thing: No additional packages needed, all is in the standard packages.
I need to construct datetime object from different parameters. For example, I get these parameters:
integer number from 0 to 6. This one indicates weekday.
hour and minutes in float format (from 0.0 to 24.0).
And then I know which week of the current year it is going to be. So, for example, let say that datetime should be from 2014-07-18 00:00:00 to 2014-07-24 23:59:00 (seconds can be ignored and left at 00). So to get exact datetime I need to use above defined parameters.
Let say I would get these parameters 4 (meaning Friday), and 9.5 (meaning 09:30).
So by doing such construction, I should get a date that would be: 2014-07-22 09:30:00. How could accomplish such thing?
Do I need to somehow get for example day of the month by knowing which is the week of the year and which weekday it is?
P.S. A bit more detailed example of what I'm trying to accomplish
from datetime import datetime
today = datetime.today() #using this to get the week I'll be working with.
today = today.replace(day=?) #how to get which day I
#need to enter by having weekday and knowing that week is the present one?
You could do something like that, if your parameters are weekday and t (time):
from datetime import timedelta
monday = today - timedelta(days=today.weekday())
result = (monday + timedelta(days=weekday)).replace(hour=int(t), minutes=int((t - int(t)) * 60))
If you have a starting date, use the relative value of the datetime.datetime.weekday() value to construct a timedelta() object that'll put you onto the right weekday, then replace the hour and minutes:
from datetime import timedelta
def relative_date(reference, weekday, timevalue):
hour, minute = divmod(timevalue, 1)
minute *= 60
days = reference.weekday() - weekday
return (reference - timedelta(days=days)).replace(
hour=int(hour), minute=int(minute), second=0, microsecond=0)
Demo:
>>> from datetime import timedelta, datetime
>>> def relative_date(reference, weekday, timevalue):
... hour, minute = divmod(timevalue, 1)
... minute *= 60
... days = reference.weekday() - weekday
... return (reference - timedelta(days=days)).replace(
... hour=int(hour), minute=int(minute), second=0, microsecond=0)
...
>>> relative_date(datetime.now(), 4, 9.5)
datetime.datetime(2014, 8, 22, 9, 30)
>>> relative_date(datetime.now() - timedelta(days=30), 6, 11.75)
datetime.datetime(2014, 7, 27, 11, 45)
I would use timedelta to add the difference between weekdays to the datetime
from datetime import datetime, timedelta
friday = 4
today = datetime.now()
friday_this_week = today + timedelta(friday - today.weekday())
In your case just replace today with a date that is in the week you want.
I'm trying to get my head around the datetime module. I know the time now as an epoch and the time an event last happened (as an epoch time). What I need to do is figure out whether that event happened between midnight and midnight of yesterday.
t = time.time() # is now
t2 = 1234567890 # some arbitrary time from my log
24 hours ago is t - 86400, but how can I round that up and down to midnight. I'm having real trouble finding a way to get timestamps in and out of datetime or then manipulating a datetime to set the time.
In the Middle of the Night
Generating the last midnight is easy:
from datetime import datetime, time
midnight = datetime.combine(datetime.today(), time.min)
That combines today's date (you can use date() or a datetime() instance, your pick), together with time.min to form a datetime object at midnight.
Yesterday
With a timedelta() you can calculate the previous midnight:
from datetime import timedelta
yesterday_midnight = midnight - timedelta(days=1)
That Was Yesterday
Now test if your timestamp is in between these two points:
timestamp = datetime.fromtimestamp(some_timestamp_from_your_log)
if yesterday_midnight <= timestamp < midnight:
# this happened between 00:00:00 and 23:59:59 yesterday
All Together Now
Combined into one function:
from datetime import datetime, time, timedelta
def is_yesterday(timestamp):
midnight = datetime.combine(datetime.today(), time.min)
yesterday_midnight = midnight - timedelta(days=1)
return yesterday_midnight <= timestamp < midnight:
if is_yesterday(datetime.fromtimestamp(some_timestamp_from_your_log)):
# ...
Midnight at the start of today is:
midnight = (int(time.time() // 86400)) * 86400
so yesterday's midnight is:
midnight = (int(time.time() // 86400)) * 86400 - 86400
Given such a timestamp, you can use divmod to compute the number of days since the epoch (which you don't care about), and how many seconds are leftover (which you do):
days_since, remaining_seconds = divmod(t, 24*3600) # Divide by number of seconds in one day
Then, you subtract the leftover seconds from your original timestamp, which produces midnight
of the current day.
t -= remaining_seconds
Rounding up is as simple as shifting your target timestamp forward exactly one day before rounding down.
tomorrow_t = t + 24 * 3600
days_since, remaining_seconds = divmod(tomorrow_t, 24*3600)
t = tomorrow_t - remaining_seconds
To get the specific timezone's midnight timestamp:
from datetime import datetime
import pytz
TZ = "Asia/Shanghai"
datetime.now(pytz.timezone(TZ)).replace(hour=0, minute=0, second=0, microsecond=0).timestamp()
In my estimation, many date and time manipulations are easier to do, and to understand, using the arrow library. This is one of them.
Create an arbitrary date and time.
>>> import arrow
>>> arbitrary = arrow.get(2017,8,16,11,5)
Calculate midnight_yesterday: first, midnight of arbitrary as its 'day' floor; then shift this back by one day. Display the result.
>>> midnight_yesterday = arbitrary.floor('day').shift(days=-1)
>>> midnight_yesterday
<Arrow [2017-08-15T00:00:00+00:00]>
Use timestamp for the desired overall result, for Python 3.3+.
>>> midnight_yesterday.datetime.timestamp()
1502755200.0
Or use this expression for Python 2.7. (Credit: https://stackoverflow.com/a/11743262/131187 for the latter two expressions.)
>>> (midnight_yesterday-arrow.get(1970,1,1)).total_seconds()
1502755200.0
You can use this code:
import time
seconds_of_day = 24 * 60 * 60 # 86400
last_midnight = (round(time.time()) // seconds_of_day) * seconds_of_day
yesterday_last_midnight = last_midnight - seconds_of_day
import time
start_str = time.strftime( "%m/%d/%Y" ) + " 00:00:00"
end_str = time.strftime( "%m/%d/%Y ") + " 23:59:59"
start_ts = int( time.mktime( time.strptime( start_str, "%m/%d/%Y %H:%M:%S" ) ) )
end_ts = int( time.mktime( time.strptime( end_str, "%m/%d/%Y %H:%M:%S" ) ) )
print (start_ts) # timestamp today at 00:00:00
print (end_ts) # timestamp today at 23:59:59
# 1552435200
# 1552521599
Source Python get unix epoch for today’s midnight and today’s 23:59:59 (start of day, end of day)