Django–ORM查询-时间匹配
1. 引入
帅帅的我遇到了一个问题,我需要从Student
表中,取出创建时间c_time
在2019-3-20
的记录。
-
首先我们确认
c_time
类型In [5]: s1 = Student.objects.get(name='灰原') In [6]: type(s1.c_time) Out[6]: datetime.datetime
-
再查看表内数据
In [10]: Student.objects.all() Out[10]: <QuerySet [ <Student: id<1>name[柯南]gender(男)age|16|c_time:2019-03-20 15:25:09+00:00>, <Student: id<2>name[元太]gender(男)age|16|c_time:2019-03-20 15:26:16+00:00>, <Student: id<3>name[萨斯给]gender(男)age|16|c_time:2019-03-20 15:27:56+00:00>, <Student: id<4>name[步美]gender(女)age|16|c_time:2019-03-20 15:28:16+00:00>, <Student: id<5>name[灰原]gender(女)age|16|c_time:2019-03-20 15:28:16+00:00>, <Student: id<8>name[纳鲁淘]gender(男)age|16|c_time:2019-03-20 15:28:16+00:00> ... ]>
- 创建日期在
2019-3-20
数据不少
- 创建日期在
2. 查错
- 查询
In [11]: Student.objects.filter(c_time__date=datetime.date(2019, 3, 20))
Out[11]: <QuerySet []>
In [12]: s1.c_time.date()==datetime.date(2019, 3, 20)
Out[12]: True
- 查询结果为空
- 有满足条件记录
- 对比
In [19]: Student.objects.filter(c_time=t1)
Out[19]: <QuerySet [
<Student: id<4>name[步美]gender(女)age|16|c_time:2019-03-20 15:28:16+00:00>,
<Student: id<5>name[灰原]gender(女)age|16|c_time:2019-03-20 15:28:16+00:00>,
...
]>
In [20]: td1 = t1.date()
In [21]: Student.objects.filter(c_time__date=td1)
Out[21]: <QuerySet []>
- 发现只有调用
__date
属性出错
- 验证
In [22]: r1 = Student.objects.filter(c_time=t1)
In [23]: str(r1.query)
Out[23]:'''
SELECT `book_student`.`id`, `book_student`.`name`, `book_student`.`age`, `book_student`.`gender`, `book_student`.`c_time`, `book_student`.`college_id`
FROM `book_student`
WHERE `book_student`.`c_time` = 2019-03-20 15:28:16'
'''
In [24]: r2 = Student.objects.filter(c_time__date=td1)
In [26]: str(r2.query)
Out[26]: '''
SELECT `book_student`.`id`, `book_student`.`name`, `book_student`.`age`, `book_student`.`gender`, `book_student`.`c_time`, `book_student`.`college_id`
FROM `book_student`
WHERE DATE(CONVERT_TZ(`book_student`.`c_time`, 'UTC', 'Asia/Shanghai')) = 2019-03-20
'''
- CONVERT_TZ(dt,from_tz,to_tz):转换datetime值dt,从 from_tz 由给定转到 to_tz 时区给出的时区,并返回的结果值。 如果参数无效该函数返回NULL。
- 测试sql
mysql> SELECT CONVERT_TZ('20190320000000', 'UTC', 'Asia/Shanghai');
+------------------------------------------------------+
| CONVERT_TZ('20190320000000', 'UTC', 'Asia/Shanghai') |
+------------------------------------------------------+
| null |
+------------------------------------------------------+
1 row in set (0.00 sec)
- 找到了问题,我的MySQL数据库应用的mysql(即系统自带的那个数据库)数据库中没有对应的time_zone表
- 解决方法请参阅:2lovecode的博客
3. 解决
- 验证sql
mysql> SELECT CONVERT_TZ('20190320000000', 'UTC', 'Asia/Shanghai');
+------------------------------------------------------+
| CONVERT_TZ('20190320000000', 'UTC', 'Asia/Shanghai') |
+------------------------------------------------------+
| 2019-03-20 08:00:00 |
+------------------------------------------------------+
1 row in set (0.00 sec)
配置好后,sql
验证通过
- 验证orm
In [32]: Student.objects.filter(c_time__date=datetime.date(2019, 3, 20)).count()
Out[32]: 8
In [33]: Student.objects.filter(c_time__date='2019-03-20').count()
Out[33]: 8
通过验证,大吉大利,晚上加餐。
4. 知识补充
c_time__date
调用的是mysql
的DATE
方法,若觉得中间容易出错,在逻辑允许情况下可更改字段
同栗,查看创建时间c_time
为2019-3-20
的记录数目。
In [38]: res = Student.objects.filter(c_time__startswith='2019-03-20')
In [39]: res.count()
Out[39]: 8
In [40]: str(res.query)
Out[40]: 'SELECT `book_student`.`id`, `book_student`.`name`, `book_student`.`age`, `book_student`.`gender`, `book_student`.`c_time`, `book_student`.`college_id` FROM `book_student` WHERE `book_student`.`c_time` LIKE BINARY 2019-03-20%'
或者
In [42]: res = Student.objects.filter(c_time__contains='2019-03-20')
In [43]: res.count()
/home/zdq/.virtualenvs/djfirst/lib/python3.5/site-packages/pymysql/cursors.py:170: Warning: (1292, "Incorrect datetime value: '%2019-03-20%' for column 'c_time' at row 1")
result = self._query(query)
Out[43]: 8
# 哎呀,警告了,看来要慎用
亦或者
In [18]: res = Student.objects.filter(c_time__range=('2019-03-20 00:00:00', '2019
...: -03-21 00:00:00'))
In [19]: str(res.query)
Out[19]: 'SELECT `book_student`.`id`, `book_student`.`name`, `book_student`.`age`, `book_student`.`gender`, `book_student`.`c_time`, `book_student`.`college_id` FROM `book_student` WHERE `book_student`.`c_time` BETWEEN 2019-03-19 16:00:00 AND 2019-03-20 16:00:00'
In [20]: res.count()
Out[20]: 8
- 会发出警告:time zone support is active.RuntimeWarning
- sql 是使用
UTC
时间的,不难看出sql
语句时间区间提前6小时。
从不同角度,使用不同的方法,不同方法的优劣这些都是语言的美丽了。
墨染是最棒的
Tuple是最强的
我是最帅的