我正在尝试为我的Web应用进行正确的日期处理设置。我有一个看起来像这样的模型
class Entity(models.Model):
name = models.CharField(max_length=255)
date = models.DateTimeField()
用户可以向我的DRF端点/api/v1/entity/
发送请求以获取此类实体的列表。现在,要求用户应该能够在一天之内请求所有Entity
对象,这由date参数确定。该应用程序的用户不在UTC时区时,日期存储在数据库的UTC中。
用户可以创建一个日期为2018-06-19T01:00:00+02:00
的实体,该日期存储为2018-06-18T23:00:00Z
在数据库中。现在,如果我尝试列出用户为2018-06-19
创建的所有实体,则不会返回任何内容,但是按2018-06-18
进行过滤将返回一个条目。
这是我正在使用的代码设置:
http://127.0.0.1:8000/api/v1/entity/?date=2018-06-18
。
def get_queryset(self):
user = self.request.user
entities = Entity.objects.filter(owner=user)
date = self.request.query_params.get('date')
if date:
entities = entities.filter(date__date=date)
return entities
因此,在这种情况下,适当的日期范围应为2018-06-18T23:00:00Z
-2018-06-19T23:00:00Z
。在用户时区的一天(或日期范围)内获取所有实体的正确方法是什么?
答案 0 :(得分:1)
如果我正确理解,则必须将本地 DateTime
转换为等效的 UTC
时间并查询数据库。所以我在下面定义了一个简单的时间转换函数
import pytz
from datetime import datetime
def convert_to_UTC(local_tz,dt_1,dt_2):
"""
local_tz : any possible timezone which supports pytz lib (https://stackoverflow.com/questions/13866926/is-there-a-list-of-pytz-timezones)
dt_1 and dt_2 : local datetime in string in this format ->> '%Y-%m-%dT%H:%M:%S'
return a list as ->> [utc_equivalent_of_dt_1_in_string,utc_equivalent_of_dt_2_in_string]
"""
format='%Y-%m-%dT%H:%M:%S'
pytz_local_tz = pytz.timezone(local_time_zone)
dt_obj_from_date_time = datetime.strptime(dt_1,format)
dt_obj_to_date_time = datetime.strptime(dt_2,format)
return [pytz_local_tz.localize(dt_obj_from_date_time).astimezone(tz=pytz.utc).strftime(format),
pytz_local_tz.localize(dt_obj_to_date_time).astimezone(tz=pytz.utc).strftime(format)]
要利用此功能,请如下更改您的get_queryset()
方法,
def get_queryset(self):
user = self.request.user
entities = Entity.objects.filter(owner=user)
date_from = self.request.query_params.get('date_from')
date_to = self.request.query_params.get('date_to')
if date_from and date_to:
entities = entities.filter(date__range=convert_to_UTC('Asia/Kolkata', date_from, date_to))
return entities
因此该网址将类似于/api/v1/entity/?date_from=2018-06-18T23:00:00&date_to=2018-06-19T23:00:00
答案 1 :(得分:0)
# simplified functions
def localize(usertimzone, date, type):
"""
type = 'date', 'time', 'datetime'
"""
from dateutil import parser
date = parser.parse(date)
if not date.tzinfo:
# "if the POST request like `2018-06-19T01:00:00`"
usertimzone = pytz.timezone(usertimzone)
date = usertimzone.localize(date)
# "if the POST request like `2018-06-19T01:00:00+02:00`" then just do this
utc_date = date.astimezone(pytz.utc)
return utc_date
#usages example
def post(self, request, *args, **kwargs):
alert_date = request.data.get('alert_date')
if alert_date:
request.data['alert_date'] = localize(request.user.timezone, alert_date, 'datetime')