Skip to content

Instantly share code, notes, and snippets.

@litzinger
Created June 5, 2019 14:43
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save litzinger/1b52b18486897f1ad0bc09e034dbd170 to your computer and use it in GitHub Desktop.
Save litzinger/1b52b18486897f1ad0bc09e034dbd170 to your computer and use it in GitHub Desktop.
Crude attempt at supporting Elasticsearch date math values in PHP's DateTime object
<?php
namespace MyNamespace;
/**
* @author Ton Sharp
* @author Brian Litzinger
* @see https://gist.github.com/66Ton99/60571ee49bf1906aaa1c
* @see https://www.elastic.co/guide/en/elasticsearch/reference/5.3/common-options.html#date-math
*/
class DateTime extends \DateTime
{
/**
* @param int|null $year
* @param int|null $month
* @param int|null $day
*
* @return $this
*/
public function setDate($year, $month, $day)
{
if (null == $year) {
$year = $this->format('Y');
}
if (null == $month) {
$month = $this->format('n');
}
if (null == $day) {
$day = $this->format('j');
}
$daysInMonth = cal_days_in_month(CAL_GREGORIAN, $month, $year);
$day = $day > $daysInMonth ? $daysInMonth : $day;
$return = parent::setDate($year, $month, $day);
return $return;
}
/**
* @inheritdoc
*/
public function modify($modify)
{
$pattern = '/(now)?([-+]\d+\w)(\/\w)?/';
preg_match_all($pattern, $modify, $allMatches, PREG_SET_ORDER);
if (empty($allMatches)) {
return $this;
}
foreach ($allMatches as $matches) {
$modify = preg_replace_callback(
$pattern,
function ($matches) use ($pattern) {
if (empty($matches[0])) {
return;
}
$value = $this->stringify($matches[2]);
$modifier = $matches[3] ?? null;
$value = parent::modify($value);
if ($value && $modifier) {
$this->applyModifier($modifier);
}
return;
},
$modify
);
if ($modify = trim($modify)) {
return parent::modify($modify);
}
}
return $this;
}
private function stringify($value)
{
$pattern = '/(\d+)(\w+)/';
return preg_replace_callback(
$pattern,
function ($matches) {
if (empty($matches)) {
return '';
}
return $matches[1].$this->transpose($matches[2]);
},
$value
);
}
private function transpose($value)
{
$options = [
'd' => ' day',
'h' => ' hour',
'H' => ' hour',
'm' => ' minutes',
'M' => ' month',
's' => ' second',
'w' => ' week',
'y' => ' year',
];
return $options[$value] ?? '';
}
private function applyModifier($modifier)
{
switch ($modifier) {
case '/d':
parent::modify('today midnight');
break;
case '/M':
parent::modify('first day of this month');
parent::modify('today midnight');
break;
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment