Converting an array of dates to datetime format and comparing them - python

I would like to convert an array of dates and times string to an array of datetime object so I can compare the dates and find the newest one (the one most in the future).
First I convert and then combine the dates and time.
I'm struggling to create an array of datetimes and after some research I'm not sure if it is possible.
dates = ['2019-02-18','2019-02-18','2019-02-18','2019-02-18','2019-02-18','2019-02-18','2019-02-18','2019-02-18','2019-02-19','2019-02-19']
times = ['06:15', '18:30', '19:45', '14:20', '16:10','06:10', '18:35', '19:40', '14:25', '16:15' ]
dates_count = len(dates)
dates_obj = []
times_obj = []
for i in range(dates_count):
dates_obj.append(datetime.strptime(dates[i], '%Y-%m-%d'))
times_obj.appned(datetime.strptime(times[i], '%H:%M'))
dates_times_obj = datetime.combine(datetime.date(dates_obj[i]), datetime.time(times[i]))
print (dates_times_obj)
Output error
dates_times_obj = datetime.combine(datetime.date(dates_obj[i]), datetime.time(times[i]))
TypeError: descriptor 'time' requires a 'datetime.datetime' object but received a 'str'

Can you try the following:
datetime.datetime.strptime(dates_obj[i] + times[i], '%Y-%m-%d%H:%M').date()
So in your code it will the following:
dates_times_obj = datetime.datetime.strptime(dates_obj[i] + times[i], '%Y-%m-%d%H:%M').date()

It appears to be a typo, since you referred to times[i] instead of times_obj[i]. Additionally, if you don't need the lists of dates and times object, I would suggest to make the use of some nice features of python language, like zip:
dates = ['2019-02-18','2019-02-18','2019-02-18','2019-02-18','2019-02-18','2019-02-18','2019-02-18','2019-02-18','2019-02-19','2019-02-19']
times = ['06:15', '18:30', '19:45', '14:20', '16:10','06:10', '18:35', '19:40', '14:25', '16:15' ]
for date_str, time_str in zip(dates, times):
date_obj = datetime.strptime(date_str, '%Y-%m-%d')
time_obj = datetime.strptime(time_str, '%H:%M').time()
dates_times_obj = datetime.combine(date_obj, time_obj)
print(dates_times_obj)

You can use the builtin function max as follow:
newest_date = max(
datetime.datetime.strptime( d + " " + t, "%Y-%m-%d %H:%M" )
for d, t in zip( dates, times )
)

Related

Concatenate and convert string to date in Python

I have a string ‘2022.10.31’ and I want to convert it to ‘2022-10-31’ and then to date.
This is the R code:
pr1$dotvoranje <- paste(substr(pr1$dotvoranje, 1, 4), substr(pr1$dotvoranje, 6, 7), substr(pr1$dotvoranje, 9, 10), sep = "-")
pr1$dotvoranje <- as.Date(pr1$dotvoranje)
I need to do the following code in Python I found that I need to use .join() , but I have a column with strings that I need to convert to dates.
I started with this code (but I do not know how to use .join here). But this line only substracted the first four rows of that column. And I need to take that column and replace "."with "-".
depoziti['ddospevanje'] = depoziti['ddospevanje'].loc[0:4] + depoziti['ddospevanje'].loc[5:7] + depoziti['ddospevanje'].loc[8:10]
I'm going to assume that by "then to date" you mean you want a datetime object.
It is not necessary to do string.replace() in order to create the datetime object.
The datetime object uses syntax like %Y to refer to a year and so we will be using that with the function strptime() to ingest the date.
import datetime
date_as_string = "2022.10.31"
date_format = "%Y.%m.%d"
date = datetime.strptime(date_as_string, date_format)
Now you have a date time object.
If you want to then print out the date as a string, you can use strftime()
new_format = "%Y-%m-%d"
date_as_new_string = date.strftime(new_format)
print(date_as_new_string)
Further reference:
https://docs.python.org/3/library/datetime.html#datetime.datetime.strptime
https://www.w3schools.com/python/python_datetime.asp -(This also contains a list of all the syntax for use with strftime() or strptime())
if you are getting your dates (as strings) in a list, then just put the above code into a for loop:
import datetime
date_format = "%Y.%m.%d"
date_as_string_list = ['2022.12.31', '2022.11.30']
date_list = []
for date_as_string in date_as_string_list:
date_list.append(datetime.strptime(date_as_string, date_format))
now you have a list of datetime objects, and you can loop through them in order to get them as strings as already shown.
Just putting it together
from datetime import datetime
dt1 = '2022.10.31'
dt2 = datetime.strptime(dt1, '%Y.%m.%d').date()
print ("type(dt2) :", type(dt2))
print ("dt2 :", dt2)
Output
type(dt2) : <class 'datetime.datetime'>
dt2 : 2022-10-31
Update : dt1 should be a series of string dates, not only one string... dt = ['2022.12.31', '2022.11.30'.....]
If it's a list, use list comprehension
dt1 = ['2022.10.31', '2022.10.1', '2022.9.1']
dt2 = [datetime.strptime(i, '%Y.%m.%d').date() for i in dt1]
dt2
If it's a column in pandas dataframe, this is one way of doing it
df = pd.DataFrame({'event' : ['x', 'y', 'z'],
'date' : ['2022.10.31', '2022.10.1', '2022.9.1']})
df['date1'] = df['date'].apply(lambda x : datetime.strptime(x, '%Y.%m.%d').date())
df

Reversing the date order of "%Y-%m-%d" to "%d-%m-%Y"

Using todays date, I would like to reformat the date so that it reads as follows:
25-09-2021
So far I have come up with a very clumsy way of doing:
from datetime import datetime, timedelta, date
print(datetime.now())
the_date = datetime.strftime(datetime.now(), '%Y-%m-%d')
print(the_date)
a = the_date[-2:]
print(a)
b = the_date[5:-3]
print(b)
c = the_date[:4]
print(c)
new_date = str(a)+'-'+str(b)+'-'+str(c)
print(new_date)
Surely there is a cleaner way of doing this?
You could simply specify the formula differently:
datetime.strftime(datetime.now(), '%d-%m-%Y')
It is not clear what type of data you are starting with. If you have an existing date string in the format YYYY-MM-DD, you can split and reorder it.
Here's an example.
date = '2021-09-25'
Y, M, D = date.split('-')
date = f"{D}-{M}-{Y}"
print(date) # Prints 25-09-2021
Assuming you start with a string with the given format
original_date_str = datetime.now().strftime('%Y-%m-%d')
#this line recreates a datetime object from the string
original_date_datetime = datetime.strptime(original_date_str, '%Y-%m-%d')
#this value will be a string with the new format
new_fmt_date_str = original_date_datetime.strftime("%d-%m-%Y")
I haven't tested the code yet, but pending some silly mistake it should work.

Fill list of start/end dates with dates in between

