added DateValidator::$timestampAttributeTimeZone

this also makes DateValidator completly functional for validating values that include time.

issue #5053
This commit is contained in:
Carsten Brandt
2015-05-02 23:46:32 +02:00
parent a366929645
commit 1c41c2bd58
3 changed files with 122 additions and 7 deletions

View File

@ -39,6 +39,7 @@ Yii Framework 2 Change Log
- Bug #5053: DateValidator is now more robust against different timezone settings (cebe)
- Enh #1468: Added ability to specify hints for model attributes via `attributeHints()` method (klimov-paul)
- Enh #3376: Added `yii\validators\EachValidator`, which allows validation of the array attributes (klimov-paul)
- Enh #5053: Added possibility to specify a format and time zone for the `timestampAttribute` of date validator making it fully usable for validating complete timestamps (cebe)
- Enh #6442: Improved error message on `FileHelper::createDirectory()` to include the path name of the directory (cebe)
- Enh #6895: Added `ignoreCategories` config option for message command to ignore categories specified (samdark)
- Enh #6975: Pressing arrows while focused in inputs of Active Form with `validateOnType` enabled no longer triggers validation (slinstj)
@ -232,7 +233,6 @@ Yii Framework 2 Change Log
- Bug #6717: Fixed issue with UrlManager not matching a route on url creation when it was prefixed with `/` and pattern was empty (cebe)
- Bug #6736: Removed `Content-Transfer-Encoding` from the list of default download headers (DaSourcerer)
- Enh #4502: Added alias support to URL route when calling `Url::toRoute()` and `Url::to()` (qiangxue, lynicidn)
- Enh #5053: Added possibility to specify a format for the `timestampAttribute` of date formatter (cebe)
- Enh #5194: `yii\console\controllers\AssetController` now handles bundle files from external resources properly (klimov-paul)
- Enh #6247: Logger and error handler are now using slightly less memory (stepanselyuk, samdark)
- Enh #6398: Added support for specifying dependent component in terms of a configuration array for classes such as `DbCache` (qiangxue)

View File

