wttr/IMPERIAL_UNITS.md

98 lines
3.2 KiB
Markdown
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 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:
1. **Explicit query parameter** (highest priority)
- `?u` - Force imperial units (°F, mph, inches, inHg)
- `?m` - Force metric units (°C, km/h, mm, hPa)
2. **Language parameter**
- `?lang=us` - Use imperial units (for us.wttr.in subdomain)
3. **Client IP geolocation**
- Requests from US IP addresses automatically use imperial units
- Uses GeoIP database to detect country code
4. **Default**
- Metric units for all other cases
## Implementation Details
### Code Changes
1. **GeoIP Module** (`src/location/geoip.zig`)
- Added `isUSIP()` method to detect US IP addresses
- Queries MaxMind database for country ISO code
- Returns `true` if country code is "US"
2. **Handler** (`src/http/handler.zig`)
- Added `geoip` to `HandleWeatherOptions`
- Implements priority logic for unit selection
- Extracts client IP from headers (X-Forwarded-For, X-Real-IP)
- Passes `use_imperial` flag to all renderers
3. **Renderers** (all updated to support imperial units)
- `ansi.zig` - Shows °F instead of °C
- `line.zig` - Shows °F and mph for formats 1-4
- `custom.zig` - Converts all units (temp, wind, precip, pressure)
- `v2.zig` - Shows imperial units in detailed format
- `json.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.zig
- `test "format 2 with imperial units"` in line.zig
- `test "render custom format with imperial units"` in custom.zig
- `test "render v2 format with imperial units"` in v2.zig
- `test "imperial units selection logic"` in handler.zig
- `test "isUSIP detects US IPs"` in geoip.zig
### Integration Testing
```bash
# 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: 8.8.8.8" "http://localhost:8002/London?format=2"
# Output: Uses imperial if 8.8.8.8 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