Laravel Eloquent 比较日期时间字段中的日期

Posted

技术标签:

【中文标题】Laravel Eloquent 比较日期时间字段中的日期【英文标题】:Laravel Eloquent compare date from datetime field 【发布时间】:2014-09-28 04:22:23 【问题描述】:

我想通过一个表达式从一个表中获取所有的行:

table.date <= 2014-07-10

但如果该列包含日期时间,我们就说:

2014-07-10 12:00:00

但如果我这样做:

where('date', '<=', $date)

它不会得到该行。

我猜这是因为 $date = 2014-07-10 这使得 mysql 假设它是 2014-07-10 00:00:00。

在常规 MySQL 中我会这样做

where DATE(date) <= $date

使用 Laravel 的 Eloquent 的等价物是什么?

【问题讨论】:

【参考方案1】:

如果您仍然想知道如何解决它。

我用

protected $dates = ['created_at', 'updated_at', 'aired'];

在我的模型和我做的地方

where('aired', '&gt;=', time());

所以只需使用 unix 在哪里进行比较。

另一方面,在视图中,您必须使用日期对象。

【讨论】:

这是唯一对我有用的,因为我已经在 $dates 中定义了 :) 谢谢 @pixie_frigo 文档中的 $protected $dates 在哪里?【参考方案2】:

这是我的逻辑: 如果您正在比较日期,那么您的方法应该是 whereDate,如果您比较完整的日期时间,那么您的方法将只在哪里:

$calendar_alert = DB::table('calendar_alerts')->whereDate('when', '=', now()->format('Y-m-d'))->where('when', '>', now()->format('H:i:s'))->get();

【讨论】:

【参考方案3】:

您可以通过选择以下一种语法来获取日期“2016-07-14”或“2016-07-14”之前的所有记录:

->whereDate('date','=','2014-07-10')

->whereDate('date', '<=', '2014-07-10')

或者使用其他代码来获取动态日期

whereDate('date',$date)

【讨论】:

这似乎根本无法回答问题。 @SteveFromAccounting 在这种情况下,代码不适用于 Laravel 吗?可以发一下代码sn-ps吗?【参考方案4】:
use Carbon\Carbon;

public function scopePublished($query)

  $now = Carbon::now();
  $date = Carbon::parse($now)->toDateString();
  $time = Carbon::parse($now)->toTimeString();
  return $query->whereDate('published_at', '<', $date)
  ->orWhere(function($query) use ($date, $time) 
    $query->whereDate('published_at', '=', $date)
    ->whereTime('published_at', '<=', $time);
  );

【讨论】:

【参考方案5】:

您是否考虑过使用:

where('date', '<', '2014-08-11')

您应该避免在 MySQL 中的索引列上使用 DATE() 函数,因为这会阻止引擎使用索引。

更新

由于似乎对DATE() 和索引的重要性存在一些分歧,我创建了一个fiddle 来展示差异,请参阅POSSIBLE KEYS

【讨论】:

为什么他应该避免在索引列上使用DATE() 这可能是一个解决方案,但看起来更像是一种 hack,而不是最佳实践。如果一个文件中包含 00:00:00 作为时间呢? @almo,一旦你习惯了 MySQL 比较日期的方式,它就不会太糟糕了。这就像字符串比较; “2014-08-10 00:00:00”大于“2014-08-10”。 @Almo 你应该避免在索引列上使用 DATE() 因为它会阻止 MySQL 使用这个索引。如果可能,请使用比较运算符右侧的表达式。不,这是最佳实践,而不是 hack! ::whereRaw("DATE(date) &lt;= '2014-08-10'")。 @Arth他没有提到索引,所以我不知道它有什么毛病。正如你所说,@almo 2014-07-10 将被转换为 DATETIME (2014-07-10 00:00:00)。但是,您将DATEDATETIME 进行比较,您要么将DATETIME 转换为DATE,要么将23:59:59 添加到$date【参考方案6】:

Laravel 4+ 为您提供这些方法:whereDay()whereMonth()whereYear() (#3946) 和 whereDate() (#6879)。

他们为您执行 SQL DATE() 工作,并管理 SQLite 的差异。

你的结果可以这样实现:

->whereDate('date', '<=', '2014-07-10')

有关更多示例,请参阅#3946 的第一条消息和此Laravel Daily article。

更新: 虽然上述方法很方便,但正如 Arth 所说,它在大型数据集上效率低下,因为必须对每条记录应用 DATE() SQL 函数,从而丢弃可能的索引。

以下是一些进行比较的方法(但请阅读下面的注释):

->where('date', '<=', '2014-07-10 23:59:59')

->where('date', '<', '2014-07-11')

// '2014-07-11'
$dayAfter = (new DateTime('2014-07-10'))->modify('+1 day')->format('Y-m-d');

->where('date', '<', $dayAfter)

注意事项:

23:59:59 可以(暂时)因为 1 秒的精度,但请看这篇文章:23:59:59 is not the end of the day. No, really! 请记住“零日期”情况(“0000-00-00 00:00:00”)。尽管应该避免这些“零日期”,但它们是许多问题的根源。如果需要,最好使该字段可以为空。

【讨论】:

同样,我建议不要使用这种方法,它会将列包装在 DATE() 函数中,并且引擎无法在列上使用索引。 没问题!我对日期像字符串一样进行比较是错误的,它们只是被转换然后比较。 2014-07-11 将在比较之前隐式转换为 2014-07-11 00:00:00,幸运的是,这与您的其他解释很好。 另外请注意,您可以愉快地使用WHERE date &lt; :date + INTERVAL 1 DAY,而不是在 php 中乱搞日期 确实是关于 MySQL INTERVAL。不过,如果可能的话,我更喜欢在 PHP 端进行处理,而不是 MySQL 甚至 Apache。我厌倦了他们所有的微妙之处。 THAX ALOT:对我有用的地方我正在使用 laravel 7+【参考方案7】:

你可以用这个

whereDate('date', '=', $date)

如果您提供 whereDate 则仅比较日期时间字段中的日期。

【讨论】:

以上是关于Laravel Eloquent 比较日期时间字段中的日期的主要内容,如果未能解决你的问题,请参考以下文章

Laravel Eloquent 查找日期超过 2 天的行

无法让 Laravel OrderBy 日期在 Eloquent 语句中工作

通过laravel Eloquent Model以dd / mm / yyyy插入日期格式

Laravel - 使用 eloquent 在开始日期和结束日期之间选择行

laravel eloquent: whereDate not found 记录包含在期间

Laravel - Eloquent - 获得没有外键的关系