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.