Windows Sucks at Location & Automatic Timezones.

New Project 4

The Problem:

We have a customer with an office located in Brisbane, Australia, who has a pretty standard setup – Windows 11 Laptops, Cisco Networking, ZScaler for Internet Security, Ethernet to every desk, a common IT SOE.

However, a couple of weeks ago we started seeing hints of an issue with some of the laptops, users were reporting that their device timezone kept changing to Adelaide (which is 2 hours behind), and then back to Brisbane randomly.

This seemed like just a temporary thing at first, but it started getting worse, it went from 1 to 2 laptops, to 5, to 10, to the whole office, it was obvious something had gone wrong, so I started looking into it.

1764657930492
Example of what we were seeing, but pretend it says Adelaide and not Beijing.

How are Timezones automatically updated on Windows?

You ask a Desktop Support guy this question, and they’d probably say “oh it’s from AD/GPO”, or “it’s from the NTP server”, or “it’s from the switch/DHCP server”, but is that actually true? – Nope – Turns out Windows Exclusively uses location for automatic Timezones.

Specifically, the below are used:

  • GPS : accurate within approximately 10 meters. You won’t find many (if any) corporate laptops with GPS built-in, so I haven’t spent much time poking at this path.
  • Wi-Fi : accurate within approximately 30 meters – 500 meters. This method works by scanning the surrounding Network at all times when Wi-Fi is turned on (even if you aren’t actually connected to Wi-Fi), Windows also doesn’t care if you are using Ethernet, it will still scan. There is ZERO public documentation of the “algorithm” or “scoring logic” that Windows uses for this, we just know that it looks at nearby BSSID’s (usually the same as the MAC address, though Microsoft only ever calls them MAC’s) then checks the Microsoft geolocation database which we aren’t allowed to even see – at least not anymore.
  • Cell towers : accurate within approximately 300 meters – 3,000 meters. This is a good one, it might not be the most precise, but it’s highly likely to be accurate, of course this is only available on devices with a cellular modem, however it apparently does not require an active service or even a SIM card, it uses the Microsoft Geolocation Database similar to the Wi-Fi method.
  • IP address: accurate within approximately 1,000 meters – 5,000 meters. As many IT folks know, IP‑based location services aren’t very precise and can be wrong at times – IP addresses change often, and IP‑to‑location databases quickly become outdated. Microsoft maintains its own database for this, but in my experience, Windows only falls back to it when WI‑Fi based location is low-confidence/accuracy.

The system automatically selects the most appropriate location source based on availability, accuracy requirements, and power consumption considerations. – Microsoft


How Timezones are NOT updated on Windows:

  • NTP – So the thing about Network Time Protocol, is it has zero concept of timezones, it uses UTC time, always, it leaves timezone settings up to the OS of the client. Interestingly, Windows actually uses UTC behind the scenes for everything and just applies your timezone offset to stuff that is user facing, who knew.
  • Active Directory – AD actually has a protocol for syncing time from DC’s that is built off of (but also distinct to) NTP, it’s barely documented, but it’s called MS-SNTP. MS-SNTP is enabled by default in AD for all clients, except if you are running under a hypervisor (then Windows shrugs and uses the HV), but both will never set timezones, only time.
1764659775434
Windows client syncing from a Domain Controller.
  • DHCP – If you are well versed in DHCP options, you may know about option 101, which allows you to configure a timezone to be available from DHCP. However, rather annoyingly, Windows won’t ever request this option from the DHCP server, not on its own. There’s a good doc here about getting Windows to pull this from DHCP and actually use it, but by default the data never goes to the Windows client, so… nope.
  • Network switches/firewalls – Fairly obvious, these don’t play any part in Timezones being set, if a switch clock is set to Antarctica it doesn’t matter (looking at you network engineers). Similarly to DHCP, the 802.11v protocol does have some capability to advertise timezones (from WAP’s in this case), but this is rarely implemented in networking hardware, OpenWRT appears to support it, but Windows does not use it anyway.
  • Group Policies/Intune – Timezones are rarely set by Group Policy, it would only make sense if you have a single office location and/or had a robust policy that applied based on user/device location. We haven’t seen any customers with a setup like this, so in 90% of cases I would immediately rule out any policies as being the source of your device Timezones. That being said, it can be done.

