Answer
f:format.date defaults to TYPO3 configuration, not PHP ini. If no timezone is passed in the template, the view helper uses the timezone resolved by TYPO3 Core for the current site: site configuration timezone first, then the Global Configuration $GLOBALS['TYPO3_CONF_VARS']['SYS']['timeZone']. It does not fall back to PHP's date.timezone.
PHP date.timezone conflicts are overridden at bootstrap. TYPO3 sets the runtime PHP default timezone early in the request via date_default_timezone_set() based on its own configuration. For web requests the ini value is therefore ignored once TYPO3 is bootstrapped. For CLI / cron / Scheduler the same override is applied when TYPO3 CLI is used, but a raw PHP script that does not bootstrap TYPO3 will still use the ini value.
Confirmed facts
- TYPO3 stores timestamps in the database as UTC integers.
- Rendering uses PHP
DateTime / DateTimeZone objects. TYPO3\CMS\Core\Utility\DateTimeHelper and the Fluid view helper f:format.date create objects with an explicit timezone from TYPO3 configuration.
- Application timezone is
$GLOBALS['TYPO3_CONF_VARS']['SYS']['timeZone']. Since TYPO3 9/10, a site-specific timezone can be set in Site Configuration under settings.timeZone or timezone. Site config overrides global config.
dateTimeFormat only affects output formatting, not the zone used for conversion.
Likely explanation for discrepancies
Drift appears when PHP's default timezone is different from TYPO3's configured zone and code bypasses TYPO3 helpers. Direct use of date(), strtotime() or a DateTime without an explicit DateTimeZone will use the PHP runtime default. If the runtime default was not set by TYPO3, e.g. in CLI scripts, custom middleware before bootstrap, or cached formatted strings, the displayed time can differ from the TYPO3-configured zone.
Steps needed for this case
- Verify the effective TYPO3 zone. Backend: Settings > System > Locale. Site config:
config.yaml settings.timeZone.
- Ensure TYPO3 can override PHP. Check that
$GLOBALS['TYPO3_CONF_VARS']['SYS']['timeZone'] is set and that no early code calls date_default_timezone_set before TYPO3 bootstrap.
- Use TYPO3 helpers for output. Prefer
{ts -> f:format.date(date: ..., format: ...)} without a manual timezone, or DateTimeHelper::convertToDateTimeByFormat() in PHP. Avoid raw date().
- Align CLI timezone. Run
php -r 'echo date_default_timezone_get();' and compare with TYPO3 config. Set date.timezone in php.ini for CLI to match TYPO3 to avoid drift in Scheduler/cron jobs that run non-TYPO3 PHP.
- Invalidate caches after changing timezone. Formatted date strings can be cached by page cache, Varnish or Fluid cache.
Verification commands:
php -i | grep date.timezone
php -r 'echo date_default_timezone_get();'
In TYPO3, dump the resolved zone in debug mode for a timestamp field and compare with expected local time.
One missing diagnostic detail that changes the recommendation: which TYPO3 major version and whether a site-specific timezone is defined in Site Configuration. The precedence of site config vs global config and the exact bootstrap override point changed between TYPO3 8, 9/10 and 12/13.