Commit 89f2e9f8 authored by Imko Schumacher's avatar Imko Schumacher Committed by Benjamin Franzke
Browse files

[BUGFIX] Set timezone on TCA dbType input

The value from columns that are marked as "dbType" date(time) fields
in TCA configuration are now explicitly interpreted using UTC timezone,
when the string value has no timezone specifier given.
JS supplied values contain Z as specifier, while records from the database
(which are processed during copy operations) do not contain a timezone
specifier.
Local time was assumed by PHP in the latter case before, as we did not
pass an explicit timezone information to the DateTime constructor.

Therefore we now assure no timezone conversion will happen and no
time/date-offset will be added, by using UTC explicitly.

Resolves: #89914
Releases: master, 10.4, 9.5
Change-Id: I8e531ae5f3367c4493ce1e7db4bec0ef02311e24
Reviewed-on: https://review.typo3.org/c/Packages/TYPO3.CMS/+/66670

Tested-by: default avatarTYPO3com <noreply@typo3.com>
Tested-by: Markus Klein's avatarMarkus Klein <markus.klein@typo3.org>
Tested-by: Benjamin Franzke's avatarBenjamin Franzke <bfr@qbus.de>
Reviewed-by: Markus Klein's avatarMarkus Klein <markus.klein@typo3.org>
Reviewed-by: Benjamin Franzke's avatarBenjamin Franzke <bfr@qbus.de>
parent e4eee470
...@@ -1680,8 +1680,11 @@ class DataHandler implements LoggerAwareInterface ...@@ -1680,8 +1680,11 @@ class DataHandler implements LoggerAwareInterface
// Convert the date/time into a timestamp for the sake of the checks // Convert the date/time into a timestamp for the sake of the checks
$emptyValue = $dateTimeFormats[$tcaFieldConf['dbType']]['empty']; $emptyValue = $dateTimeFormats[$tcaFieldConf['dbType']]['empty'];
// We store UTC timestamps in the database, which is what getTimestamp() returns. // We expect the ISO 8601 $value to contain a UTC timezone specifier.
$dateTime = new \DateTime($value); // We explicitly fallback to UTC if no timezone specifier is given (e.g. for copy operations).
$dateTime = new \DateTime($value, new \DateTimeZone('UTC'));
// The timestamp (UTC) returned by getTimestamp() will be converted to
// a local time string by gmdate() later.
$value = $value === $emptyValue ? null : $dateTime->getTimestamp(); $value = $value === $emptyValue ? null : $dateTime->getTimestamp();
} }
} }
......
...@@ -365,6 +365,74 @@ class DataHandlerTest extends UnitTestCase ...@@ -365,6 +365,74 @@ class DataHandlerTest extends UnitTestCase
$this->subject->_call('checkValueForInput', '', $tcaFieldConf, '', 0, 0, ''); $this->subject->_call('checkValueForInput', '', $tcaFieldConf, '', 0, 0, '');
} }
/**
* @returns array
*/
public function inputValueCheckDbtypeIsIndependentFromTimezoneDataProvider()
{
return [
// Values of this kind are passed in from the inputDateTime control
'time from inputDateTime' => [
'1970-01-01T18:54:00Z',
'time',
'18:54:00',
],
'date from inputDateTime' => [
'2020-11-25T00:00:00Z',
'date',
'2020-11-25',
],
'datetime from inputDateTime' => [
'2020-11-25T18:54:00Z',
'datetime',
'2020-11-25 18:54:00',
],
// Values of this kind are passed in when a data record is copied
'time from copying a record' => [
'18:54:00',
'time',
'18:54:00',
],
'date from copying a record' => [
'2020-11-25',
'date',
'2020-11-25',
],
'datetime from copying a record' => [
'2020-11-25 18:54:00',
'datetime',
'2020-11-25 18:54:00',
],
];
}
/**
* Tests whether native dbtype inputs are parsed independent from the server timezone.
*
* @param $value
* @param $dbtype
* @param $expectedOutput
* @test
* @dataProvider inputValueCheckDbtypeIsIndependentFromTimezoneDataProvider
*/
public function inputValueCheckDbtypeIsIndependentFromTimezone($value, $dbtype, $expectedOutput)
{
$tcaFieldConf = [
'input' => [],
'dbType' => $dbtype,
];
$oldTimezone = date_default_timezone_get();
date_default_timezone_set('Europe/Berlin');
$returnValue = $this->subject->_call('checkValueForInput', $value, $tcaFieldConf, '', 0, 0, '');
// set before the assertion is performed, so it is restored even for failing tests
date_default_timezone_set($oldTimezone);
self::assertEquals($expectedOutput, $returnValue['value']);
}
/////////////////////////////////////////// ///////////////////////////////////////////
// Tests concerning checkModifyAccessList // Tests concerning checkModifyAccessList
/////////////////////////////////////////// ///////////////////////////////////////////
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment