Lavorare Con Le Date E I18N

Ho due campi mysql DATE.

Sto usando un CJuiDatePicker nella _form




<?php 			

                        $this->widget('zii.widgets.jui.CJuiDatePicker', array(

                            'name'=>'Listing[validFromDate]',

                            'value'=>$model->validFromDate,

                            'language'=> Yii::app()->language,

                            'options'=>array(

                                'showAnim'=>'fold',

                                

                            ),

                            'htmlOptions'=>array(

                                'class' => 'mws-textinput',

                            ),

                        ));				

                        ?>



Fino qui tutto bene, anche la questione della lingua.

L’unica scocciatura è che usa il formato data con 4 cifre per l’anno, che è ok, se non che sto usando un validator fatto così:




	public function rules()

	{

	    

	    $localizedTimeFormat = Yii::app()->getLocale()->getDateFormat('short');

	    $localizedTimeFormat .= "yy";   // 4 cifre per l'anno

	    

		// NOTE: you should only define rules for those attributes that

		// will receive user inputs.

		return array(

			....

		    array('validFromDate, validToDate', 'date', 

                          'format' => $localizedTimeFormat, .

                          'message' => Yii::t('general',"dateFormatError")." '$localizedTimeFormat'" ),

		     ......   

		);

	}




Come avete visto ho fatto la schifezza di appendere due ‘yy’ al formato short. Altro non mi è venuto in mente, comunque per le 5-6 lingue che ci servono attualmente, va tutto bene, la validazione resiste.

Ora però mi trovo che salvando il record… beh… mi salva (in qualsiasi lingua) … ‘0000-00-00’ segno che ovviamente la stringa in formato localizzato non coincide con quella di mysql.

Come e dove devo intervenire per far salvare il dato correttamente ?

Prova modificandola così:




	$localizedTimeFormat = str_replace("yy", "yyyy", Yii::app()->locale->getDateFormat('short'));



… se non altro lavora bene anche quando l’anno non è a destra

Le date vanno convertite alla beforeSave, qualcosa tipo:


protected function beforeSave()

{

  $this->date=date('Y-m-d H:i:s', strtotime('localizedFormat' $this->date));

  return parent::beforeSave();

}

Riassunto:

Helper:




 public static function localizedDateFormat() {

        return str_replace('yy','yyyy', Yii::app()->getLocale()->getDateFormat('short') );

    }



Model rules:




array('validFromDate, validToDate', 'date', 

		          'format' => MyHelper::localizedDateFormat(), 

		          'message' => Yii::t('general',"dateFormatError"). " " . MyHelper::localizedDateFormat() ),



Model before save:




// Conversione dal formato data localizzata per l'utente verso il formato mysql

    protected function beforeSave()

    {

      $this->validFromDate=date('Y-m-d', strtotime( MyHelper::localizedDateFormat() , $this->validFromDate ) );

      $this->validToDate=date('Y-m-d', strtotime( MyHelper::localizedDateFormat() , $this->validToDate ) );

      return parent::beforeSave();

   }



Le date però mi vengono salvate come 1970-01-01, indifferentemente da lingua e dalla data in se (la validazione però sembra corretta, ho provato ad inserire date strane per il formato atteso e vengono rifiutate)

Hai un qualche errore nelle conversioni, fai delle echo per i valori intermedi.

Soluzione: un helper:




    // Converte una data dal formato locale al formato mysql 'date'

    // da usare nei beforeSave();

    public static function convertLocalizedDateToMySql($dateString) 

    {

        $df = CprHelper::localizedDateFormat();

        $search = array ('/d+/','/M+/','/y+/');

        $replace = array ('d','m','Y');

        $phpDf = preg_replace($search,$replace,$df);

        $objDate = DateTime::createFromFormat($phpDf,$dateString);

        return $objDate->format('Y-m-d');

    }



Ora il problema opposto: quando vado in modifica, la data mi viene presentata nel formato mysql, ma io la voglio nel formato localizzato

invece del beforeSave, di quale metodo devo fare l’override ?

Davvero Yii non ha un modo per gestire queste situazioni ?

Ho identificato l’afterFind come metodo giusto. Sto provando




      $from = $this->validFromDate;

      $to = $this->validToDate;

      Yii::log($from, CLogger::LEVEL_INFO, "afterFind" );

      Yii::log($to, CLogger::LEVEL_INFO, "afterFind" );

      $timeFrom = strtotime($from);

      $timeTo = strtotime($to);

      $stringFrom = Yii::app()->dateFormatter->formatDateTime($timeFrom, 'short' ,'null');

      Yii::log($stringFrom, CLogger::LEVEL_INFO, "afterFind" );

      $stringTo = Yii::app()->dateFormatter->formatDateTime($timeTo, 'short' ,'null');

      Yii::log($stringTo, CLogger::LEVEL_INFO, "afterFind" );

      $this->validFromDate = $stringFrom;

      $this->validToDate = $stringTo;



Ottengo quasi quello che voglio… a me la data serve con l’anno a 4 cifre… in italiano, e tutto nasce dal fatto che quel CJuiDatePicker usa l’anno a 4 cifre fregandosene della reale localizzazione … com’è possibile !!!

… sono nervoso nervoso nervoso … :angry:

Addirittura … ora ho scoperto che tra le options è possibile settare il formato…




'dateFormat' => Yii::app()->getLocale()->getDateFormat('short'),




…ebbene … il formato short viene inteso da CJuiDatePicker come ‘02/Ottobre/2012’ … ma vi sembra possibile ???

Devi settare il formato anche le CJuiDatePicker, tieni presente che usa uno standard diverso per le date.

eh già … è quello il problema, usando nelle options del componente come date_format il formato short loale, lui usa due cifre per l’anno.

Avendo a che fare con almeno 5 lingue, come posso fare per affrontare la questione del triangolo tra

Yii | JuiDatePicker | MySql

?

Come è possibile che Yii manchi di questa cosa nel 2012 !??!

Questa cosa, e il fatto di dover leggere i parametri da $_GET e da $_POST a manina mi hanno deluso parecchio… Speriamo in una 1.2 … oppure che tra un paio di anni quando sarà pronta la 2 tutto questo sarà solo un lontano ricordo…

EDIT: non avevo visto getParam() :unsure:

Il problema delle date si risolve in questa maniera:

  1. scrivi la before save per convertire da locale a database

  2. scrivi la afterFind per convertire da database a locale

  3. imposti il datepicker per avere lo stesso formato di yii.

Il datepicker usa uno standard per le date piu’ povero, per questo Yii non si puo’ limitare allo standard scelto da jquery UI.

Quello che devi fare e’ prepararti delle funzioni per avere i formati che ti servono, per esempio puoi estendere il PFormatter:




class PFormatter extends CFormatter

{

	public $dateFormat = 'd.m.Y';

	public $parserDateFormat = 'dd.MM.yyyy';

	

	

	public $datetimeFormat = 'd.m.Y H:i';

	public $parserDatetimeFormat = 'dd.MM.yyyy HH:mm';

	

	public function __construct()

	{

		switch (Yii::app()->language)  {

			case 'en':

			$this->dateFormat = 'd/m/Y';

			$this->parserDateFormat = 'dd/MM/yyyy';

			

			$this->datetimeFormat = 'd/m/Y H:i';

			$this->parserDatetimeFormat = 'dd/MM/yyyy HH:mm';

			break;

			case 'de':

			$this->dateFormat = 'd.m.Y';

			$this->parserDateFormat = 'dd.MM.yyyy';

			

			$this->datetimeFormat = 'd.m.Y H:i';

			$this->parserDatetimeFormat = 'dd.MM.yyyy HH:mm';

			break;

		}

	}



Nella beforeSave e afterFind usi:


$this->date=date(ii::app()->formatter->dateFormat, CDateTimeParser::parse($this->date, Yii::app()->formatter->parserDateFormat);



La gestione delle date e’ un po’ un nervo scoperto di Yii, cerca di prenderla con filosofia.

A propostio dei post, io non li “prendo mai a manina”, nel controller li assegno in blocco a qualche model ed e’ poi il model a sbrigarsi la faccenda.

posto che proverò a implementare le date come mi suggerisci e poi riferirò ,

apro una parentesi sui POST. Ho provato in una form ad inserire una $form->dropdown usando come nome una variabile pubblica del model, ma salvando la form in fase di update, in caso di errori, comunque il campo non viene ripopolato ed ho dovuto prendere $_POST[NomeOggetto][NomeCampo] ed assegnarlo a $model->NomeCampo.

Approfitto di questo post per completarlo, spiegando cosa devo fare.

in una view devo mostrare un campo datetime in italiano:




<?php echo CHtml::encode($model->DATA_CREAZIONE); ?>



La classe postata da zaccaria sembra fare proprio quello che mi serve,

tuttavia non mi è chiaro come usarla.

Devo scrivere qualcosa in /config/main.php o cosa?