Skip to content

Migrate system dates from local server time to UTC#19798

Merged
AndyButland merged 10 commits intov17/feature/utc-system-datesfrom
v17/feature/utc-system-dates-data-migration
Jul 30, 2025
Merged

Migrate system dates from local server time to UTC#19798
AndyButland merged 10 commits intov17/feature/utc-system-datesfrom
v17/feature/utc-system-dates-data-migration

Conversation

@AndyButland
Copy link
Contributor

@AndyButland AndyButland commented Jul 25, 2025

Prerequisites

  • I have added steps to test this contribution in the description below

Description

This is the second part of the effort to make Umbraco's handling of system dates more consistent by using UTC throughout.

#19705 makes changes such that we persist and expose UTC dates. This PR is a migration to update all the existing system dates stored in local server time to UTC.

The migration will run automatically and will detect the server time. If for some reason there's a need to disable the migration, or to override the detection of the local server time, this can be done in configuration:

To disable:

  "SystemDateMigration": {
    "Enabled": false
  }

To use a specific timezone for the local server:

  "SystemDateMigration": {
    "LocalServerTimeZone": "Eastern Standard Time"
  }

Testing

To test, run Umbraco and verify the migration completes via the log messages. Examine the database before and after to check the datetime values.

Verify the configuration values act as expected.

In my own testing I've run this locally where I'm on W. Europe Standard Time.

I've verified with SQL Server using the following queries:

select createDate from umbracoNode where id = 4258
-- Before: 2025-03-10 08:37:01.830
-- After: 2025-03-10 07:37:01.830

select eventDateUtc from umbracoAudit where id = 1
-- Before: 2024-12-20 11:21:51.167
-- After: 2024-12-20 10:21:51.167

select registeredDate from umbracoServer where id = 1003
-- Before: 2025-01-08 11:49:10.123
-- After: 2025-01-08 10:49:10.123

select lastLoginDate from umbracoUser where id = -1
-- Before: 2025-07-10 11:49:01.873
-- After: 2025-07-10 09:49:01.873

Note that the first three go back one hour, and the last one two hours - this as the latter is during summer time when the offset from UTC is two hours rather than one. So with SQL Server we can handle daylight saving time in the conversions.

And with SQLite using:

select id, createDate from umbracoNode where id = 1056
-- Before: 2025-02-05 07:08:53.8950557
-- After: 2025-02-05 06:08:53

select eventDateUtc from umbracoAudit where id = 1
-- Before: 2025-05-05 05:06:51.0795237
-- After: 2025-05-05 04:06:51

select registeredDate from umbracoServer where id = 1
-- Before: 2025-05-05 07:07:48.8035498
-- After: 2025-05-05 06:07:48

select lastLoginDate from umbracoUser where id = -1
-- Before: 2025-07-23 08:08:05.2174383
-- After: 2025-07-23 07:08:05

Note here for all we just go back one hour. As per the comment in the code, we don't have the same features available in the database to handle daylight saving, but this is acceptable given it's likely non-production and these are historical dates where 100% accuracy is unlikely to be necessary.

And then with "Eastern Standard Time" configured as my local server time zone:

select eventDateUtc from umbracoAudit where id = 1
-- Before: 2025-05-05 05:06:51.0795237
-- After: 2025-05-05 10:06:51

@AndyButland AndyButland requested a review from Copilot July 25, 2025 09:45
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull Request Overview

This PR implements a migration to convert existing system dates from local server time to UTC as part of Umbraco's effort to make date handling more consistent. The migration automatically detects the server timezone and updates all relevant datetime columns across multiple tables in the database.

Key changes:

  • Adds a new migration MigrateSystemDatesToUtc that converts dates in 27 database columns from local time to UTC
  • Introduces configuration options to disable the migration or override timezone detection
  • Includes validation for configuration settings to ensure valid timezone names

Reviewed Changes

Copilot reviewed 7 out of 7 changed files in this pull request and generated 1 comment.

Show a summary per file
File Description
MigrateSystemDatesToUtc.cs Core migration class that handles timezone detection and updates datetime columns across all relevant tables
SystemDateMigrationSettings.cs Configuration model defining migration settings with timezone and enabled properties
SystemDateMigrationSettingsValidator.cs Validator ensuring configured timezone names are valid system timezones
UmbracoPlan.cs Registers the new migration in the upgrade plan
UmbracoBuilder.Configuration.cs Adds configuration registration for the new settings
Constants-Configuration.cs Defines configuration key constant for the new settings
SystemDateMigrationSettingsValidatorTests.cs Unit tests covering validation scenarios for the configuration settings
Comments suppressed due to low confidence (2)

src/Umbraco.Infrastructure/Migrations/Upgrade/V_17_0_0/MigrateSystemDatesToUtc.cs:102

  • Missing opening brace for the method. The method declaration should be followed by an opening brace.
    private static TimeSpan GetTimezoneOffset(string timeZoneName)

src/Umbraco.Infrastructure/Migrations/Upgrade/V_17_0_0/MigrateSystemDatesToUtc.cs:107

  • Parameter name 'columName' appears to be a typo. It should be 'columnName' for consistency and clarity.
    private void MigrateDateColumn(IScope scope, string tableName, string columName, string timezoneName, TimeSpan timeZoneOffset)

…em-dates-data-migration

# Conflicts:
#	src/Umbraco.Infrastructure/Migrations/Upgrade/UmbracoPlan.cs
@AndyButland AndyButland merged commit 5a21cf3 into v17/feature/utc-system-dates Jul 30, 2025
3 of 4 checks passed
@AndyButland AndyButland deleted the v17/feature/utc-system-dates-data-migration branch July 30, 2025 09:28
AndyButland added a commit that referenced this pull request Aug 22, 2025
* Persist and expose Umbraco system dates as UTC (#19705)

* Updated persistence DTOs defining default dates to use UTC.

* Remove ForceToUtc = false from all persistence DTO attributes (default when not specified is true).

* Removed use of SpecifyKind setting dates to local.

* Removed unnecessary Utc suffixes on properties.

* Persist current date time with UtcNow.

* Removed further necessary Utc suffixes and fixed failing unit tests.

* Added migration for SQL server to update database date default constraints.

* Added comment justifying not providing a migration for SQLite default date constraints.

* Ensure UTC for datetimes created from persistence DTOs.

* Ensure UTC when creating dates for published content rendering in Razor and outputting in delivery API.

* Fixed migration SQL syntax.

* Introduced AuditItemFactory for creating entries for the backoffice document history, so we can control the UTC setting on the retrieved persisted dates.

* Ensured UTC dates are retrieved for document versions.

* Ensured UTC is returned for backoffice display of last edited and published for variant content.

* Fixed SQLite syntax for default current datetime.

* Apply suggestions from code review

Co-authored-by: Laura Neto <[email protected]>

* Further updates from code review.

---------

Co-authored-by: Laura Neto <[email protected]>

* Migrate system dates from local server time to UTC (#19798)

* Add settings for the migration.

* Add migration and implement for SQL server.

* Implement for SQLite.

* Fixes from testing with SQL Server.

* Fixes from testing with SQLite.

* Code tidy.

* Cleaned up usings.

* Removed audit log date from conversion.

* Removed webhook log date from conversion.

* Updated update date initialization on saving dictionary items.

* Updated filter on log queries.

* Use timezone ID instead of system name to work cross-culture.

---------

Co-authored-by: Laura Neto <[email protected]>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants