За последние 24 часа нас посетили 18366 программистов и 1628 роботов. Сейчас ищут 1849 программистов ...

Преобразование даты из dd.mm.[yy]yy в yyyy-mm-dd

Тема в разделе "Регулярные выражения", создана пользователем IVB, 1 ноя 2010.

  1. IVB

    IVB Активный пользователь

    С нами с:
    1 ноя 2010
    Сообщения:
    11
    Симпатии:
    0
    Адрес:
    Северодонецк, Украина
    Вроде бы - ничего сложного. Но получается только вот так:

    PHP:
    1.  
    2. function date2date ( $date )
    3. {
    4.     $p2 = '~^(0?[1-9]|[12]\d|3[01])[-./ ](0?[1-9]|1[012])[-./ ](\d{2})$~';
    5.     $p4 = '~^(0?[1-9]|[12]\d|3[01])[-./ ](0?[1-9]|1[012])[-./ ]((?:19|20)\d{2})$~';
    6.     if ( preg_match ( $p2, $date ) )
    7.     {
    8.         return preg_replace ( $p2, '20$3-$2-$1', $date );
    9.     }
    10.     elseif ( preg_match ( $p4, $date ) )
    11.     {
    12.         return preg_replace ( $p4, '$3-$2-$1', $date );
    13.     }
    14.     else
    15.         return FALSE;
    16. }
    17.  
    Можно ли этот код упростить - избавиться от двух preg_replace?
     
  2. Padaboo

    Padaboo Старожил
    Команда форума Модератор

    С нами с:
    26 окт 2009
    Сообщения:
    5.242
    Симпатии:
    1
    в качестве аватарки разрешены только личные фото, удалите или замените
     
  3. tommyangelo

    tommyangelo Старожил

    С нами с:
    6 дек 2009
    Сообщения:
    2.549
    Симпатии:
    0
    Адрес:
    Мариуполь
    Писец


    $date = date('Y-m-d', strtotime($date));
     
  4. IVB

    IVB Активный пользователь

    С нами с:
    1 ноя 2010
    Сообщения:
    11
    Симпатии:
    0
    Адрес:
    Северодонецк, Украина
    Не умничай, а сначала сам попробуй.
    PHP:
    1. echo date ('Y-m-d', strtotime ( '01.02.03' ) ) . "\n";
    Правда, очень неожиданный результат?
     
  5. tommyangelo

    tommyangelo Старожил

    С нами с:
    6 дек 2009
    Сообщения:
    2.549
    Симпатии:
    0
    Адрес:
    Мариуполь
    При решении задачи у тебя неизвестен формат года?
     
  6. Apple

    Apple Активный пользователь

    С нами с:
    13 янв 2007
    Сообщения:
    4.984
    Симпатии:
    2
    Тут больше подходит для решения функция mktime с нормализацией формата года.
     
  7. IVB

    IVB Активный пользователь

    С нами с:
    1 ноя 2010
    Сообщения:
    11
    Симпатии:
    0
    Адрес:
    Северодонецк, Украина
    Да, это видно из темы поста и из кода. Год вводится с формы и может быть как двузначным, так и 4-хзначным.

    Проверить формат можно одним preg_match, но вот как сделать замену одним preg_replace - не могу придумать.
     
  8. Apple

    Apple Активный пользователь

    С нами с:
    13 янв 2007
    Сообщения:
    4.984
    Симпатии:
    2
    preg_replace_callback, если год 00+ заменяется на 20$1 и 10+ на 19$1
     
  9. IVB

    IVB Активный пользователь

    С нами с:
    1 ноя 2010
    Сообщения:
    11
    Симпатии:
    0
    Адрес:
    Северодонецк, Украина
    Вполне возможно. Нужно будет померить, что будет быстрее выполняться.
     
  10. tommyangelo

    tommyangelo Старожил

    С нами с:
    6 дек 2009
    Сообщения:
    2.549
    Симпатии:
    0
    Адрес:
    Мариуполь
    При твоем нынешнем решении

    Код (Text):
    1. echo date2date('01.02.84');die();
    тоже не самое очевидное поведение ;-)
     
  11. IVB

    IVB Активный пользователь

    С нами с:
    1 ноя 2010
    Сообщения:
    11
    Симпатии:
    0
    Адрес:
    Северодонецк, Украина
    Не, здесь все правильно. Если столетие не указано явно - значит, 20ХХ.
     
  12. tommyangelo

    tommyangelo Старожил

    С нами с:
    6 дек 2009
    Сообщения:
    2.549
    Симпатии:
    0
    Адрес:
    Мариуполь
    ну, я бы тогда в своем варианте привел тоже привел к формату 01.02.2003 ;-)
    Короче говоря, всё от ситуации зависит. Имхо - излишнее юзабилити тоже вредно
    Если дата именно важная - я пользователю вводить её не дам, рассчитаю как-нибудь. А если это ему больше надо - типа его дня рождения - суну Дейтпикер. Если не так ввёл - его проблемы, будет 1970-01-01 или текущая )))) Сам виноват)))
     
  13. IVB

    IVB Активный пользователь

    С нами с:
    1 ноя 2010
    Сообщения:
    11
    Симпатии:
    0
    Адрес:
    Северодонецк, Украина
    Я не поленился и сравнил все три предложенных варианта по скорости.

    1-й вариант - мой (2 preg_match и 2 preg_replace). Процедура изменена по сравнению с той, которая приводилась в 1-м посте. Я возвращаю не текстовую дату в формате yyyy-mm-dd, а сразу Unix Timestamp (т.к. в дальнейшем мне нужен именно timestamp).
    PHP:
    1.  
    2. function date2date_v1 ( $date )
    3. {
    4.     $p2 = '~^(0?[1-9]|[12]\d|3[01])[-./ ](0?[1-9]|1[012])[-./ ](\d{2})$~';
    5.     $p4 = '~^(0?[1-9]|[12]\d|3[01])[-./ ](0?[1-9]|1[012])[-./ ]((?:19|20)\d{2})$~';
    6.     if ( preg_match ( $p2, $date ) )
    7.     {
    8.         $date = preg_replace ( $p2, '20$3-$2-$1', $date );
    9.     }
    10.     elseif ( preg_match ( $p4, $date ) )
    11.     {
    12.         $date = preg_replace ( $p4, '$3-$2-$1', $date );
    13.     }
    14.     else
    15.         return FALSE;
    16.     return strtotime ( $date );
    17. }
    18.  
    Второй вариант - отказаться от preg_replace и использовать mktime:
    PHP:
    1.  
    2. function date2date_v2 ( $date )
    3. {
    4.     $p = '~^(0?[1-9]|[12]\d|3[01])[-./ ](0?[1-9]|1[012])[-./ ]((19|20)?\d{2})$~';
    5.     if ( preg_match ( $p, $date, $m ) )
    6.         return mktime ( 0, 0, 0, $m[2], $m[1], isset ( $m[4] ) ? $m[3] : 2000 + $m[3] );
    7.     else
    8.         return FALSE;
    9. }
    10.  
    И третий вариант - вместо preg_replace использовать preg_replace_callback:
    PHP:
    1.  
    2. function date2date_v3 ( $date )
    3. {
    4.     $p = '~^(0?[1-9]|[12]\d|3[01])[-./ ](0?[1-9]|1[012])[-./ ]((19|20)?\d{2})$~';
    5.     if ( preg_match ( $p, $date ) )
    6.         return strtotime ( preg_replace_callback ( $p, create_function ( '$m', 'return ( isset ( $m[4] ) ? $m[3] : 2000 + $m[3] ) . "-" . $m[2] . "-" . $m[1];' ), $date ) );
    7.     else
    8.         return FALSE;
    9. }
    10.  
    Дальше я сделал коротенький тестик. Каздый вариант функции вызывался по 10000 раз с одним вариантом даты (2 цифры года) и по 10000 раз с другим вариантом даты (4 цифры года). Вот результаты (время в милисекундах):
    Код (Text):
    1.  
    2. 01.02.03, v1: 0.33652591705322
    3. 01.02.03, v2: 0.30608820915222
    4. 01.02.03, v3: 0.77662396430969
    5. 01.02.2003, v1: 0.35748696327209
    6. 01.02.2003, v2: 0.31534099578857
    7. 01.02.2003, v3: 0.79184579849243
    Победил вариант с mktime. Тему можно закрывать. Всем откликнувшимся - спасибо.