Skip to content

Persist and expose Umbraco system dates as UTC #19705

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 16 commits into
base: v17/feature/utc-system-dates
Choose a base branch
from

Conversation

AndyButland
Copy link
Contributor

@AndyButland AndyButland commented Jul 10, 2025

Prerequisites

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

Description

This is a first PR toward making Umbraco's handling of system dates more consistent by using UTC throughout. It's targeted at v17/feature/utc-system-dates, a feature branch taken from v17/dev, with the idea that we create a few, smaller PRs into the feature branch and then finally merge it into v17/dev when we are happy with it.

When merged, this PR will make the following changes:

  • Remove NPoco attributes that would ensure we didn't treat retrieved datetimes as UTC, as we now do want to do this and use the default behaviour.
  • Removed cases where we use SpecifyKind to ensure we have local server time when we have otherwise retrieved UTC. Again UTC is what we want now.
  • Removed some UTC suffixes from property names. Now we are using UTC throughout, we don't need to have this suffix to indicate this.
  • Updated all cases relating to persisted system dates where we explicitly set a date to DateTime.Now to use DateTime.UtcNow.
  • Migrate existing database date constraints from server datetime to UTC datetime (SQLServer only - as noted in comments, I don't think this is necessary for SQLite given the limited ALTER TABLE support, the existing constraints aren't correct, and we don't rely on them in application code).
  • Updated the persistence DTOs such that they no longer create database constraints on new installs for the current datetime, rather for the UTC datetime.
  • Added an extension method that ensures UTC when we expect it, as currently, at least with some databases, NPoco returns an unspecified Kind, and it's the same when retrieving from the hybrid cache. Used this in factory methods to ensure entities and published content are built with datetimes as UTC.
    • It would be nice to avoid this, as it has led to a few cases where I've had to chase down dates that were coming through incorrectly in the management API and fix them in the appropriate repository or factory method. But it seems it's necessary. Doing it here is at least encapsulated somewhat in factories where entities are built, and this is the point where we know for sure we have UTC and by setting the Kind we ensure anywhere downstream gets this too.

Note that the following is not part of this PR, so isn't expected to work correctly:

  • Migration of existing system dates from server time to UTC
  • No changes have been made to content dates via the datetime picker.

Note also that I've removed some tests from files that were completely commented out (since Umbraco 15 I believe, with the introduction of the Hybrid cache). Most of them used dates and would get out of sync if we kept them, so I thought it was better now to remove.

Testing

Date Persistence

Easiest for testing to start with is to start off with a clean database and install Umbraco. Using database queries like the following you can verify that the default data installed uses UTC:

select key, updated from umbracoKeyValue
select id,text,createDate from umbracoNode
select nodeId, versionDate from umbracoContentVersion
select * from umbracoContentSchedule
select userGroupAlias, createDate,updateDate from umbracoUserGroup
select id, lastPasswordChangeDate, lastLoginDate, createDate, updateDate from umbracoUser
select eventDetails, eventDateUtc from umbracoAudit
select logComment, datestamp from umbracoLog

Then make some updates that will affect dates, e.g.:

  • Logout and in as a user
  • Update a user group
  • Create a document type
  • Create some content based on that document type, save it, and schedule it.
  • Verify with the above and similar database queries that the expected UTC dates are stored.

Date Presentation

Management API

Verify management API endpoints are returning the expected dates, e.g.:

GET /umbraco/management/api/v1/document/{id}

Should return datetime responses like:

  ...
  "variants": [
    {
      "state": "Draft",
      "publishDate": null,
      "scheduledPublishDate": "2025-07-17T10:49:00+00:00",
      "scheduledUnpublishDate": null,
      "createDate": "2025-07-10T10:45:49.3874959+00:00",
      "updateDate": "2025-07-10T10:45:49.3874959+00:00",
      "culture": null,
      "segment": null,
      "name": "Test"
    }
  ]
  ...
Backoffice

Verify that the backoffice is displaying the dates in the user's local time. I haven't touched this, but seems they "just work" due to the use of localized dates, so long as we are providing a date with timezone information from the management API, which we are.

Delivery API

Verify delivery API endpoints are returning the expected dates, e.g.:

GET /umbraco/delivery/api/v2/content/item/{id}

Should return datetime responses like:

{
    "contentType": "testPage",
    "name": "Test",
    "createDate": "2025-07-10T10:45:49.3874959Z",
    "updateDate": "2025-07-10T12:40:35.9592863Z",
Templates

Verify that Razor rendering makes available the system dates as UTC, e.g. with:

<div>Created On: @Model.CreateDate (Kind: @Model.CreateDate.Kind)</div>
<div>Updated On: @Model.UpdateDate (Kind: @Model.UpdateDate.Kind)</div>

Migration of Database DateTime Default Constraints

For this one take an Umbraco database for Umbraco 16, and verify for example that the umbracoNode.createDate table has a default value of getdate().

Then connect the database to the code in this PR and restart so the migration runs.

You should find that the default is now getutcdate().

@AndyButland AndyButland marked this pull request as ready for review July 10, 2025 17:26
@AndyButland AndyButland changed the title Persist Umbraco system dates as UTC Persist and expose Umbraco system dates as UTC Jul 11, 2025
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.

1 participant