Skip to content

Commit 68aa6c2

Browse files
committed
Don't adjust the app's timezone, keep timezone management within Cms
1 parent 1ede24e commit 68aa6c2

File tree

27 files changed

+111
-125
lines changed

27 files changed

+111
-125
lines changed

src/Cms.php

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,8 @@
1313
use Illuminate\Support\Facades\Context;
1414
use Illuminate\Support\Facades\DB;
1515
use Illuminate\Support\Facades\Log;
16+
use IntlDateFormatter;
17+
use IntlException;
1618
use PDOException;
1719
use Throwable;
1820

@@ -31,6 +33,30 @@ public static function config(): GeneralConfig
3133
return app(GeneralConfig::class) ?? GeneralConfig::create();
3234
}
3335

36+
public static function timezone(): string
37+
{
38+
$timezone = Cms::config()->timezone
39+
?? ProjectConfig::get('system.timeZone')
40+
?? config('app.timezone', 'UTC');
41+
42+
$timezone = Env::parse($timezone);
43+
44+
if ($timezone !== 'UTC') {
45+
// Make sure that ICU supports this timezone
46+
try {
47+
$formatter = new IntlDateFormatter(app()->getLocale(), IntlDateFormatter::NONE, IntlDateFormatter::NONE);
48+
if (! $formatter->setTimeZone($timezone)) {
49+
$timezone = 'UTC';
50+
}
51+
} catch (IntlException) {
52+
Log::warning("Time zone “{$timezone}” does not appear to be supported by ICU: ".intl_get_error_message());
53+
$timezone = 'UTC';
54+
}
55+
}
56+
57+
return $timezone;
58+
}
59+
3460
public static function systemName(): string
3561
{
3662
$name = Env::parse(ProjectConfig::get('system.name'));

src/Config/GeneralConfig.php

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2961,6 +2961,24 @@ class GeneralConfig extends BaseConfig
29612961
*/
29622962
public ?string $tempAssetUploadFs = null;
29632963

2964+
/**
2965+
* @var string|null The timezone of the site. If set, it will take precedence over the Timezone setting in Settings → General.
2966+
*
2967+
* This can be set to one of PHP’s [supported timezones](https://php.net/manual/en/timezones.php).
2968+
*
2969+
* ::: code
2970+
* ```php Static Config
2971+
* ->timezone('Europe/London')
2972+
* ```
2973+
* ```shell Environment Override
2974+
* CRAFT_TIMEZONE=Europe/London
2975+
* ```
2976+
* :::
2977+
*
2978+
* @group System
2979+
*/
2980+
public ?string $timezone = null;
2981+
29642982
/**
29652983
/**
29662984
* @var bool Whether GIF files should be cleansed/transformed.
@@ -6146,6 +6164,29 @@ public function tempAssetUploadFs(?string $value): self
61466164
return $this;
61476165
}
61486166

6167+
/**
6168+
* Configures Craft to send all system emails to either a single email address or an array of email addresses
6169+
* for testing purposes.
6170+
*
6171+
* The timezone of the site. If set, it will take precedence over the Timezone setting in Settings → General.
6172+
*
6173+
* This can be set to one of PHP’s [supported timezones](https://php.net/manual/en/timezones.php).
6174+
*
6175+
* ```php
6176+
* ->timezone('Europe/London')
6177+
* ```
6178+
*
6179+
* @group System
6180+
*
6181+
* @see $timezone
6182+
*/
6183+
public function timezone(?string $value): self
6184+
{
6185+
$this->timezone = $value;
6186+
6187+
return $this;
6188+
}
6189+
61496190
/**
61506191
* Whether GIF files should be cleansed/transformed.
61516192
*

src/Cp/Icons.php

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
namespace CraftCms\Cms\Cp;
66

77
use CraftCms\Aliases\Aliases;
8+
use CraftCms\Cms\Cms;
89
use CraftCms\Cms\Support\Facades\I18N;
910
use CraftCms\Cms\Support\Html;
1011
use Illuminate\Support\Facades\Log;
@@ -187,7 +188,7 @@ public static function fallbackSvg(string $label): string
187188

188189
public static function earth(): string
189190
{
190-
$tzGroup = explode('/', (string) app()->getTimezone(), 2)[0];
191+
$tzGroup = explode('/', Cms::timezone(), 2)[0];
191192

192193
return match ($tzGroup) {
193194
'Africa' => 'earth-africa',

src/Field/Date.php

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66

77
use craft\base\ElementInterface;
88
use craft\helpers\Db;
9+
use CraftCms\Cms\Cms;
910
use CraftCms\Cms\Entry\Elements\Entry;
1011
use CraftCms\Cms\Field\Conditions\DateFieldConditionRule;
1112
use CraftCms\Cms\Field\Contracts\CrossSiteCopyableFieldInterface;
@@ -228,7 +229,7 @@ public function getInputId(): string
228229
protected function inputHtml(mixed $value, ?ElementInterface $element, bool $inline): string
229230
{
230231
/** @var DateTime|null $value */
231-
$timezone = $this->showTimeZone && $value ? $value->getTimezone()->getName() : app()->getTimezone();
232+
$timezone = $this->showTimeZone && $value ? $value->getTimezone()->getName() : Cms::timezone();
232233

233234
if ($value === null) {
234235
// Override the initial value being set to null by CustomField::inputHtml()

src/Gql/Directives/FormatDateTime.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,6 @@ public static function apply(mixed $source, mixed $value, array $arguments, Reso
9797

9898
public static function defaultTimeZone(): string
9999
{
100-
return Cms::config()->setGraphqlDatesToSystemTimeZone ? app()->getTimezone() : self::DEFAULT_TIMEZONE;
100+
return Cms::config()->setGraphqlDatesToSystemTimeZone ? Cms::timezone() : self::DEFAULT_TIMEZONE;
101101
}
102102
}

src/Providers/AppServiceProvider.php

Lines changed: 0 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,6 @@
1515
use CraftCms\Cms\Support\Facades\Updates;
1616
use CraftCms\Cms\Support\File;
1717
use GuzzleHttp\Utils;
18-
use Illuminate\Contracts\Config\Repository as ConfigRepository;
1918
use Illuminate\Foundation\Application;
2019
use Illuminate\Foundation\Console\AboutCommand;
2120
use Illuminate\Foundation\Events\LocaleUpdated;
@@ -29,13 +28,10 @@
2928
use Illuminate\Support\Facades\Config;
3029
use Illuminate\Support\Facades\Event;
3130
use Illuminate\Support\Facades\Gate;
32-
use Illuminate\Support\Facades\Log;
3331
use Illuminate\Support\Facades\Redirect;
3432
use Illuminate\Support\Facades\URL;
3533
use Illuminate\Support\ServiceProvider;
3634
use Illuminate\Validation\Rules\Password;
37-
use IntlDateFormatter;
38-
use IntlException;
3935
use Override;
4036
use ReflectionClass;
4137
use RuntimeException;
@@ -70,7 +66,6 @@ public function boot(): void
7066
'Version' => Cms::VERSION,
7167
]);
7268

