我有一个MySQL数据库,该数据库具有一个名为orders
的表和一个名为timestamp
的created_at
列]
所有时间戳均以UTC格式存储,并转换回前端的用户本地时间-当前设置为'欧洲/伦敦'
[伦敦在4月到11月之间有夏令时,这里的时钟是格林尼治标准时间(GMT + 1),例如,在当地时间27-10-2019 00:00
创建的订单将保存为26-10-2019 23:00
UTC
用户可以搜索在某些日期之间创建的所有订单。在MySQL中,我可以使用以下函数将日期转换回本地时区以实现此目标,例如:
SELECT * FROM orders WHERE DATE(CONVERT_TZ(created_at, 'UTC','Europe/London')) >= '27-10-2019' AND DATE(CONVERT_TZ(created_at, 'UTC','Europe/London')) <= '27-10-2019'
但是我在共享主机上,并且未加载MySQL时区表,因此无法使用命名时区。我只需要使用一个时区,您可能在想为什么不将所有时间戳都存储为
Europe/London
而不是UTC
。我想将其保留为'UTC'以在将来适应其他时区。
是否存在不使用命名时区来返回正确结果的解决方法?
请注意,查询实际上是使用php中的laravels eloqeunt查询生成器编写的,如下所示:
if (isset($queryString['from_date'])) { $query = $query->whereRaw('DATE(orders.created_at) >= ?', [Carbon::parse($queryString['from_date'])->format('Y-m-d')]); } if (isset($queryString['to_date'])) { $query = $query->whereRaw('DATE(orders.created_at) <= ?', [Carbon::parse($queryString['to_date'])->format('Y-m-d')]); }
起初,我认为解决方案是将用户输入的日期也转换为UTC,但是当我在以下日期创建订单时,结果将丢失第二条记录:
created_at ------------------------------------------------------------- 27-10-2019 00:00 (localtime) - saved as 26-10-2019 23:00 (UTC) 27-10-2019 01:00 (localtime) - saved as 27-10-2019 00:00 (UTC)
感谢任何帮助。
*更新*
通过增加结束日期(在DST无效时,用<
而不是<=
检查结果日期时间不起作用。在英国,DST于2019-10-27于今年关闭。Lets说您在以下日期创建了订单:
created_at (Europe/London) created_at (UTC) as saved in DB ------------------------------------ -------------------------------- 2019-10-26 23:00 2019-10-26 22:00 (UTC) 2019-10-27 03:00 2019-10-27 03:00 (UTC)
用户想要列出在
2019-10-27
上创建的所有订单。使用2019-10-27
作为用户选择的日期,使用php Carbon将开始日期变为2019-10-26
:
Carbon\Carbon::parse('27 Oct 2019', 'Europe/London')->timezone('UTC')->format('Y-m-d') => "2019-10-26"
结束日期变为
2019-10-28
Carbon\Carbon::parse('27 Oct 2019', 'Europe/London')->addDay()->timezone('UTC')->format('Y-m-d') => "2019-10-28"
这意味着查询最终以:
WHERE created_at >= "2019-10-26" AND created_at < "2019-10-28"
因此,在上述情况下,您最终得到一个结果集,该结果集将包含在
2019-10-26
上创建的订单,而这并不是理想的结果。
我有一个MySQL数据库,该数据库带有一个名为orders的表和一个名为created_at的时间戳记列。所有时间戳记均以UTC格式存储并在前端转换回用户本地时间-...