1

When I pull events start times from Facebook Graph in comes in this form:

2017-09-26T18:00:00+0300

I'd like to convert it into readable format so I use this:

readable_event_date = dateutil.parser.parse(event_date).strftime('%a, %b %d %Y %H:%M:%S')

and it comes out like this:

Tue, 26 Sep 2017 18:00:00

Which is good but it loses the offset from UTC and I'd like it in AM PM format.

Thus, I would like it like this:

Tue, 26 Sep 2017 9:00 PM
glegoux
  • 3,505
  • 15
  • 32
Seif
  • 701
  • 4
  • 13
  • 32
  • See answer to [this question](https://stackoverflow.com/questions/13855111/how-can-i-convert-24-hour-time-to-12-hour-time). – Sam Chats Jun 25 '17 at 10:02

2 Answers2

1

To get into 12 hours format and keep offset from UTC for printing :

from dateutil.parser import parse

event_date = '2017-09-26T18:00:0+0300'

date = parse(event_date)
offset = date.tzinfo._offset

readable_event_date = (date + offset).strftime('%a, %b %d %Y %I:%M:%S %p')

print(readable_event_date)

Output:

'Tue, Sep 26 2017 09:00:00 PM'
glegoux
  • 3,505
  • 15
  • 32
  • This is not the right way to do this at all. Do not use `_offset`, do not manually add the offset to the date. Use `.astimezone(dateutil.tz.tzutc())` if you just want the date in UTC or use %z if you want to show the offset. – Paul Jun 25 '17 at 15:40
  • Also there is no need to parse the date twice. – Paul Jun 25 '17 at 15:41
  • Here you don't know the timezone `date.astimezone(dateutil.tz.tzutc())` -> `datetime.datetime(2017, 9, 26, 15, 0, tzinfo=tzutc())` it is false, you know only the offset. Precise your answer, if you think to have right again ? – glegoux Jun 25 '17 at 20:46
  • In your answer, you are pulling the offset *from the parsed date's tzinfo*. What you are doing in this answer is just adding the offset so the date is the same as it would be in UTC, but not removing the tzinfo. You have a fixed-offset zone, which means that while you may not be able to do valid datetime arithmetic on this date, you can at least convert it to UTC (if that's what you want). – Paul Jun 25 '17 at 22:21
  • One reason to use `.astimezone` that I didn't realize until I tried writing my own answer is that it actually gives the right answer. Your date returns 9 PM, when the actual input date represents 3PM. – Paul Jun 25 '17 at 23:14
1

It seems like what you want is this time, expressed in UTC, in the format '%a, %b %d %Y %I:%M:%S %p'. Luckily, all the information you need to do this is contained in the datetime object that you parsed, you just need to convert to UTC

Python 2.6+ or Python 3.3+:

The approach you've taken using dateutil will work for Python 2.6+ or Python 3.3.+ (and also works for a greater variety of datetime string formats):

from dateutil.parser import parse

# In Python 2.7, you need to use another one
from dateutil.tz import tzutc
UTC = tzutc()

dt_str = '2017-09-26T18:00:00+0300'
dt = parse(dt_str)
dt_utc = dt.astimezone(UTC)  # Convert to UTC

print(dt_utc.strftime('%a, %b %d %Y %I:%M:%S %p'))
# Tue, Sep 26 2017 03:00:00 PM

One thing I notice is that the date you've provided, as far as I can tell, represents 3PM in UTC, not 9PM (as your example states). This is one reason you should use .astimezone(UTC) rather than some other approach.

If you want to include the time zone offset information, you can also use the %z parameter on the non-converted version of the datetime object.

print(dt.strftime('%a, %b %d %Y %I:%M:%S%z %p'))
# Tue, Sep 26 2017 06:00:00+0300 PM

This %z parameter may also be useful even if you are keeping it in UTC, because then you can at least be clear that the date the user is seeing is a UTC date.

Python 3.2+ only:

Given that you know the exact format of the input string, in Python 3.2+, you can achieve this same thing without pulling in dateutil, and it will almost certainly be faster (which may or may not be a concern for you).In your case here is how to rewrite the code so that it works with just the standard library:

from datetime import datetime, timezone
UTC = timezone.utc

dt_str = '2017-09-26T18:00:00+0300'
dt = datetime.strptime(dt_str, '%Y-%m-%dT%H:%M:%S%z')
dt_utc = dt.astimezone(UTC)

print(dt_utc.strftime('%a, %b %d %Y %I:%M:%S %p'))
# Tue, Sep 26 2017 03:00:00 PM

print(dt.strftime('%a, %b %d %Y %I:%M:%S%z %p'))
# Tue, Sep 26 2017 06:00:00+0300 PM
Graham
  • 7,431
  • 18
  • 59
  • 84
Paul
  • 10,381
  • 13
  • 48
  • 86