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 am fairly new to python and I am looking for an efficient way to organize time in designated bins. I have a table with [start_time] and [duration]. I want to fill the time spent in each hourly interval based on this table.
Example: if I have this table,
start_time duration
12:25 1:00
13:35 0:15
14:03 0:20
15:40 0:10
16:15 1:05
17:30 0:40
then the expected output is
bins time
12:00 - 13:00 0:35
13:00 - 14:00 0:40
14:00 - 15:00 0:20
15:00 - 16:00 0:10
16:00 - 17:00 0:45
17:00 - 18:00 0:50
18:00 - 19:00 0:10
19:00 - 20:00 0:00
I would appreciate any help on this task! :)
The python-ranges library I wrote a while ago could be useful for this:
from ranges import Range, RangeSet
from datetime import datetime, timedelta
from functools import reduce
# times, transcribed from above
# and converted to datetimes (so that we can use timedelta math)
times = [
(datetime(1, 1, 1, 12, 25), timedelta(hours=1)), # (12:25, 1:00),
(datetime(1, 1, 1, 13, 35), timedelta(minutes=15)), # (13:35, 0:15),
(datetime(1, 1, 1, 14, 3), timedelta(minutes=20)), # (14:03, 0:20),
(datetime(1, 1, 1, 15, 40), timedelta(minutes=10)), # (15:40, 0:10),
(datetime(1, 1, 1, 16, 15), timedelta(minutes=65)), # (16:15, 1:05),
(datetime(1, 1, 1, 17, 30), timedelta(minutes=40)), # (17:30, 0:40),
]
# make a RangeSet that encompasses the entire day
wholeDay = RangeSet(Range(datetime(1, 1, 1, 12, 00), datetime(1, 1, 1, 20, 00)))
# remove our times from the whole day
wholeDay -= [Range(start, start + duration) for (start, duration) in times]
# get a list of correspondences with timedeltas
bins = {}
for h in range(12, 20):
# create the 1-hour-long range
period = Range(datetime(1, 1, 1, h), datetime(1, 1, 1, h + 1))
# compute number of minutes in this range *were consumed* during the whole day
# which is the same as the number of minutes in this period that are not contained in wholeDay
# (in other words, the length of the set difference)
# We have to do this roundabout counting-second method,
# because timedelta() doesn't work with sum() natively
time_seconds = sum(rng.length().seconds for rng in period.difference(wholeDay))
# finally, add to dict
bins[period] = timedelta(seconds=time_seconds)
This produces the following bins:
{Range[datetime.datetime(1, 1, 1, 12, 0), datetime.datetime(1, 1, 1, 13, 0)): datetime.timedelta(seconds=2100),
Range[datetime.datetime(1, 1, 1, 13, 0), datetime.datetime(1, 1, 1, 14, 0)): datetime.timedelta(seconds=2400),
Range[datetime.datetime(1, 1, 1, 14, 0), datetime.datetime(1, 1, 1, 15, 0)): datetime.timedelta(seconds=1200),
Range[datetime.datetime(1, 1, 1, 15, 0), datetime.datetime(1, 1, 1, 16, 0)): datetime.timedelta(seconds=600),
Range[datetime.datetime(1, 1, 1, 16, 0), datetime.datetime(1, 1, 1, 17, 0)): datetime.timedelta(seconds=2700),
Range[datetime.datetime(1, 1, 1, 17, 0), datetime.datetime(1, 1, 1, 18, 0)): datetime.timedelta(seconds=3000),
Range[datetime.datetime(1, 1, 1, 18, 0), datetime.datetime(1, 1, 1, 19, 0)): datetime.timedelta(seconds=600),
Range[datetime.datetime(1, 1, 1, 19, 0), datetime.datetime(1, 1, 1, 20, 0)): datetime.timedelta(0)}
which is your intended output, represented by datetimes.
I want to make one function that will take input current month and current year and will give the output of last 12 and 24 months with years,
for example, lets suppose the function is f,
f(4,2019) # 4 is the current month and 2019 is the current year
This function will return two two outputs
first output:
[3,2,1,12,11,10,9,8,7,6,5,4] # last 12 months from current month i.e. 4
[2019,2019,2019,2018,2018,2018,2018,2018,2018,2018,2018,2018]
# the years of corresponding months
second output:
[3,2,1,12,11,10,9,8,7,6,5,4,3,2,1,12,11,10,9,8,7,6,5,4] # last 24 months
[2019,2019,2019,2018,2018,2018,2018,2018,2018,2018,2018,2018,
2018,2018,2018,2017,2017,2017,2017,2017,2017,2017,2017,2017]
# years of above months
How to do it in most effective way in python ?
You could use `Pandas' library to set the today's date, and your target prior months.
import pandas as pd
today = pd.to_datetime('today').strftime("%d/%m/%Y")
last = (pd.to_datetime(today) - pd.DateOffset(years=1)).strftime("%d/%m/%Y")
listofmonths = pd.date_range(start=last, end=today, freq='MS')
If you want to get 24 months, set years to 2.
The most effective way is to avoid doing the date arithmetic yourself and use dateutil to do it for you.
>>> from dateutil import parser, relativedelta
>>> d = parser.parse('2019-04-01')
>>> d
datetime.datetime(2019, 4, 1, 0, 0)
>>> previous = [d - relativedelta.relativedelta(months=m) for m in range(1,13)]
>>> previous
[datetime.datetime(2019, 3, 1, 0, 0), datetime.datetime(2019, 2, 1, 0, 0),
datetime.datetime(2019, 1, 1, 0, 0), datetime.datetime(2018, 12, 1, 0, 0),
datetime.datetime(2018, 11, 1, 0, 0), datetime.datetime(2018, 10, 1, 0, 0),
datetime.datetime(2018, 9, 1, 0, 0), datetime.datetime(2018, 8, 1, 0, 0),
datetime.datetime(2018, 7, 1, 0, 0), datetime.datetime(2018, 6, 1, 0, 0),
datetime.datetime(2018, 5, 1, 0, 0), datetime.datetime(2018, 4, 1, 0, 0)]
To get 24 months rather than 12, substitute 25 for 13 in the list comprehension.
You will probably find it more convenient to get datetimes back from your function rather than integers. It's easy to extract date and month from a datetime, formatting is much more convenient, and you will probably have to turn them back into datetimes at some point anyway.
Even if stackoverflow isn't actually a code-writing service... this should do it:
#!/usr/bin/env python
# -*- coding: utf-8 -*-
def f(month, year):
m=range(12, 0, -1)*3
y=[year]*12+[year-1]*12
return m[13-month:(13-month+12)], y[13-month:(13-month+12)]
print f(4, 2019)
Output is:
([3, 2, 1, 12, 11, 10, 9, 8, 7, 6, 5, 4], [2019, 2019, 2019, 2018, 2018, 2018, 2018, 2018, 2018, 2018, 2018, 2018])
You can derive the version for two years from it yourself.
Function:
import datetime
import dateutil.relativedelta
def get_prev_month_date(year, month, period):
years, months = ([] for j in range(2))
for i in range(1, period+ 1):
date = datetime.date(year, month, 3)
months.append((date - dateutil.relativedelta.relativedelta(months=i)).month)
years.append((date - dateutil.relativedelta.relativedelta(months=i)).year)
return years, months
Code:
years_list, months_list = get_prev_month_date(2019, 4, 12)
Results:
[2019, 2019, 2019, 2018, 2018, 2018, 2018, 2018, 2018, 2018, 2018, 2018]
[3, 2, 1, 12, 11, 10, 9, 8, 7, 6, 5, 4]
I'm using rrule from python dateutil and don't know how to create an rruleset for the following example:
Monday, three weeks in a row. Then a week not, then again three weeks in a row, one not, and so on.
Any advice on creating an rrule(set) for this?
One way to do this is to use an rruleset with a WEEKLY rrule and a corresponding exrule for every 4th week:
from dateutil.rrule import rrule, rruleset
from dateutil.rrule import WEEKLY
from dateutil.relativedelta import relativedelta
from datetime import datetime, timedelta
dtstart = datetime(2011, 1, 1)
rrset = rruleset()
weekly_rule = rrule(freq=WEEKLY, dtstart=dtstart)
every_4_weeks = rrule(freq=WEEKLY, interval=4,
dtstart=dtstart + relativedelta(weeks=4))
rrset.rrule(weekly_rule)
rrset.exrule(every_4_weeks)
rrset.between(dtstart, dtstart + timedelta(days=65))
The result:
[datetime.datetime(2011, 1, 8, 0, 0),
datetime.datetime(2011, 1, 15, 0, 0),
datetime.datetime(2011, 1, 22, 0, 0),
datetime.datetime(2011, 2, 5, 0, 0),
datetime.datetime(2011, 2, 12, 0, 0),
datetime.datetime(2011, 2, 19, 0, 0),
datetime.datetime(2011, 3, 5, 0, 0)]
The way it works is weekly_rule generates one date per week, and the every_4_weeks generates every 4th week, starting with the 4th week after dtstart. That gives you a 3-on 1-off schedule.
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.