So what’s causing our problem?

This is the tricky part, figuring out what location source Windows is getting the wrong information from.

Let’s start with logs, in addition to the notification the user gets, the following event is logged (event ID 1). As you can see, the change is coming from svchost.exe, so this is almost certainly the “Auto Time Zone Updater” service completing its regular check-in.

1764716707198
Event ID 1, the system time zone has changed.

Alright, so we know when changes are happening, but we don’t know why. Let’s check for more logs, right? – Nope. This is it.

Windows keeps its location tracking methods close to the chest. It won’t tell you which source it used, and it offers no real diagnostics. So when something goes sideways, we’re essentially on our own.

Screw it, I’ll make my own troubleshooting tool.

I wasn’t going to sit in front of a laptop all day, wait for the device timezone/location to be wrong and then quickly troubleshoot for the few minutes I had each time, there had to be a better way.

So I spun up PowerShell ISE and wrote a script to monitor the issue and collect data for troubleshooting. This is what is does:

1764718961572
My Timezone logging script

It’s fairly barebones, it uses GeoCoordinateWatcher to pull coordinates, looks them up against OpenStreetMap, and simultaneously scans nearby access points with netsh to capture BSSIDs. It grabs this data every 15 seconds. It’s a bit of a patchwork tool, and there’s plenty of room for refinement, but it collected exactly what I needed.

Add-Type -AssemblyName System.Device

$watcher = New-Object System.Device.Location.GeoCoordinateWatcher
$watcher.Start()
Start-Sleep 2

# CSV log files
$logFile = "$env:USERPROFILE\location_log.csv"
$alertFile = "$env:USERPROFILE\location_alerts.csv"

# Create CSV headers if files don't exist
if (-not (Test-Path $logFile)) {
    "Timestamp,Latitude,Longitude,Accuracy,City,State,Country,Source,PublicIP,SSIDs,BSSIDs" | Out-File $logFile -Encoding UTF8
}
if (-not (Test-Path $alertFile)) {
    "Timestamp,Latitude,Longitude,Accuracy,City,State,Country,Source,PublicIP,SSIDs,BSSIDs" | Out-File $alertFile -Encoding UTF8
}