Given a list with the following structure :
[start_date_cycle1, end_date_cycle1, start_date_cycle2, end_date_cycle2, ..., end_date_cycleK]
where all elements are timestamps, I would like to get the following
[[start_date_cycle1, start_date_cycle1 +1d, start_date_cycle1 +2d, ..., end_date_cycle1],
[start_date_cycle2, start_date_cycle2 +1d ...]]
So if the input is ['10-23-2019', '10-26-2019' , '11-02-2019', '11-06-2019'], the output would be :
[['10-23-2019', '10-24-2019','10-25-2019', '10-26-2019'] ,
['11-02-2019', '11-03-2019','11-04-2019','11-05-2019','11-06-2019']]
P.S : The length of the list will always be an even number (so no start of cycle without end).
You can use timedelta from datetime module to iterate from start to end date, as below
from datetime import datetime as dt, timedelta as td
strp,strf,fmt=dt.strptime,dt.strftime,"%m-%d-%Y"
a=['10-23-2019', '10-26-2019' , '11-02-2019', '11-06-2019']
print([[strf(k,fmt) for k in (strp(i,fmt)+td(days=n) for n in range((strp(j,fmt)-strp(i,fmt)).days+1))] for i,j in zip(a[::2],a[1::2])])
Output
[['10-23-2019', '10-24-2019', '10-25-2019', '10-26-2019'], ['11-02-2019', '11-03-2019', '11-04-2019', '11-05-2019', '11-06-2019']]
You can parse the strings as datetime objects, use them to do the necessary calculations (by adding timedelta objects), and then convert back to strings at the end.
To produce the output as a nested list, as specified in the question, the temporary variable dates_out is used to generate the inner lists, which are appended to the main list (out) inside the loop.
If you want to use day-month-year ordering, change the '%m-%d-%Y' to '%d-%m-%Y' in the one place where it occurs.
import datetime
dates = ['10-23-2019', '10-26-2019' , '11-02-2019', '11-06-2019']
format = '%m-%d-%Y'
dts = [datetime.datetime.strptime(date, format) for date in dates]
out = []
i = iter(dts)
for start, end in zip(i, i):
dt = start
dates_out = []
while dt <= end:
dates_out.append(datetime.datetime.strftime(dt, format))
dt += datetime.timedelta(days=1)
out.append(dates_out)
print(out)
This gives:
[['10-23-2019', '10-24-2019', '10-25-2019', '10-26-2019'],
['11-02-2019', '11-03-2019', '11-04-2019', '11-05-2019', '11-06-2019']]
(newline inserted for readability)
This is one approach using datetime module
Ex:
import datetime
data = ['10-23-2019', '10-26-2019' , '11-02-2019', '11-06-2019']
result = []
for s, e in zip(data[::2], data[1::2]): # (10-23-2019, 10-26-2019)....
s = datetime.datetime.strptime(s, "%m-%d-%Y")
e = datetime.datetime.strptime(e, "%m-%d-%Y")
temp = []
while s <= e:
temp.append(s.strftime("%m-%d-%Y"))
s += datetime.timedelta(days=1)
if temp:
result.append(temp)
print(result)
Output:
[['10-23-2019', '10-24-2019', '10-25-2019', '10-26-2019'],
['11-02-2019', '11-03-2019', '11-04-2019', '11-05-2019', '11-06-2019']]
You can do this easily using dateutil module. You can install it by doing pip install python-dateutil.
map(parse, lst) would convert the dates from string to datetime obj; zip(*[map(parse, lst)]*2) would create pairs of datetime objs, so that you can navigate them as (start,end) pairs. And finally rrule(freq=DAILY, dtstart=start, until=end) creates a range of datetime objs from start to end
>>> from dateutil.rrule import rrule, DAILY
>>> from dateutil.parser import parse
>>>
>>> lst = ['10-23-2019', '10-26-2019' , '11-02-2019', '11-06-2019']
>>> res = [[dt.strftime('%m-%d-%Y') for dt in rrule(freq=DAILY, dtstart=start, until=end)] for start,end in zip(*[map(parse, lst)]*2)]
>>>
>>> print(res)
[['10-23-2019', '10-24-2019', '10-25-2019', '10-26-2019'],
['11-02-2019', '11-03-2019', '11-04-2019', '11-05-2019', '11-06-2019']]

How to create a list of dates using datetime in python?

