3.2 KiB
3.2 KiB
Imperial Units Implementation
Overview
The application automatically selects between metric and imperial (USCS) units based on the request context, matching the behavior of the original Python implementation.
Unit Selection Priority
The system determines which units to use in the following priority order:
-
Explicit query parameter (highest priority)
?u- Force imperial units (°F, mph, inches, inHg)?m- Force metric units (°C, km/h, mm, hPa)
-
Language parameter
?lang=us- Use imperial units (for us.wttr.in subdomain)
-
Client IP geolocation
- Requests from US IP addresses automatically use imperial units
- Uses GeoIP database to detect country code
-
Default
- Metric units for all other cases
Implementation Details
Code Changes
-
GeoIP Module (
src/location/geoip.zig)- Added
isUSIP()method to detect US IP addresses - Queries MaxMind database for country ISO code
- Returns
trueif country code is "US"
- Added
-
Handler (
src/http/handler.zig)- Added
geoiptoHandleWeatherOptions - Implements priority logic for unit selection
- Extracts client IP from headers (X-Forwarded-For, X-Real-IP)
- Passes
use_imperialflag to all renderers
- Added
-
Renderers (all updated to support imperial units)
ansi.zig- Shows °F instead of °Cline.zig- Shows °F and mph for formats 1-4custom.zig- Converts all units (temp, wind, precip, pressure)v2.zig- Shows imperial units in detailed formatjson.zig- Already outputs both units (no changes needed)
Conversions
- Temperature:
°F = °C × 9/5 + 32 - Wind speed:
mph = km/h × 0.621371 - Precipitation:
inches = mm × 0.0393701 - Pressure:
inHg = hPa × 0.02953
Testing
Unit Tests
All renderers have unit tests verifying imperial units:
test "render with imperial units"in ansi.zigtest "format 2 with imperial units"in line.zigtest "render custom format with imperial units"in custom.zigtest "render v2 format with imperial units"in v2.zigtest "imperial units selection logic"in handler.zigtest "isUSIP detects US IPs"in geoip.zig
Integration Testing
# Test with lang=us
curl "http://localhost:8002/London?lang=us&format=2"
# Output: 51.5074,-0.1278: ☁️ 54°F 🌬️SW19mph
# Test with explicit ?u
curl "http://localhost:8002/London?format=2&u"
# Output: 51.5074,-0.1278: ☁️ 54°F 🌬️SW19mph
# Test metric override
curl "http://localhost:8002/London?lang=us&format=2&m"
# Output: 51.5074,-0.1278: ☁️ 12°C 🌬️SW30km/h
# Test from US IP (automatic detection)
curl -H "X-Forwarded-For: 1.1.1.1" "http://localhost:8002/London?format=2"
# Output: Uses imperial as 1.1.1.1 is detected as US IP
Documentation Updates
- API_ENDPOINTS.md - Added "Unit System Defaults" section explaining priority
- README.md - Updated "Implemented Features" to mention auto-detection
- IMPERIAL_UNITS.md - This document
Compatibility
This implementation matches the original Python behavior in lib/parse_query.py:
- Same priority order
- Same detection logic
- Same unit conversions
- Compatible with existing clients and scripts