while ($true) {
    # Wait for a valid location fix
    $loc = $watcher.Position.Location
    if ($loc -eq $null -or ($loc.Latitude -eq 0 -and $loc.Longitude -eq 0)) {
        Write-Host "Waiting for location fix..."
        Start-Sleep 5
        continue
    }

    $accuracy = $loc.HorizontalAccuracy
    $lat = $loc.Latitude
    $lon = $loc.Longitude

    # Source Classification
    if ($accuracy -le 20) {
        $source = "GPS"
    }
    elseif ($accuracy -le 80) {
        $source = "Likely WiFi"
    }
    elseif ($accuracy -le 300) {
        $source = "WiFi"
    }
    elseif ($accuracy -le 600) {
        $source = "WiFi/Cell"
    }
    elseif ($accuracy -le 1200) {
        $source = "Likely Cell"
    }
    elseif ($accuracy -le 2500) {
        $source = "Cell/IP"
    }
    elseif ($accuracy -le 5000) {
        $source = "Likely IP"
    }
    else {
        $source = "Unknown/Hybrid"
    }

    # Public IP
    try { 
        $publicIP = (Invoke-RestMethod -Uri "https://api.ipify.org?format=json").ip 
    } catch { 
        $publicIP = "Unavailable" 
    }

    # Wi-Fi SSID + BSSID scan
    try {
        $wifiScan = netsh wlan show networks mode=bssid
        $ssidMatches = @()
        $bssidMatches = @()

        foreach ($line in $wifiScan) {
            if ($line -match '^\s*SSID\s+\d+\s+:\s+(.*)$') { 
                $ssidMatches += $Matches[1].Trim() 
            }
            elseif ($line -match '^\s*BSSID\s+\d+\s+:\s+([0-9a-fA-F:]+)') { 
                $bssidMatches += $Matches[1].Trim() 
            }
        }

        if (-not $ssidMatches) { $ssidMatches = @("None found") }
        if (-not $bssidMatches) { $bssidMatches = @("None found") }

        $ssidCSV = '"' + ($ssidMatches -join "; ") + '"'
        $bssidCSV = '"' + ($bssidMatches -join "; ") + '"'

    } catch { 
        $ssidCSV = "Unavailable"
        $bssidCSV = "Unavailable"
    }

    # Reverse geocoding
    try {
        $geo = Invoke-RestMethod -Uri "https://nominatim.openstreetmap.org/reverse?format=json&lat=$lat&lon=$lon"

        if ($geo.address.city) { $city = $geo.address.city }
        elseif ($geo.address.town) { $city = $geo.address.town }
        elseif ($geo.address.suburb) { $city = $geo.address.suburb }
        else { $city = "Unknown" }

        if ($geo.address.state) { $state = $geo.address.state } else { $state = "Unknown" }
        if ($geo.address.country) { $country = $geo.address.country } else { $country = "Unknown" }

        # Normalise specific cities
        if ($city -match 'Brisbane') { $city = "Brisbane" }

    } catch {
        $city = $state = $country = "Unknown"
    }

    # Construct CSV line
    $csvLine = "{0},{1},{2},{3},{4},{5},{6},{7},{8},{9},{10}" -f `
        (Get-Date -Format "yyyy-MM-dd HH:mm:ss"), $lat, $lon, $accuracy, $city, $state, $country, $source, $publicIP, $ssidCSV, $bssidCSV

    # Output to console
    Write-Host $csvLine

    # Append to CSV logs
    Add-Content -Path $logFile -Value $csvLine
    if ($city -ne "Brisbane") { Add-Content -Path $alertFile -Value $csvLine }

    Start-Sleep 15
}

So I found a few affected users, set it to run quietly in the background, and logged about an hour’s worth of data.

Before I wrote this script, I had a hunch that the issue was somehow ZScaler related, since they don’t have any Brisbane datacentres (at least with our contract right now) and our egress IP through ZIA appeared in Sydney. We raised a ticket with them early on, (because it couldn’t hurt) and 2 days later got a response from them.

We have confirmed that this issue is not related to Zscaler, as Zscaler does not set or modify user timezones.

we recommend checking with your internal IT team, specifically focusing on your Windows/Active Directory (AD) settings, as these are the most likely sources of the timezone changes.

It seems that they didn’t really understand the issue, which was a common problem when trying to get any engineering/vendor help on this. If our Timezone was changing to Sydney instead of Adelaide, we would have pushed them further as this would be directly caused by ZIA.

Anyway, from my script it was pretty clear that the public IP address was not changing at all, which ruled out ZScaler, and based on the accuracy field, it aligned perfectly with the Wi-Fi scanning accuracy expected in metres.

So if we disable Wi-Fi it should stop scanning, and we can see if the issue goes away? Yep, I turned off WLAN on the affected devices and none of them changed their location from Brisbane, perfect.

So this means that Microsoft’s Wi-Fi location database is wrong for this location, but if that’s the case it should be affecting the business next door too, right?

So I spoke to the IT team from the business next door, and confirmed that they have the exact same issue, with Adelaide as well, and they have a completely separate network to us, wild.


Now, how do we fix this?

Well, for most customers, it’d be pretty simple, just disable automatic Timezones on Windows, you could push this via Intune or GPO pretty easily, it’s well documented.

For our customer, though, this wasn’t a valid option, for these reasons:

  • Users travel a lot as part of their roles, and the customer would like Timezones to be automatically updated for them.
  • Users are not comfortable managing the system Timezone themselves.
  • Service Desk don’t have the capacity to be fielding calls for incorrect system times.
  • The customer would like the core issue to be resolved rather than using a band-aid solution (fair enough).

Let’s get Microsoft to fix the Geolocation Database.

This is the next logical step, log a support ticket with Microsoft, tell them the problem, give them any data they need, and they should be able to fix it just fine, people seemed to have luck with this, though apparently it’s quite a long and painful process.

So we logged an MS ticket, SEV B (as we’ve since had a second location affected), and we’ll see where it goes.

Thank you. Your request was successfully submitted to Microsoft Support.

We actually logged our ticket through SoftwareOne, which handles vendor management for this customer via their USMV program, they helped a little at getting this through to MS.

This cost our customer some of their USMV credits, which is kind of wild to think about, considering this is a Microsoft issue and we don’t actually need technical support – we just need Microsoft to fix their problem, but this is basically our only channel to go through.

SoftwareOne had us get a bunch of things, the usual rubbish:

  • When did the issue start?
  • Has it happened before?
  • Timestamp when the timezone flipped
  • Whether the device roamed between APs

Microsoft’s first actual response was:

Are all the impacted machines Windows 11 24H2?

Does timezone change for all devices to the same location or random?

Was there any Wi-Fi access point from one location to another?

Please collect the below TSS logs.

Here we go, now we’re getting somewhere, the TSS logs gather exactly what Microsoft needs to fix the problem, and (annoyingly) a bunch of the other system information we have already provided.

So we just downloaded the file here. Ran the command requested below, and then uploaded the logs to a file transfer link they provided.

.\TSS.ps1 -NET_GeoLocation

5 days pass

I have analysed the logs, please refer them and advise a timeframe to discuss with you.

Please could you refer to the below BSSIDs and MAC’s, verify and confirm if they belong to your office network.

Attached were a bunch of logs, with a row similar to below, that had 79 different BSSID’s.

WifiMACs=aa11bb22cc01,-36,aa11bb22cc02,-35,aa11bb22cc0e,-52,aa11bb22cc0f,-52,bb22cc33dd10

At the end of the post I’ll also go into some findings from these logs 🙂

Our Network Engineer replied back, and we’re now waiting for a new response, with Christmas approaching soon we expect some more delays here.


What else can we do?

Well, if you don’t want to go the Microsoft route, there’s a few things you can try.


Undocumented Findings:

Our response from Microsoft included some logs from our device that are not visible in event viewer, and it reveals a bit about how the location service works (this guy had luck pulling them too). I won’t post our whole output, as it’d take me a while to anonymise it, but here are some interesting findings.

1. Windows Prioritises Wi-Fi over IP

Although Microsoft mentions that Windows uses “Wi-Fi, IP address, Cellular, and GPS,” the logs show a clear priority order and a provider evaluation system called PE’s. I saw this in practice as our office IP was very rarely used for location, lfsvc almost always uses Wi-Fi.

[Debug ] [Cpe] TotalPeCount=5, AvailPes=[Wifi,IpAddr,Unknown,Unknown,Unknown]
[Debug ] Acquire[...] SelectedPes: PrimaryPe=Wifi

2. Windows treats consent from users and policies differently

We can see here that Windows records whether location consent was provided via policy or via users. What Windows does with that information is unknown.

[Microsoft.Geolocation.Service] [Permission_IsLocationServiceHasAccessThroughGlobalSwitchOrPolicy] consentGranted=1, consentGrantedByPolicy=0

3. Windows also captures RSSI and channels for Wi-Fi based Location

We can see that Windows is sending the RSSI and channel information of nearby WAP’s (in addition to the BSSID’s) to the server http://inference.location.live.com

[Microsoft.Geolocation.Service.PII] [WebproxyRequest] RequestId=random, RequestType=2, serviceUrl=https://inference.location.live.net/inferenceservice/v21/pox/GetLocationUsingFingerprint, TrackingId=dd159-redacted-removed, RequestPayload=<?xml version="1.0" encoding="UTF-8"?>
BeaconFingerprint><Detections><Wifi7 cf="2412" BssId="08:7b:87:se:cr:et" rssi="-36" /><Wifi7 cf="2412" BssId="08:7b:87:se:cr:et" rssi="-35" /><Wifi7 cf="5240" BssId="08:7b:87:se:cr:et" rssi="-52" /><Wifi7 cf="5240" BssId="08:7b:87:se:cr:et" rssi="-52" /><Wifi7 cf="2462" BssId="08:7b:87:se:cr:et" rssi="-45" /><Wifi7 cf="2462" BssId="08:7b:87:se:cr:et" rssi="-43" /><Wifi7 cf="5500" BssId="08:7b:87:se:cr:et" rssi="-43" /><Wifi7 cf="5500"

4. Windows sends a lot of information about your endpoint to Microsoft.

The location service captures the following information about your computer.

  • OS Version (the specific build number)
  • Device type and platform architechture (e.g. PC, x86/ARM)
  • Device ID (uniquely identifies your device on their servers)
  • Device Manufacturer (e.g. Lenovo)
  • Your exact device model (e.g. 20VYS2VH00)
<GetLocationUsingFingerprint xmlns="http://inference.location.live.com" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema"><RequestHeader><Timestamp>2025-12-05T02:49:30.980+00:00</Timestamp><Authorization /><TrackingId>dd159-redacted-removed</TrackingId><ApplicationId>redacted-and-removed-caf98-98dasd-9a8sdua8</ApplicationId><DeviceProfile OSVersion="26100.1.amd64fre.ge_release.240331-1435" LFVersion="4.0" DeviceType="PC" Platform="" DeviceId="redacted-aaf2-removed-for-post" ExtendedDeviceInfo="LENOVO/20VYS2VH00" ClientGuid="00000000-0000-0000-0000-000000000000" /></RequestHeader><BeaconFingerprint><Detections><Wifi7 cf="2412" BssId="08:7b:87:se:cr:et" rssi="-36" /><Wifi7 cf="2412" BssId="08:7b:87:se:cr:et" rssi="-35" /><Wifi7 cf="5240" BssId="08:7b:87:se:cr:et" rssi="-52" /><Wifi7 cf="5240" BssId="c8:9e:43:se:cr:et" rssi="-73" /></Detections></BeaconFingerprint></GetLocationUsingFingerprint>

5. The problematic database is provided by Qualcomm..

In the logs we can see the below.

<ResolverStatus Status="Success" Source="SkyhookExternal"/>

This is the source of the location data Windows is using in our setup, and other environments.

We can read more about Skyhook Wireless here, they were acquired by Qualcomm around 2022, and they provide “Qualcomm Aware Positioning Services”.

Again, this is all undocumented, Windows might use different databases in different locations around the world, and accuracy can vary, I am just documenting what I’ve seen with our environment.

Sidenote, I’ve contacted Qualcomm using the form here, which has options to create technical support requests, but I get the feeling it all goes to their sales team. If we can go through them to get the database updated that would help a lot, I’ll update on how I go.

6. Windows Applies Rate Limiting “Budgets”) to Location Requests

This behaviour is completely undocumented. Logs show a budget system, presumably to prevent excessive scanning.:

[Budget_Replenished] remainingBudget=3, maxBudget=3, timeWindowS=10

And that’s it.

As of writing this, our problem is ongoing, we’ve passed the issue on to Microsoft and once we hear back I’ll update this article. Our customer isn’t particularly interested in any of the available workarounds, so that leaves us standing around, for now.

🙉 Wanna know when I post?

I don’t spam! – Just one email, every couple of days, when there’s a new post.

Sharing is caring!

Comments

Note: any comments identifying companies or individuals discussed above will not be approved.

One response to “Windows Sucks at Location & Automatic Timezones.”

  1. Chris Avatar

    Just leaving a note for myself here, since this is effectively evergreen content, but it’s a bit of a difficult/large read.

    I’ll probably separate the Timezone stuff from the Location stuff, by having 2 separate posts, I reckon this would be better for discoverability and readability.

Leave a Reply

Your email address will not be published. Required fields are marked *