[Form] 12H format for Time Field #6587

Open
tworzenieweb opened this Issue Jan 6, 2013 · 31 comments
@tworzenieweb

Is there a way to use 12H format in Time Field?

@stloyd

No, it's not possible with TimeType, but it's probably doable with DateTimeType and usage of format option:

$builder->add('somedate', 'datetime', array(
    'widget' => 'single_text',
    'format' => 'yyyy-MM-dd hh:mm A',
));
@webmozart
Symfony member

I think that's a very reasonable feature. Tagging this as feature request.

@webmozart
Symfony member

What do you think about naming this hour_format? Other suggestions?

$builder->add('opensAt', 'time', array(
    'hour_format' => 12,
));

If AM/PM is chosen, a drop down for AM/PM should be displayed at the end of the widget. The default value of the option should be determined by the current Locale.

@shaneog

Would clock_format be a more suitable moniker, given that it relates to the clock rather than the hours?

@davedevelopment

How about hour_notation or time_notation

@stloyd

IMO we should be consistent here and as we have date_format we should use time_format (as well as simple format).

@bendavies

since it is called the 12 or 24 hour clock, i agree with clock_format

@marfillaster

I suggest use 'format' as is as option name to be consistent with date type. It should also follow the time codes in php date format.

Maybe throw invalid argument if a passed code does not have anything to do with time formating such as year, months and days. But it should allow literal codes which are escaped by backslash i think.

The allowed codes

a   Lowercase Ante meridiem and Post meridiem   am or pm
A   Uppercase Ante meridiem and Post meridiem   AM or PM
B   Swatch Internet time    000 through 999
g   12-hour format of an hour without leading zeros 1 through 12
G   24-hour format of an hour without leading zeros 0 through 23
h   12-hour format of an hour with leading zeros    01 through 12
H   24-hour format of an hour with leading zeros    00 through 23
i   Minutes with leading zeros  00 to 59
s   Seconds, with leading zeros 00 through 59
@davedevelopment

I was under the impression we were discussing a switch between 12/24 clock, not allowing formatting with minutes, seconds and the whole shebang.

@webmozart
Symfony member

Exactly. This has nothing in common with the format option.

@webmozart
Symfony member

Would just clock with the possible values 12h and 24h be sufficient?

@davedevelopment

Just throwing time_convention in to the mix.

12 Hour Clock opens with:

The 12-hour clock is a time convention

@tworzenieweb

i vote for time_format for the same reason as @stloyd mentioned - naming consistency.

@webmozart
Symfony member

@tworzenieweb Naming consistency means that similar things should have similar names. This option is not similar to format or date_format.

@marfillaster

@davedevelopment format is more flexible and the fact that time field is not an hour only type.

@shaneog

I think it should have format in the name since it defines how a time is displayed/formatted to the user, but if verbosity is frowned at then just clock is an acceptable alternative.

@marfillaster

@bschussek i guess so but it still needed for single_text widget. For dropdowns, I aggree that there must be another option but it also means adding another dropdown to select am/pm.

@webmozart
Symfony member

@marfillaster I think that in all cases an AM/PM dropdown should be appended to the widget if clock is 12h, no matter if widget is single_text, text or choice

@sprain

How about time_convention based on these two wikipedia entries: http://en.wikipedia.org/wiki/12-hour_clock, http://en.wikipedia.org/wiki/24-hour_clock?

@althaus

I'd go with clock or clock_format.

@acasademont

Ubuntu calls that "clock format"

@http-teapot

No work around for this issue? I could extend the DateTimeType class with my own but that's not a great solution.

@webmozart
Symfony member

Let's stick with clock in TimeType and DateTimeType then with the possible values 12h and 24h.

@tayhimself

It would be fantastic if you could provide a recipe here or in the cookbook on how to get 12h times when using currently supported symfony versions. I assume you would use a custom form field type that extended DateTimeType rather than AbstractType.

@webmozart
Symfony member

We're already past feature freeze for 2.3, so this won't make it into 2.3 anymore. The best recipe I can give is to backport the feature once it is available for a later version.

@jakraska

Any Progress on this? Seems like it should be easy to add a time format option

@inssein inssein referenced this issue in sonata-project/SonataCoreBundle May 17, 2014
Closed

[WIP] Adding a time picker #64

@lologhi

👍

@jarofgreen

So I've just been digging into this and I see what may be an easy answer, at least in "choice" mode ....

https://github.com/symfony/symfony/blob/2.7/src/Symfony/Component/Form/Extension/Core/Type/TimeType.php

Has this in it (starts line 58):

 $hours = $minutes = array();
            foreach ($options['hours'] as $hour) {
                $hours[$hour] = str_pad($hour, 2, '0', STR_PAD_LEFT);
            } 

This is what is passed to the Hours dropdown widget. This has the effect of splatting over whatever values you try to pass it, and crucially, splatting over whatever keys and values you try to pass.

If I replace the code with

            foreach ($options['hours'] as $value=>$hour) {
                $hours[$value] = $hour;
            }