Interestingly, I have searched a lot of questions but I cannot find just a simple answer to this question. Or I do find an answer but it won't allow me the flexibility to alter the format of the dates I require.
If I have a specified start and end date like this:
start = '2015-08-01' #YYY-MM-DD
end = '2020-07-06'
Is there a simple way using datetime in python to create a list of dates between these dates that adhere to this format of YYY-MM-DD? And if so, how can I subsequently reverse this list so list[0] is equal to today?
Here's a way using list comprehensions, which is far faster than the loop examples, and doesn't require any external libraries.
from datetime import date, timedelta
start = '2015-08-01'
end = '2020-07-06'
start_date = date.fromisoformat(start)
end_date = date.fromisoformat(end)
date_range = [
# end_date - timedelta(days=i) # For date objects
(end_date - timedelta(days=i)).isoformat() # For ISO-8601 strings
for i
in range((end_date - start_date).days)
]
reverse_range = list(reversed(date_range))
print(date_range[0])
print(reverse_range[0])
Output
2020-07-06
2015-08-02
You can also use pandas
import pandas as pd
start = '2015-08-01' #YYY-MM-DD
end = '2020-07-06'
pd.date_range(start, end)
# to start from today
pd.date_range(pd.Timestamp.today(), end)
You can also create a range with your desired frequency
pd.date_range(start, end, freq='14d') # every 14 dayes
pd.date_range(start, end, freq='H') # hourly and etc
The datetime.timedelta() function will help here. Try this:
import datetime
dates = []
d = datetime.date(2015,8,1)
while d <= datetime.date(2020,7,6):
dates.append(datetime.datetime.strftime(d,'%Y-%m-%d'))
d += datetime.timedelta(days=1)
This will populate the list dates, which will look like this:
['2015-08-01', '2015-08-02', '2015-08-03', .... , '2020-07-04', '2020-07-05', '2020-07-06']
EDIT:
Just use dates.append(d) instead of dates.append(datetime.datetime.strftime(d,'%Y-%m-%d')) to get a list of datetime.date objects instead of strings.
Reversing a list is pretty straight-forward in Python:
dates = dates[::-1]
After the above, dates[0] will be '2020-07-06'.
something like this ?
import datetime
def date_range(start, end):
r = (end+datetime.timedelta(days=1)-start).days
return [start+datetime.timedelta(days=i) for i in range(r)]
start = datetime.date(2015,01,01)
end = datetime.date(2020,07,06)
dateList = date_range(start, end)
print '\n'.join([str(date) for date in dateList])

Reformatting a list of date strings to day, month, year in Python

I want to change the format of strings in a list. They are dates but have been converted into strings.
I have looked all over for this solution, but there seem to only be answers for a single element.
First I make a series
Date_List = df.loc['receiveddate']
print Date_List
Element1 2015-06-26
Element2 2015-06-25
Element3 2015-06-26
Element4 2015-06-25
Element5 2015-06-25
Element6 2015-07-01
Then I convert it into a list.
Date_List = [str(i) for i in Date_List]
which gives me
['2015-06-26', '2015-06-25', '2015-06-26', '2015-06-25', '2015-06-25', '2015-07-01']
Instead, I want a list of strings that go day, month, year
['06-26-2015', '06-25-2015...etc.]
I've found that the most common suggestion is to use strftime. Trying Date_List = (datetime.datetime.strptime(i, "%B %d-%Y") for i in Date_List) Just gave me ValueError: time data '2015-06-26' does not match format '%B %d-%Y'
So I tried
Date_List = (datetime.datetime.strptime(i, "%Y-%m-%d") for i in Date_List)
This returned ['2015-06-26 00:00:00', '2015-06-25 00:00:00', '2015-06-26 00:00:00', '2015-06-25 00:00:00', '2015-06-25 00:00:00', '2015-07-01 00:00:00']
Does anybody know how to reformat the list? Or perhaps earlier, reformatting the Series? Thank you.
You're almost there. The datetime.datetime.strptime converts a string into datetime object. You need datetime.datetime.strftime to convert it back to string:
Date_List = (datetime.datetime.strptime(i, "%Y-%m-%d") for i in Date_List)
Date_List = (datetime.datetime.strftime(i, "%m-%d-%Y") for i in Date_List)
You don't even need to use datetime here. Just map those objects to a function that turns them into strings and splits them on the -, then use str.format():
Date_List = ['{}-{}-{}'.format(m,d,y) for y, m, d in map(lambda x: str(x).split('-'), Date_List)]
Also, from your code snippet it looks like you want the month first, not the day.
You can solve it by a string point of view
New_Date_List = [d[8:10]+"-"+d[5:7]+"-"+d[:4] for d in Date_List]
Change your comprehension to
import datetime
Date_List = [datetime.datetime.strptime(str(i), '%Y-%m-%d').strftime('%m-%d-%Y') for i in Date_List]
Regular expressions provide a pretty straightforward solution:
>>> import re
>>> re.sub(r'(\d{4})-(\d{2})-(\d{2})', r'\2-\3-\1', '2015-06-25')
'06-25-2015'
While it's not pretty, it should work to generate a month-day-year list.
New_Date_List = [[d][5:7] + '-' + Date_List[d][-2:] + '-' + Date_List[d][:4] for d in Date_List]

Categories

Resources