Best practice date localization in gridview + filter?

What is a best practice regarding the locale of the user and place to do the date conversion when using a gridview with filter ?

Consider this scenario:

  1. Developer created default controllers and views with Gii
  2. A user in the admin view enters a locale date in the filter field of a date column, example “31-12-2020”
  3. The gridview refreshes, all dates shown are localized.

My ‘best’ solution, with the lowest impact I think, is:

  • only convert the entered date within the search() function of the AR class,
  • format the column in the gridview as date or datetime

The somewhat downside of this is the model in the MVC pattern that handles the user input, that feels as it’s not the right location to do that. But any other location I tried involves multiple transformations wich can become very tricky in a growing application.

A complete code snippet showing my solution, and as input for ‘the best practice’ on this problem:
I only show the code here that’s not ‘default’ gii generated code.

Gridview:

$this->widget('CGridView',array(
	'id'=>'service-grid',
	'dataProvider'=>$model->search(),
	'enablePagination' => false,
	'filter'=>$model,
	'columns'=>array(
		array
		(
			'class'=>'bootstrap.widgets.BsButtonColumn',
			'template'=>'{view}',
		),
		'id',
		'name',
		'is_active',
		'sys_date_created:datetime',
		'sys_date_modified:datetime',
	),
));

Model, within the function search():

$sys_date_created = '';
		$sys_date_modified = '';
		
		// convert user entered date time to db format when searching
		if($this->scenario=='search')
		{
			if($this->sys_date_created)
				$sys_date_created = Yii::app()->format->toDatabaseDateTime(trim($this->sys_date_created));
			
			if($this->sys_date_modified)
				$sys_date_modified = Yii::app()->format->toDatabaseDateTime(trim($this->sys_date_modified));
		}
$criteria->compare("sys_date_created",$sys_date_created,true);
		$criteria->compare("sys_date_modified",$sys_date_modified, true);

Functions from my own Formatter class:

public function formatOnlySearchOperator($value)
	{
		// This snippet is taken from CDbCriteria->compare()
		if(preg_match('/^(?:\s*(<>|<=|>=|<|>|=))?(.*)$/',$value,$matches))
		{
			$value=$matches[2];
			$op=$matches[1];
		}
		else
			$op='';
		
		return $op;
	}

public function formatWithoutSearchOperator($value)
	{
		// This snippet is taken from CDbCriteria->compare()
		if(preg_match('/^(?:\s*(<>|<=|>=|<|>|=))?(.*)$/',$value,$matches))
		{
			$value=$matches[2];
			$op=$matches[1];
		}
		else
			$op='';
		
		return $value;
	}

/*
	* Format a localized datetime back to a database datetime (Y-m-d H:i:s).
	* If a comparison operator is given, it is preserved. So strip it if you need to save the date in the database.
	* If no time given, it's also not returned (MySQL database appends '00:00:00' as time to it upon saving).
	* With this function the following localized datetimes just work like the stock datetime filters:
	* 	- "30-12-2018" becomes "2018-12-30"
	* 	- "30-12-2018 " becomes "1970-01-01" (note the extra space in input)
	* 	- ">30-12-2018" becomes ">2018-12-30"
	* 	- "30-12-2018 23:59:49" becomes "2018-12-30 23:59:49"
	* 	- ">=30-12-2018 23:59:49" becomes ">=2018-12-30 23:59:49"
	* 
	* For save() and afterFind() integration see:
	* https://github.com/YetOpen/i18n-datetime-behavior
	*/
	public function formatToDatabaseDatetime($value)
	{
		// get the comparison operator from the string:
		$comparator = $this->onlySearchOperator($value);
		
		// get the datetime without the comparison operator:
		$datetime = $this->withoutSearchOperator($value);
		
		// parse the given datetime according to the locale format to a timestamp
		$datetime_parsed = CDateTimeParser::parse(
			$datetime, 
			strtr(
				Yii::app()->locale->datetimeFormat, 
				array(
					"{0}" => Yii::app()->locale->getTimeFormat(Yii::app()->format->timeFormat),
					"{1}" => Yii::app()->locale->getDateFormat(Yii::app()->format->dateFormat)
				)
			)
		);
		
		// if its not a valid date AND time, check if it can be parsed to a date only:
		if($datetime_parsed === false)
		{
			$date_parsed = CDateTimeParser::parse(
				$datetime, 
				Yii::app()->locale->getDateFormat(Yii::app()->format->dateFormat)
			);
		}
		
		// If no time part given, also output only the date
		if($datetime_parsed===false)
		{
			$transformed = date(
				'Y-m-d', 
				$date_parsed
			);
		}
		else
		{
			$transformed = date(
				'Y-m-d H:i:s', 
				$datetime_parsed
			);
		}
	
		return 	$comparator . $transformed;
	}

I would appreciate any feedback/ideas/comments !