
Heads-up: This is a longer post. If your email app cuts it short, look for "View entire message" at the bottom, or read it online.
Every Azure SQL database has always lived in one time zone: UTC. Ask for GETDATE() at 8:49 PM in Texas, and the database answers 1:49 AM. Tomorrow.
That changed on September 28. Microsoft announced the public preview of local time zone support in Azure SQL Database. With one statement, a database can now answer in Central, Tokyo or India time.
It sounds like a small setting. It isn't. Time looks simple until you store it, sort it, and compare it across a daylight saving change.
So before writing about it, I built a lab. Two databases, one left in UTC and one switched to Central time, and 15 test scenarios. Most confirmed what the announcement says. Some gave wrong answers without a single error message. And one found a problem the announcement doesn't mention.
In this post: how the feature works, where it helps, what broke in my lab, and the pros and cons of local time versus UTC. If you don't work with databases, there's a glossary at the end, and the main lesson applies to any system that records time.
How it works
There are two new controls.
The database setting is persistent. Every new connection inherits it, and it takes effect immediately:
ALTER DATABASE SCOPED CONFIGURATION
SET TIME_ZONE = 'Central Standard Time';
-- back to the default (UTC)
ALTER DATABASE SCOPED CONFIGURATION SET TIME_ZONE = LOCAL;The session setting applies to one connection only. It follows the ANSI SQL standard:
SET TIME ZONE 'India Standard Time';
-- back to the database setting
SET TIME ZONE LOCAL;When both exist, the most specific one wins: the session first, then the database, then the platform default, which is UTC.

The setting changes what the "current time" functions return: GETDATE(), SYSDATETIME(), CURRENT_TIMESTAMP, CURRENT_DATE and SYSDATETIMEOFFSET(). Two functions ignore it and always return UTC: GETUTCDATE() and SYSUTCDATETIME().
Here's what my two databases returned at the same moment, 8:49 PM Central on October 15:
Function | Database in UTC | Database in Central time |
|---|---|---|
GETDATE() | 2026-10-16 01:49 | 2026-10-15 20:49 |
CURRENT_DATE | 2026-10-16 | 2026-10-15 |
SYSDATETIMEOFFSET() | 01:49 +00:00 | 20:49 −05:00 |
GETUTCDATE() | 01:49 | 01:49 (unchanged) |
Notice the date. Same moment, two different days. That detail comes back later.
What the setting doesn't change matters just as much. Data you already stored is not converted. System views, DMVs and Query Store stay in UTC. Temporal table history stays in UTC. And AT TIME ZONE works exactly as before.
Yes, that Arnold Schwarzenegger.
He has a newsletter on beehiiv. So do Codie Sanchez, Jay Shetty, David Begnaud, Colin & Samir, and Joanna Stern.
They could publish just about anywhere. They chose beehiiv to build a direct connection with the people who want to hear from them most. And you can do the same, whether you’re world-famous or just at the start of your plan for world domination.
Where it helps: five use cases
1. Moving a database from a server that ran on local time
For decades, on-premises SQL Server took its time zone from Windows. Many applications were built on that: a procedure that closes the business day at midnight, a report that asks for "today", a DEFAULT GETDATE() on every order.
Moving them to Azure SQL Database used to mean rewriting that logic, or choosing Azure SQL Managed Instance, where you pick the time zone only when you create the instance. Now a new database can be set to the old server's zone before the first row arrives. This is the strongest use case.
2. Reports and ad hoc queries
People think in local time. Asking an analyst to write AT TIME ZONE 'UTC' AT TIME ZONE 'Central Standard Time' in every query is how mistakes happen. With the session setting, a reporting connection runs SET TIME ZONE once, and the stored data stays in UTC. I come back to this one at the end, because it's the pattern I recommend.
3. One database per customer
Software providers that give each customer its own database can set each one to that customer's zone, on the same logical server or elastic pool. End-of-day jobs and default timestamps line up with each customer's business hours.
4. An existing database full of UTC history
This is where to be careful. If your database already holds months or years of UTC timestamps in datetime or datetime2 columns, switching the database to local time mixes two kinds of values in the same column, with nothing to tell them apart. The next section shows what that looks like.
5. Global systems
If your data comes from several regions, flows through services that use UTC, or must be compared across systems, UTC is still the right choice for what you store.
What broke in my lab
Lab setup: Azure SQL Database in Central US, two databases, tested with sqlcmd and SqlPackage on October 15, 2026, while Central time was on daylight saving (UTC−5). Everything ran in my own lab subscription, with test data only. Every script and result is in the lab runbook.
1. Old UTC rows and new local rows in one column
I created an Orders table with a DEFAULT GETDATE() column and inserted 10 orders while the database was still in UTC. Then I switched the database to Central time and let the unchanged "application" insert 5 more.
The switch succeeded. The inserts succeeded. Then I asked a few simple questions.

