symfony表单无法与UTC时区一起正常工作(html5日期时间选取器)

uurity8g  于 2022-11-16  发布在  HTML5
关注(0)|答案(1)|浏览(173)

我在应用中使用UTC日期时间,当我打开一个表单编辑该时间时,它会正确地预填充,但如果没有更改任何内容,并且保存了表单,则时间会向后设置2个小时,就好像提交的时间是我的本地时区(UTC+2)一样。
但提交的时间已经是UTC。
这种行为只发生在我的虚拟主机环境中,当我在自己的机器上运行localhost(MAMP Apache)时,这种行为不存在。
是不是有什么地方的区域设置在捉弄我?
我应该在我的控制器中解决这个问题吗?
根据本例中的视频https://drive.google.com/file/d/1zuqASzy70U7yzFfkokoLcCopHsA-HpEb/view?usp=sharing,时间最初为13:15开始,15:00停止
这也是编辑时表单中显示的内容。提交表单后(没有更改时间),结果值为start 11:15,stop 13:00
控制器:

public function editAction(Request $request, Entry $entry)
{
    $unit = $entry->getPosition()->getACRGroup();
    $editForm = $this->createForm('App\Form\EntryType', $entry, ['unit' => $unit]);
    $editForm->handleRequest($request);

    if ($editForm->isSubmitted() && $editForm->isValid()) {
        
        // (Do a bunch of checks so see if new parameters of entry conflicts anywhere)

            $this->em->persist($entry);
            $this->em->flush();
            return $this->redirectToRoute('operator_history_position', array('positionId' => $entry->getPosition()->getId() ));                

        } else {

            //and continue below, back to the form it is
        }
    }

    return $this->render('entry/edit.html.twig', array(
        'entry' => $entry,
        'edit_form' => $editForm->createView(),
    ));
}

实体:

namespace App\Entity\Poslog;

use Doctrine\ORM\Mapping as ORM;

/**
 * Entry
 *
 * @ORM\Table(name="entry")
 * @ORM\Entity
 */
class Entry
{

    public function __construct() 
    {
        $this->verifiedAsCorrect = false;
    }

    /**
     * @var int
     *
     * @ORM\Column(name="id", type="integer")
     * @ORM\Id
     * @ORM\GeneratedValue(strategy="AUTO")
     */
    private $id;

    /**
     * @var int
     *
     * @ORM\Column(name="start", type="integer")
     */
    private $start;

    /**
     * @var int|null
     *
     * @ORM\Column(name="stop", type="integer", nullable=true)
     */
    private $stop;

    /**
     * @var bool
     *
     * @ORM\Column(name="verified_as_correct", type="boolean")
     */
    private $verifiedAsCorrect;

    /**
    * @var object \App\Entity\Poslog\Position
    *  
    * @ORM\ManyToOne(targetEntity="\App\Entity\Poslog\Position", inversedBy="entries")
    * @ORM\JoinColumn(name="position", referencedColumnName="id", nullable=false)
    */
    protected $position;

    /**
    * @var object \App\Entity\Poslog\Operator
    *  
    * @ORM\ManyToOne(targetEntity="\App\Entity\Poslog\Operator", inversedBy="entries")
    * @ORM\JoinColumn(name="operator", referencedColumnName="id", nullable=false)
    */
    protected $operator;

    /**
    * @var object \App\Entity\Poslog\Operator
    *  
    * @ORM\ManyToOne(targetEntity="\App\Entity\Poslog\Operator", inversedBy="studentEntries")
    * @ORM\JoinColumn(name="student", referencedColumnName="id", nullable=true)
    */
    protected $student;

    /**
     * Get id.
     *
     * @return int
     */
    public function getId()
    {
        return $this->id;
    }

    /**
     * Set start.
     *
     * @param int $start
     *
     * @return Entry
     */
    public function setStart($start)
    {
        $this->start = $start->getTimestamp();
        return $this;
    }

    /**
     * Get start.
     *
     * @return \DateTime
     */
    public function getStart($timezone = null)
    {
        $val = $this->start;
        $date = new \DateTime("@".$val, new \DateTimeZone("UTC"));

            if ($timezone) {
                $date->setTimezone( new \DateTimeZone( $timezone ) );
            }

        return $date;
    }

    /**
     * Set stop.
     *
     * @param int|null $stop
     *
     * @return Entry
     */
    public function setStop($stop = null)
    {
        if ($stop == null) {
            $this->stop = null;    
        } else {
            $this->stop = $stop->getTimestamp();
        }
        return $this;
    }

    /**
     * Get stop.
     *
     * @return \DateTime|null
     */
    public function getStop($timezone = null)
    {
        $val = $this->stop;

        if ($val == null) {
            return null;
        } else {
            $date = new \DateTime("@".$val, new \DateTimeZone("UTC"));

            if ($timezone) {
                $date->setTimezone( new \DateTimeZone( $timezone ) );
            }

            return $date;
        }
    }

    /**
     * Set verifiedAsCorrect.
     *
     * @param bool $verifiedAsCorrect
     *
     * @return Entry
     */
    public function setVerifiedAsCorrect($v)
    {

        $this->verifiedAsCorrect = $v;

        return $this;
    }

    /**
     * Get verifiedAsCorrect.
     *
     * @return bool
     */
    public function getVerifiedAsCorrect()
    {
        return $this->verifiedAsCorrect;
    }

    /**
     * Set Position
     *
     * @param \App\Entity\Poslog\Position $position
     *
     * @return Entry
     */
    public function setPosition(\App\Entity\Poslog\Position $position)
    {
        $this->position = $position;

        return $this;
    }

    /**
     * Get Position
     *
     * @return \App\Entity\Poslog\Position
     */
    public function getPosition()
    {
        return $this->position;
    }

    /**
     * Set Operator
     *
     * @param \App\Entity\Poslog\Operator $operator
     *
     * @return Entry
     */
    public function setOperator(\App\Entity\Poslog\Operator $operator)
    {
        $this->operator = $operator;

        return $this;
    }

    /**
     * Get Operator
     *
     * @return \App\Entity\Poslog\Operator
     */
    public function getOperator()
    {
        return $this->operator;
    }

    /**
     * Set Student
     *
     * @param \App\Entity\Poslog\Operator $student
     *
     * @return Entry
     */
    public function setStudent(\App\Entity\Poslog\Operator $student = null)
    {
        $this->student = $student;

        return $this;
    }

    /**
     * Get Student
     *
     * @return \App\Entity\Poslog\Operator
     */
    public function getStudent()
    {
        return $this->student;
    }    

    
    public function getDuration($format = null)
    {
        $start = $this->getStart();
        $stop = $this->getStop();

        if ($stop == null) {
            /*
            $t_start = strtotime( $start->format('Y-m-d H:i:s') );
            $now = new \DateTime("now", new \DateTimeZone("UTC"));
            //$now = new \DateTime("now"); //for the local time version
            $t_stop = strtotime( $now->format('Y-m-d H:i:s') );
            $duration = $t_stop - $t_start;
            */
            $now = new \DateTime("now", new \DateTimeZone("UTC"));
            $duration = $now->getTimestamp() - $start->getTimestamp();
        } else {
            /*
            $t_start = strtotime( $start->format('Y-m-d H:i:s') );
            $t_stop = strtotime( $stop->format('Y-m-d H:i:s') );
            $duration = $t_stop - $t_start;
            */
            $duration = $stop->getTimestamp() - $start->getTimestamp();
        }

        if ($format == 'minutes') {
            return round($duration / 60);
        } elseif ($format == 'hours') {
            return ($duration / 60 / 60);
        } elseif ($format == 'time') {
            $hours = floor($duration / 3600);
            $minutes = floor(($duration / 60) % 60);
            $seconds = $duration % 60;

            if ($seconds > 29) { //round up, we don't display seconds
                $minutes++;
            }

            if ($hours < 10) {
                $hours = "0" . $hours;
            }
            
            if ($minutes < 10) {
                $minutes = "0" . $minutes;
            }

            return $hours . ":" . $minutes;

        } elseif ($format == 'time_human') {
            $hours = floor($duration / 3600);
            
            //if starttime is set into the future duration will be negative and hours will whow up incorrectly at -1 (for zero hours) due to the flooring business above 
            if ($duration<0) {
                $hours++;
            }            
            
            $minutes = floor(($duration / 60) % 60);
            $seconds = $duration % 60;

            if ($seconds > 29) { //round up, we don't display seconds
                $minutes++;
            }

            if ($hours == 1) {
                $h = 'timme';
            } else {
                $h = 'timmar';
            }

            if ($minutes == 1) {
                $m = 'minut';
            } else {
                $m = 'minuter';
            }

            return $hours . " " . $h . " och " . $minutes . " " . $m;

        } elseif ($format == 'time_human_short') {
            $hours = floor($duration / 3600);

            //if starttime is set into the future duration will be negative and hours will whow up incorrectly at -1 (for zero hours) due to the flooring business above 
            if ($duration<0) {
                $hours++;
            }

            $minutes = floor(($duration / 60) % 60);
            $seconds = $duration % 60;

            if ($seconds > 29) { //round up, we don't display seconds
                $minutes++;
            }

            $h = 'h';
            $m = 'm';

            return $hours . $h . " " . $minutes . $m;

        } else { //seconds
            return $duration; //seconds
        }
    
    }

    public function getStartDate() {

        $full = $this->getStart();
        return $full->format('Y-m-d');

    }
}

表格:

<?php

namespace App\Form;

use App\Entity\Poslog\Entry;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolver;

use Symfony\Bridge\Doctrine\Form\Type\EntityType;
use Symfony\Component\Form\Extension\Core\Type\TextType;
use Symfony\Component\Form\Extension\Core\Type\IntegerType;
use Symfony\Component\Form\Extension\Core\Type\DateTimeType;
use Doctrine\ORM\EntityRepository;

class EntryType extends AbstractType
{

    public function buildForm(FormBuilderInterface $builder, array $options): void
    { 
        
        $this->unit = $options['unit'];

        $builder
            ->add('position', EntityType::class, array(
                'label' => 'Position',
                'class' => 'App\Entity\Poslog\Position',
                'query_builder' => function (EntityRepository $er) {
                        $qb = $er->createQueryBuilder('p');
                        $qb->where('p.ACRGroup = (:unit)');
                        $qb->andWhere('p.archived = false');
                        $qb->setParameters( array('unit' => $this->unit) );
                        return $qb;
                },
                'choice_label' => function ($position) {
                    //return $position->getACRGroup()->getDesignator() . " " . $position->getName();
                    return $position->getName();
                }
            ))

            ->add('start', DateTimeType::class, array(
                'label' => 'Starttid (' . $this->unit->getTimezone() . ')',
                'date_widget' => 'single_text',
                'time_widget' => 'single_text',

            ))   
            ->add('stop', DateTimeType::class, array(
                'label' => 'Sluttid (' . $this->unit->getTimezone() . ')',
                'date_widget' => 'single_text',
                'time_widget' => 'single_text',
            ))
            
        ;
    }

    public function configureOptions(OptionsResolver $resolver): void
    {
        $resolver->setDefaults([
            'data_class' => Entry::class,
            'unit' => null
        ]);
    }
}
axr492tv

axr492tv1#

看来我忽略了表单配置中的一个细节=)
将“UTC”添加到“model_timezone”键会使其将提交的数据存储为UTC。在我的示例中,它也应该显示为UTC。

->add('start', DateTimeType::class, array(
            'label' => 'Starttid (' . $this->unit->getTimezone() . ')',
            'date_widget' => 'single_text',
            'time_widget' => 'single_text',
            'model_timezone' => 'UTC',
            'view_timezone' => 'UTC',

        ))

相关问题