Have a list of hours between two dates in python - python

I have two times and I want to make a list of all the hours between them using the same format in Python
from= '2016-12-02T11:00:00.000Z'
to= '2017-06-06T07:00:00.000Z'
hours=to-from
so the result will be something like this
2016-12-02T11:00:00.000Z
2016-12-02T12:00:00.000Z
2016-12-02T13:00:00.000Z
..... and so on
How can I so this and what kind of plugin should I use?

If possible I would recommend using pandas.
import pandas
time_range = pandas.date_range('2016-12-02T11:00:00.000Z', '2017-06-06T07:00:00.000Z', freq='H')
If you need strings then use the following:
timestamps = [str(x) + 'Z' for x in time_range]
# Output
# ['2016-12-02 11:00:00+00:00Z',
# '2016-12-02 12:00:00+00:00Z',
# '2016-12-02 13:00:00+00:00Z',
# '2016-12-02 14:00:00+00:00Z',
# '2016-12-02 15:00:00+00:00Z',
# '2016-12-02 16:00:00+00:00Z',
# ...]

simpler solution using standard library's datetime package:
from datetime import datetime, timedelta
DATE_TIME_STRING_FORMAT = '%Y-%m-%dT%H:%M:%S.%fZ'
from_date_time = datetime.strptime('2016-12-02T11:00:00.000Z',
DATE_TIME_STRING_FORMAT)
to_date_time = datetime.strptime('2017-06-06T07:00:00.000Z',
DATE_TIME_STRING_FORMAT)
date_times = [from_date_time.strftime(DATE_TIME_STRING_FORMAT)]
date_time = from_date_time
while date_time < to_date_time:
date_time += timedelta(hours=1)
date_times.append(date_time.strftime(DATE_TIME_STRING_FORMAT))
will give us
>>>date_times
['2016-12-02T11:00:00.000000Z',
'2016-12-02T12:00:00.000000Z',
'2016-12-02T13:00:00.000000Z',
'2016-12-02T14:00:00.000000Z',
'2016-12-02T15:00:00.000000Z',
'2016-12-02T16:00:00.000000Z',
'2016-12-02T17:00:00.000000Z',
'2016-12-02T18:00:00.000000Z',
'2016-12-02T19:00:00.000000Z',
'2016-12-02T20:00:00.000000Z',
...]

Related

Calculate the same month from previous year

I have a date object like
Date = '202011'
This is yyyymm format.
I want to get the same month but n years prior. For example if n = 2, then I should get '201811'
Is there any function available to achieve this?
You can use the datetime module and dateutil library for this:
import datetime
from dateutil.relativedelta import relativedelta
fmt = '%Y%m'
date_string = '202011'
n = 2
# Parse `date_string` into a date object.
date = datetime.datetime.strptime(date_string, fmt).date()
# 2020-11-01
# Subtract `n` years.
new_date = date + relativedelta(years=-n)
# Output in the same format.
print(new_date.strftime(fmt)) # -> 201811
Related questions:
Python date string to date object
How do I calculate the date six months from the current date using the datetime Python module?
Just parse it into a Python datetime object and use its replace() method.
from datetime import datetime
years_ago = 2
date = datetime.strptime('202011','%Y%m')
date = date.replace(year=date.year-years_ago)
# This is the modified date object
print(date)
# Formatted back in your format
print(date.strftime('%Y%m'))
This solution does not require any external dependency
Here's a similar solution to the others, but only using the standard library, and as a function.
def subtract_years(date_string: str, diff: int) -> str:
dt = datetime.strptime(date_string, "%Y%m")
new_dt = dt.replace(year=dt.year - diff)
return new_dt.strftime("%Y%m")
# ❯ subtract_years("202011", 2)
# '201811'

Running Function on all Items in a List (Converting List of Dates to Unix Timestamp)

I'm stuck trying to figure out what is wrong with my for loop. Why is this appending the same UNIX timestamp in all of the UNIX dates variable?
now = datetime.datetime.today()
dates = []
for x in range(7):
d = now - timedelta(days=x)
dates.append(d.strftime("%Y/%m/%d"))
print(dates)
unixdates = []
for date in dates:
e = time.mktime(datetime.datetime.strptime(datetime.date.today().strftime("%m/%d/%Y"), '%m/%d/%Y').timetuple())
unixdates.append(e)
print(unixdates)
Here is the output:
['2021/11/03', '2021/11/02', '2021/11/01', '2021/10/31', '2021/10/30', '2021/10/29', '2021/10/28']
[1635912000.0, 1635912000.0, 1635912000.0, 1635912000.0, 1635912000.0, 1635912000.0, 1635912000.0]
because you use the same date over and over again which will always give the same UNIX time (datetime.date.today(), with datetime being the datetime module here).
simplify your code by using the datetime.timestamp method to get UNIX time:
from datetime import datetime, timedelta
today = datetime.now().date()
dates, unixdates = [], []
for x in range(7):
d = today - timedelta(days=x)
dates.append(d.strftime("%Y/%m/%d"))
unixdates.append(datetime.combine(d, datetime.min.time()).timestamp())
print(dates)
print(unixdates) # my machine is on UTC+1
# ['2021/11/03', '2021/11/02', '2021/11/01', '2021/10/31', '2021/10/30', '2021/10/29', '2021/10/28']
# [1635894000.0, 1635807600.0, 1635721200.0, 1635631200.0, 1635544800.0, 1635458400.0, 1635372000.0]
Also notice that you use naive datetime here, which will assume local time if you don't set the tz argument, e.g.
today = datetime.now(timezone.utc)
to get UTC.

How to add a certain time to a datetime?

I want to add hours to a datetime and use:
date = date_object + datetime.timedelta(hours=6)
Now I want to add a time:
time='-7:00' (string) plus 4 hours.
I tried hours=time+4 but this doesn't work. I think I have to int the string like int(time) but this doesn't work either.
Better you parse your time like below and access datetime attributes for getting time components from the parsed datetime object
input_time = datetime.strptime(yourtimestring,'yourtimeformat')
input_seconds = input_time.second # for seconds
input_minutes = input_time.minute # for minutes
input_hours = input_time.hour # for hours
# Usage: input_time = datetime.strptime("07:00","%M:%S")
Rest you have datetime.timedelta method to compose the duration.
new_time = initial_datetime + datetime.timedelta(hours=input_hours,minutes=input_minutes,seconds=input_seconds)
See docs strptime
and datetime format
You need to convert to a datetime object in order to add timedelta to your current time, then return it back to just the time portion.
Using date.today() just uses the arbitrary current date and sets the time to the time you supply. This allows you to add over days and reset the clock to 00:00.
dt.time() prints out the result you were looking for.
from datetime import date, datetime, time, timedelta
dt = datetime.combine(date.today(), time(7, 00)) + timedelta(hours=4)
print dt.time()
Edit:
To get from a string time='7:00' to what you could split on the colon and then reference each.
this_time = this_time.split(':') # make it a list split at :
this_hour = this_time[0]
this_min = this_time[1]
Edit 2:
To put it all back together then:
from datetime import date, datetime, time, timedelta
this_time = '7:00'
this_time = this_time.split(':') # make it a list split at :
this_hour = int(this_time[0])
this_min = int(this_time[1])
dt = datetime.combine(date.today(), time(this_hour, this_min)) + timedelta(hours=4)
print dt.time()
If you already have a full date to use, as mentioned in the comments, you should convert it to a datetime using strptime. I think another answer walks through how to use it so I'm not going to put an example.

Comparing dates and finding the closest date to the current date