And then set up my form like this:

$hours = array(
        0=>'midnight',
        1=>'1am',
        2=>'2am',
        3=>'3am',
        4=>'4am',
        5=>'5am',
        6=>'6am',
        7=>'7am',
        8=>'8am',
        9=>'9am',
        10=>'10am',
        11=>'11am',
        12=>'noon',
        13=>'1pm',
        14=>'2pm',
        15=>'3pm',
        16=>'4pm',
        17=>'5pm',
        18=>'6pm',
        19=>'7pm',
        20=>'8pm',
        21=>'9pm',
        22=>'10pm',
        23=>'11pm',
    );
$startOptions = array(
        'date_widget'=> 'single_text',
        'date_format'=>'d/M/y',
        'model_timezone' => 'UTC',
        'view_timezone' => $timeZoneName,
        'hours'=> $hours,
    );
$builder->add('start_at', 'datetime' , $startOptions);

It works!

screen shot 2015-04-13 at 10 57 50

Obvs, this is not a patch that could be applied right away. The str_pad stuff that was there before was there for a reason and can't just be removed. A proper patch would have to check if user had passed keys and values and use them if so, or do the str_pad stuff if not.

But hopefully this will reformulate this bug report: in "choices" mode, the Time widget splats all over key/value data in hours and if this was fixed developers could specify 12 hour, 4 hour or whatever odd hour scheme they liked really easily.

@jarofgreen

Looking at this again quickly, I would guess the proper thing to do is set the default and let programmers override this. Oh, and this applies to minutes and seconds to.

diff --git a/src/Symfony/Component/Form/Extension/Core/Type/TimeType.php b/src/Symfony/Component/Form/Extension/Core/Type/TimeType.php
index 49f77c5..a7e9f83 100644
--- a/src/Symfony/Component/Form/Extension/Core/Type/TimeType.php
+++ b/src/Symfony/Component/Form/Extension/Core/Type/TimeType.php
@@ -55,33 +55,17 @@ class TimeType extends AbstractType
             );

             if ('choice' === $options['widget']) {
-                $hours = $minutes = array();
-
-                foreach ($options['hours'] as $hour) {
-                    $hours[$hour] = str_pad($hour, 2, '0', STR_PAD_LEFT);
-                }
-
                 // Only pass a subset of the options to children
-                $hourOptions['choices'] = $hours;
+                $hourOptions['choices'] = $options['hours'];
                 $hourOptions['placeholder'] = $options['placeholder']['hour'];

                 if ($options['with_minutes']) {
-                    foreach ($options['minutes'] as $minute) {
-                        $minutes[$minute] = str_pad($minute, 2, '0', STR_PAD_LEFT);
-                    }
-
-                    $minuteOptions['choices'] = $minutes;
+                    $minuteOptions['choices'] = $options['minutes'];
                     $minuteOptions['placeholder'] = $options['placeholder']['minute'];
                 }

                 if ($options['with_seconds']) {
-                    $seconds = array();
-
-                    foreach ($options['seconds'] as $second) {
-                        $seconds[$second] = str_pad($second, 2, '0', STR_PAD_LEFT);
-                    }
-
-                    $secondOptions['choices'] = $seconds;
+                    $secondOptions['choices'] = $options['seconds'];
                     $secondOptions['placeholder'] = $options['placeholder']['second'];
                 }

@@ -190,9 +174,9 @@ class TimeType extends AbstractType
         };

         $resolver->setDefaults(array(
-            'hours' => range(0, 23),
-            'minutes' => range(0, 59),
-            'seconds' => range(0, 59),
+            'hours' => array_map(function($hour) { return str_pad($hour, 2, '0', STR_PAD_LEFT); }, range(0, 23)),
+            'minutes' => array_map(function($mins) { return str_pad($mins, 2, '0', STR_PAD_LEFT); }, range(0, 59)),
+            'seconds' => array_map(function($secs) { return str_pad($secs, 2, '0', STR_PAD_LEFT); }, range(0, 59)),
             'widget' => 'choice',
             'input' => 'datetime',
             'with_minutes' => true,

If someone from the project gives the nod that this could be a good option, I'm happy to boot up a VM with PHP 5.5 so I can test this against the branch master which I notice is branded V3? Would be cool to get this in that.

@javiereguiluz javiereguiluz added Hack Day and removed Hack Day labels Mar 10, 2016
@yvoloshin

Hi @jarofgreen ,
Thank you for introducing this patch! I'm trying to implement it by creating an extension of TimeType (named MyTimeType) in my project and adding your changes to the extension. MyTimeType was added to config.yml under doctrine: dbal: types: time: 'MyTimeType\location'. The problem is that the property I'm trying to enter in 12-hour format belongs to DateTimeType, not TimeType. As far as I understand, DateTimeType uses DateType and TimeType to create a DateTimeType object. My question is, how can I direct DateTimeType to use MyTimeType instead of TimeType?
Thank you for any help!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment