How to parse time string without date and date string without time? - python

Is there any way to automatically parse strings with time only to datetime.time object (or something similar)? Same for datetime.date.
I've tried dateutil, arrow, moment, pandas.to_datetime.
All these parsers create timestamps with a current date.
>>> from dateutil.parser import parse
>>> parse('23:53')
datetime.datetime(2019, 1, 8, 23, 53) # datetime.time(23, 53) expected
>>> parse('2018-01-04')
datetime.datetime(2018, 1, 4, 0, 0) # datetime.date(2018, 1, 4) expected
UPD:
Thanks for the responses. Think that I should clarify the problem.
The program doesn't know what will be in the input (timestamp, date or time), and it should decide to set appropriate type. The problem is to distinguish these types.
For example, I can parse 23:53 and get a timestamp. How can I decide to extract the time from it or not?

You can use fromisoformat() from datetime.
import datetime
datetime.time.fromisoformat('23:53')
datetime.date.fromisoformat('2018-01-04')

What you basically want is for '23:53' to become a datetime.time object and for '2018-01-04' to become a datetime.date object. This cannot be achieved by using dateutil.parser.parse():
Returns a datetime.datetime object or, if the fuzzy_with_tokens option is True, returns a tuple, the first element being a datetime.datetime object, the second a tuple containing the fuzzy tokens.
From the documentation. So you'll always get a datetime.datetime object when using dateutil.parser.parse()
I would guess you need to interpret the input string yourself to define wether you're trying to parse a time or a date. When you do that, you can still use the dateutil.parser.parse() function to get the object you want:
from dateutil.parser import parse
my_time = parse('23:53')
my_time.time() # datetime.time(23, 53)
my_time.date() # datetime.date(2019, 1, 8)

Here you have an example. Just set the date attributes with replace, and select the output with strftime.
import datetime
date = datetime.datetime.now()
newdate = date.replace(hour=11, minute=59)
print(newdate.strftime('%H:%M'))
newdate2 = date.replace(year=2014, month=1, day=3)
print(newdate2.strftime('%Y-%m-%d'))

You can use either time or datetime modules, but one thing to bear in mind, is that these always create an object, that specifies a moment in time. (Also, if parsing strings, consider using the strptime function and displaying as string, strftime function respectively)
e.g.
>>> hours = time.strptime("23:59", "%H:%M")
>>> days = time.strptime("2018-01-04", "%Y-%m-%d")
>>> time.strftime("%H:%M", hours)
'23:59'
>>> time.strftime("%H:%M %Y", hours)
'23:59 1900'
Not recommended, but if you wish to separate these two object for some reason and wish to only care for a specific portion of your assignement, you can still adress the respective numbers with
>>> hours.tm_hour
23
>>> hours.tm_min
59
>>> days.tm_mon
1
>>> days.tm_mday
4
>>> days.tm_year
2018
A far better approach, in my opinion would be formatting the complete date string and using the strptime to form a complete timestamp - even if you get the time and date as separate inputs:
>>> ttime = "22:45"
>>> dday = "2018-01-04"
You can use the % formatter, or the "new" python f-Strings
>>> complete_t_string = "{} {}".format(dday, ttime)
>>> complete_t_string
'2018-01-04 22:45'
Now that we have a complete string, we can specify how it should be read and create a complete timestamp:
>>> complete_time = time.strptime(complete_t_string, "%Y-%m-%d %H:%M")
>>> complete_time
time.struct_time(tm_year=2018, tm_mon=1, tm_mday=4, tm_hour=22, tm_min=45, tm_sec=0, tm_wday=3, tm_yday=4, tm_isdst=-1)
EDIT:
Somebody will probably kill me, but if you absolutely know that you will only get two types of values, you could just do a simple try / except construct. It can probably be written more Pythonically:
try:
time.strptime(t_string, "%H:%M")
except ValueError:
time.strptime(t_string, "%Y-%m-%d")

Related

datetime.strptime formatting

