如何在Django中获取本地时区日期时间以进行日期比较
我想根据用户的时区来发送提醒。用户的时区是“America/New_York”。
我尝试用下面的代码获取用户的时间:
now = datetime.now()
now_plus_10 = test_customer.time_zone.localize(now + timedelta(minutes = 10))
now_minus_10 = test_customer.time_zone.localize(now + timedelta(minutes = -10))
提醒的时间是13:00。这是从客户对象中获取的,像这样:
reminder = customer.reminder #set to 13:00
然后我想在提醒时间前后10分钟内发送提醒。
我进行比较的代码是:
if reminder > now_minus_10 and gb_real_time < now_plus_10:
reminder_email.send()
else:
print 'ceiling '+str(now_plus_10)
print 'not in window don t send'
print 'floor '+str(now_minus_10)
这段代码输出:
ceiling 2014-09-03 10:10:54.547901-04:00
not in window don t send
floor 2014-09-03 09:50:54.547901-04:00
我在“America/Los_Angeles”这个时区,现在是早上10:00。
我想知道,尽管我已经把now_plus_10和now_minus_10的日期进行了本地化,但它们为什么没有转换成纽约时间,也就是13:00,这样就能触发提醒了呢?
1 个回答
1
我觉得你可能误解了 localize()
的作用。(我假设你是在说 pytz 的 localize()
,你可以在 这里查看文档。)
它并不是在 转换 时间,而是把一个不带时区的日期时间(也就是“天真”的日期时间)变成带时区的(给它分配 一个时区)。在你的例子中,事情是这样的:
now = datetime.now() # 10:00am local time (no timezone)
later = now + timedelta(minutes=10) # 10:10am (no timezone)
now_plus_10 = ny_timezone.localize(later) # 10:10am (NY timezone)
如果你真的想直接在时区之间转换,使用 pytz
,你可以这样做:
now = la_timzeone.localize(datetime.now()) # 10:00am local time (LA timezone)
later = now + timedelta(minutes=10) # 10:10am (LA timezone)
later_safe = la_timezone.normalize(later) # because of DST and such
later_ny = later_safe.astimezone(ny_timezone) # 13:10 (NY timezone)
later_ny_safe = ny_timezone.normalize(later_ny) # again
这可就复杂了!所以 pytz
和 Django 都不建议你手动去本地化和转换时区。你需要查看一下 文档,但基本上,Django 的做法是这样的:
- 所有内部的日期时间都是带时区的,并且使用 UTC 时间。
- 使用
django.utils.timezone.now()
来获取当前的 UTC 时间。 - 用户输入的日期时间(比如用户在表单中输入的提醒时间)会自动变成带时区的。为了做到这一点,你需要知道用户的时区,然后调用
activate()
。你也可以手动使用localtime()
来实现。 - 所有的比较和运算都要使用这些 UTC 日期时间。
我强烈推荐按照 Django 的方式来做。