Mountain Time Isn't As Simple As Everyone Thinks
I spent six months debugging a production scheduler that kept drifting by an hour every spring and fall. The culprit was a team in Denver, a satellite office in Phoenix, and a deployment script that trusted system locale strings instead of explicit UTC offsets. I learned more from that than from any documentation I'd read. Denver sits in the Mountain Time Zone. In standard time it is UTC-7, called MST. During daylight saving it shifts to UTC-6, called MDT. That part is textbook. What nobody tells you is how messy the boundary gets when your infrastructure touches neighboring zones.
Time Zone Alert Uncovering The Secrets Of Denver Colorado's Time Zone
The practical reality is that Denver follows the federal DST schedule set by Congress in 2005. Clocks spring forward the second Sunday in March at 2:00 AM, and fall back the first Sunday in November at 2:00 AM. Most people know that. What trips engineers up is the Arizona exception, which lives about three hours away and breaks half the time zone aware tools out there. Arizona does not observe daylight saving time. It stays on MST year round. But the Navajo Nation, which sits in the northeastern part of the state, does follow DST because it extends into Utah. So you have a state where Phoenix runs UTC-7 always, most of Arizona shares that offset, and a patch of land in the corner shifts to UTC-6 for seven months. When I was building alert routing for a monitoring platform, our database treated "Mountain Time" as a single zone. Alerts scheduled for 9:00 AM Denver would arrive at 9:00 AM Flagstaff during summer, which is wrong. Flagstaff was already on MST while Denver was on MDT. The alert showed as early by an hour to the team in Arizona. The fix was to stop using the zone string "America/Denver" for any cross-border logic and instead map each city to its own precise offset at any given timestamp. I wrote a small lookup table that resolved the active offset for a given date and municipality. It cut our alert misdelivery rate from roughly four incidents per month to zero. The code is straightforward, but it requires acknowledging that a time zone is not a single thing. It is a moving target that changes on different dates in different places within the same region.
How The Offset Actually Works In Production
When you store timestamps, use UTC. Always. I cannot emphasize this enough. Store everything as Unix epoch seconds or ISO 8601 with a Z suffix. Convert to local time only at the edges, right before you display something to a human or dispatch an alert to a user. That rule alone prevents about ninety percent of timezone bugs. The remaining ten percent come from DST transition edges, which need explicit handling. During the spring transition, Denver jumps from 2:00 AM MST to 3:00 AM MDT. There is no 2:30 AM in Denver. If your system schedules something for 2:30 AM on that day, the behavior depends on your language runtime. Node.js pushes it forward to 3:00 AM. Python's pytz raises an AmbiguousTimeError in the fall and skips it in the spring. .NET throws a TimeZoneNotFoundException if you are not careful. I spent an afternoon tracing a missing batch job to exactly this issue. The job was queued at 2:30 AM on the spring changeover day, and the scheduler silently dropped it because the datetime library converted it to a non-existent local time, which then normalized upward past the intended window. In the fall transition, Denver goes from 2:00 AM MDT back to 1:00 AM MST. The hour from 1:00 to 2:00 AM occurs twice. A schedule set for 1:30 AM on that day could fire once or twice depending on whether the runtime treats it as the first occurrence or the second. Our payment reconciliation pipeline fired twice once because the cron expression did not specify which occurrence to use. We lost two hours of duplicate processing before anyone noticed. After that, I started using the IANA zone database exclusively and added a pre-flight check that warned on ambiguous or skipped local times. It added maybe fifteen minutes to our deployment pipeline and saved us from repeating that mistake.
Get the Full Details

Alert Systems And The Mountain Zone
If you are building an alerting system for a team spread across Mountain Time cities, you need to handle three distinct behaviors. Denver shifts with DST. Phoenix does not. Places like Salt Lake City shift with DST and share the same offset as Denver most of the year but diverge during the overlap period if you are doing something like comparing scheduled start times across state lines. I once had a support ticket where a customer in Billings, Montana complained that alerts were arriving an hour early. Billings is on Mountain Standard Time year round because Montana does not observe DST in practice for some legacy systems, or the customer had misconfigured their device. Actually, Montana does observe DST. The real issue was that the customer's server was running on UTC-7 hardcoded, which matched MST but not MDT. During summer, the alert arrived one hour early relative to local clock time. Hardcoding offsets is the fastest way to create a bug that looks correct for eleven months and fails spectacularly for one. The proper approach is to reference the IANA time zone database, not fixed offsets. Use America/Denver for Denver, America/Phoenix for Phoenix, and resolve the offset dynamically for any timestamp. Most modern runtimes handle this correctly if you ask them to. The gotcha is that some libraries default to the host OS timezone, which may not match the zone you intend. If your deployment container is based on a minimal image without timezone data installed, the system falls back to UTC regardless of what you configured. I found this in a Docker build where the base image stripped /usr/share/zoneinfo. The app thought it was running Mountain Time but was actually using UTC. Alerts fired at the wrong hour for two weeks. Adding the timezone data package and explicitly setting TZ=America/Denver in the environment fixed it.
What Breaks And What To Do Instead
Cron expressions are the usual suspect. A cron set to run at 8:00 AM Mountain Time will shift its UTC equivalent by an hour twice a year. If your crontab stores local time without a zone context, the scheduler may interpret it as UTC or as the system local time, which could be anywhere. Always specify the zone in the cron configuration or run the scheduler in UTC and convert the target time explicitly. Most cron implementations today support timezone-aware scheduling. The ones that do not are usually legacy systems that should be replaced, not worked around. Database functions are another weak point. MySQL's CONVERT_TZ function works but requires the timezone tables to be populated. If you are running a trimmed-down MySQL instance, those tables may be empty, and the function returns NULL silently. PostgreSQL handles timezone conversions through the session timezone setting and the AT TIME ZONE operator, which is more reliable but still requires the underlying data to be stored consistently. I prefer storing everything as TIMESTAMPTZ in PostgreSQL and letting the client handle display conversion. That avoids the NULL trap entirely. For alert delivery, the safest pattern is to store the user's preferred timezone alongside their profile, compute the next alert time in UTC, and convert only at send time. This means your backend never needs to know what time it is in Denver. It only needs to know when to send the message in UTC. The frontend or notification service handles the local time display. This architecture eliminates most cross-zone errors because the conversion happens once, at the boundary, instead of everywhere in the middle.
The downside of this approach is that you need timezone preference stored for every user, and you need to handle users who travel or move. If a user's timezone preference is stale, their alerts will fire at the wrong local time. I have seen this happen when a remote worker changed cities but did not update their profile. The alert arrived at 9:00 AM for their old timezone, which was 11:00 AM in their new location. A simple monthly re-confirmation prompt or geolocation-based timezone detection can reduce this, but neither is perfect. Geolocation based detection is inaccurate near zone boundaries and raises privacy concerns. Manual confirmation is reliable but depends on the user actually doing it.

Practical Notes For Anyone Working With Denver Schedules
During the two weeks around each DST transition, any system that caches timezone offsets will be wrong for part of that window. Cache invalidation on the transition dates is a cheap insurance policy. I add a scheduled job that clears timezone caches forty-eight hours before and after each transition. It runs in under a second and prevents a class of bugs that is otherwise very hard to reproduce because it only happens twice a year. If you are integrating with external services that send schedules or alerts, verify whether they respect DST. Some older vendor portals hardcode offsets and ignore daylight saving changes. I encountered this with a weather data provider that published forecast times in local Mountain Time but never updated for DST. Their API returned 14:00 for a noon forecast during summer, which was actually 13:00 local time. The fix was to subtract one hour during the MDT period and add nothing during MST. It was a pain to maintain, but it was the only option without switching providers. For most teams, the takeaway is simple. Store UTC, display local, handle transitions explicitly, and never hardcode an offset for a region that observes DST. Denver follows DST. Arizona generally does not. Treat them as different zones even when their offsets match for part of the year. The extra effort is small, and the cost of getting it wrong is measured in missed alerts, duplicate processing, and angry customers.