I recommend using python-dateutil. Its parser has been able to parse every date format I've thrown at it so far.

>>> from dateutil import parser
>>> parser.parse("Tue Jun 22 07:46:22 EST 2010")
datetime.datetime(2010, 6, 22, 7, 46, 22, tzinfo=tzlocal())
>>> parser.parse("Fri, 11 Nov 2011 03:18:09 -0400")
datetime.datetime(2011, 11, 11, 3, 18, 9, tzinfo=tzoffset(None, -14400))
>>> parser.parse("Sun")
datetime.datetime(2011, 12, 18, 0, 0)
>>> parser.parse("10-11-08")
datetime.datetime(2008, 10, 11, 0, 0)

and so on. No dealing with strptime() format nonsense... just throw a date at it and it Does The Right Thing.

Answer from Joe Shaw on Stack Overflow
🌐
Python documentation
docs.python.org › 3 › library › datetime.html
datetime — Basic date and time types
If format does not contain microseconds or timezone information, this is equivalent to: ... ValueError is raised if the date_string and format cannot be parsed by time.strptime() or if it returns a value which is not a time tuple.
Discussions

`Time::Piece` and `strptime()` processing timezones documentation discrepancy
Delimiter in timezone offset isn’t permitted for %z. More on reddit.com
🌐 r/perl
9
10
January 1, 2022
Using strftime from Datetime with "+02:00" as UTC/timezone?
Maybe it's because I have +02:00, but I should have +0200? Yes, that's a problem and you'll have to remove that colon in order to use datetime.strptime. Or did I make another mistake? You also left the % off of the minute placeholder. Instead of this headache, you could instead install the dateutil package, which automagically parses common formats like this: >>> from dateutil.parser import parse >>> parse("2020-06-13T17:27:24.165+02:00") datetime.datetime(2020, 6, 13, 17, 27, 24, 165000, tzinfo=tzoffset(None, 7200)) More on reddit.com
🌐 r/learnpython
2
1
June 28, 2020
datetime - How to parse dates with -0400 timezone string in Python? - Stack Overflow
I have a date string of the form '2009/05/13 19:19:30 -0400'. It seems that previous versions of Python may have supported a %z format tag in strptime for the trailing timezone specification, but 2... More on stackoverflow.com
🌐 stackoverflow.com
python - Convert timestamps with offset to datetime obj using strptime - Stack Overflow
Change -%z to %z. The - (or +) is part of the offset. ... The Python 2 strptime() function indeed does not support the %z format for timezones (because the underlying time.strptime() function doesn't support it). More on stackoverflow.com
🌐 stackoverflow.com
People also ask

How to use strptime() parsing a datetime string with a timezone offset?
Include the %z format specifier to correctly interpret timezone offsets.
🌐
intellipaat.com
intellipaat.com › home › blog › convert timestamps with offset to datetime obj using strptime
Convert timestamps with offset to datetime obj using strptime - ...
Is it possible to use the strptime() to handle the UTC or named time zones (e.g., EST, PST)?
No, the strptime() supports numeric timezone offsets (e.g., +0530) only. Handling the named time zones can be achieved by using the libraries like pytz or zoneinfo.
🌐
intellipaat.com
intellipaat.com › home › blog › convert timestamps with offset to datetime obj using strptime
Convert timestamps with offset to datetime obj using strptime - ...
What happens if the datetime string does not have a timezone offset?
If the string lacks a timezone and having the %z in the format, the strptime() will raise a ValueError, which will ensure that the format matches the input string exactly.
🌐
intellipaat.com
intellipaat.com › home › blog › convert timestamps with offset to datetime obj using strptime
Convert timestamps with offset to datetime obj using strptime - ...
🌐
RDocumentation
rdocumentation.org › packages › base › versions › 3.6.2 › topics › strptime
strptime function - RDocumentation
Signed offset in hours and minutes from UTC, so -0800 is 8 hours behind UTC. Values up to +1400 are accepted. (Standard only for output.
🌐
Cheat Sheets
cheat.readthedocs.io › en › latest › python › timezones.html
Timezones in Python — Dan's Cheat Sheets 1 documentation
>>> fmt = "%a, %d %B %Y %H:%M:%S" >>> dt = datetime.datetime.strptime(s[:-6], fmt) >>> dt datetime.datetime(2012, 7, 3, 14, 11, 3) That is assuming we know exactly how long the timezone string was, but we might not.
🌐
Reddit
reddit.com › r/perl › `time::piece` and `strptime()` processing timezones documentation discrepancy
r/perl on Reddit: `Time::Piece` and `strptime()` processing timezones documentation discrepancy
January 1, 2022 -

My log files have the date/time formatted as: 2022-01-01T11:53:42-08:00. I need to convert that to a Unixtime. I think strptime() is the easiest way to do this?

Here is the code I came up with to process this specific time string.

#!/usr/bin/env perl

use strict;
use warnings;
use Time::Piece;

my $input = '2022-01-01T11:53:42-08:00';
my $tp     = Time::Piece->strptime($input, "%Y-%m-%dT%H:%M:%S");

print "Input : $input\n";
print "Epoch : " . $tp->epoch . "\n";
print "Format: " . $tp->cdate . "\n";

When I run this I get an error about the timezone string at the end

Garbage at end of string in strptime: -08:00 at /usr/lib64/perl5/Time/Piece.pm line 598.
Perhaps a format flag did not match the actual input? at /usr/lib64/perl5/Time/Piece.pm line 598.

The documentation says to add %z to process timezones, but when I do that it fails completely. How do I make strptime() process this string correctly? Is there a better/easier way to convert this?

🌐
Python
bugs.python.org › issue31800
Issue 31800: datetime.strptime: Support for parsing offsets with a colon - Python tracker
This issue tracker has been migrated to GitHub, and is currently read-only. For more information, see the GitHub FAQs in the Python's Developer Guide · This issue has been migrated to GitHub: https://github.com/python/cpython/issues/75981
Find elsewhere
Top answer
1 of 6
135

You can use the parse function from dateutil:

>>> from dateutil.parser import parse
>>> d = parse('2009/05/13 19:19:30 -0400')
>>> d
datetime.datetime(2009, 5, 13, 19, 19, 30, tzinfo=tzoffset(None, -14400))

This way you obtain a datetime object you can then use.

As answered, dateutil2.0 is written for Python 3.0 and does not work with Python 2.x. For Python 2.x dateutil1.5 needs to be used.

2 of 6
62

%z is supported in Python 3.2+:

>>> from datetime import datetime
>>> datetime.strptime('2009/05/13 19:19:30 -0400', '%Y/%m/%d %H:%M:%S %z')
datetime.datetime(2009, 5, 13, 19, 19, 30,
                  tzinfo=datetime.timezone(datetime.timedelta(-1, 72000)))

On earlier versions:

from datetime import datetime

date_str = '2009/05/13 19:19:30 -0400'
naive_date_str, _, offset_str = date_str.rpartition(' ')
naive_dt = datetime.strptime(naive_date_str, '%Y/%m/%d %H:%M:%S')
offset = int(offset_str[-4:-2])*60 + int(offset_str[-2:])
if offset_str[0] == "-":
   offset = -offset
dt = naive_dt.replace(tzinfo=FixedOffset(offset))
print(repr(dt))
# -> datetime.datetime(2009, 5, 13, 19, 19, 30, tzinfo=FixedOffset(-240))
print(dt)
# -> 2009-05-13 19:19:30-04:00

where FixedOffset is a class based on the code example from the docs:

from datetime import timedelta, tzinfo

class FixedOffset(tzinfo):
    """Fixed offset in minutes: `time = utc_time + utc_offset`."""
    def __init__(self, offset):
        self.__offset = timedelta(minutes=offset)
        hours, minutes = divmod(offset, 60)
        #NOTE: the last part is to remind about deprecated POSIX GMT+h timezones
        #  that have the opposite sign in the name;
        #  the corresponding numeric value is not used e.g., no minutes
        self.__name = '<%+03d%02d>%+d' % (hours, minutes, -hours)
    def utcoffset(self, dt=None):
        return self.__offset
    def tzname(self, dt=None):
        return self.__name
    def dst(self, dt=None):
        return timedelta(0)
    def __repr__(self):
        return 'FixedOffset(%d)' % (self.utcoffset().total_seconds() / 60)
🌐
kodintent
kodintent.wordpress.com › 2021 › 06 › 13 › parsing-with-strptime
Parsing timezones with strptime - kodintent - WordPress.com
June 13, 2021 - But strptime puts the parsed timezone offset into a separate variable, rather than into the main datetime object. It thus removes the timezone from the datetime object – which is then treated as if it is the local timezone!
Top answer
1 of 4
76

The Python 2 strptime() function indeed does not support the %z format for timezones (because the underlying time.strptime() function doesn't support it). You have two options:

  • Ignore the timezone when parsing with strptime:

    time_obj = datetime.datetime.strptime(time_str[:19], '%Y-%m-%dT%H:%M:%S')
    
  • use the dateutil module, it's parse function does deal with timezones:

    from dateutil.parser import parse
    time_obj = parse(time_str)
    

Quick demo on the command prompt:

>>> from dateutil.parser import parse
>>> parse("2012-07-24T23:14:29-07:00")
datetime.datetime(2012, 7, 24, 23, 14, 29, tzinfo=tzoffset(None, -25200))

You could also upgrade to Python 3.2 or newer, where timezone support has been improved to the point that %z would work, provided you remove the last : from the input, and the - from before the %z:

>>> import datetime
>>> time_str = "2012-07-24T23:14:29-07:00"
>>> datetime.datetime.strptime(time_str, '%Y-%m-%dT%H:%M:%S%z')
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/Users/mj/Development/Library/buildout.python/parts/opt/lib/python3.4/_strptime.py", line 500, in _strptime_datetime
    tt, fraction = _strptime(data_string, format)
  File "/Users/mj/Development/Library/buildout.python/parts/opt/lib/python3.4/_strptime.py", line 337, in _strptime
    (data_string, format))
ValueError: time data '2012-07-24T23:14:29-07:00' does not match format '%Y-%m-%dT%H:%M:%S%z'
>>> ''.join(time_str.rsplit(':', 1))
'2012-07-24T23:14:29-0700'
>>> datetime.datetime.strptime(''.join(time_str.rsplit(':', 1)), '%Y-%m-%dT%H:%M:%S%z')
datetime.datetime(2012, 7, 24, 23, 14, 29, tzinfo=datetime.timezone(datetime.timedelta(-1, 61200)))
2 of 4
31

In Python 3.7+:

from datetime import datetime

time_str = "2012-07-24T23:14:29-07:00"
dt_aware = datetime.fromisoformat(time_str)
print(dt_aware.isoformat('T'))
# -> 2012-07-24T23:14:29-07:00

In Python 3.2+:

from datetime import datetime

time_str = "2012-07-24T23:14:29-0700"
dt_aware = datetime.strptime(time_str, '%Y-%m-%dT%H:%M:%S%z')
print(dt_aware.isoformat('T'))
# -> 2012-07-24T23:14:29-07:00

Note: Before Python 3.7 this variant didn't support : in the -0700 part (both formats are allowed by rfc 3339). See datetime: add ability to parse RFC 3339 dates and times.

On older Python versions such as Python 2.7, you could parse the utc offset manually:

from datetime import datetime

time_str = "2012-07-24T23:14:29-0700"
# split the utc offset part
naive_time_str, offset_str = time_str[:-5], time_str[-5:]
# parse the naive date/time part
naive_dt = datetime.strptime(naive_time_str, '%Y-%m-%dT%H:%M:%S')
# parse the utc offset
offset = int(offset_str[-4:-2])*60 + int(offset_str[-2:])
if offset_str[0] == "-":
   offset = -offset
dt = naive_dt.replace(tzinfo=FixedOffset(offset))
print(dt.isoformat('T'))

where FixedOffset class is defined here.

🌐
GeeksforGeeks
geeksforgeeks.org › convert-string-to-datetime-in-python-with-timezone
Convert string to datetime in Python with timezone - GeeksforGeeks
November 29, 2022 - # Python3 code to demonstrate # ... to get datetime object datetime_obj = datetime.datetime.strptime( date_string, '%Y-%m-%d %H:%M:%S.%f %z') print("converted to datetime:") # Printing datetime print(datetime_obj) # Checking ...
🌐
Splunk Community
community.splunk.com › t5 › Getting-Data-In › Time-zone-in-TIME-FORMAT › m-p › 52193
Solved: Time zone in TIME_FORMAT - Splunk Community
February 23, 2020 - | makeresults | eval time1="01/Mar/2011:17:25:49.666+0000" | appendpipe [ eval time2="2015-10-22T22:41:52.546249+00:00"] | eval _time=coalesce(strptime(time2,"%FT%T.%6Q%:z"),strptime(time1,"%d/%B/%Y:%T.%3Q%z")) ... Rather than submitting yet another question about timestamp formating, could you please update your answer with the correct format string to successfully parse a timestamp like 2015-10-22T22:41:52.546249+00:00? I tried %Y-%m-%dT%H:%M:%S.%6N%:z, but it doesn't seems to be working. The timezone info is probably not being captured as all event times are being translated as if the event timezone (always UTC) was the same as the splunk server (-0500), which, translated to my splunk user timezone (-0200), gives me 2015-10-23T01:41:52.546249-02:00.
🌐
GitHub
github.com › python › cpython › issues › 66571
%Z in strptime doesn't match EST and others · Issue #66571 · python/cpython
September 9, 2014 - assignee = None closed_at = None created_at = <Date 2014-09-09.22:24:15.542> labels = ['3.7', '3.8', 'type-bug', 'library', '3.9'] title = "%Z in strptime doesn't match EST and others" updated_at = <Date 2021-11-01.12:58:19.684> user = 'https://github.com/cool-RR'
Author   cool-RR
🌐
Inductive Automation
forum.inductiveautomation.com › ignition
Strptime and runPrepUpdate timezone offset - Ignition - Inductive Automation Forum
August 27, 2019 - I have a code that I tested in Ignition 7.9 before our new system was set up and it now has an issue with Ignition 8.03. The simplified code below works fine to put the date into our MS SQL database in Ignition 7.9. When I copied the script to Ignition 8.03, I found that instead of writing the date to the database, it first subtracts the timezone offset and then writes it to the database, hence the date below is written as 08/28/17 04:17:16 instead of 08/28/17 11:17:16.
🌐
Python Forum
python-forum.io › thread-42051.html
Convert UTC now() to local time to compare to a strptime()
I have a string that contains a local time '2024-12-31 23:59:59'. The local time is 'America/Edmonton'. The time zone on my machine is UTC, so datetime.now() returns UTC time. if the current time is less than 30 minutes before the time in my string...
🌐
Medium
medium.com › @eleroy › 10-things-you-need-to-know-about-date-and-time-in-python-with-datetime-pytz-dateutil-timedelta-309bfbafb3f7
10 things you need to know about Date and Time in Python with datetime, pytz, dateutil & timedelta | by Emmanuel | Medium
October 8, 2023 - In the example above, note how the PST timezone setting becomes actually LMT time (Local Mean Time) which is 16:07:00 offset from UTC, NOT 16:00:00. You end up with a 16h07m offset: bad! import datetime from zoneinfo import ZoneInfo d = datetime.datetime.strptime('01/12/2011 16:43:45', '%d/%m/%Y %H:%M:%S') >>> datetime.datetime(2011, 12, 1, 16, 43, 45)# add proper timezone pst = ZoneInfo('America/Los_Angeles') d = d.replace(tzinfo=pst) >>> datetime.datetime(2011, 12, 1, 16, 43, 45, tzinfo=<DstTzInfo 'America/Los_Angeles' PST-1 day, 16:00:00 STD>)d.isoformat() >>> "2011-12-01T16:43:45-08:00"