Skip to content

FIX: Updates TimeZone support for DATETIMEOFFSET type, fixes incorrect Now() in USE_TZ=True cases.#484

Merged
bewithgaurav merged 7 commits into
microsoft:devfrom
trolldbois:dev
May 22, 2026
Merged

FIX: Updates TimeZone support for DATETIMEOFFSET type, fixes incorrect Now() in USE_TZ=True cases.#484
bewithgaurav merged 7 commits into
microsoft:devfrom
trolldbois:dev

Conversation

@trolldbois
Copy link
Copy Markdown
Contributor

@trolldbois trolldbois commented Dec 26, 2025

  1. handle_datetimeoffset Fixes the datetime parsing of column type DATETIMEOFFSET. This updates Pull Add TimeZone support #140 that forgot to parse the timezone offset part of the type. This is a straightforward bugfix. (see Datetimeoffset support ? #136 )

  2. sqlserver_now Fixes Now(), to use timezone-aware SYSDATETIMEOFFSET(), to ensure a timezone aware (USE_TZ) django get a correct value for Now() when the database OS is not configured as UTC timezone.

This also fixes #371 .

This fixes the handling of the timezone part for a DATETIMEOFFSET type.
When USE_TZ=True, it's important that Now() reflect the current time, with timezone offset. If the database system OS is not using UTC , the SYSDATETIME() is a local-timezone value, which incorrectly CASTED as UTC (because offset = 00:00). This fix and the previous one allows to leverage the timezone part of SYSDATETIMEOFFSET() to ensure the timezone offset makes Now() the correct value.
@trolldbois
Copy link
Copy Markdown
Contributor Author

@microsoft-github-policy-service agree

@trolldbois trolldbois changed the title Updates TimeZone support for DATETIMEOFFSET type, fixes incorrect Now() in USE_TZ=True cases. FIX: Updates TimeZone support for DATETIMEOFFSET type, fixes incorrect Now() in USE_TZ=True cases. Dec 26, 2025
@trolldbois
Copy link
Copy Markdown
Contributor Author

trolldbois commented Dec 26, 2025

An explainer for fix 2. sqlserver_now
If you have a model that uses auto_now or auto_now_add the database value of that field will use the SQL server's Now() function. Using Now=SYSDATETIME() returns a timezone deficient value, with the database OS's local time (So lets say time in Africa/Nairobi +03:00).
But with settings.USE_TZ=True, django will parse this timezone-deficient value, and incorrectly replace the empty timezone offset (tzinfo) with the default django UTC offset (00:00) instead of the offset that the OS's system timezone used (+03:00).
So previous to this fix, all usage of Now(), for database OS not using UTC as system timezone, have stored a localtime, that is incorrectly parsed back by django as UTC. In this example, Now() would be parsed back by django as a datetime 3 hours in the future.
By using Now=SYSDATETIMEOFFSET(), we allow the storage of the timezone offset in DATETIMEOFFSET columns, whereas for DATETIME2 columns, the offset is truncated by sql server, and the value remains the same as SYSDATETIME().
With the addition of the handle_datetimeoffset bugfix, django will parse back a datetime with the correct timezone information, and now becomes the present, once again.

Notably, if your model still use a DATETIME2 column, and the Database timezone is not UTC, you will still experience a bug when using Now() or a model with auto_now, auto_now_add , unless you set your django database setting to the correct TIME_ZONE. But then you will experience other issues when USE_TZ=True . Logically, DATETIME2 is not compatible with USE_TZ=True when the SQL Server OS is using a timezone that is not UTC. See https://github.com/microsoft/mssql-django/wiki/Timezone-Support for migration.

Copilot AI review requested due to automatic review settings May 21, 2026 04:01
Copy link
Copy Markdown
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 improves timezone correctness in the SQL Server backend by (1) decoding DATETIMEOFFSET values into timezone-aware Python datetimes (including the stored offset) and (2) updating the SQL emitted for Django’s Now() so tz-aware projects don’t receive misleading “local time treated as UTC” results.

Changes:

  • Parse DATETIMEOFFSET binary values into datetime objects with a tzinfo derived from the stored offset.
  • Emit SYSDATETIMEOFFSET() for Now() when settings.USE_TZ=True (and keep SYSDATETIME() otherwise).

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated 4 comments.

File Description
mssql/base.py Extends handle_datetimeoffset() to include timezone offset when constructing Python datetime values.
mssql/functions.py Updates Now() SQL generation to use SYSDATETIMEOFFSET() under USE_TZ.

Comment thread mssql/functions.py Outdated
Comment thread mssql/base.py Outdated
Comment thread mssql/base.py Outdated
Comment thread mssql/functions.py Outdated
bewithgaurav and others added 3 commits May 21, 2026 18:40
…t tests

- Add missing 'from django.conf import settings' to functions.py
  (fixes NameError when Now() is compiled)
- Update handle_datetimeoffset comment to document full 9-element tuple
- Add tests for positive/negative timezone offsets in handle_datetimeoffset
- Add NowSQLTemplateTests to verify SYSDATETIMEOFFSET vs SYSDATETIME
  based on USE_TZ setting
- Remove unnecessary else branch in sqlserver_now

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Cover edge cases raised during review: -09:30 (Marquesas)
and +05:45 (Nepal) to verify signed offset components are
handled correctly by handle_datetimeoffset.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@bewithgaurav
Copy link
Copy Markdown
Collaborator

/azp run

@azure-pipelines
Copy link
Copy Markdown

Azure Pipelines successfully started running 1 pipeline(s).

…ame)

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@bewithgaurav
Copy link
Copy Markdown
Collaborator

/azp run

@azure-pipelines
Copy link
Copy Markdown

Azure Pipelines successfully started running 1 pipeline(s).

@bewithgaurav bewithgaurav merged commit 34888f4 into microsoft:dev May 22, 2026
62 checks passed
@bewithgaurav
Copy link
Copy Markdown
Collaborator

@trolldbois - thanks a lot for raising this PR
I've added a few tests and merged this off - thanks again! :)

This was referenced May 22, 2026
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.

Datetime conversion issue with USE_TZ and settings.TIME_ZONE != 'UTC'?

4 participants