0

I am working on a search field. User can write anything on search bar. If I search by typing only October, I need only October. If search is October 2020, it should return month & year.

How can I validate if the string used is only month or year or day ?

        $dateValue = strtotime($searchString);

        $year = date("Y", $dateValue);
        $month = date("m", $dateValue);
        $day = date("d", $dateValue);
nas
  • 2,289
  • 5
  • 32
  • 67
  • Will months always be verbose? – brombeer Nov 10 '20 at 08:50
  • 1
    You could use a rather simple regular expression, that checks for one or more characters from a-z/A-Z first, then demands a space (or arbitrary whitespace), and then four digits. But what if the type in `NotAMonthName 1234`, do you need to recognize that as “something else” then? And is the search expression _only_ allowed to contain this format, or can there be other stuff before/after? Rather under-defined question so far. – CBroe Nov 10 '20 at 08:51
  • It needs to be valid date. It can be only 2020 or November or can be `Nov 2020` – nas Nov 10 '20 at 08:53
  • 1
    Explode or split it at the white space in between, if that gives you only one result, validate whether it is a valid year, and if you get two, also check whether the first part matches your list of month names / month name abbreviations. (And if you get more than two parts, probably reject it right away.) – CBroe Nov 10 '20 at 08:57
  • 1
    Also, this might be one of those cases, where using two select fields that provide only valid selections to begin with, might perhaps make more sense, than allowing free-form text input in the first place …? – CBroe Nov 10 '20 at 08:59
  • Thanks @CBroe that gives me some idea.. – nas Nov 10 '20 at 09:01
  • no truer words were said, i've never seen a free text for a date search field. but anyway, you could let `DateTime` classes parse and decide. https://www.tehplayground.com/rd11vmboFBIUmDcs – Kevin Nov 10 '20 at 09:03
  • Well thats the requirement I got. – nas Nov 10 '20 at 09:08

3 Answers3

1

See this example of how strtotime might be useful to you. Provided its flexibility results in a good enough UX for your purpose. If you want to be able to accept typos and abbreviations like the one strtotime() didn't understand (see comments), then you will need something smarter.

<?php

// 1 November 2020
echo (new DateTime)->setTimestamp(strtotime('November 2020'))->format('j F Y') . "\n";

// 10 November 2020
echo (new DateTime)->setTimestamp(strtotime('November'))->format('j F Y') . "\n";

// 5 November 1999
echo (new DateTime)->setTimestamp(strtotime('5 November 1999'))->format('j F Y') . "\n";

// 5 November 2020
echo (new DateTime)->setTimestamp(strtotime('November 5'))->format('j F Y') . "\n";

// 5 November 2020
echo (new DateTime)->setTimestamp(strtotime('November 5th'))->format('j F Y') . "\n";

// 1 January 1970 - CAN'T PARSE THIS
echo (new DateTime)->setTimestamp(strtotime('2nd of jan'))->format('j F Y') . "\n";

// 2 January 1985
echo (new DateTime)->setTimestamp(strtotime('jan 2nd 1985'))->format('j F Y') . "\n";
Ro Achterberg
  • 2,504
  • 2
  • 17
  • 17
1

You could use checkdate. For example

$arr  = explode('/', $searchString);
if (checkdate($arr[0], $arr[1], $arr[2])) {
    // valid date ...
}

Duplicate ?

a55
  • 376
  • 3
  • 13
1

This checking is working but not perfect

  var_dump(searchDate("October")); //string(7) "October"
  var_dump(searchDate("20 2021 Jan")); //string(15) "January 20 2021"
  var_dump(searchDate("February 2020 2")); //string(16) "February 02 2020"
  var_dump(searchDate("October 20")); //string(10) "October 20"
  var_dump(searchDate("DeC 2020")); //string(13) "December 2020"
  var_dump(searchDate("2020 Sept ")); //string(14) "September 2020"
  var_dump(searchDate("2020 Nov 1")); //string(16) "November 01 2020"
  var_dump(searchDate("2020 Apr")); //string(10) "April 2020"
  var_dump(searchDate("jUnE 12,2020")); //string(10) "June 12 2020"
  var_dump(searchDate("2020 March 12")); //string(13) "March 12 2020"
  var_dump(searchDate("2020")); //string(5) "2020"
  var_dump(searchDate("12")); //string(3) "12"
  var_dump(searchDate("Jan 30 2020")); //string(15) "January 30 2020"
 
  function searchDate($search,$calendar = CAL_GREGORIAN) {

    $date = array();

    $months = [
      'January',
      'February',
      'March',
      'April',
      'May',
      'June',
      'July',
      'August',
      'September',
      'October',
      'November',
      'December'
    ];

    foreach($months as $month) {

      $alpha = preg_replace("/[^a-zA-Z]+/", "", $search);

      if(false !== stripos($month,$alpha)) {

        $date['month'] = $month;

      }

    }

    if(preg_match_all('!\d+!', $search, $matches)) {
      $date['numeric'] = $matches[0];
    }

    if(isset($date['numeric'])) {

      foreach($date['numeric'] as $d) {
        
        if(strlen($d) == 4) {
          
          if( false !== (strtotime($d) )) $date['year'] = $d;
          else $date['year'] = false;
          
        }
        
        if(strlen($d) <= 2 ) {

          if($d >= 1) {
            $date['day'] = $d < 10 ? "0{$d}" : $d;
          }

        }

      }

    unset($date['numeric']);

    }

    if(isset( $date['year'] ) && isset($date['month']) ) {
      $len = cal_days_in_month($calendar,date_parse($date['month'])['month'], $date['year']);

      if(isset($date['day']) && $date['day'] > $len) unset($date['day']);
    }

    $join = '';

    if(isset($date['month']))
      $join .= $date['month'];
    if(isset($date['day']))
      $join .= " {$date['day']}";
    if(isset($date['year']))
      $join .= " {$date['year']}";

    return trim($join);
  }
Jerson
  • 1,700
  • 2
  • 10
  • 14