Округление даты-времени MYSQL до самого раннего 15-минутного интервала в миллисекундах (PHP) - PullRequest
2 голосов
/ 12 августа 2010

Я извлекаю дату и время из MYSQL, которые выглядят так:

2010-08-11 11: 18: 28

Мне нужно преобразовать его в «пол» или самый ранний 15-минутный интервал и вывести в миллисекундах для другой функции.

Итак, этот случай будет:

2010-08-11 11:15:00 в миллисекундах


Упс! Извините - нужно уточнить - мне нужен код, который преобразует его в миллисекунды В ТЕЧЕНИЕ php!


Проведение временного теста показало следующее:

$time_start = microtime(true);
for($i=0;$i<10000;$i++)
    floor(strtotime('2010-08-11 23:59:59')/(60*15))*60*15*1000;
$time_end = microtime(true);
echo 'time taken = '.($time_end - $time_start);

затраченное время = 21,440743207932

$time_start = microtime(true);
for($i=0;$i<10000;$i++)
    strtotime('2010-08-11 23:59:59')-(strtotime('2010-08-11 23:59:59') % 900);
$time_end = microtime(true);
echo 'time taken = '.($time_end - $time_start);

затраченное время = 39,597450017929

$time_start = microtime(true);
for($i=0;$i<10000;$i++)
    bcmul((strtotime('2010-08-11 23:59:59')-(strtotime('2010-08-11 23:59:59') % 900)), 1000);
$time_end = microtime(true);
echo 'time taken = '.($time_end - $time_start);

затраченное время = 42,297260046005

$time_start = microtime(true);
for($i=0;$i<10000;$i++)
    floor(strtotime('2010-08-11 23:59:59')/(900))*900000;
$time_end = microtime(true);
echo 'time taken = '.($time_end - $time_start);

затраченное время = 20,687357902527

затраченное время = 19,32729101181

затраченное время = 19,938629150391

Похоже, что функция strtotime () медленная, и нам, вероятно, следует избегать ее двойного использования каждый раз, когда она требуется. Время (60 * 15)! = Время (900) было немного неожиданным ...

Ответы [ 4 ]

1 голос
/ 13 августа 2010

Будет ли это работать? Есть ли какая-нибудь функция, которая могла бы сделать это лучше?

echo floor(strtotime('2010-08-11 11:18:28')/(60*15))*60*15*1000;
1281505500000
Wednesday, August 11, 2010 11:15:00 AM

echo floor(strtotime('2010-08-11 11:28:28')/(60*15))*60*15*1000;
1281505500000
Wednesday, August 11, 2010 11:15:00 AM

echo floor(strtotime('2010-08-11 00:00:00')/(60*15))*60*15*1000;
1281465000000
Wednesday, August 11, 2010 12:00:00 AM

echo floor(strtotime('2010-08-11 23:59:59')/(60*15))*60*15*1000;
1281550500000
Wednesday, August 11, 2010 11:45:00 PM
1 голос
/ 12 августа 2010

Следующее даст вам самый ранний 15-минутный интервал:

select UNIX_TIMESTAMP(YOURDATETIME)-MOD(UNIX_TIMESTAMP(YOURDATETIME), 900) 
from YOURTABLE

Результат указывается в секундах эпохи (секундах с UTC 1970-01-01 00:00:00), если вы хотите, чтобы это значение в миллисекундах, вы должны умножиться на 1000 (в запросе или в PHP, так как вы сочту нужным).

EDIT

В PHP для вашего набора значений это будет:

$values = array('2010-08-11 11:18:28', '2010-08-11 11:28:28', '2010-08-11 00:00:00', '2010-08-11 23:59:59');
foreach($values as $value) {
    $result = (strtotime($value)-(strtotime($value) % 900));
    echo "$value -> $result\n";
}

Когда вы умножите $ result на 1000 (чтобы получить значение в мс), вы, вероятно, получите переполнение, и результат будет преобразован в число с плавающей точкой. Возможно, это не то, что вам нужно, поэтому вам лучше использовать bcmul :

$result = bcmul((strtotime($value)-(strtotime($value) % 900)), 1000);
0 голосов
/ 12 августа 2010

Хорошо, давайте посмотрим на худшее решение:

<?php

$ts    = explode(' ', '2010-08-11 11:18:28');
$date  = explode('-', $ts[0]);
$time  = explode(':', $ts[1]);
$ts    = mktime($time[0], $time[1], $time[2], $date[1], $date[2], $date[0]);
$floor = mktime($time[0], round($time[1]/15)*15, 0, $date[1], $date[2], $date[0]);
0 голосов
/ 12 августа 2010

Попробуйте и посмотрите, что произойдет:

select DATE(myColumn) 
       + CONVERT(HOUR(myColumn),CHAR(2)) + ':'
       + CASE 
         WHEN MINUTE(myColumn) < 15 THEN '00'
         WHEN MINUTE(myColumn) < 30 THEN '15'
         WHEN MINUTE(myColumn) < 45 THEN '30'
         ELSE '45'
       END 
       + ':00' as myDate
...