Related
I have this code and I want to count the days between 2 dates.
from datetime import date, datetime
checkin= datetime(2022, 1, 30, 1, 15, 00)
checkout= datetime(2022, 1, 31, 0, 0, 00)
count_days= (checkout - checkin).days
In this case, the result of count_days result is 0, because in an operation with 2 datetimes, it takes into account hours, minutes and seconds.
I want the result to be 1 because is +1 day of difference. Type of variables must be datetimes. Thanks!
Convert them to dates first, with the date method.
from datetime import date, datetime
checkin = datetime(2022, 1, 30, 1, 15, 00)
checkout = datetime(2022, 1, 31, 0, 0, 00)
count_days = (checkout.date() - checkin.date()).days
Could you do something like this?
(assuming you want a minimum since the solution you have is similar)
from datetime import date, datetime
check_in= datetime(2022, 1, 30, 1, 15, 00)
check_out= datetime(2022, 1, 31, 0, 0, 00)
# Number of days between two dates (min 1 day)
days = (check_out - check_in).days + 1
print(days)
I have some trouble to understand the behavior of dateutil.relativedelta.
I understand that relativedelta could return past dates if I use negative arguments as specified in relativedelta doc.
However, when I provide positive parameters, I expect that it always return a date in the future... that seems legit right?
My use case is the following : we are Tuesday, it is 8:35. I want to get the date of the closest Monday and Tuesday at 6:00.
Here what I did. The first result seems correct to me, while the second one is wrong.
>>> import datetime
>>> now = datetime.datetime.now()
>>> now
datetime.datetime(2016, 11, 29, 8, 35, 23, 786349)
>>> from dateutil import relativedelta
>>> now.weekday()
1
>>> now + relativedelta.relativedelta(weekday=0, hour=6, minute=0) # should give a time in the future
datetime.datetime(2016, 12, 5, 6, 0, 23, 786349) # here this is correct, in the future
>>> now + relativedelta.relativedelta(weekday=1, hour=6, minute=0) # should give a time in the future
datetime.datetime(2016, 11, 29, 6, 0, 23, 786349) # but this is in the past / I would expect result (2016, 12, 6, 6, 0, 23, 786349)
So , am I doing something wrong here ?
So according to your initial date, you're actually at 8AM, but you're targeting 6AM by using the hour param, if you're trying to increment one hour, you should use hours and minutes respectively
>>> now
datetime.datetime(2016, 11, 29, 3, 5, 41, 763818)
>>> now.weekday()
1
>>> now + relativedelta.relativedelta(weekday=1, hour=1)
datetime.datetime(2016, 11, 29, 1, 5, 41, 763818) # Notice how it's in the past
>>> now + relativedelta.relativedelta(weekday=1, hours=1)
datetime.datetime(2016, 11, 29, 4, 5, 41, 763818) # Notice how it's one hour in the future
>>> n + relativedelta.relativedelta(weekday=1, hour=6, minute=0, weeks=1)
datetime.datetime(2016, 12, 6, 6, 0, 41, 763818)
I think it's in the doc:
Starting with, about weekday:
These instances may receive a parameter N, specifying the Nth weekday, which could be positive or negative (like MO(+1) or MO(-2). Not specifying it is the same as specifying +1.
So by passing 1, it's like you're passing (1, 1)
Then, continuing on the doc, on the 7th dot of behavior of operations with relativedelta:
Notice that if the calculated date is already Monday, for example, using (0, 1) or (0, -1) won’t change the day.
So the 29th of November is already a Tuesday, and you're asking for a Tuesday.
So nothing changes.
I want to write a function that returns a tuple of (start,end) where start is the Monday at 00:00:00:000000 and end is Sunday at 23:59:59:999999. start and end are datetime objects. No other information is given about day, month or year. i tried this function
def week_start_end(date):
start= date.strptime("00:00:00.000000", "%H:%M:%S.%f")
end = date.strptime("23:59:59.999999", "%H:%M:%S.%f")
return (start,end)
print week_start_end(datetime(2013, 8, 15, 12, 0, 0))
should return (datetime(2013, 8, 11, 0, 0, 0, 0), datetime(2013, 8, 17, 23, 59, 59, 999999))
but the function returns tuple with dates (datetime.datetime(1900, 1, 1, 0, 0), datetime.datetime(1900, 1, 1, 23, 59, 59, 999999))
I think using datetime.isocalendar is a nice solution. This give the correct outputs for your example:
import datetime
def iso_year_start(iso_year):
"The gregorian calendar date of the first day of the given ISO year"
fourth_jan = datetime.date(iso_year, 1, 4)
delta = datetime.timedelta(fourth_jan.isoweekday()-1)
return fourth_jan - delta
def iso_to_gregorian(iso_year, iso_week, iso_day):
"Gregorian calendar date for the given ISO year, week and day"
year_start = iso_year_start(iso_year)
return year_start + datetime.timedelta(days=iso_day-1, weeks=iso_week-1)
def week_start_end(date):
year = date.isocalendar()[0]
week = date.isocalendar()[1]
d1 = iso_to_gregorian(year, week, 0)
d2 = iso_to_gregorian(year, week, 6)
d3 = datetime.datetime(d1.year, d1.month, d1.day, 0,0,0,0)
d4 = datetime.datetime(d2.year, d2.month, d2.day, 23,59,59,999999)
return (d3,d4)
As an example:
>>> d = datetime.datetime(2013, 8, 15, 12, 0, 0)
>>> print week_start_end(d)
(datetime.datetime(2013, 8, 11, 0, 0), datetime.datetime(2013, 8, 17, 23, 59, 59, 999999))
And should help you with your problem.
I have a code like this:
import time
from datetime import date
startyear = raw_input("start year: ")
startmonth = raw_input("start month: ")
startday = raw_input("start day: ")
endyear = raw_input("end year: ")
endmonth = raw_input("end month: ")
endday = raw_input("end day: ")
startdate = date(int(startyear), int(startmonth), int(startday))
while startdate < date(int(endyear), int(endmonth), int(endday)):
print startdate
startdate = startdate.replace(day=startdate.day + 1)
what this code does is:
1.get start and end date by manual input
2.generate a list of dates between them
but the problem is, if I set up the date like, for example,
startdate: 2012-10-28
enddate: 2012-11-4
the output would be like:
2012-10-28
2012-10-29
2012-10-30
2012-10-31
ValueError: day is out of range for month
I want the output to be like:
2012-10-28
2012-10-29
2012-10-30
2012-10-31
2012-11-01
2012-11-02
2012-11-03
2012-11-04
So I want the dates to go through month.
any suggestions? any help would be really great.
Instead of startdate.replace(), you should use timedelta...
from datetime import date, timedelta
# Get input here...
while startdate < date(int(endyear), int(endmonth), int(endday)):
print startdate
startdate += timedelta(days=1)
There's a module called python-dateutil which is very useful for this kind of thing:
from datetime import datetime
from dateutil.rrule import rrule, DAILY
list(rrule(DAILY, dtstart=datetime(2012, 11, 24), until=datetime(2012,11,30)))
# [datetime.datetime(2012, 11, 24, 0, 0), datetime.datetime(2012, 11, 25, 0, 0), datetime.datetime(2012, 11, 26, 0, 0), datetime.datetime(2012, 11, 27, 0, 0), datetime.datetime(2012, 11, 28, 0, 0), datetime.datetime(2012, 11, 29, 0, 0), datetime.datetime(2012, 11, 30, 0, 0)]
And has other options, for instance, by days of the week (useful to only include MO, TU, WE, TH, FR for working weeks):
from dateutil.rrule import MO, WE
list(rrule(DAILY, byweekday=[MO, WE], dtstart=datetime(2012, 11, 24), until=datetime(2012,11,30))
# [datetime.datetime(2012, 11, 26, 0, 0), datetime.datetime(2012, 11, 28, 0, 0)]
How can I generate recurring dates using Python? For example I want to generate recurring date for "Third Friday of every second month". I want to generate recurring dates for daily, weekly, monthly, yearly (i.e., same as the recurrence function in Outlook Express).
import dateutil.rrule as dr
import dateutil.parser as dp
import dateutil.relativedelta as drel
start=dp.parse("19/02/2010") # Third Friday in Feb 2010
This generates the third Friday of every month
rr = dr.rrule(dr.MONTHLY,byweekday=drel.FR(3),dtstart=start, count=10)
This prints every third Friday:
print map(str,rr)
# ['2010-02-19 00:00:00', '2010-03-19 00:00:00', '2010-04-16 00:00:00', '2010-05-21 00:00:00', '2010-06-18 00:00:00', '2010-07-16 00:00:00', '2010-08-20 00:00:00', '2010-09-17 00:00:00', '2010-10-15 00:00:00', '2010-11-19 00:00:00']
rr is an iterable, so you can use slicing notation to pick out every other item. This prints the third Friday of every other month:
print map(str,rr[::2])
# ['2010-02-19 00:00:00', '2010-04-16 00:00:00', '2010-06-18 00:00:00', '2010-08-20 00:00:00', '2010-10-15 00:00:00']
Above, I used str to prettify the output a little bit. For more flexible string formatting of dates, use strftime: See http://au2.php.net/strftime or the man page for strftime for all the options.
print [d.strftime('%d/%m/%Y') for d in rr[::2]]
# ['19/02/2010', '16/04/2010', '18/06/2010', '20/08/2010', '15/10/2010']
You can give dateutil a try - especially its relativedelta and rrule fetures.
you may try to write this yourself. you will first need an iterator which generates dates separated by a given interval:
import datetime
def dateiter(start, resolution):
date = start
while True:
yield date
date += resolution
now, you can generate dates and filter them:
# generate a list of every tuesday of february
# this iterates over every day from now, and filtered according to the rules
# warning: infinite generator below, there is nothing to end the iteration
tuesdays_of_february = (date for date in dateiter(datetime.datetime.now(), datetime.timedelta(days=1)) if date.weekday() == 4 and date.month == 2)
you can call the iterator yourself until you have enough dates:
>>> next(tuesdays_of_february)
datetime.datetime(2010, 2, 19, 14, 25, 46, 171000)
now, you need to limit the results:
>>> from itertools import *
>>>
>>> # get the five next valid dates:
>>> list(islice(tuesdays_of_february),5)
[datetime.datetime(2010, 2,26, 14, 25, 46, 171000), datetime.datetime(2011, 2, 4
, 14, 25, 46, 171000), datetime.datetime(2011, 2, 11, 14, 25, 46, 171000), datet
ime.datetime(2011, 2, 18, 1 4, 25, 46, 171000), datetime.datetime(2011, 2, 25
, 14, 25, 46, 171000)]
>>>
>>> # or until a condition is met:
>>> list(takewhile( lambda date: date.year < 2014, tuesdays_of_february ))
[datetime.datetime(2012, 2, 3, 14, 25, 46, 171000), datetime.datetime(2012, 2, 1
0, 14, 25, 46, 171000), datetime.datetime(2012, 2, 17, 14, 25, 46, 171000), date
time.datetime(2012, 2, 24, 14, 25, 46, 171000), datetime.datetime(2013, 2, 1, 14
, 25, 46, 171000), datetime.datetime(2013, 2, 8, 14, 25, 46, 171000), datetime.d
atetime(2013, 2, 15, 14, 25, 46, 171000), datetime.datetime(2013, 2, 22, 14, 25,
46, 171000)]
don't forget to have a look at the documentation for the datetime module.