From b10b136a39db7c6fa553b689904c04ffa7fa0971 Mon Sep 17 00:00:00 2001 From: Daniel McKnight Date: Thu, 28 Aug 2025 12:34:01 -0700 Subject: [PATCH 1/2] Add `nice_time` to WeatherCondition for better LLM generation --- neon_skill_weather/api_data_models.py | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/neon_skill_weather/api_data_models.py b/neon_skill_weather/api_data_models.py index 4fb52ccf..6c20dc68 100644 --- a/neon_skill_weather/api_data_models.py +++ b/neon_skill_weather/api_data_models.py @@ -39,6 +39,7 @@ class WeatherRequest(BaseModel): class WeatherCondition(BaseModel): dt: int = Field(description="timestamp of the forecasted condition") + nice_time: str = Field(description="human-readable time") temp: float = Field(description="temperature") feels_like: float = Field(description="perceived temperature") pressure: int = Field(description="atmospheric pressure in hPa") @@ -66,12 +67,21 @@ def validate_input(cls, data: Dict[str, Any]) -> Dict[str, Any]: data["condition"] = weather_data.get("main", "Unknown") data["description"] = weather_data.get("description", "Unknown") data["icon"] = weather_data.get("icon", "") + from datetime import datetime + from zoneinfo import ZoneInfo + + nice_time = datetime.fromtimestamp( + data["dt"], tz=ZoneInfo(data["timezone"]) + ).strftime("%a, %b %-d at %H:%M") + weather_data["nice_time"] = nice_time return data class DailyWeatherCondition(WeatherCondition): summary: str = Field(description="summary of the day's weather") - visibility: Optional[float] = Field(default=None) # Daily data does not include visibility + visibility: Optional[float] = Field( + default=None + ) # Daily data does not include visibility temp: Dict[str, float] = Field( description="temperature details for the day" ) From 2159593944feb8b8a81f8dd578c3dc3e74fed435 Mon Sep 17 00:00:00 2001 From: Daniel McKnight Date: Thu, 28 Aug 2025 13:03:20 -0700 Subject: [PATCH 2/2] Fix addition of strftime to WeatherCondition objects --- neon_skill_weather/api_data_models.py | 31 ++++++++++++++++++++------- 1 file changed, 23 insertions(+), 8 deletions(-) diff --git a/neon_skill_weather/api_data_models.py b/neon_skill_weather/api_data_models.py index 6c20dc68..84a97dbf 100644 --- a/neon_skill_weather/api_data_models.py +++ b/neon_skill_weather/api_data_models.py @@ -39,7 +39,7 @@ class WeatherRequest(BaseModel): class WeatherCondition(BaseModel): dt: int = Field(description="timestamp of the forecasted condition") - nice_time: str = Field(description="human-readable time") + nice_time: Optional[str] = Field(default=None, description="human-readable time") temp: float = Field(description="temperature") feels_like: float = Field(description="perceived temperature") pressure: int = Field(description="atmospheric pressure in hPa") @@ -67,13 +67,6 @@ def validate_input(cls, data: Dict[str, Any]) -> Dict[str, Any]: data["condition"] = weather_data.get("main", "Unknown") data["description"] = weather_data.get("description", "Unknown") data["icon"] = weather_data.get("icon", "") - from datetime import datetime - from zoneinfo import ZoneInfo - - nice_time = datetime.fromtimestamp( - data["dt"], tz=ZoneInfo(data["timezone"]) - ).strftime("%a, %b %-d at %H:%M") - weather_data["nice_time"] = nice_time return data @@ -103,6 +96,7 @@ class WeatherAlert(BaseModel): class WeatherResponse(BaseModel): + timezone: str = Field(description="Timezone of the forecast location") current: WeatherCondition = Field(description="Current weather data") minutely: List[MinutelyWeatherCondition] = Field( description="Minutely weather data" @@ -114,4 +108,25 @@ class WeatherResponse(BaseModel): alerts: Optional[List[WeatherAlert]] = Field( default=None, description="Weather alerts" ) + + @model_validator(mode="after") + def include_formatted_times(self) -> "WeatherResponse": + """Add human-readable time strings to weather conditions""" + from datetime import datetime + from zoneinfo import ZoneInfo + + def _add_nice_time(condition: WeatherCondition) -> None: + nice_time = datetime.fromtimestamp( + condition.dt, tz=ZoneInfo(self.timezone) + ).strftime("%a, %b %-d at %H:%M") + condition.nice_time = nice_time + + _add_nice_time(self.current) + for condition in self.hourly: + _add_nice_time(condition) + for condition in self.daily: + _add_nice_time(condition) + return self + + # TODO: Shared with `neon-hana`; implement in `neon_data_models`