Introduction: The Midnight Geofencing Mystery
You’ve spent hours crafting the perfect Home Assistant automation. Your lights turn on when you arrive home. Your thermostat adjusts when you leave. Everything works beautifully — until midnight hits.
Then, suddenly, your geofencing-triggered automation just… stops working.
I’ve been there. I remember sitting in my car at 1:30 AM after a late shift, staring at my phone, wondering why my porch lights refused to turn on even though I was clearly in the geofence zone. The automation worked perfectly at 8 PM. But after midnight? Complete silence.
If you’re reading this, you probably know exactly what I’m talking about. And the frustration is real — because this isn’t a random bug. There’s a very specific, logical reason why this happens, and once you understand it, the fix is surprisingly straightforward.
In this guide, I’ll walk you through every possible cause, share real YAML examples, and give you tested solutions that actually work. No filler. No guesswork. Just answers.
<!– Image Placeholder 1 –>
[IMAGE: Screenshot showing a Home Assistant automation trace with a failed geofencing trigger after midnight]
Alt text: Home Assistant automation trace showing geofencing trigger failure after midnight with condition evaluation details
Understanding How Home Assistant Handles Time in YAML Automations
Before we dive into fixes, you need to understand how Home Assistant interprets time conditions — because this is where 90% of midnight geofencing failures originate.
How Time Conditions Work Internally
Home Assistant uses a time condition that evaluates whether the current time falls within a specified window. Here’s the catch most people miss:
When your after time is later than your before time, Home Assistant assumes the window does NOT cross midnight.
So if you write this:
YAMLcondition:
- condition: time
after: "18:00:00"
before: "06:00:00"
You might think you’re saying: “Between 6 PM and 6 AM.” But depending on your Home Assistant version and configuration, this can be interpreted inconsistently — especially when combined with geofencing triggers that fire at unpredictable times.
Why Geofencing Makes This Worse
Geofencing triggers are event-driven, not time-scheduled. Unlike a time-based trigger that fires at a predictable moment, a geofence trigger fires when your phone’s GPS detects a zone boundary crossing. This means:
- The trigger can fire at any time, including 12:01 AM
- The time condition evaluation happens at the exact moment of the trigger
- If your time window logic is broken at midnight, the condition fails silently
<!– Image Placeholder 2 –>
[IMAGE: Diagram showing the difference between a time window that crosses midnight vs. one that doesn’t]
Alt text: Visual diagram comparing Home Assistant time condition windows that cross midnight versus those that stay within a single day
The Root Causes: Why Your Automation Fails After Midnight
Let me break down the specific technical reasons this happens. I’ve encountered all of these in real setups — both my own and in the Home Assistant community forums.
Cause 1: Time Condition Window Doesn’t Cross Midnight Properly
This is the number one cause. Here’s a real-world example that fails:
YAMLautomation:
- alias: "Turn on porch light when I arrive home at night"
trigger:
- platform: zone
entity_id: person.john
zone: zone.home
event: enter
condition:
- condition: time
after: "20:00:00"
before: "05:00:00"
action:
- service: light.turn_on
target:
entity_id: light.porch
Why it fails: In some configurations, Home Assistant evaluates after: 20:00 and before: 05:00 as an impossible window on the same day — because 20:00 never comes before 05:00 on the same calendar day. After midnight, the system is now on a new day, and the logic breaks.
Cause 2: Sun-Based Conditions with Edge Cases
Many people use sun conditions instead of hard-coded times:
YAMLcondition:
- condition: sun
after: sunset
before: sunrise
This generally works better, but there are edge cases around astronomical twilight and timezone transitions that can cause failures, particularly if your Home Assistant timezone configuration doesn’t match your actual location.
Cause 3: Date Change Resets State
Some automations use input_boolean helpers or last_triggered checks that reset at midnight because they reference the date. If your automation has logic like “only trigger once per day,” the day resets at midnight, but the state evaluation might not behave as expected.
Cause 4: Phone GPS Behavior After Midnight
This one is often overlooked. After midnight, many phones enter aggressive battery optimization mode:
- GPS polling frequency decreases
- The Home Assistant Companion App may not update location as frequently
- Geofence exit/enter events can be delayed by minutes or even hours
This isn’t a YAML problem — it’s a device problem that manifests as a YAML failure.
Cause 5: Timezone and UTC Mismatch
If your Home Assistant instance uses UTC internally but your automations reference local time, midnight in your timezone might not align with what Home Assistant considers midnight.
<!– Image Placeholder 3 –>
[IMAGE: Home Assistant Companion App battery optimization settings on Android showing location permissions]
Alt text: Android battery optimization settings for Home Assistant Companion App showing unrestricted location access configuration
Real Scenario: My Personal Debugging Journey
Let me share exactly what happened to me, because I think it’ll help you identify your own issue faster.
The Setup:
- Home Assistant 2024.1 running on a Raspberry Pi 4
- Geofencing through the HA Companion App on a Pixel 7
- Automation: Turn on living room lights + disarm alarm when I arrive home after dark
What Worked: Arriving home at 7 PM, 8 PM, 9 PM, 10 PM, 11 PM — flawless every time.
What Failed: Arriving home at 12:15 AM, 1:30 AM, 2:00 AM — nothing happened. No lights, no alarm disarm.
The Debugging Process:
- I checked the automation trace — the trigger fired correctly (the geofence detected my arrival)
- The condition evaluation showed
result: falseon the time condition - My time condition was
after: "19:00:00"/before: "04:00:00" - At 12:15 AM, HA evaluated: “Is 00:15 after 19:00? No.” → Condition failed
The Fix: I replaced the single time condition with a template condition that properly handles the midnight crossing. Problem solved permanently.
Step-by-Step Solutions (Tested and Working)
Here are the exact fixes you can apply right now, ordered from simplest to most robust.
Solution 1: Use a Template Condition for Time Windows Crossing Midnight
This is the most reliable fix. Replace your time condition with a template condition:
YAMLautomation:
- alias: "Turn on porch light when arriving home at night"
trigger:
- platform: zone
entity_id: person.john
zone: zone.home
event: enter
condition:
- condition: template
value_template: >
{% set current_hour = now().hour %}
{{ current_hour >= 20 or current_hour < 5 }}
action:
- service: light.turn_on
target:
entity_id: light.porch
Why this works: The or operator handles midnight crossing naturally. If the hour is 20, 21, 22, 23, 0, 1, 2, 3, or 4 — the condition is true. No ambiguity.
Solution 2: Use Sun-Based Conditions (More Dynamic)
If you want the automation to follow actual darkness rather than fixed hours:
YAMLautomation:
- alias: "Lights on arrival after dark"
trigger:
- platform: zone
entity_id: person.john
zone: zone.home
event: enter
condition:
- condition: state
entity_id: sun.sun
state: "below_horizon"
action:
- service: light.turn_on
target:
entity_id: light.porch
Why this works: sun.sun state is either above_horizon or below_horizon. It doesn’t care about midnight. It simply checks if the sun is down right now. Clean. Simple. Reliable.
Solution 3: Split Into Two Automations
If templates feel too complex, just create two separate automations:
YAML# Automation for before midnight
automation:
- alias: "Arrival lights - evening"
trigger:
- platform: zone
entity_id: person.john
zone: zone.home
event: enter
condition:
- condition: time
after: "20:00:00"
before: "23:59:59"
action:
- service: light.turn_on
target:
entity_id: light.porch
# Automation for after midnight
- alias: "Arrival lights - late night"
trigger:
- platform: zone
entity_id: person.john
zone: zone.home
event: enter
condition:
- condition: time
after: "00:00:00"
before: "05:00:00"
action:
- service: light.turn_on
target:
entity_id: light.porch
Why this works: Each automation has a time window that stays within a single day. No midnight crossing needed.
Solution 4: Fix Your Phone’s Geofencing Reliability
Even with perfect YAML, your automation will fail if your phone doesn’t report location properly after midnight.
For Android:
- Go to Settings → Apps → Home Assistant Companion
- Set Battery optimization to “Unrestricted”
- Enable “Allow all the time” for Location permissions
- In the Companion App: Settings → Companion App → Location Sensors → Enable all
- Set High Accuracy Mode for location
For iPhone:
- Go to Settings → Privacy → Location Services → Home Assistant
- Select “Always”
- Enable “Precise Location”
- Ensure Background App Refresh is enabled
Solution 5: Verify Your Timezone Configuration
Check your configuration.yaml:
YAMLhomeassistant:
time_zone: "America/New_York" # Replace with YOUR timezone
latitude: 40.7128
longitude: -74.0060
Then verify in Developer Tools → Template:
jinja{{ now() }}
{{ now().hour }}
{{ states('sun.sun') }}
Make sure the output matches your actual local time.
<!– Image Placeholder 4 –>
[IMAGE: Home Assistant Developer Tools Template panel showing timezone verification output]
Alt text: Home Assistant Developer Tools Template editor displaying current time, hour, and sun state for timezone verification
Advanced Debugging: How to Trace the Exact Failure Point
If you’ve applied the solutions above and things still aren’t working, here’s how to systematically debug the issue.
Step 1: Enable Automation Tracing
Make sure automation tracing is enabled (it is by default in recent HA versions):
YAMLautomation:
- alias: "Your automation"
trace:
stored_traces: 20
Step 2: Check the Trace After a Failure
- Go to Settings → Automations & Scenes
- Click on your automation
- Click “Traces” in the top right
- Look at the condition evaluation — it will show you exactly which condition returned
false
Step 3: Test Manually with Developer Tools
Go to Developer Tools → Template and paste:
jinjaTime condition test:
Current time: {{ now().strftime('%H:%M:%S') }}
Hour: {{ now().hour }}
After 20:00 OR before 05:00: {{ now().hour >= 20 or now().hour < 5 }}
Sun state: {{ states('sun.sun') }}
Person location: {{ states('person.john') }}
Run this at different times to verify your logic works.
Step 4: Check the Logbook for Geofence Events
Go to Logbook and filter by your person entity. Verify that zone enter/exit events are actually being recorded after midnight. If they’re not, the problem is with your phone’s location reporting, not your YAML.
<!– Image Placeholder 5 –>
[IMAGE: Home Assistant automation trace showing condition evaluation path with timestamps]
Alt text: Home Assistant automation trace view displaying the step-by-step condition evaluation with pass/fail indicators and timestamps
Common YAML Mistakes That Cause Midnight Failures
Here are specific YAML patterns I’ve seen cause issues — with corrected versions.
Mistake 1: Using and Logic Instead of or for Midnight-Crossing Windows
❌ Wrong:
YAMLcondition:
- condition: template
value_template: "{{ now().hour >= 20 and now().hour < 5 }}"
This will never be true because no hour is both ≥ 20 AND < 5 simultaneously.
✅ Correct:
YAMLcondition:
- condition: template
value_template: "{{ now().hour >= 20 or now().hour < 5 }}"
Mistake 2: Forgetting Seconds in Time Conditions
❌ Problematic:
YAMLcondition:
- condition: time
before: "00:00:00"
At exactly midnight, 00:00:00 is NOT before 00:00:00. This edge case can cause a one-second failure window.
✅ Better:
YAMLcondition:
- condition: time
before: "00:01:00"
Mistake 3: Mixing state and zone Triggers Incorrectly
❌ Unreliable:
YAMLtrigger:
- platform: state
entity_id: person.john
to: "home"
✅ More Reliable for Geofencing:
YAMLtrigger:
- platform: zone
entity_id: person.john
zone: zone.home
event: enter
The zone trigger is specifically designed for geofencing and handles edge cases better than a generic state trigger.
Best Practices for Reliable Geofencing Automations (Any Time of Day)
Based on everything I’ve learned from debugging my own setup and helping others in the community, here are my recommendations:
1. Always Use Template Conditions for Time Windows Crossing Midnight
The built-in time condition is great for same-day windows. For overnight windows, use templates.
2. Prefer sun.sun State Over Fixed Times
Seasons change. Sunset at 5 PM in winter vs. 9 PM in summer. Using below_horizon adapts automatically.
3. Add Fallback Notifications
Add a notification action so you know when the automation fires (or doesn’t):
YAMLaction:
- service: light.turn_on
target:
entity_id: light.porch
- service: notify.mobile_app_your_phone
data:
message: "Welcome home! Porch light turned on at {{ now().strftime('%H:%M') }}"
4. Use Multiple Location Sources
Don’t rely solely on GPS. Consider:
- Router-based detection (device_tracker via your router)
- Bluetooth-based detection (ESPresense or similar)
- WiFi-based detection (when phone connects to home WiFi)
YAMLtrigger:
- platform: zone
entity_id: person.john
zone: zone.home
event: enter
- platform: state
entity_id: device_tracker.johns_phone_wifi
to: "home"
5. Test at Midnight Specifically
Don’t assume your automation works after midnight just because it works at 11 PM. Actually test it at 12:15 AM. Set a reminder. Go outside. Walk back in. Verify.
<!– Image Placeholder 6 –>
[IMAGE: Home Assistant dashboard showing multiple device trackers (GPS, WiFi, Bluetooth) for reliable presence detection]
Alt text: Home Assistant dashboard displaying multiple device tracker entities including GPS geofence, WiFi connection, and Bluetooth presence for redundant location detection
Useful External Resources
For deeper reading and community solutions, check these trusted resources:
- Home Assistant Official Documentation — Automation Trigger: Zone
- Home Assistant Official Documentation — Time Condition
- Home Assistant Community Forum — Geofencing Best Practices
- Home Assistant Companion App — Location Troubleshooting
- Home Assistant Cookbook — Presence Detection
Frequently Asked Questions (FAQ)
Why does my Home Assistant geofencing automation work before midnight but not after?
The most common reason is that your time condition defines a window that crosses midnight (e.g., 8 PM to 5 AM), but Home Assistant interprets it as a same-day window. After midnight, you’re on a new calendar day, and the condition evaluates to false. The fix is to use a template condition with or logic or to use the sun.sun entity state.
How do I make a time condition that spans across midnight in Home Assistant?
Use a template condition with or logic:
YAMLcondition:
- condition: template
value_template: "{{ now().hour >= 20 or now().hour < 5 }}"
This correctly evaluates to true for hours 20, 21, 22, 23, 0, 1, 2, 3, and 4.
Does the Home Assistant Companion App report location accurately after midnight?
It depends on your phone’s battery optimization settings. Many phones reduce GPS polling frequency at night to save battery. To ensure reliable geofencing, disable battery optimization for the Companion App and set location permission to “Always” with “Precise Location” enabled.
Can I use sun.sun instead of time conditions for night-based automations?
Yes, and it’s often more reliable. Using condition: state with entity_id: sun.sun and state: "below_horizon" avoids all midnight-crossing issues because it simply checks whether the sun is currently down, regardless of what time it is.
Why does my automation trace show the trigger fired but the condition failed?
This confirms the geofence is working correctly — your phone did report the zone entry. The failure is in the condition evaluation. Check the trace details to see which specific condition returned false. In midnight-related failures, it’s almost always the time condition.
Should I split my overnight automation into two separate automations?
You can, and it works. One automation covers 8 PM to 11:59 PM, and another covers 12 AM to 5 AM. However, using a single automation with a template condition is cleaner and easier to maintain long-term.
How do I check my Home Assistant timezone setting?
Go to Developer Tools → Template and enter {{ now() }}. The output will show your HA instance’s current time with timezone offset. Compare it to your actual local time. If they don’t match, update the time_zone value in your configuration.yaml.
What’s more reliable for geofencing — GPS, WiFi, or Bluetooth?
All three combined give the best results. GPS handles outdoor detection, WiFi detects when your phone connects to your home network, and Bluetooth (via ESPresense or similar) provides room-level precision. Using multiple sources as triggers creates a redundant, highly reliable presence detection system.
Final Thoughts: Don’t Let Midnight Break Your Smart Home
The midnight geofencing failure is one of those problems that feels mysterious until you understand the underlying time logic. It’s not a bug in Home Assistant — it’s a logical edge case in how time windows are evaluated.
The good news? Once you apply the fixes in this guide, your automations will work reliably at any hour, whether you’re coming home at 7 PM from dinner or at 3 AM from a late flight.
Start with the template condition fix (Solution 1) — it solves the problem for most people in under two minutes. Then optimize your phone’s location settings (Solution 4) to ensure the trigger itself is reliable.
Your smart home should work for you around the clock. Now it will.
<!– Image Placeholder 7 –>
[IMAGE: Home Assistant automation editor showing a completed, working geofencing automation with template time condition]
Alt text: Home Assistant YAML automation editor displaying a fully configured geofencing automation with template-based midnight-crossing time condition and zone trigger