@ -37,6 +37,7 @@ class DateValidator extends Validator
* ```php
* 'MM/dd/yyyy' // date in ICU format
* 'php:m/d/Y' // the same date in PHP format
* 'MM/dd/yyyy HH:mm' // not only dates but also times can be validated
* ```
*/
public $format;
@ -63,6 +64,7 @@ class DateValidator extends Validator
* This can be the same attribute as the one being validated. If this is the case,
* the original value will be overwritten with the timestamp value after successful validation.
* @see timestampAttributeFormat
* @see timestampAttributeTimeZone
*/
public $timestampAttribute;
/**
@ -76,6 +78,18 @@ class DateValidator extends Validator
* @since 2.0.4
*/
public $timestampAttributeFormat;
/**
* @var string the timezone to use when populating the [[timestampAttribute]]. Defaults to `UTC`.
*
* This can be any value that may be passed to [date_default_timezone_set()](http://www.php.net/manual/en/function.date-default-timezone-set.php)
* e.g. `UTC`, `Europe/Berlin` or `America/Chicago`.
* Refer to the [php manual](http://www.php.net/manual/en/timezones.php) for available timezones.
*
* If [[timestampAttributeFormat]] is not set, this property will be ignored.
* @see timestampAttributeFormat
* @since 2.0.4
*/
public $timestampAttributeTimeZone = 'UTC';
/**
* @var array map of short format names to IntlDateFormatter constant values.
@ -184,14 +198,11 @@ class DateValidator extends Validator
if ($this->timestampAttributeFormat === null) {
return $parsedDate;
// } elseif ($hasTimeInfo) {
// $date = new DateTime();
// $date->setTimezone(new \DateTimeZone('UTC'));
// $date->setTimestamp($parsedDate);
// return $this->formatTimestamp($date, $this->timestampAttributeFormat);
} else {
$date = new DateTime();
$date->setTimezone(new \DateTimeZone('UTC'));
if (!$hasTimeInfo) {
$date->setTimezone(new \DateTimeZone('UTC'));
}
$date->setTimestamp($parsedDate);
return $this->formatTimestamp($date, $this->timestampAttributeFormat);
}
@ -233,6 +244,7 @@ class DateValidator extends Validator
} else {
$format = FormatConverter::convertDateIcuToPhp($format, 'date');
}
$timestamp->setTimezone(new \DateTimeZone($this->timestampAttributeTimeZone));
return $timestamp->format($format);
}
}

View File

@ -305,5 +305,108 @@ class DateValidatorTest extends TestCase
$this->assertFalse($model->hasErrors('attr_date'));
$this->assertFalse($model->hasErrors('attr_timestamp'));
$this->assertSame(1379082195, $model->attr_timestamp);
$val = new DateValidator(['format' => 'yyyy-MM-dd HH:mm:ss', 'timestampAttribute' => 'attr_timestamp', 'timestampAttributeFormat' => 'yyyy-MM-dd HH:mm:ss', 'timeZone' => 'UTC']);
$model = new FakedValidationModel;
$model->attr_date = '2013-09-13 14:23:15';
$model->attr_timestamp = true;
$val->validateAttribute($model, 'attr_date');
$this->assertFalse($model->hasErrors('attr_date'));
$this->assertFalse($model->hasErrors('attr_timestamp'));
$this->assertSame('2013-09-13 14:23:15', $model->attr_timestamp);
$val = new DateValidator(['format' => 'yyyy-MM-dd HH:mm:ss', 'timestampAttribute' => 'attr_timestamp', 'timestampAttributeFormat' => 'yyyy-MM-dd HH:mm:ss', 'timeZone' => 'Europe/Berlin']);
$model = new FakedValidationModel;
$model->attr_date = '2013-09-13 16:23:15';
$model->attr_timestamp = true;
$val->validateAttribute($model, 'attr_date');
$this->assertFalse($model->hasErrors('attr_date'));
$this->assertFalse($model->hasErrors('attr_timestamp'));
$this->assertSame('2013-09-13 14:23:15', $model->attr_timestamp);
$val = new DateValidator(['format' => 'yyyy-MM-dd HH:mm:ss', 'timestampAttribute' => 'attr_timestamp', 'timestampAttributeFormat' => 'php:Y-m-d H:i:s', 'timeZone' => 'UTC']);
$model = new FakedValidationModel;
$model->attr_date = '2013-09-13 14:23:15';
$model->attr_timestamp = true;
$val->validateAttribute($model, 'attr_date');
$this->assertFalse($model->hasErrors('attr_date'));
$this->assertFalse($model->hasErrors('attr_timestamp'));
$this->assertSame('2013-09-13 14:23:15', $model->attr_timestamp);
$val = new DateValidator(['format' => 'yyyy-MM-dd HH:mm:ss', 'timestampAttribute' => 'attr_timestamp', 'timestampAttributeFormat' => 'php:Y-m-d H:i:s', 'timeZone' => 'Europe/Berlin']);
$model = new FakedValidationModel;
$model->attr_date = '2013-09-13 16:23:15';
$model->attr_timestamp = true;
$val->validateAttribute($model, 'attr_date');
$this->assertFalse($model->hasErrors('attr_date'));
$this->assertFalse($model->hasErrors('attr_timestamp'));
$this->assertSame('2013-09-13 14:23:15', $model->attr_timestamp);
}
/**
* @dataProvider provideTimezones
*/
public function testIntlValidationWithTimeAndOutputTimeZone($timezone)
{
$this->testValidationWithTime($timezone);
}
/**
* @dataProvider provideTimezones
*/
public function testValidationWithTimeAndOutputTimeZone($timezone)
{
date_default_timezone_set($timezone);
$val = new DateValidator(['format' => 'yyyy-MM-dd HH:mm:ss', 'timestampAttribute' => 'attr_timestamp', 'timestampAttributeFormat' => 'yyyy-MM-dd HH:mm:ss', 'timestampAttributeTimeZone' => 'Europe/Berlin', 'timeZone' => 'UTC']);
$model = new FakedValidationModel;
$model->attr_date = '2013-09-13 14:23:15';
$model->attr_timestamp = true;
$val->validateAttribute($model, 'attr_date');
$this->assertFalse($model->hasErrors('attr_date'));
$this->assertFalse($model->hasErrors('attr_timestamp'));
$this->assertSame('2013-09-13 16:23:15', $model->attr_timestamp);
$val = new DateValidator(['format' => 'php:Y-m-d H:i:s', 'timestampAttribute' => 'attr_timestamp', 'timestampAttributeFormat' => 'yyyy-MM-dd HH:mm:ss', 'timestampAttributeTimeZone' => 'Europe/Berlin', 'timeZone' => 'UTC']);
$model = new FakedValidationModel;
$model->attr_date = '2013-09-13 14:23:15';
$model->attr_timestamp = true;
$val->validateAttribute($model, 'attr_date');
$this->assertFalse($model->hasErrors('attr_date'));
$this->assertFalse($model->hasErrors('attr_timestamp'));
$this->assertSame('2013-09-13 16:23:15', $model->attr_timestamp);
$val = new DateValidator(['format' => 'yyyy-MM-dd HH:mm:ss', 'timestampAttribute' => 'attr_timestamp', 'timestampAttributeFormat' => 'yyyy-MM-dd HH:mm:ss', 'timestampAttributeTimeZone' => 'Europe/Berlin', 'timeZone' => 'Europe/Berlin']);
$model = new FakedValidationModel;
$model->attr_date = '2013-09-13 16:23:15';
$model->attr_timestamp = true;
$val->validateAttribute($model, 'attr_date');
$this->assertFalse($model->hasErrors('attr_date'));
$this->assertFalse($model->hasErrors('attr_timestamp'));
$this->assertSame('2013-09-13 16:23:15', $model->attr_timestamp);
$val = new DateValidator(['format' => 'php:Y-m-d H:i:s', 'timestampAttribute' => 'attr_timestamp', 'timestampAttributeFormat' => 'yyyy-MM-dd HH:mm:ss', 'timestampAttributeTimeZone' => 'Europe/Berlin', 'timeZone' => 'Europe/Berlin']);
$model = new FakedValidationModel;
$model->attr_date = '2013-09-13 16:23:15';
$model->attr_timestamp = true;
$val->validateAttribute($model, 'attr_date');
$this->assertFalse($model->hasErrors('attr_date'));
$this->assertFalse($model->hasErrors('attr_timestamp'));
$this->assertSame('2013-09-13 16:23:15', $model->attr_timestamp);
$val = new DateValidator(['format' => 'yyyy-MM-dd HH:mm:ss', 'timestampAttribute' => 'attr_timestamp', 'timestampAttributeFormat' => 'yyyy-MM-dd HH:mm:ss', 'timestampAttributeTimeZone' => 'America/New_York', 'timeZone' => 'Europe/Berlin']);
$model = new FakedValidationModel;
$model->attr_date = '2013-09-13 16:23:15';
$model->attr_timestamp = true;
$val->validateAttribute($model, 'attr_date');
$this->assertFalse($model->hasErrors('attr_date'));
$this->assertFalse($model->hasErrors('attr_timestamp'));
$this->assertSame('2013-09-13 10:23:15', $model->attr_timestamp);
$val = new DateValidator(['format' => 'php:Y-m-d H:i:s', 'timestampAttribute' => 'attr_timestamp', 'timestampAttributeFormat' => 'yyyy-MM-dd HH:mm:ss', 'timestampAttributeTimeZone' => 'America/New_York', 'timeZone' => 'Europe/Berlin']);
$model = new FakedValidationModel;
$model->attr_date = '2013-09-13 16:23:15';
$model->attr_timestamp = true;
$val->validateAttribute($model, 'attr_date');
$this->assertFalse($model->hasErrors('attr_date'));
$this->assertFalse($model->hasErrors('attr_timestamp'));
$this->assertSame('2013-09-13 10:23:15', $model->attr_timestamp);
}
}