Create a parse function for different date formats in Python - python

I want to create a parse function with lambda able to recognize two different formats
"2014-01-06 15:23:00"
and
"2014-01-06"
The idea is to use this function to create a pandas dataframe but in some of the values the hour is missing
This is my first idea
parse = lambda x: pd.datetime.strptime(x, '%Y-%m-%d %H:%M:%S') if x is True else pd.datetime.strptime(x, '%Y-%m-%d')
it seems that x is True is not correct
Any idea??

dateutil has a parser that handles multiple formats:
>>> dateutil.parser.parse('2015-07-04')
datetime.datetime(2015, 7, 4, 0, 0)
>>> dateutil.parser.parse('2015-07-04 11:23:00')
datetime.datetime(2015, 7, 4, 11, 23)
>>> dateutil.parser.parse('2015-07-04T11:23:56')
datetime.datetime(2015, 7, 4, 11, 23, 56)
Even non iso formats like this
>>> dateutil.parser.parse('5-6-15')
datetime.datetime(2015, 5, 6, 0, 0)

Related

I need to find the difference in years between today and a list of dates

I am trying to write a simple function to compare a list of dates to today in order to find dates that are more than 13 years old. For the first part of the challenge I’m just trying to write the function that will compare the dates to find the difference today and each in the birthdays list.
import datetime
birthdays = [
datetime.datetime(2012, 4, 29),
datetime.datetime(2006, 8, 9),
datetime.datetime(1978, 5, 16),
datetime.datetime(1981, 8, 15),
datetime.datetime(2001, 7, 4),
datetime.datetime(1999, 12, 30)
]
today = datetime.datetime.today()
def is_over_13(dt):
Diff = (today - dt)
Return (diff)
Is_over_13(birthdays)
The problem I seem to be facing is that I’m trying to compare a datetime object to a list. So my thinking is that I need to be able to do something to the list to make it compatible to compare? Or the other way round.
I’m learning Python and this is step 1 of a specific code challenge so I can’t use lambda or panda or libraries. I’m expected to do it using functional chaining or comprehensions.
Thanks in advance
I think you need a loop.
for dt in birthdays:
diff=(today-dt)
return diff
You can loop over a list of datetimes to all compare them one by one with today.
This function will return True if one date is over 13 years.
def is_it_over_13(birthday_list):
for date in birthday_list:
if abs(today - date) > datetime.timedelta(days = 13*365):
return True
else:
return False
import datetime
birthdays = [
datetime.datetime(2012, 4, 29),
datetime.datetime(2006, 8, 9),
datetime.datetime(1978, 5, 16),
datetime.datetime(1981, 8, 15),
datetime.datetime(2001, 7, 4),
datetime.datetime(1999, 12, 30)
]
def is_over_13(dt):
today = datetime.datetime.today()
diff = (datetime.datetime.now() - dt).days
# 4745 == 13*365
if diff>4745:
return dt
for i in birthdays:
print(is_over_13(i))
You have a few tweaks to makes.
import datetime
birthdays = [
datetime.datetime(2012, 4, 29),
datetime.datetime(2006, 8, 9),
datetime.datetime(1978, 5, 16),
datetime.datetime(1981, 8, 15),
datetime.datetime(2001, 7, 4),
datetime.datetime(1999, 12, 30)
]
today = datetime.datetime.today()
def is_over_13(dt):
diff = (today - dt) # you have capital D, need to match variable name with lower case.
return diff # Return should be return
for birthday in birthdays: # loop over each day to check
print(is_over_13(birthday)) ## you have capital I, needs to match your function name with lower case i
Also your function name says is_over_13 which implies true or false return i think. You might want to take the diff value and compare it to 13 years and return true or false
This might look like
import datetime
birthdays = [
datetime.datetime(2012, 4, 29),
datetime.datetime(2006, 8, 9),
datetime.datetime(1978, 5, 16),
datetime.datetime(1981, 8, 15),
datetime.datetime(2001, 7, 4),
datetime.datetime(1999, 12, 30)
]
today = datetime.datetime.today()
DAYS_IN_YEAR = 365
YEARS = 13
def is_over_13(dt):
diff = (today - dt).days # get the days for your diff
return diff > (DAYS_IN_YEAR * YEARS) # return if greater than 13 or not
for birthday in birthdays:
print(is_over_13(birthday))
This will get you started. You need a loop. In this case, I used a comprehension:
import datetime
birthdays = [
datetime.datetime(2012, 4, 29),
datetime.datetime(2006, 8, 9),
datetime.datetime(1978, 5, 16),
datetime.datetime(1981, 8, 15),
datetime.datetime(2001, 7, 4),
datetime.datetime(1999, 12, 30)
]
today = datetime.datetime.today()
>>> [f'{today.date()} - {bd.date()}>13: {((today-bd).days)>365.2425*13}' for bd in birthdays]
['2022-01-05 - 2012-04-29>13: False', '2022-01-05 - 2006-08-09>13: True', '2022-01-05 - 1978-05-16>13: True', '2022-01-05 - 1981-08-15>13: True', '2022-01-05 - 2001-07-04>13: True', '2022-01-05 - 1999-12-30>13: True']
Because of leap years, time differences are expressed in days, minutes, seconds. This uses a common, but less than perfect, shortcut of estimating a year difference by multiplying a day difference by 365.2425 that is usually accurate but not 100%.
To get 100% accuracy, you need to detect leap year birthdays and adjust the date to 2/28/the_year in a non-leap year.
To do that, use this function:
def is_older_than(bd, age, day=datetime.datetime.today()):
try:
age_date=bd.replace(year=bd.year+age)
except ValueError:
age_date=bd.replace(year=bd.year+age, day=28)
return age_date<=day
Then redo the loop that will be accurate by the day no matter what:
>>> [f'{today.date()} - {bd.date()}>13: {is_older_than(bd, 13)}' for bd in birthdays]
['2022-01-05 - 2012-04-29>13: False', '2022-01-05 - 2006-08-09>13: True', '2022-01-05 - 1978-05-16>13: True', '2022-01-05 - 1981-08-15>13: True', '2022-01-05 - 2001-07-04>13: True', '2022-01-05 - 1999-12-30>13: True']