I'm looking to compare a list of dates with todays date and would like to return the closest one. Ive had various ideas on it but they are seem very convoluted and involve scoring based on how many days diff and taking the smallest diff. But I have no clue how to do this simply any pointers would be appreciated.
import datetime
import re
date_list = ['2019-02-10', '2018-01-13', '2019-02-8',]
now = datetime.date.today()
for date_ in date_list:
match = re.match('.*(\d{4})-(\d{2})-(\d{2}).*', date_)
if match:
year = match.group(1)
month = match.group(2)
day = match.group(3)
delta = now - datetime.date(int(year), int(month), int(day))
print(delta)
As I was Waiting EDIT
So I solved this using the below
import datetime
import re
date_list = ['2019-02-10', '2018-01-13', '2019-02-8',]
now = datetime.date.today()
for date_ in date_list:
match = re.match('.*(\d{4})-(\d{2})-(\d{2}).*', date_)
if match:
year = match.group(1)
month = match.group(2)
day = match.group(3)
delta = now - datetime.date(int(year), int(month), int(day))
dates_range.append(int(delta.days))
days = min(s for s in dates_range)
convert each string into a datetime.date object, then just subtract and get the smallest difference
import datetime
import re
date_list = ['2019-02-10', '2018-01-13', '2019-02-8',]
now = datetime.date.today()
date_list_converted = [datetime.datetime.strptime(each_date, "%Y-%m-%d").date() for each_date in date_list]
differences = [abs(now - each_date) for each_date in date_list_converted]
minimum = min(differences)
closest_date = date_list[differences.index(minimum)]
This converts the strings to a datetime object, then subracts the current date from that and returns the date with the corresponding lowest absolute difference:
import datetime
import re
date_list = ['2019-02-10', '2018-01-13', '2019-02-8',]
numPattern = re.compile("[0-9]+")
def getclosest(dates):
global numPattern
now = datetime.date.today()
diffs = []
for day in date_list:
year, month, day = [int(i) for i in re.findall(numPattern, day)]
currcheck = datetime.date(year, month, day)
diffs.append(abs(now - currcheck))
return dates[diffs.index(min(diffs))]
It's by no means the most efficient, but it's semi-elegant and works.
Using inbuilts
Python's inbuilt datetime module has the functionality to do what you desire.
Let's first take your list of dates and convert it into a list of datetime objects:
from datetime import datetime
date_list = ['2019-02-10', '2018-01-13', '2019-02-8']
datetime_list = [datetime.strptime(date, "%Y-%m-%d") for date in date_list]
Once we have this we can find the difference between those dates and today's date.
today = datetime.today()
date_diffs = [abs(date - today) for date in datetime_list]
Excellent, date_diffs is now a list of datetime.timedelta objects. All that is left is to find the minimum and find which date this represents.
To find the minimum difference it is simple enough to use min(date_diffs), however, we then want to use this minimum to extract the corresponding closest date. This can be achieved as:
closest_date = date_list[date_diffs.index(min(date_diffs))]
With pandas
If performance is an issue, it may be worth investigating a pandas implementation. Using pandas we can convert your dates to a pandas dataframe:
from datetime import datetime
import pandas as pd
date_list = ['2019-02-10', '2018-01-13', '2019-02-8']
date_df = pd.to_datetime(date_list)
Finally, as in the method using inbuilts we find the differences in the dates and use it to extract the closest date to today.
today = datetime.today()
date_diffs = abs(today - date_df)
closest_date = date_list[date_diffs.argmin()]
The advantage of this method is that we've removed the for loops and so I'd expect this method to be more efficient for large numbers of dates
one fast and simple way will be to use bisect algorithm, especially if your date_list is significantly big :
import datetime
from bisect import bisect_left
FMT = '%Y-%m-%d'
date_list = ['2019-02-10', '2018-01-13', '2019-02-8', '2019-02-12']
date_list.sort()
def closest_day_to_now(days):
"""
Return the closest day form an ordered list of days
"""
now = datetime.datetime.now()
left_closest_day_index = bisect_left(days, now.strftime(FMT))
# check if there is one greater value
if len(days) - 1 > left_closest_day_index:
right_closest_day_index = left_closest_day_index + 1
right_day = datetime.datetime.strptime(days[right_closest_day_index], FMT)
left_day = datetime.datetime.strptime(days[left_closest_day_index], FMT)
closest_day_index = right_closest_day_index if abs(right_day - now) < abs(left_day - now) \
else left_closest_day_index
else:
closest_day_index = left_closest_day_index
return days[closest_day_index]
print(closest_day_to_now(date_list))

Subtracting Dates of Different Formats and converting to Int

I asked a similar question earlier and got some great feedback. I combined several answers to arrive at a solution, but it seems highly inefficient. I'm looking for a better way to get the total number of days between a variable (ts) and today in the form of an integer.
My Code:
import datetime
ts = '2015-03-01T17:09:00.000+0000'
ts = ts[:10]
f = '%Y-%m-%d'
date_from_sql = datetime.datetime.strptime(ts, f)
now = datetime.datetime.now()
now = str(now)
now = now[:10]
now = datetime.datetime.strptime(str(now), f)
delta = date_from_sql - now
print delta.total_seconds()/(3600*24)
Output:
67.0
delta.total_seconds()/(3600*24) is not needed, just get use .days
from datetime import datetime
now = datetime.now()
ts = '2015-03-01T17:09:00.000+0000'
ts = ts[:10]
f = '%Y-%m-%d'
date_from_sql = datetime.strptime(ts, f)
print(date_from_sql - now).days
If you dont want to take the time into account just use dates:
now = datetime.now().date()
ts = '2015-03-01T17:09:00.000+0000'
ts = ts[:10]
f = '%Y-%m-%d'
date_from_sql = datetime.strptime(ts, f).date()
print(date_from_sql - now).days
If there is a chance the date string may be in different formats you might want dateutil:
from dateutil import parser
now = datetime.now().date()
ts = '2015-03-01T17:09:00.000+0000'
ts = parser.parse(ts).date()
print(ts - now).days
#Padraic, yes agree, My solution also same,
from datetime import datetime
ts = '2015-03-01T17:09:00.000+0000'
print "days:-", (datetime.strptime(ts[:10], '%Y-%m-%d').date() - datetime.now().date()).days
If you don't care about the time of the day (and timezones) i.e., the result has a day resolution; you could use datetime.date class and .toordinal() method to get the number of days:
from datetime import date
ts = '2015-03-01T17:09:00.000+0000'
date_from_sql = date(*map(int, ts[:10].split('-')))
print(date_from_sql.toordinal() - date.today().toordinal())
# -> 66

Categories