My datetime in my CSV file is like the following:
2011/1/1 0:00
2011/1/1 0:30
2011/1/1 1:00
when I run:
date = datetime.strptime(row[0], '%Y/%m/%d %H:%M')
I get datetime output as:
[datetime.datetime(2011, 1, 1, 0, 0)]
[datetime.datetime(2011, 1, 1, 0, 30)]
How can i format it to the original datetime?
You have already parsed a string into a datetime object. This is done by using datetime.datetime.strptime(). To format the object back into a string you can use the same syntax but using method datetime.datetime.strftime(), e.g.:
date.strftime('%Y/%m/%d %H:%M')
See also documentation.
If you want exactly your input string (without leading 0), you can put a hyphen between percentage operator and directive character where necessary, e.g.:
date.strftime('%Y/%-m/%-d %-H:%M')
This is well explained in: Python strftime - date without leading 0 but it is platform dependent.
Try printing date in string format:
from datetime import datetime
row = "2011/1/1 0:30"
date = datetime.strptime(row, '%Y/%m/%d %H:%M')
print str(date)
output:
'2011-01-01 00:30:00'
What you are currently doing is creating a datetime object from a string and formatter as shown here. Likely somewhere in your code you put this object in a list and referenced it. Python doesn't know that you want to print the container(the list) with it in a certain string format.
If I'm understanding your question you want to print/return the element and not the container. Shown below:
import datetime
l = []
today = datetime.date.today()
l.append(today)
#what you have
print(l)
#addressing just the first element
print(l[0])

String to time stamp conversion

I have a data file with about 5.6million time-stamps in the format "2016-10-17 15:00:40.739". They are all strings at the moment for some reason and I need to convert them all to date times as I will later need to calculate the difference between groups of them (e.g: stamp1 -> stamp2 = 2hours, 4minutes etc).
I found another question "Converting string into datetime" but mine are in a different format and I cannot get that answer to work for me.
Any help is much appreciated.
Use numpy's datetime64:
>>> np.datetime64('2016-10-17 15:00:40.739')
numpy.datetime64('2016-10-17T15:00:40.739')
You can easily find differences by simply subtracting, or using numpy's timedelta64:
>>> np.datetime64('2016-10-17 15:00:40.739') - np.datetime64('2016-10-15 15:00:40.739')
numpy.timedelta64(172800000,'ms')
>>> np.datetime64('2016-10-17 15:00:40.739') + np.timedelta64(1,'D')
numpy.datetime64('2016-10-18T15:00:40.739')
Try this:
from datetime import datetime
a = "2016-10-17 15:00:40.739"
b = datetime.strptime(a,'%Y-%m-%d %H:%M:%S.%f')
print(b)
>>> datetime.datetime(2016, 10, 17, 15, 0, 40, 739000)
To define the format of your dates. Follow this guide: https://www.tutorialspoint.com/python/time_strptime.htm
You can use the dateutil module to convert the string date to datetime object.
from dateutil import parser
dt = parser.parse("2016-10-17 15:00:40.739")
print dt
print type(dt)
Output:
2016-10-17 15:00:40.739000
<type 'datetime.datetime'>

Python how to save datetime.strptime in datetime.time format

So I was trying to make a simple code using datetime and came across an error.
import time
from datetime import datetime
x = True
b = datetime.strptime("06:10", "%H:%M")
while x == True:
a = datetime.now().time()
print(a)
if a > b:
x = False
time.sleep(0.945)
As a result I get
TypeError: unorderable types: datetime.time() > datetime.datetime()
So I was wondering if it's possible to save a datetime.strptime in the datetime.time() format.
Thanks in advance
You tried to compare a datetime and time object, which Python won't let you compare.
If you do datetime.strptime() you get an object which holds a date and time (called datetime). But because you do not also parse the date it defaults to 01-01-1900. Now datetime.now() also gets you a datetime object but with the current date. So directly comparing datetime.now() and b won't work because the dates are different.
Now you already use the current time only by doing datetime.now().time(), so you also need to apply that to b by doing b = b.time() somewhere before the comparison.
use 'datetime.now()' insted of 'datetime.now().time()'
Compare .time() of both a and b as:
if a > b.time(): # if you want to compare only time
and not the datetime objects. Reason at the end of the answer.
datetime.now().time() is of datetime.time type:
>>> type(datetime.now().time())
<type 'datetime.time'>
whereas, datetime.strptime() and datetime.now() are of datetime.datetime type:
>>> type(datetime.strptime("06:10", "%H:%M"))
<type 'datetime.datetime'>
>>> type(datetime.now())
<type 'datetime.datetime'>
Edit based on comment from Martijn.
On creating datetime object like datetime.strptime("06:10", "%H:%M") date will be set as 1900-01-01. And definitely I dont't think you want to compare with that. You may check the date as:
>>> d = datetime.strptime("06:10", "%H:%M")
>>> d
datetime.datetime(1900, 1, 1, 6, 10)

Converting dates in Python

I have dates in the form 26/11/2015. How can I convert them into the format 26-Nov-2015 and still keep them as dates and not strings?
Your question does not make much sense. If you keep them as dates, they have no format. The format is only manifested when you convert them to strings.
So the answer is: Store the dates as date (or datetime) objects, and use datetime.strftime with some specific format whenever you need them as a string:
>>> from datetime import date
>>> d = date(2016, 11, 26)
>>> d.strftime("%Y/%m/%d")
'2016/11/26'
>>> d.strftime("%d-%b-%Y")
'26-Nov-2016'
Conversely, use strptime to parse strings in different formats to dates:
>>> datetime.datetime.strptime("26-Nov-2015", "%d-%b-%Y")
datetime.datetime(2015, 11, 26, 0, 0)
from datetime import datetime
date = datetime.strptime('26/11/2015', '%d/%m/%Y')
print date.strftime("%d-%B-%Y")
In the above example, we are taking your input string 'dd/mm/yyyy' and turning it into a python datetime saving it to a variable called date (for future usage as per your request), and then printing it out in the format requested.
You want to use the datetime module I think. For example:
from datetime import date
a = date(2015, 11, 26)
a.strftime("%A %d of %B, %Y")
should give you 'Thursday 26 of November, 2015'
Or for your specific formatting request:
a.strftime("%d-%b-%Y") #'26-Nov-2015'
Hope this helps, good luck!

Get a datetime object from the result of str(datetime)

If I print a datetime object in python with a simple print myDateTime (or print(myDateTime) in python3), how can I recover the datetime object from the resulting string?
I could have asked "what is the python strftime format used by datetime.__str__()"?
ps: There are many questions about conversion of strings to python datetime objects. In the spirit of using stack overflow as a repository of quickly available, useful programming tips, I'm asking this since none of those questions answer this rather specific and oft needed query.
By definition, str(datetime_obj) is datetime_obj.isoformat(' '). There is no method that would parse the ISO 8601 format back; you have to provide the format to strptime() explicitly:
>>> from datetime import datetime, timezone
>>> now = datetime.now(timezone.utc)
>>> s = str(now)
>>> s
'2015-04-06 10:31:08.256426+00:00'
>>> s[:26]
'2015-04-06 10:31:08.256426'
>>> datetime.strptime(s[:26]+s[26:].replace(':',''), '%Y-%m-%d %H:%M:%S.%f%z')
datetime.datetime(2015, 4, 6, 10, 31, 8, 256426, tzinfo=datetime.timezone.utc)
%z supports +HHMM but it doesn't support +HH:MM that is why the replace() call is used here.
datetime.timezone is available since Python 3.2. For older versions, see
How to parse ISO formatted date in python?
Convert timestamps with offset to datetime obj using strptime.
If the datetime object doesn't have timezone info (perhaps interpreted as UTC time), you can do something like this (python 2 in this case, but the same in python 3):
import datetime
unprintStrptimeFmt = "%Y-%m-%d %H:%M:%S.%f"
d = datetime.datetime.utcnow()
print d
# produces e.g.: 2015-04-06 03:11:23.840526
dd = datetime.datetime.strptime("2015-04-06 03:11:23.840526",unprintStrptimeFmt)
print dd == d
# produces: True

Categories