8000 [Form] Improved test coverage of MonthChoiceList and fixed timezone u… · ivanrey/symfony@c9c8b5c · GitHub
[go: up one dir, main page]

Skip to content
8000

Commit c9c8b5c

Browse files
committed
[Form] Improved test coverage of MonthChoiceList and fixed timezone used in it. Fixes symfony#433
Based on dfb93b1: [FORM] Fixed DateField Month Choices The month choices were calculated using the current day of the month with gmmktime rather than the 1st of the month. Additionally, this provides a UTC timestamp which is passed to the formatter (IntlDateFormatter) which converts the timestamp using the current timezone. This means that the UTC timestamp for 1st March was being converted for my timezone (EST) and giving a date of 28th February, leading to Feb appearing again in the popup form instead of Mar.
1 parent 77bea81 commit c9c8b5c

File tree

4 files changed

+103
-3
lines changed

4 files changed

+103
-3
lines changed

src/Symfony/Component/Form/ChoiceList/MonthChoiceList.php

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,17 +34,23 @@ protected function load()
3434
parent::load();
3535

3636
$pattern = $this->formatter->getPattern();
37+
$timezone = $this->formatter->getTimezoneId();
38+
39+
$this->formatter->setTimezoneId(\DateTimeZone::UTC);
3740

3841
if (preg_match('/M+/', $pattern, $matches)) {
3942
$this->formatter->setPattern($matches[0]);
4043

4144
foreach ($this->choices as $choice => $value) {
42-
$this->choices[$choice] = $this->formatter->format(gmmktime(0, 0, 0, $choice));
45+
// It's important to specify the first day of the month here!
46+
$this->choices[$choice] = $this->formatter->format(gmmktime(0, 0, 0, $choice, 1));
4347
}
4448

4549
// I'd like to clone the formatter above, but then we get a
4650
// segmentation fault, so let's restore the old state instead
4751
$this->formatter->setPattern($pattern);
4852
}
53+
54+
$this->formatter->setTimezoneId($timezone);
4955
}
5056
}

src/Symfony/Component/Form/ChoiceList/PaddedChoiceList.php

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,10 @@ protected function load()
4343
{
4444
parent::load();
4545

46-
foreach ($this->choices as $value) {
46+
$choices = $this->choices;
47+
$this->choices = array();
48+
49+
foreach ($choices as $value) {
4750
$this->choices[$value] = str_pad($value, $this->padLength, $this->padString, $this->padType);
4851
}
4952
}

src/Symfony/Component/Form/Type/DateType.php

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,8 @@ public function buildForm(FormBuilder $builder, array $options)
2929
$formatter = new \IntlDateFormatter(
3030
\Locale::getDefault(),
3131
$options['format'],
32-
\IntlDateFormatter::NONE
32+
\IntlDateFormatter::NONE,
33+
\DateTimeZone::UTC
3334
);
3435

3536
if ($options['widget'] === 'text') {
Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,90 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the Symfony package.
5+
*
6+
* (c) Fabien Potencier <fabien@symfony.com>
7+
*
8+
* For the full copyright and license information, please view the LICENSE
9+
* file that was distributed with this source code.
10+
*/
11+
12+
namespace Symfony\Tests\Component\Form\ChoiceList;
13+
14+
use Symfony\Component\Form\ChoiceList\MonthChoiceList;
15+
16+
class MonthChoiceListTest extends \PHPUnit_Framework_TestCase
17+
{
18+
private $formatter;
19+
20+
protected function setUp()
21+
{
22+
if (!extension_loaded('intl')) {
23+
$this->markTestSkipped('The "intl" extension is not available');
24+
}
25+
26+
\Locale::setDefault('en');
27+
28+
// I would prefer to mock the formatter, but this leads to weird bugs
29+
// with the current version of PHPUnit
30+
$this->formatter = new \IntlDateFormatter(
31+
\Locale::getDefault(),
32+
\IntlDateFormatter::SHORT,
33+
\IntlDateFormatter::NONE,
34+
\DateTimeZone::UTC
35+
);
36+
}
37+
38+
public function testNumericMonthsIfPatternContainsNoMonth()
39+
{
40+
$this->formatter->setPattern('yy');
41+
42+
$months = array(1, 4);
43+
$list = new MonthChoiceList($this->formatter, $months);
44+
45+
$names = array(1 => '01', 4 => '04');
46+
$this->assertSame($names, $list->getChoices());
47+
}
48+
49+
public function testFormattedMonthsShort()
50+
{
51+
$this->formatter->setPattern('dd.MMM.yy');
52+
53+
$months = array(1, 4);
54+
$list = new MonthChoiceList($this->formatter, $months);
55+
56+
$names = array(1 => 'Jan', 4 => 'Apr');
57+
$this->assertSame($names, $list->getChoices());
58+
}
59+
60+
public function testFormattedMonthsLong()
61+
{
62+
$this->formatter->setPattern('dd.MMMM.yy');
63+
64+
$months = array(1, 4);
65+
$list = new MonthChoiceList($this->formatter, $months);
66+
67+
$names = array(1 => 'January', 4 => 'April');
68+
$this->assertSame($names, $list->getChoices());
69+
}
70+
71+
public function testFormattedMonthsLongWithDifferentTimezone()
72+
{
73+
$this->formatter = new \IntlDateFormatter(
74+
\Locale::getDefault(),
75+
\IntlDateFormatter::SHORT,
76+
\IntlDateFormatter::NONE,
77+
'PST'
78+
);
79+
80+
$this->formatter->setPattern('dd.MMMM.yy');
81+
82+
$months = array(1 6371 , 4);
83+
$list = new MonthChoiceList($this->formatter, $months);
84+
85+
$names = array(1 => 'January', 4 => 'April');
86+
// uses UTC internally
87+
$this->assertSame($names, $list->getChoices());
88+
$this->assertSame('PST', $this->formatter->getTimezoneId());
89+
}
90+
}

0 commit comments

Comments
 (0)
0