8

I've been trying to convert this specific date format to a string in Python like so:

datetime.strptime(‘2017-01-12T14:12:06.000-0500’,'%Y-%m-%dT%H:%M:%S.%f%Z')

But it doesn't work.

What am I doing wrong?

hansaplast
  • 11,007
  • 2
  • 61
  • 75
mrjextreme6
  • 143
  • 1
  • 2
  • 5
  • 4
    Welcome to the site! Check out the [tour](https://stackoverflow.com) and ["How to ask"](https://stackoverflow.com/help/how-to-ask/) for more about asking questions that will attract quality answers. Please [edit your question](https://stackoverflow.com/posts/41684991/edit) to show the output or error message you get, compared to what you expect. Thanks! **Also**, use straight quotes `''`, not curly quotes. – cxw Jan 16 '17 at 21:09

7 Answers7

14

The error was that you used %Z instead of %z. From the documentation, you should use %z to match e.g. (empty), +0000, -0400, +1030

import datetime

result = datetime.datetime.strptime('2017-01-12T14:12:06.000-0500','%Y-%m-%dT%H:%M:%S.%f%z')

print(result)

Output

2017-01-12 14:12:06-05:00
Tagc
  • 8,736
  • 7
  • 61
  • 114
6

Assuming Python 3, the format %f may not be a valid format character for strptime on your platform. The strptime docs reference strftime for the formats, and %f isn't in the strftime list. However, the format string reference says that

The full set of format codes supported varies across platforms, because Python calls the platform C library’s strftime() function, and platform variations are common.

On my test system, which is Cygwin with Py 3.4.5, I used:

import datetime
datetime.datetime.strptime('2017-01-12T14:12:06.000-0500','%Y-%m-%dT%H:%M:%S.%f%Z')

and got

ValueError: time data '2017-01-12T14:12:06.000-0500' does not match format '%Y-%m-%dT%H:%M:%S.%f%Z'

I checked the man pages for strftime(3) and found that I don't have %f, and %z should be lowercase. I therefore used

datetime.datetime.strptime('2017-01-12T14:12:06.000-0500','%Y-%m-%dT%H:%M:%S.000%z')
#          straight quotes ^ not curly                  ^
#                                                      literal .000 (no %f) ^^^^ 
#                                                                  lowercase %z ^^

and got a successful parse.

Edit @Tagc found that %f worked fine running under Python 3.5 in PyCharm on a Windows 10 machine.

cxw
  • 16,685
  • 2
  • 45
  • 81
  • This is incorrect. `%f` is a valid format character according to the documentation. https://docs.python.org/3/library/datetime.html#strftime-strptime-behavior – Tagc Jan 16 '17 at 21:17
  • @Tagc It actually depends on which documentation you read, and it turns out it's platform-specific. Please see edited answer. – cxw Jan 16 '17 at 21:19
  • Ah okay. I'm confused so I'll lift my downvote. FWIW the `%f` worked fine for me running under Python 3.5 in PyCharm on a Windows 10 machine. – Tagc Jan 16 '17 at 21:21
  • 1
    @Tagc Thanks! Yes, I was unpleasantly surprised to discover the internal inconsistency in the documentation. Thanks for the extra data! – cxw Jan 16 '17 at 21:23
4

Task:

"convert this specific date format to a string in Python"

import datetime  

Solution:

First modify your datetime.strptime code as follows:

  obj = datetime.datetime.strptime('2017-01-12T14:12:06.000-0500','%Y-%m-%dT%H:%M:%S.%f%z')

This is a useful site for your reference and will help you modify the output as per your preference.

Then use strftime to convert it to a string:

obj.strftime("%b %d %Y %H:%M:%S")

Out:

'Jan 12 2017 14:12:06'
nipy
  • 5,138
  • 5
  • 31
  • 72
4

Having date as the input str:

from dateutil import parser
parsed_date = parser.parse(date)

python-transforming-twitter

ericson.cepeda
  • 1,875
  • 2
  • 16
  • 15
3

Solution for Python 2.7

From the comments it became clear that OP needs a solution for Python 2.7.

Apparently, there's no %z in strptime for python 2.7 even though the documentation claims the contrary, the raised error is ValueError: 'z' is a bad directive in format '%Y-%m-%dT%H:%M:%S.000%z'.

To solve this, you need to parse the date without timezone first and add the timezone later. Unfortunately you need to subclass tzinfo for that. This answer is based on this answer

from datetime import datetime, timedelta, tzinfo

class FixedOffset(tzinfo):
    """offset_str: Fixed offset in str: e.g. '-0400'"""
    def __init__(self, offset_str):
        sign, hours, minutes = offset_str[0], offset_str[1:3], offset_str[3:]
        offset = (int(hours) * 60 + int(minutes)) * (-1 if sign == "-" else 1)
        self.__offset = timedelta(minutes=offset)
        # 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
        '<%+03d%02d>%+d' % (int(hours), int(minutes), int(hours)*-1)
    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)

date_with_tz = "2017-01-12T14:12:06.000-0500"
date_str, tz = date_with_tz[:-5], date_with_tz[-5:]
dt_utc = datetime.strptime(date_str, "%Y-%m-%dT%H:%M:%S.%f")
dt = dt_utc.replace(tzinfo=FixedOffset(tz))
print(dt)

The last line prints:

2017-01-12 14:12:06-05:00
Community
  • 1
  • 1
hansaplast
  • 11,007
  • 2
  • 61
  • 75
  • Thank you @hansaplast this was exactly what I needed since I'm working with an ancient version of Python :P – mrjextreme6 Jan 17 '17 at 16:09
  • well.. I wouldn't call python 2.7 ancient, it's still widely used by people who don't want to do the switch to python 3 (or their modules don't support python 3 yet) – hansaplast Jan 17 '17 at 16:12
3

If you don't have timezone information, replacing the '%Z' with 'Z' works in Python 3.

datetime.strptime('2010-10-04T03:41:22.858Z','%Y-%m-%dT%H:%M:%S.%fZ')
# datetime.datetime(2010, 10, 4, 3, 41, 22, 858000)
0

if it is a string, e.g. load from a JSON file, you can try

date = '2017-01-12T14:12:06.000-0500'

print(date = date[:10]+" "+date[11:19])

returns:

2017-01-12 14:12:06
NumberVII
  • 5
  • 2