Python datetime library not able to handle 01022018 i.e as in MMDDYYYY format when left most zero is truncated

I have an issue that I am encountering with one of the modules. Due to the requirement of data handlers, one of the modules has to use the datetime library and the strptime function. But the code behavior does not seem to be consistent, when the left most zero from a date series in format MMDDYYYY is truncated especially for Jan month. Below are some example,you can see the 2nd and third command are identical but the month is getting corrupted. Anyways around how to handle it?
>>> datetime.strptime('01082018',"%m%d%Y")
datetime.datetime(2018, 1, 8, 0, 0)
>>> datetime.strptime('1082018',"%m%d%Y")
datetime.datetime(2018, 10, 8, 0, 0)
>>> datetime.strptime('8082018',"%m%d%Y")
datetime.datetime(2018, 8, 8, 0, 0)
>>> datetime.strptime('08082018',"%m%d%Y")
datetime.datetime(2018, 8, 8, 0, 0)
You can try to split it in two multiple commands and append a zero (if need be)
>>> date_str = '01082018'
>>> if len(date_str)==7:
>>> date_str = '0'+date_str
>>> datetime.strptime(date_str ,"%m%d%Y")
datetime.datetime(2018, 1, 8, 0, 0)
AND
>>> date_str = '8082018'
>>> if len(date_str)==7:
>>> date_str = '0'+date_str
>>> datetime.strptime(date_str ,"%m%d%Y")
datetime.datetime(2018, 8, 8, 0, 0)

Convert integer date format to human readable format

I have a date time format where dates are represented as integers from 1/1/1900 .
For example: 1 is 1/1/1900 and 42998 is 20/9/2017.
How can I convert this format to a human readable format like dd/mm/yyyy ? I checked datetime documentation but I did not find any way to do this. I want to do this either on python 3 or 2.7.
Thanks for any suggestion.
You can define your dates as offsets from your basetime and construct a datetime:
In[22]:
import datetime as dt
dt.datetime(1900,1,1) + dt.timedelta(42998)
Out[22]: datetime.datetime(2017, 9, 22, 0, 0)
Once it's a datetime object you can convert this to a str via strftime using whatever format you desire:
In[24]:
(dt.datetime(1900,1,1) + dt.timedelta(42998-1)).strftime('%d/%m/%Y')
Out[24]: '21/09/2017'
So you can define a user func to do this:
In[27]:
def dtToStr(val):
base = dt.datetime(1900,1,1)
return (base + dt.timedelta(val-1)).strftime('%d/%m/%Y')
dtToStr(42998)
Out[27]: '21/09/2017'
import datetime
base_date = datetime.datetime(1900, 1, 1)
convert = lambda x: base_date + datetime.timedelta(days=x-1)
>>> convert(42998)
datetime.datetime(2017, 9, 21, 0, 0)
You can use a datetime object to do that.
import datetime
d = datetime.datetime(1900, 1, 1, 0, 0)
d + datetime.timedelta(days = 42998)
>> datetime.datetime(2017, 9, 22, 0, 0)

max date in python list

I have an list:
a=[datetime.date(2010,10,20),1,4,datetime.date(2013,10,20)]
As you can see the list contains different types of elements. How can I get the max date within the list?
My attempt:
from datetime import datetime
b=datetime.max(a)
print b
For guidence Find oldest/youngest datetime object in a list
from datetime import datetime
datetime_list = [
datetime(2009, 10, 12, 10, 10),
datetime(2010, 10, 12, 10, 10),
datetime(2010, 10, 12, 10, 10),
datetime(2015, 2, 12, 10, 10), # future
datetime(2016, 2, 12, 10, 10), # future
]
oldest = min(datetime_list)
youngest = max(datetime_list)
The prior post has filter to exclude future events
First, keeping dates and integers together in the same list -- except as an intermediate step -- can be a sign your data structure isn't appropriate. That said, you can easily take the max only of the dates by using a generator expression:
>>> import datetime
>>> a=[datetime.date(2010,10,20),1,4,datetime.date(2013,10,20)]
>>> max(d for d in a if isinstance(d, datetime.date))
datetime.date(2013, 10, 20)

Convert a Date in String Format to a datetime.date

I have some strings which come to me in formats like
29-Jul-2014 or 03-Aug-2015
What is the easiest way to convert this to a datetime.date object?
I can only think to make a dictionary like d = {'Jul': 7, 'Aug': 8, ...} and then do
dt = datetime.date(year, d[month], day)
Is there any other easier way and avoid the creation of this dictionary?
Thanks
Use datetime.datetime.strptime to convert the string to datetime.datetime object.
>>> datetime.datetime.strptime('29-Jul-2014', '%d-%b-%Y')
datetime.datetime(2014, 7, 29, 0, 0)
Then, use datetime.datetime.date method to convert it to datetime.date object:
>>> datetime.datetime.strptime('29-Jul-2014', '%d-%b-%Y').date()
datetime.date(2014, 7, 29)
The easy way is use dateutil.parse module, it lets to parse the common date formats, even if you don't know what it is using currently
Ex:
>>> import dateutil.parser
>>>
>>> utc_time = '2014-07-29T00:00:00'
>>> verbose_time = '29-Jul-2014'
>>> some_locale = '29/7/14'
>>> dateutil.parser.parse(utc_time)
datetime.datetime(2014, 7, 29, 0, 0)
>>> dateutil.parser.parse(verbose_time)
datetime.datetime(2014, 7, 29, 0, 0)
>>> dateutil.parser.parse(some_locale)
datetime.datetime(2014, 7, 29, 0, 0)
Once you have a datetime object, you only should invoke the datetime.date() method

Categories

Resources