Use
published_time = pytz.utc.localize(datetime.utcfromtimestamp(calendar.timegm(parsed_entry.published_parsed)))
Feedparser can parse a large range of date formats, you can find them here.
As you can see in feedparser/feedparser/datetimes/__init__.py
, the built-in function from Feedparser _parse_date
does the following:
Parses a variety of date formats into a 9-tuple in GMT
This means that in parsed_entry.published_parsed
you have a time.struct_time
object in GMT timezone.
When you convert it to a datetime
object using
published_time = datetime.fromtimestamp(mktime(parsed_entry.published_parsed))
the problem is that mktime
assumes that the passed tuple is in local time, which is not, it's GMT/UTC! Other than that you don't properly localize the datetime
object at the end of the conversion.
You need to replace that conversion with the following, remembering that Feedparser returns a GMT struct_time
, and localize that with the timezone you like (UTC for the sake of simplicity).
- You use
calendar.timegm
, which gives the number of seconds between epoch and the date passed as a parameter, assuming that the passed object is in UTC/GMT (we know from Feedparser it is)
- You use
utcfromtimestamp
to obtain a naive datetime
object (which we know represents a datetime in UTC, but Python does not at this moment)
- With
pytz.utc.localize
you properly localize in UTC the datetime
object.
Example:
import calendar
from datetime import datetime
import pytz
localized_dt = pytz.utc.localize(datetime.utcfromtimestamp(calendar.timegm(parsed_entry.published_parsed)))
As long as you are consistent, it doesn't matter if you use fromtimestamp
or utcfromtimestamp
. If you use fromtimestamp
you need to tell Python that the datetime
object you created has the local timezone. Supposing you are in Europe/Berlin, this is also fine:
pytz.timezone('Europe/Berlin').localize(datetime.fromtimestamp(calendar.timegm(parsed_entry.published_parsed)))
Were parsed_entry.published_parsed
also in local timezone, mktime
must be used in place of calendar.timegm
.
As an alternative you can parse yourself the data string you get from Feedparser parsed_entry['published']
from dateutil import parser
localized_dt = parser.parse(parsed_entry['published'])
You can check that the following returns True
:
parser.parse(parsed_entry['published']) == pytz.utc.localize(datetime.utcfromtimestamp(calendar.timegm(parsed_entry.published_parsed)))
The Django TIME_ZONE
setting doesn't actually matter, because it's used only for visualization purposes or to automatically convert naive datetimes.
When USE_TZ is True, this is the default time zone that Django will use to display datetimes in templates and to interpret datetimes entered in forms.
What is important is to always use properly localized datetimes, no matter which time zone is used. As long as they are not in naive format, they will be properly handled by Django.