Как сделать strtotime разбора дат в австралийском (то есть в Великобритании) формате: дд / мм / гггг? - PullRequest
11 голосов
/ 15 марта 2010

Я не могу поверить, я никогда не сталкивался с этим раньше.

По сути, я анализирую текст в созданных человеком текстовых документах, и одно из полей, которые мне нужно проанализировать, - это дата и время. Поскольку я нахожусь в Австралии, даты отформатированы как dd/mm/yyyy, но strtotime хочет только проанализировать их как дату в США. Кроме того, взорвать по / не получится, потому что, как я уже говорил, эти документы напечатаны вручную, а некоторые из них имеют вид d M yy.

Я пробовал несколько комбинаций setlocale, но независимо от того, что я пробую, язык всегда установлен на американский английский.

Я вполне уверен, что ключом здесь является setlocale, но я не могу найти правильный код. Пробовал эти:

  • аи
  • аи-ен
  • en_AU
  • Австралия
  • AUS

Что-нибудь еще, что я могу попробовать?

Для ясности: я работаю на IIS с коробкой Windows.

Большое спасибо:)

Иэн

Пример: * 1 034 *

$mydatetime = strtotime("9/02/10 2.00PM");
echo date('j F Y H:i', $mydatetime);

Производит

2 September 2010 14:00

Я хочу, чтобы это произвело:

9 February 2010 14:00

Мое решение

Я ставлю галочку на один из ответов здесь, так как это гораздо более легкое для чтения решение, но вот что я придумала:

$DateTime = "9/02/10 2.00PM";
$USDateTime = preg_replace('%([0-3]?[0-9]{1})\s*?[\./ ]\s*?((?:1[0-2])|0?[0-9])\s*?[./ ]\s*?(\d{4}|\d{2})%', '${2}/${1}/${3}', $DateTime);  
echo date('j F Y H:i',strtotime($USDateTime));

Поскольку я не могу полагаться на то, что пользователи согласуются с вводом даты, я сделал свое регулярное выражение немного более сложным:

  • 0 или 1 цифра от 0 до 3
  • 1 цифра от 0 до 9 - да, это будет соответствовать 37 как действительная дата, но я думаю, что регулярное выражение уже достаточно большое!
  • Может быть пробел
  • Символ-разделитель («.», «/» Или «»)
  • Может быть пробел
  • Либо:
    • Число от 10 до 12 ИЛИ
    • Число от 1 до 9 с необязательным начальным 0
  • Может быть пробел
  • Символ-разделитель («.», «/» Или «»)
  • Может быть пробел
  • Либо:
    • Номер длиной 2 цифры ИЛИ
    • Номер длиной 4 цифры

Надеюсь, это будет соответствовать большинству стилей написания дат ...

Ответы [ 6 ]

19 голосов
/ 11 апреля 2011

Существует быстрое исправление, которое, похоже, заставляет PHP strtotime использовать британский формат даты. То есть: заменить все '/' во входящей строке на '-'.

Пример:

date('Y-m-d', strtotime('01/04/2011'));

Будет производить: 2011-01-04

date('Y-m-d', strtotime('01-04-2011'));

будет производить: 2011-04-01

Вы можете использовать str_replace для достижения этой цели.

Пример:

str_replace('/', '-', '01/04/2011');

EDIT:

Как указано в комментариях, это работает, потому что PHP интерпретирует косые черты как американские, а точки / тире как европейские.

Я широко использовал этот трюк и у меня до сих пор не было проблем.

Если у кого-либо есть веские причины не использовать это, пожалуйста, прокомментируйте.

3 голосов
/ 15 марта 2010

Проблема в том, что strtotime не принимает аргумент format . А как насчет strptime?

1 голос
/ 15 марта 2010

Ах, старая проблема, с которой сталкиваются мы, счастливчики, австралийцы.

То, что я делал в прошлом, примерно так

public static function getTime($str) { // 3/12/2008

       preg_match_all('/^(\d{1,2})\/(\d{1,2})\/(\d{4})$/', $str, $matches);

       return (isset($matches[0][0])) ? strtotime($matches[3][0] . '-' . $matches[2][0] . '-' . $matches[1][0]) : NULL;

    }

Хотя это зависит от даты в этом формате dd/mm/yyyy.

Вероятно, вы можете использовать другое регулярное выражение для преобразования из d M yy или использовать модифицированное. Я не знаю, будет ли это правильно, но это может быть началом:

/^(\d{1,2})(?:\/|\s)(\d{1,2})(?:\/|\s)(\d{2,4})$/

1 голос
/ 15 марта 2010

setlocale () отстой точно по той причине, которую вы описываете: вы никогда не знаете, что получите.Лучше всего обрабатывать строку вручную.

Zend Framework Zend_Date - одна из альтернатив, обещающая более точную и последовательную обработку даты.У меня пока нет опыта работы с ним, я только начинаю с ним работать, но пока мне это нравится.

0 голосов
/ 09 февраля 2018

Для будущих читателей попробуйте следующее для анализа дат из ненадежного пользовательского ввода, для которого strptime() слишком жестко. Он выводит строки даты ISO, которые вы можете передать new Date(), strtotime() и т. Д., Либо false для недопустимых дат, либо null, если ввод невозможен. Вы должны адаптировать его к времени обработки. Также допускается ввод двухзначного года и даты ISO.

function parseUserDate($input, $allow_zero = false) {
    if (!is_string($input)) {
        return $input === null ? null : false;
    }
    $input = preg_split('/\\D+/', $input, null, PREG_SPLIT_NO_EMPTY);
    if (!$input) {
        return null;# no date
    }
    if (count($input) == 3) {
        list($od, , $oy) = $input;
        if (strlen($od) > 2 && strlen($oy) < 3) {# assume ISO
            $oy = $od;
            $input = array_reverse($input);
        }
        $intify = function($dig) {
            return (int) ltrim($dig, '0');# prevent octals
        };
        list($d, $m, $y) = array_map($intify, $input);
        if (strlen($oy) < 3) {
            $current_year = date('Y');
            $current_year_2 = $intify(substr($current_year, -2));
            $diff = $y - $current_year_2;
            if ($diff > 50) {
                $diff -= 100;
            }
            elseif ($diff < -50) {
                $diff += 100;
            }
            $y = $diff + $current_year;
        }
        if (
            ($allow_zero && $d == 0 && $m == 0 && $y == 0)
            || checkdate($m, $d, $y)# murrican function
        ) {
            return sprintf('%04d-%02d-%02d', $y, $m, $d);
        }
    }
    return false;# invalid date
}
0 голосов
/ 24 июля 2015
$date = date_create_from_format('d/m/Y', $date_string);
$unix_timestamp = $date->getTimestamp();

или

$date = DateTime::createFromFormat('d/m/Y', $date_string);
$unix_timestamp = $date->getTimestamp();
...