73-
$this->setTimezone();
7469
$this->setNamespace();
7570
$this->bootAliases();
7671

@@ -121,11 +116,6 @@ private function registerMacros(): void
121116
return Env::parseBoolean(app(ProjectConfig::class)->get('system.live')) ?? false;
122117
});
123118

124-
Application::macro(
125-
'getTimezone',
126-
fn (): string => $this->make(ConfigRepository::class)->get('app.timezone') ?? date_default_timezone_get(),
127-
);
128-
129119
// Register Collection::one() as an alias of first()
130120
Collection::macro('one', fn () => $this->first(...func_get_args()));
131121

@@ -196,31 +186,6 @@ private function registerMacros(): void
196186
));
197187
}
198188

199-
private function setTimezone(): void
200-
{
201-
$timezone = app(ProjectConfig::class)->get('system.timeZone')
202-
?? $this->app->make(ConfigRepository::class)->get('app.timezone')
203-
?? 'UTC';
204-
205-
$timezone = Env::parse($timezone);
206-
207-
if ($timezone !== 'UTC') {
208-
// Make sure that ICU supports this timezone
209-
try {
210-
$formatter = new IntlDateFormatter($this->app->getLocale(), IntlDateFormatter::NONE, IntlDateFormatter::NONE);
211-
if (! $formatter->setTimeZone($timezone)) {
212-
$timezone = 'UTC';
213-
}
214-
} catch (IntlException) {
215-
Log::warning("Time zone “{$timezone}” does not appear to be supported by ICU: ".intl_get_error_message());
216-
$timezone = 'UTC';
217-
}
218-
}
219-
220-
$this->app->make(ConfigRepository::class)->set('app.timezone', $timezone);
221-
date_default_timezone_set($timezone);
222-
}
223-
224189
private function setNamespace(): void
225190
{
226191
/**

src/Support/DateTimeHelper.php

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -144,7 +144,7 @@ public static function toDateTime(mixed $value, bool $assumeSystemTimeZone = fal
144144
return false;
145145
}
146146

147-
$defaultTimeZone = $assumeSystemTimeZone ? app()->getTimezone() : 'UTC';
147+
$defaultTimeZone = $assumeSystemTimeZone ? Cms::timezone() : 'UTC';
148148

149149
if (is_array($value)) {
150150
if (empty($value['datetime']) && empty($value['date']) && empty($value['time'])) {
@@ -201,7 +201,7 @@ public static function toDateTime(mixed $value, bool $assumeSystemTimeZone = fal
201201
}
202202

203203
if ($setToSystemTimeZone) {
204-
$dateTime->setTimezone(new DateTimeZone(app()->getTimezone()));
204+
$dateTime->setTimezone(new DateTimeZone(Cms::timezone()));
205205
}
206206

207207
return $dateTime;
@@ -316,7 +316,7 @@ public static function now(?DateTimeZone $timeZone = null): DateTime
316316
{
317317
if (! empty(self::$_now)) {
318318
$date = clone self::$_now[0];
319-
$date->setTimezone($timeZone ?? new DateTimeZone(app()->getTimezone()));
319+
$date->setTimezone($timeZone ?? new DateTimeZone(Cms::timezone()));
320320

321321
return $date;
322322
}

src/Translation/Formatter.php

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
namespace CraftCms\Cms\Translation;
66

77
use Carbon\CarbonInterface;
8+
use CraftCms\Cms\Cms;
89
use CraftCms\Cms\Support\Str;
910
use DateInterval;
1011
use DateTime;
@@ -31,7 +32,7 @@ class Formatter
3132
}
3233

3334
public string $timeZone {
34-
get => $this->timeZone ?? app()->getTimezone();
35+
get => $this->timeZone ?? Cms::timezone();
3536
}
3637

3738
public string $defaultDateFormat = 'medium';

src/Twig/Twig.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -132,7 +132,7 @@ public function create(): Environment
132132
}
133133

134134
$core = $twig->getExtension(CoreExtension::class);
135-
$core->setTimezone(app()->getTimezone());
135+
$core->setTimezone(Cms::timezone());
136136

137137
event(new TwigCreated($twig, TemplateMode::get()));
138138

tests/TestCase.php

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66

77
use Craft;
88
use craft\test\TestSetup;
9+
use CraftCms\Cms\Cms;
910
use CraftCms\Cms\Dashboard\Widgets\Widget;
1011
use CraftCms\Cms\Database\LaravelMigrations;
1112
use CraftCms\Cms\Database\Migrations\Install;
@@ -30,7 +31,6 @@
3031
use Illuminate\Foundation\Testing\RefreshDatabase;
3132
use Illuminate\Foundation\Testing\RefreshDatabaseState;
3233
use Illuminate\Support\Facades\Cache;
33-
use Illuminate\Support\Facades\Config;
3434
use Illuminate\Support\Facades\Context;
3535
use Illuminate\Support\Facades\DB;
3636
use Illuminate\Support\Facades\File;
@@ -62,8 +62,7 @@ protected function setUp(): void
6262
// Reset timezone to a consistent value for tests
6363
// This is needed because AppServiceProvider::setTimezone() runs during boot,
6464
// before RefreshDatabase has prepared the database, potentially reading stale data
65-
Config::set('app.timezone', 'America/Los_Angeles');
66-
date_default_timezone_set('America/Los_Angeles');
65+
Cms::config()->timezone('America/Los_Angeles');
6766

6867
// Tests run in Cp by default
6968
TemplateMode::set(TemplateMode::Cp);

0 commit comments

Comments
 (0)