Проблема форматирования с разницей в DateTime - PullRequest
0 голосов
/ 11 января 2019

Я пытаюсь найти разницу в днях между двумя датами, используя DateTime. Я понимаю, что есть несколько других постов, объясняющих, как это сделать. Тем не менее, я получаю сообщение об ошибке при запуске моего кода. Я думаю, что это может быть проблема форматирования, но я в растерянности.

Как вы можете видеть, я пытался отформатировать $ orderdate в формат Y-m-d, рекомендованный в документации. Кажется, делает свое дело. Я что-то пропустил? Согласно документам это должно работать.

$orderdate = strip_tags(str_replace(array('"', "'"), "", str_replace(array("\n", "\r"), ' ', $_POST['pickupship-date'])));
$orderdate = $conn->real_escape_string($orderdate);
$orderdate = date( "Y-m-d", strtotime($orderdate) );
echo $orderdate;

date_default_timezone_set('America/Chicago');
$completiondate = date("m/d/Y");
$completiondate = date( "Y-m-d", strtotime($completiondate) );
echo $completiondate;

$duration = $orderdate->diff($completiondate);
$duration->format('%R%a days');
echo $duration;

РЕДАКТИРОВАТЬ: я обновил код на основе предложений, которые я получил. echo $ orderdate и echo $ завершение выдаются точно так, как ожидалось. Тем не менее, я ничего не получаю за $ продолжительности.

Ответы [ 3 ]

0 голосов
/ 11 января 2019

Непонятно, чего вы хотите достичь с помощью этого кода. Большая часть того, что он делает, неверна или не нужна.

$orderdate = strip_tags(str_replace(array('"', "'"), "", str_replace(array("\n", "\r"), ' ', $_POST['pickupship-date'])));

Вы должны установить фиксированный формат для поля pickupship-date. Что-то вроде Y-m-d (или m/d/Y, если вы предпочитаете это больше) и придерживайтесь его. Не имеет смысла иметь кавычки, апострофы, переводы строк или HTML-теги в поле даты и времени. Если введенное значение не соответствует ожидаемому формату, отобразите ошибку и остановите обработку здесь.

$orderdate = $conn->real_escape_string($orderdate);

Используйте функцию экранирования строки БД только с теми данными, которые вы используете для построения запроса SQL. Эта операция не имеет смысла для операций, которые вы выполняете ниже с $orderdate.
Вы должны использовать подготовленные SQL-запросы для защиты приложения от внедрения SQL-кода, а не произвольного экранирования и построения запроса путем объединения строк.

$completiondate = date("m/d/Y");
$completiondate = date( "Y-m-d", strtotime($completiondate) );

date("m/d/Y") форматирует текущую дату и время в виде строки, используя формат m/d/Y.
strtotime($completionDate) делает обратное; он пытается проанализировать только что сгенерированную строку обратно в текущее время и возвращает число (количество секунд с 1970-01-01 00:00:00 UTC).

Затем date("Y-m-d", ...) создает другое текстовое представление только что проанализированной даты и времени. В общем, эти две строки делают так же, как $completiondate = date('Y-m-d');

$duration = $orderdate->diff($completiondate);

Это совершенно неправильно. $orderdate - это строка, в ней нет метода diff() (в ней нет метода, строка не является объектом в PHP).
Более того, DateTime::diff() ожидает еще один DateTime объект в качестве аргумента.

$duration->format('%R%a days');

Эта строка правильная (но она работает только в том случае, если $duration создан правильно, а сейчас этого не происходит).

Как должен выглядеть ваш код.

Поскольку это 2019, а не 2009, вы должны держаться подальше от старых функций даты и времени (они не знают, как обращаться с часовыми поясами, и они в любом случае неудобны) и использовать только DateTime класс (и его друзья ).

Код, который вам нужен, может выглядеть так:

// The timezone
$tz = new DateTimeZone('America/Chicago');

// Parse the input value, get a DateTime object back, or FALSE on error
$orderDate = date_create($_POST['pickupship-date'], $tz);
if (! $orderDate) {
  // The input value does not look like a valid date
  // Display an error, stop the processing here
  // ...
}

// Get the current date & time
$processingDate = new DateTime('now', $tz);

// Compute the difference
$duration = $orderdate->diff($completionDate);

// Format the difference for display
$duration->format('%R%a days')

Примечания

Звонок:

date_create($_POST['pickupship-date'], $tz)

почти так же, как:

new DateTime($_POST['pickupship-date'], $tz)

, но возвращает FALSE, если введенное значение недопустимо.
Нет способа получить значение, которое сигнализирует о неверном вводе, используя new.

Код выглядит чище, когда вы используете new DateTime(), но он работает как положено, только если вы уже проверили (другими способами) значение, которое вы ему передали. Если входная строка не является допустимой датой, новый объект DateTime инициализируется с 1970-01-01 00:00:00 или другим значением, которое вы не хотите / не ожидаете.

date_create() предотвращает это, возвращая FALSE, когда входная строка не является допустимой датой и временем.

Оба способа принимают несколько форматов для аргумента, включая частичное представление даты и времени и почти любое текстовое описание даты и времени на английском языке (например, 'yesterday noon').

Если вы хотите использовать фиксированный формат для входной строки, вы можете использовать DateTime::createFromFormat().
Он использует дополнительный параметр (первый), который является строкой формата (в формате, принятом date() или DateTime::format()) и возвращает объект DateTime, только если строка ввода соответствует указанному формату (и FALSE в противном случае).

0 голосов
/ 11 января 2019

Сделайте свою жизнь проще и используйте класс DateTime, который многое сделает для вас. важно: функция date () возвращает строку, а не какой-либо объект Date. Так

$orderdate = date( "Y-m-d", strtotime($orderdate) );
$orderdate->diff

Различаются строки, а не то, что вам нужно.

<?php
$_POST['pickupship-date'] = "2018-03-04";
$replaceNewLines = str_replace(array("\n", "\r"), ' ', $_POST['pickupship-date']);
//not necessary when you use prepared statements. Always use prepared statements!!!
// $replaceQuotes = str_replace(array('"', "'"), "", $replaceNewLines);
$orderdate = strip_tags($replaceNewLines);
//always use prepared statements, then you don't have to do this
//$orderdate = $conn->real_escape_string($orderdate);
// strtotime not necessary $orderdate = date( "Y-m-d ", strtotime($orderdate) );
$orderdate = new DateTime($orderdate);
echo '$orderdate :';
var_dump($orderdate->format("Y-m-d"));

date_default_timezone_set('America/Chicago');
$completiondate = new DateTime();
echo '$completiondate :';
var_dump( $completiondate->format("Y-m-d"));

$duration = $orderdate->diff($completiondate);
echo '$duration :';
var_dump($duration->format('%d days'));
0 голосов
/ 11 января 2019

Это код, который работал на меня:

$orderdate = strip_tags(str_replace(array('"', "'"), "", str_replace(array("\n", "\r"), ' ', $_POST['pickupship-date'])));
$orderdate = $conn->real_escape_string($orderdate);

$completiondate = new DateTime('now', new DateTimeZone('America/Chicago'));
$completiondate = $completiondate->format('Y-m-d');

$orderdate = new DateTime($orderdate);
$completiondate = new DateTime($completiondate);
$duration = $orderdate->diff($completiondate);
$duration = $duration->format('%R%a days');
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...