The 5 new orders were stored 5 hours "behind" the old ones. So the database said the latest order was number 10, when it was 15. It counted 15 orders in the last hour instead of 10. It found 10 orders in the future: all the old data. And sorted from oldest to newest, the newest orders came first.
A datetimeoffset column in the same table kept the right order the whole time, because each value carries its own offset.
Nothing failed. The answers were simply wrong. That's the most dangerous kind of bug, because nobody gets paged for it.
2. Is there a performance gain? Let's check
With the database speaking local time, a filter like WHERE event_time > GETDATE() needs no conversion on the column, so it can use an index. Does that make queries faster? I tested "orders since midnight, local time" on 200,000 rows stored in UTC, four different ways:
Query | Index | Reads | Rows | Correct? |
|---|---|---|---|---|
A. Convert the column with AT TIME ZONE | Scan | 425 | 5,786 | Yes |
B. Convert local midnight to UTC once, then compare | Seek | 16 | 5,786 | Yes |
C. Compare the UTC column to today's local date | Seek | 19 | 7,175 | No, +1,389 rows |
D. Same filter on a column stored in local time | Seek | 16 | 5,786 | Yes |
Query C used the index and was fast. It also returned 1,389 extra rows: five hours that belong to another day.
So, is there a gain? Yes, when the column holds local time (query D): an index seek, 16 reads, and the right answer. On a column that holds UTC, the same shortcut is fast but wrong. For UTC data, convert the boundary, not the column (query B):
DECLARE @start datetime2 =
CAST(CAST(GETDATE() AS date) AS datetime2) -- local midnight
AT TIME ZONE CURRENT_TIMEZONE_ID()
AT TIME ZONE 'UTC'; -- same moment in UTC
SELECT COUNT(*) FROM dbo.Events WHERE EventTimeUtc >= @start;3. Time travel to nowhere
System-versioned temporal tables keep their history in UTC, no matter the setting. A query FOR SYSTEM_TIME AS OF the local current time returned 0 rows, with no error. Passing SYSUTCDATETIME() or a datetimeoffset value returned the right history.
4. WAITFOR TIME still runs on UTC
I asked a script to wait until a Central time 5 seconds away. It was still waiting when my 30-second timeout stopped it. The engine read the target as UTC, about 19 hours away. A UTC target returned in 5 seconds. Jobs that use WAITFOR TIME still need a UTC target.
5. Daylight saving: the hour that happens twice
On November 1, Central time falls back from 2:00 AM to 1:00 AM. In the lab, two events one hour apart, at 06:30 and 07:30 UTC, both became 1:30 AM local. The naive difference between them was 0 minutes. The real difference was 60.
In March it's the opposite: 2:30 AM doesn't exist. A naive difference from 1:59 AM to 3:00 AM says 61 minutes. Only 1 minute passed.
And a fixed "minus 5 hours" conversion is right in July and wrong by an hour in January. Let the engine do it with AT TIME ZONE and a zone name, never a fixed offset.
6. The small errors that will catch you
Error | What I tried | What to do instead |
|---|---|---|
Msg 12149 | 'CST', 'America/Chicago', 'Central Time', '-06:00' | Use Windows zone names from sys.time_zone_info, like 'Central Standard Time' |
Msg 102 | Curly quotes pasted from a web page | Use plain straight quotes |
Msg 102 | SET TIME ZONE @tz | Variables aren't accepted. Build the statement with dynamic SQL |
Msg 226 | The database setting inside BEGIN TRAN | Run it outside a transaction. The error also stops the rest of the batch |
Msg 443 | SET TIME ZONE inside a scalar function | Not allowed. The function inherits the caller's zone |
Msg 12110 | A different zone for secondary replicas | Not supported. Secondaries follow the primary |
Msg 5074 + 4922 | Changing OrderDate to datetimeoffset | Drop the DEFAULT GETDATE() constraint first, recreate it after |
And a few surprises with no error at all:
SET TIME ZONE survives a ROLLBACK. It isn't part of the transaction.
SET TIME ZONE LOCAL goes back to the database setting, not to UTC.
CURRENT_TIMEZONE() showed (UTC-06:00) while the real offset was −05:00. Don't read the offset from that text.
The session DMV runs one batch behind. sys.dm_exec_sessions shows the zone from when the current batch started.
The zone name is stored exactly as typed. 'central standard time' works, but it's saved in lower case, which deployment scripts that compare text may flag as drift.
7. Exports and deployments
The announcement lists one known issue: when tools script the database setting, the zone name loses its quotes. I reproduced it. The generated deployment script said SET TIME_ZONE = CENTRAL STANDARD TIME;, without quotes and in upper case, and it failed with Msg 102.
I also hit one the announcement doesn't mention. BACPAC export failed completely when any stored procedure or trigger contained SET TIME ZONE (error SQL46010, SqlPackage 170.5.96). With those objects removed, the export worked. If you rely on BACPAC exports for copies or archives, test this before you put SET TIME ZONE in your code.
What worked exactly as promised
The database setting took effect immediately, for the current connection and new ones. No reconnect.
SET TIME ZONE inside a procedure reverted when the procedure ended, even in nested procedures and even when the procedure failed with an error. Triggers and dynamic SQL behaved the same way.
A session setting never leaked into a new connection.
AT TIME ZONE ignored both settings, as documented.
DMVs, Query Store and object creation dates all stayed in UTC.
Converting a mixed column worked once each row was tagged correctly: 0 of 15 rows differed from the true time. The hard part in real life is knowing which rows are which.
Local time or UTC? The pros and cons
Area | Local time in the database | UTC in the database |
|---|---|---|
Migrating a local-time server | ✅ Behaves like the old server | ❌ Code changes wherever "now" or "today" is used |
Reports for people | ✅ "Today" means today | ⚠️ Needs conversion, or a session setting |
Daylight saving | ❌ Missing and repeated hours in naive columns | ✅ No gaps, no repeats |
Existing UTC data | ❌ Silently mixes two kinds of values | ✅ Nothing changes |
Many regions, global totals | ❌ Each database has its own clock | ✅ One clock for everything |
Logs, Query Store, temporal history | ⚠️ Those stay in UTC, so you compare two clocks | ✅ Same clock |
WAITFOR TIME and scheduled logic | ⚠️ Targets still need UTC | ✅ Works as is |
Export and deployment (preview) | ⚠️ Known scripting issue, and BACPAC export fails with SET TIME ZONE in code | ✅ No impact |
What I recommend
My conclusion after the lab: the best use of this feature isn't changing how you store time. It's changing how you look at it.
A new database moving from a local-time server: set the database zone before you load any data, and use
datetimeoffsetfor new columns where you can.An existing database with UTC history: leave the database in UTC. Use
SET TIME ZONEin reporting sessions to see the same data in local time.If you must switch an existing database: treat it as a data migration, not a setting change. Convert the columns to
datetimeoffset, tag old rows as UTC and new rows as local using a cut-over time or ID, and only then change the setting.Global and distributed systems: stay in UTC.
Here's the pattern from option 2. The data stays in UTC, and the report shows local time:
SET TIME ZONE 'Central Standard Time';
SELECT OrderID,
OrderDateUtc AT TIME ZONE 'UTC'
AT TIME ZONE CURRENT_TIMEZONE_ID() AS OrderDateLocal
FROM dbo.Orders;Before you change the setting on any database:
Search your code for GETDATE(), SYSDATETIME(), CURRENT_TIMESTAMP and CURRENT_DATE.
Find every column with a DEFAULT GETDATE() or SYSDATETIME().
Check temporal table queries, WAITFOR TIME, and anything scheduled.
Test a BACPAC export and your deployment pipeline.
Test the daylight saving dates for your zone, both in March and in November.
Remember it's a preview. Behavior can change before general availability.
Try it yourself
Everything I ran is in the lab runbook: the setup commands, the T-SQL for all 15 steps, the results, and a download with the full script set. Run it in a test subscription, never in production.
The announcement has the full syntax and the list of what is and isn't affected: Announcing the Public Preview of Local Time Zone Support in Azure SQL Database. If you find an issue, report it through the Azure SQL feedback site. That's what previews are for.
Will you use it? Hit reply and tell me which use case fits your systems, or which one worries you. I read every reply.
Glossary
Term | What it means |
|---|---|
BACPAC / DACPAC | Files that package a database. A BACPAC holds the schema and the data; a DACPAC holds only the schema, for deployments. |
datetime / datetime2 | Date and time types with no time zone information. The same value could be UTC or local, and nothing in the data says which. |
datetimeoffset | A date and time type that also stores the offset from UTC, like −05:00, so the exact moment is never ambiguous. |
Daylight saving time (DST) | Moving clocks forward in spring and back in fall. It creates one missing hour and one repeated hour each year. |
DMV | Dynamic management view: a system view that shows what the database engine is doing, such as sessions and queries. |
Index seek / scan | A seek jumps straight to the rows it needs. A scan reads the whole index. Seeks are usually much faster. |
Public preview | A feature that anyone can try before it's final. It may change, and it isn't covered like a generally available feature. |
Session | One connection to the database, from the moment it opens until it closes. |
Temporal table | A table that keeps the history of every change automatically, so you can query it "as of" a past moment. |
UTC | Coordinated Universal Time, the world's reference clock. It never changes for daylight saving. |
Until Friday, and thank you for your time.
Alex
How I write: every post starts from my own notes and experience. I use AI tools to help draft and edit, and I review every word before it goes out.
Disclaimer: The views expressed in this article are those of the author and do not necessarily reflect the official policy or position of Microsoft. The author is a Microsoft employee. All technical details and product behaviors described are based on publicly available Microsoft documentation as of October 2026 and on the author's own tests of a public preview feature, and are intended to provide a high-level overview for educational and architectural planning purposes.


