This question already has answers here:
Convert timestamps with offset to datetime obj using strptime
(4 answers)
Closed 5 years ago.
The format from api google calendar is like '2017-04-26T13:00:00+02:00'.
I tried to convert to datetime without success:
datetime.datetime.strptime('2017-04-26T13:00:00+02:00', '%Y-%m-%dT%H:%M:%S+%z')
Es error I get:
'ValueError: time data, '2017-04-26T13:00:00+02:00' does not match format '%Y-%m-%dT%H:%M:%S+%z'
How do I get this code to work?
Take a look at dateutil, the parse function will help you out.
>>> from dateutil.parser import parse
>>> dt = parse('2017-04-26T13:00:00+02:00')
>>> dt
datetime.datetime(2017, 4, 26, 13, 0, tzinfo=tzoffset(None, 7200))
this is because strptime expects for the %z format a string that looks like: +0200 not +02:00, i.e.:
>>> datetime.datetime.strptime('2017-04-26T13:00:00+0200', '%Y-%m-%dT%H:%M:%S%z')
datetime.datetime(2017, 4, 26, 13, 0, tzinfo=datetime.timezone(datetime.timedelta(0, 7200)))
so depending on your context, either you modify the string to fit strptime() expectations, or you can use a higher level library to handle your dates. Like maya or pendulum, that offer very flexible facilities to handle format parsing and relative date management.
>>> import pendulum, maya # you need to pip install them
>>> pendulum.parse('2017-04-26T13:00:00+02:00')
<Pendulum [2017-04-26T13:00:00+02:00]>
>>> maya.parse('2017-04-26T13:00:00+02:00')
<MayaDT epoch=1493204400.0>
You may want to take a look in the documentation for PyTZ and Arrow, tho external modules that add functionality related to date and time. For instance, with arrow, you can do it pretty easily like this:
import arrow
my_arrow_object = arrow.get('2017-04-26T13:00:00+02:00')
my_datetime_object = my_arrow_object.datetime
print(my_datetime_object)
print(type(my_datetime_object))
This code prints the obtained timestamp and the type of my_datetime_object object, which is a datetime.datetime:
2017-04-26 13:00:00+02:00
<class 'datetime.datetime'>
Arrow also allows to easily generate "humanized" time strings (like "an hour ago" ou "two months ago"), which can be handy.
Related
I have a Dataframe in python, with the data coming from a csv.
In the column "Date" I have a date (:)) but I don't know the date format. How can I detect it?
e.g.: I can have 05/05/2022. this can be M/D/Y or D/M/Y. I can manually understand it by looking at other entries, but I wish I can do it automatically.
Is there a way to do so?
thank you
datetime.strptime requires you to know the format.
trying (try - exept)-commands isn't good since there are so many different format I can receive.
it would be nice to have something that recognizes the format...
Update:
Thank you for the first answers, but the output I would like to have is THE FORMAT of the date that is used in the column.
Knowing also the fact that the format is unique within each column
You can try the dateutil library.
To deal with dates and also with the diversity of timezones people often use external libraries such as pytz or dateutil.
dateutil has a very powerful parser.
from dateutil.parser import parse
parse('05/05/2022') # datetime.datetime(2022, 5, 5, 0, 0)
parse('2022-05-05') # datetime.datetime(2022, 5, 5, 0, 0)
Use the isinstance built-in function to check if a variable is a datetime object in Python, e.g. if isinstance(today, datetime): . The isinstance function returns True if the passed in object is an instance or a subclass of the passed in class. Copied!20-Apr-2022
check out here
https://www.folkstalk.com/2022/10/python-check-if-string-is-date-format-with-code-examples.html
Is there an easy way to convert an RFC 3339 nano time into a regular Python timestamp?
For example, time = '2022-07-14T12:01:25.225089838+08:00',
I found a way using datetime
from datetime import datetime
time = '2022-07-14T12:01:25.225089+08:00'
date = datetime.fromisoformat(time) # good
time = '2022-07-14T12:01:25.225089838+08:00'
date = datetime.fromisoformat(time) # error
It works with string like '2022-07-14T12:01:25.225089+08:00', but it doesn't work with the time above.
There are a few ways to do it.
Depends on what is the input format and how you define an easy way.
There are actually many post asking similar issues you have.
I'll post a few at the end for your reference if you are interested and please check next time before posting.
The main issue of datetime object is that it only holds 6 digit after second.
You will need a different data structure to save it if you want to preserve all of the digits.
If you are ok with cutting off at 6 digit, FObersteiner's answer is perfect.
Another methodology is vanilla datetime string parsing
from datetime import datetime
date = '2022-07-14T12:01:25.225089838+08:00'.removesuffix('+08:00')
x = datetime.strptime( date[:-3], '%Y-%m-%dT%H:%M:%S.%f')
If you would like to preserve all the digits. You may want to create your own class extending from the datetime class or create some function for it.
Convert an RFC 3339 time to a standard Python timestamp
Parsing datetime strings containing nanoseconds
from datetime.fromisoformat docs:
Caution: This does not support parsing arbitrary ISO 8601 strings - it is only intended as the inverse operation of datetime.isoformat(). A more full-featured ISO 8601 parser, dateutil.parser.isoparse is available in the third-party package dateutil.
dateutil's isoparse will do the job:
from dateutil.parser import isoparse
time = '2022-07-14T12:01:25.225089838+08:00'
date = isoparse(time)
print(date)
# 2022-07-14 12:01:25.225089+08:00
print(repr(date))
# datetime.datetime(2022, 7, 14, 12, 1, 25, 225089, tzinfo=tzoffset(None, 28800))
Note: it doesn't round to microseconds, it just slices off the last 3 decimal places. So basically, if you're dealing with a standardized format like RFC 3339, you can do the slicing yourself like
from datetime import datetime
time = '2022-07-14T12:01:25.225089838+08:00'
date = datetime.fromisoformat(time[:-9] + time[-6:])
print(date)
# 2022-07-14 12:01:25.225089+08:00
Using '%z' pattern of datetime.strptime()
I have a string text that represent a date and I'm perfectly able to parse it and transform it into a clean datetime object:
date = "[24/Aug/2014:17:57:26"
dt = datetime.strptime(date, "[%d/%b/%Y:%H:%M:%S")
Except that I can't catch the entire date string with the timezone using the %z pattern as specified here
date_tz = 24/Aug/2014:17:57:26 +0200
dt = datetime.strptime(date, "[%d/%b/%Y:%H:%M:%S %z]")
>>> ValueError: 'z' is a bad directive in format '[%d/%b/%Y:%H:%M:%S %z]'
Because as this bug report says
strftime() is implemented per platform
I precise that there is no such a problem with the naive tzinfo directive '%Z'
Workaround : Casting tzinfo string into tzinfo object
I can perfectly make the following workaround by transforming the GST time format string into a tzinfo object [as suggested here][4] using dateutil module
and then insert tzinfo into datetime object
Question: Make %z available for my plateform?
But as I will obviously need %z pattern for further project I would like to find a solution to avoid this workaround and using external module for this simple task.
Can you suggest me some reading on it? I supposed that newer version of python (I'm on 2.7) can handle it but I'd rather not changing my version now for this little but crucial detail.
[EDIT]
Well, seeing comments make me reformulated my question how to parse Email time zone indicator using strptime() without being aware of locale time?
strptime() is implemented in pure Python. Unlike strftime(); it [which directives are supported] doesn't depend on platform. %z is supported since Python 3.2:
>>> from datetime import datetime
>>> datetime.strptime('24/Aug/2014:17:57:26 +0200', '%d/%b/%Y:%H:%M:%S %z')
datetime.datetime(2014, 8, 24, 17, 57, 26, tzinfo=datetime.timezone(datetime.timedelta(0, 7200)))
how to parse Email time zone indicator using strptime() without being aware of locale time?
There is no concrete timezone implementation in Python 2.7. You could easily implement the UTC offset parsing, see How to parse dates with -0400 timezone string in python?
In continue to #j-f-sebastians 's answer, here is a fix for python 2.7
Instead of using:
datetime.strptime(t,'%Y-%m-%dT%H:%M %z')
use the timedelta to account for the timezone, like this:
from datetime import datetime,timedelta
def dt_parse(t):
ret = datetime.strptime(t[0:16],'%Y-%m-%dT%H:%M')
if t[17]=='+':
ret-=timedelta(hours=int(t[18:20]),minutes=int(t[20:]))
elif t[17]=='-':
ret+=timedelta(hours=int(t[18:20]),minutes=int(t[20:]))
return ret
print(dt_parse('2017-01-12T14:12 -0530'))
The Answer of Uri is great, saved my life, but when you have
USE_TZ = True you need to be careful with the time, for avoid the warning "RuntimeWarning: DateTimeField" is better if you add the utc to the return.
import pytz
from datetime import datetime, timedelta
def dt_parse(t):
ret = datetime.strptime(t[0:19],'%Y-%m-%dT%H:%M:%S')
if t[23]=='+':
ret-=timedelta(hours=int(t[24:26]), minutes=int(t[27:]))
elif t[23]=='-':
ret+=timedelta(hours=int(t[24:26]), minutes=int(t[27:]))
return ret.replace(tzinfo=pytz.UTC)
I've always hated the headache of managine dates, times, datetimes, and the various formats and conversions that are needed with them. I'm taking an online course on using the google app engine and it says to use the datetime property, which is returning a date in the format:
2012-06-25 01:17:40.273000
I tried
datetime.strptime('2012-06-25 01:17:40.273000','%y-%m-%d %H:%M:%S')
but it didn't work..
I just want to extract the 2012-06-25 part without using a hacky regex or string slicing solution.
How do I parse this and convert it to the proper format?
Finally found it (shortly after asking the question, but I've been trying for the past hour)
datetime.strptime('2012-06-25 01:17:40.273000','%Y-%m-%d %H:%M:%S.%f')
What I wanted:
datetime.strptime('2012-06-25 01:17:40.273000','%Y-%m-%d %H:%M:%S.%f').strftime('%m-%d-%Y')
If you are using a datetime property then the object you get back is a datetime instance not a string.
On the console
>>> from datetime import datetime
>>> x = datetime.now()
>>> print x
2012-06-25 12:03:15.835467
>>> x.date()
datetime.date(2012, 6, 25)
>>>
>>> print x.date()
2012-06-25
>>>
See the print statement. It does an implicit conversion to string. If your outputting the datetime property value in a template, this is probably what is happening.
So in your code you should just use .date() method on the datetime object.
Now to convert this strings to date time object in Python or django?
2010-08-17T19:00:00Z
2010-08-17T18:30:00Z
2010-08-17T17:05:00Z
2010-08-17T14:30:00Z
2010-08-10T22:20:00Z
2010-08-10T21:20:00Z
2010-08-10T20:25:00Z
2010-08-10T19:30:00Z
2010-08-10T19:00:00Z
2010-08-10T18:30:00Z
2010-08-10T17:30:00Z
2010-08-10T17:05:00Z
2010-08-10T17:05:00Z
2010-08-10T15:30:00Z
2010-08-10T14:30:00Z
whrn i do this datestr=datetime.strptime( datetime, "%Y-%m-%dT%H:%M:%S" )
it tell me that unconverted data remains: Z
You can parse the strings as-is without the need to slice if you don't mind using the handy dateutil module. For e.g.
>>> from dateutil.parser import parse
>>> s = "2010-08-17T19:00:00Z"
>>> parse(s)
datetime.datetime(2010, 8, 17, 19, 0, tzinfo=tzutc())
>>>
Use slicing to remove "Z" before supplying the string for conversion
datestr=datetime.strptime( datetime[:-1], "%Y-%m-%dT%H:%M:%S" )
>>> test = "2010-08-17T19:00:00Z"
>>> test[:-1]
'2010-08-17T19:00:00'
Those seem to be ISO 8601 dates. If your timezone is always the same, just remove the last letter before parsing it with strptime (e.g by slicing).
The Z indicates the timezone, so be sure that you are taking that into account when converting it to a datetime of a different timezone. If the timezone can change in your application, you'll have to parse that information also and change the datetime object accordingly.
You could also use the pyiso8601 module to parse these ISO dates, it will most likely also work with slighty different ISO date formats. If your data may contain different timezones I would suggest to use this module.
change your format string to ""%Y-%m-%dT%H:%M:%SZ" so that it includes the trailing Z (which makes it no longer unconverted). Note, however, that this Z perhaps is there to indicate that the time is in UTC which might be something you need to account for otherwise