How to Handle Server vs Session Time Zone Settings in SQL Server

Working with dates and times in SQL Server can get tricky, especially once you add time zones into the mix. One common point of confusion is the difference between the server’s time zone and the session’s time zone. If you’re not careful, you can end up with inconsistent data or timestamps that don’t line up with what your users expect.

Let’s look at how SQL Server treats time zones and how you can handle server versus session time zone differences cleanly.

Server Time Zone vs Session Time Zone

First, SQL Server doesn’t have a built-in concept of “session time zones” like Oracle or PostgreSQL. Instead:

  • The server time zone is determined by the operating system that SQL Server runs on. If the OS is set to UTC+2, then GETDATE() will return local time in UTC+2.
  • The session (your connection) doesn’t automatically carry a time zone setting. However, you can control how you interpret or display times within a session by using functions like AT TIME ZONE or by always working in UTC and converting when needed.

This means that two queries run on the same server at the same time will return the same timestamp with GETDATE(), regardless of which user or session runs them. But if you want user-specific time zones, you’ll need to explicitly convert.

Why This Matters

Imagine your SQL Server is hosted in New York (Eastern Time), but your users are in London (GMT). If you insert rows with GETDATE(), those times will be stamped in Eastern Time. A London-based user will see times that are five hours off. Without a clear strategy for dealing with such scenarios, your reporting, scheduling, or auditing could quickly get very messy.

Functions That Help

SQL Server has several built-in functions to make working with time zones manageable, including:

  • GETUTCDATE() – Returns the current UTC datetime (datetime type). Use this when you want to store everything in UTC.
  • SYSDATETIMEOFFSET() – Returns the current datetime including the server’s offset.
  • AT TIME ZONE – Converts a date/time value to another time zone using Windows time zone identifiers.

Here’s an example that demonstrates some of these:

-- Current UTC datetime (use this when storing values)
SELECT GETUTCDATE() AS UtcNow;

-- Current server datetime with offset info
SELECT SYSDATETIMEOFFSET() AS ServerDateWithOffset;

-- Convert UTC to a user’s local time zone (e.g., Pacific)
DECLARE @UserTimeZone NVARCHAR(50) = 'Pacific Standard Time';

SELECT 
    GETUTCDATE() AT TIME ZONE 'UTC' 
                 AT TIME ZONE @UserTimeZone AS PacificTime;

A Practical Approach

The safest approach in most systems is:

  1. Store in UTC – Insert all timestamps in UTC (using GETUTCDATE() or SYSUTCDATETIME()). This makes the data consistent regardless of where your server is located.
  2. Convert on output – When presenting data back to users, convert the UTC value to their preferred time zone using AT TIME ZONE.
  3. Track user time zones – If you have users across multiple zones, store their preferred time zone in a profile table and apply conversion dynamically.

Example

Here’s a quick example to demonstrate how it can be done:

-- Create the Orders table (storing all times in UTC)
CREATE TABLE dbo.Orders
(
    OrderID INT IDENTITY(1,1) PRIMARY KEY,
    CustomerName NVARCHAR(20) NOT NULL,
    Product NVARCHAR(15) NOT NULL,
    Quantity INT NOT NULL,
    OrderDateUtc DATETIME2 NOT NULL DEFAULT SYSUTCDATETIME()
);
GO

-- Insert sample data in UTC
INSERT INTO dbo.Orders (CustomerName, Product, Quantity, OrderDateUtc)
VALUES
    ('Shiza Johnson', 'Laptop', 1, SYSUTCDATETIME()),
    ('Shelly Smith', 'Headphones', 2, DATEADD(HOUR, -5, SYSUTCDATETIME())),
    ('Grant Green', 'Keyboard', 1, DATEADD(DAY, -1, SYSUTCDATETIME())),
    ('Ella Lopez', 'Ergonomic Chair', 1, DATEADD(DAY, -2, SYSUTCDATETIME())),
    ('Olly Brown', '4K Monitor', 2, DATEADD(DAY, -7, SYSUTCDATETIME()));
GO

-- Convert on output for a specific user time zone
DECLARE @UserTimeZone NVARCHAR(50) = 'GMT Standard Time';

SELECT 
    OrderID,
    CustomerName,
    Product,
    Quantity,
    OrderDateUtc AS StoredUtc,
    OrderDateUtc AT TIME ZONE 'UTC' 
                 AT TIME ZONE @UserTimeZone AS LocalOrderTime
FROM dbo.Orders;

Output:

OrderID     CustomerName         Product         Quantity    StoredUtc                              LocalOrderTime                               
----------- -------------------- --------------- ----------- -------------------------------------- ---------------------------------------------
1 Shiza Johnson Laptop 1 2025-08-26 23:56:01.2835046 2025-08-27 00:56:01.2835046 +01:00
2 Shelly Smith Headphones 2 2025-08-26 18:56:01.2835046 2025-08-26 19:56:01.2835046 +01:00
3 Grant Green Keyboard 1 2025-08-25 23:56:01.2835046 2025-08-26 00:56:01.2835046 +01:00
4 Ella Lopez Ergonomic Chair 1 2025-08-24 23:56:01.2835046 2025-08-25 00:56:01.2835046 +01:00
5 Olly Brown 4K Monitor 2 2025-08-19 23:56:01.2835046 2025-08-20 00:56:01.2835046 +01:00

By handling it this way, your data stays consistent, and you avoid problems when the server changes daylight saving rules or if you migrate SQL Server to a host in a different region.

Edge Cases to Watch

  • Daylight Saving Time (DST): Using AT TIME ZONE is safer than manually adding offsets because it automatically accounts for DST changes.
  • Old SQL Server versions: If you’re on SQL Server 2014 or earlier, you’ll need to handle offsets manually (storing UTC is even more important here).
  • Applications with multiple time zones: Don’t rely on the server’s clock. Always normalize to UTC and convert for display.

Final Thoughts

SQL Server doesn’t give each session its own time zone setting, so the difference between “server” and “session” time zones really comes down to how you handle conversions. If you stick to storing in UTC and only convert on output, you’ll avoid most headaches. The AT TIME ZONE function is your friend – it bridges the gap between server-local timestamps and user-specific expectations without requiring messy math.