timezone.localize() 应该用于naive datetime 对象(没有自己的时区的对象)。时区附加到datetime,就好像日期和时间对于那个时区是正确的。因此,在您的情况下,您将 UTC 本地化,就好像它是没有 DST 的本地时间一样,将它朝错误的方向移动 8 小时。
但是,您使用的是 UTC 时间戳,因此您需要将 UTC 时区附加到该时间戳,然后将时间戳移动到所需的时区:
utc = pytz.utc.localize(datetime.utcnow())
instance_time_zone = pytz.timezone(instance.timezone) # 'US/Pacific'
start_date = utc.astimezone(instance_time_zone)
请注意,utc 值现在是带有时区的 datetime 对象,因此您可以使用 datetime.astimezone() method 从中生成所需目标时区的值。
演示:
>>> from datetime import datetime
>>> utc = pytz.utc.localize(datetime.utcnow())
>>> utc
datetime.datetime(2015, 10, 2, 17, 58, 10, 168575, tzinfo=<UTC>)
>>> instance_time_zone = pytz.timezone('US/Pacific')
>>> utc.astimezone(instance_time_zone)
datetime.datetime(2015, 10, 2, 10, 58, 10, 168575, tzinfo=<DstTzInfo 'US/Pacific' PDT-1 day, 17:00:00 DST>)
现在生成的datetime 与 UTC 相差 5 小时。
但是,如果您将这些值输出到 Django 模板中,请注意 Django 也会转换时区。请参阅Django timezone documentation,特别是section on using aware datetime objects in templates:
当您启用时区支持时,当它们在模板中呈现时,Django 会将可感知的日期时间对象转换为 current time zone。这与格式本地化非常相似。
来自current time zone section:
您应该使用activate() 将当前时区设置为最终用户的实际时区。否则,使用默认时区。
然后,您将datetime 对象移动到哪个时区并不重要;它将使用当前时区来显示该值。您通常希望在 UTC 时区中使用有意识的 datetime 对象,然后使用 activate() 切换显示所有内容的时区。
所以在 Django 中,只需在任何地方使用 timezone.now(),然后让模板系统担心将其转换为给定的时区。