meteostat/
lib.rs

1#![allow(clippy::too_many_lines)]
2//! Provides a Rust interface for accessing historical weather and climate data
3//! from [Meteostat](https://meteostat.net/), using their free bulk data interface.
4//!
5//! This crate allows fetching hourly, daily, monthly, and climate normal data
6//! for thousands of weather stations worldwide, either by station ID or by
7//! geographical coordinates (latitude/longitude). Data is returned efficiently
8//! as Polars `LazyFrame` wrappers, enabling powerful filtering and analysis
9//! before loading data into memory. Automatic caching of station metadata and
10//! weather data files minimizes redundant downloads.
11//!
12//! # Features
13//!
14//! *   **Fetch by Station ID or Location:** Initiate requests via frequency-specific clients
15//!     (`client.hourly()`, `client.daily()`, etc.) and then specify either `.station("ID")`
16//!     or `.location(LatLon)`.
17//! *   **Find Nearby Stations:** Search for stations near coordinates using `client.find_stations()`,
18//!     optionally filtering by distance and required data availability (inventory).
19//! *   **Multiple Frequencies:** Supports Hourly, Daily, Monthly, and Climate Normals data.
20//! *   **Efficient Data Handling:** Returns data as wrappers around Polars `LazyFrame`s
21//!     (e.g., [`HourlyLazyFrame`]), allowing for powerful, memory-efficient filtering
22//!     and manipulation *before* collecting results.
23//! *   **Convenient Filtering:** Frame wrappers provide methods for easy filtering by date,
24//!     year, month, or datetime ranges (e.g., `daily_lazy.get_for_period(Year(2023))`).
25//! *   **Flexible Collection:** Collect results either as a Polars `DataFrame` (`.frame.collect()`)
26//!     or directly into Rust structs (`.collect_hourly()`, `.collect_single_daily()`, etc.)
27//!     using methods on the frame wrappers.
28//! *   **Automatic Caching:** Downloads and caches station metadata and weather data files
29//!     locally to speed up subsequent requests.
30//! *   **Asynchronous:** Built with `tokio` for non-blocking I/O.
31//!
32//! # Basic Usage
33//!
34//! ```no_run
35//! use meteostat::{Meteostat, LatLon, MeteostatError, Year};
36//! use polars::prelude::*;
37//! use chrono::{NaiveDate};
38//!
39//! #[tokio::main]
40//! async fn main() -> Result<(), MeteostatError> {
41//!     let client = Meteostat::new().await?;
42//!     // Period for which we want hourly data:
43//!     let period = NaiveDate::from_ymd_opt(2023, 9, 1).unwrap();
44//!
45//!     // --- Example 1: Collect 24 hourly data points into `Vec<Hourly>` ---
46//!     let hourly_vec = client
47//!         .hourly()
48//!         .location(LatLon(52.0836403, 5.1257283))
49//!         .call()
50//!         .await? // `HourlyLazyFrame`
51//!         .get_for_period(period)? // `HourlyLazyFrame` with filter plan
52//!         .collect_hourly()?; // `Vec<Hourly>`
53//!
54//!     // Do something with the hourly data...
55//!
56//!     // --- Example 2: Collect daily data from 2023 into a `DataFrame` ---
57//!     let daily_df = client
58//!         .daily()
59//!         .location(LatLon(52.0836403, 5.1257283))
60//!         .call()
61//!         .await? // `DailyLazyFrame`
62//!         .get_for_period(Year(2023))? // `DailyLazyFrame` with filter plan
63//!         .frame // `LazyFrame` with filter plan
64//!         .collect()?; // `DataFrame`
65//!
66//!     // Do something with the daily data...
67//!
68//!     Ok(())
69//! }
70//! ```
71//!
72//! # Core Concepts
73//!
74//! *   **[`Meteostat`]:** The main entry point client struct. Created via [`Meteostat::new`] or [`Meteostat::with_cache_folder`].
75//! *   **Frequency Clients:** Accessed via methods on `Meteostat` (e.g., [`Meteostat::hourly`], [`Meteostat::daily`]). These return builders.
76//! *   **Source Specification:** Use `.station("ID")` or `.location(LatLon)` on the frequency client builders.
77//! *   **`LazyFrame` Wrappers:** Fetching data returns structs like [`HourlyLazyFrame`], [`DailyLazyFrame`], [`MonthlyLazyFrame`], [`ClimateLazyFrame`] which contain a Polars `LazyFrame` and provide convenience filtering and collection methods.
78//! *   **Filtering:** Use methods like `get_range`, `get_at`, `get_for_period` on the frame wrappers, or access `.frame` for advanced Polars operations.
79//! *   **Collecting:** Call `.frame.collect()?` on the frame wrappers to execute the query and get a `DataFrame`, OR use specific methods like `.collect_daily()`, `.collect_single_hourly()`, etc., to get results directly as Rust structs (e.g., `Vec<Daily>`, `Hourly`).
80//! *   **Finding Stations:** Use [`Meteostat::find_stations`] to search for [`Station`] objects near a [`LatLon`], optionally filtering by [`InventoryRequest`] criteria.
81//!
82//! # Data Source and Attribution
83//!
84//! *   All weather data is sourced from **[Meteostat](https://meteostat.net/)**.
85//! *   This crate uses Meteostat's **free bulk data interface**. No API key is required. Please consider supporting them if you find their service useful.
86
87// Module structure
88mod clients;
89mod error;
90mod meteostat;
91mod stations;
92mod types;
93mod utils;
94mod weather_data;
95
96// --- Core Exports ---
97pub use error::MeteostatError;
98pub use meteostat::{InventoryRequest, LatLon, Meteostat};
99
100// --- Data Types & Enums ---
101pub use types::frequency::{Frequency, RequiredData};
102pub use types::station::Station;
103pub use types::weather_condition::WeatherCondition;
104
105// --- Time/Date Trait Exports (for filtering convenience) ---
106pub use types::traits::any::any_date::AnyDate;
107pub use types::traits::any::any_datetime::AnyDateTime;
108pub use types::traits::any::any_month::AnyMonth;
109pub use types::traits::period::date_period::DatePeriod;
110pub use types::traits::period::datetime_period::DateTimePeriod;
111pub use types::traits::period::month_period::MonthPeriod;
112// Concrete time period types
113pub use types::traits::types::{Month, Year};
114
115// --- Clients ---
116pub use clients::climate_client::ClimateClient;
117pub use clients::daily_client::DailyClient;
118pub use clients::hourly_client::HourlyClient;
119pub use clients::monthly_client::MonthlyClient;
120
121// --- Result Struct Exports (Needed for Vec<Struct> collection) ---
122// These are the structs returned by collect_daily(), collect_hourly(), etc.
123pub use types::frequency_frames::climate_frame::Climate;
124pub use types::frequency_frames::daily_frame::Daily;
125pub use types::frequency_frames::hourly_frame::Hourly;
126pub use types::frequency_frames::monthly_frame::Monthly;
127
128// --- LazyFrame Wrapper Exports ---
129// These are the types returned *after* fetching data (e.g., from `client.daily().station().await?`)
130pub use types::frequency_frames::climate_frame::ClimateLazyFrame;
131pub use types::frequency_frames::daily_frame::DailyLazyFrame;
132pub use types::frequency_frames::hourly_frame::HourlyLazyFrame;
133pub use types::frequency_frames::monthly_frame::MonthlyLazyFrame;
134
135// --- Sub-Error Type Exports (useful for specific error matching) ---
136pub use stations::error::LocateStationError;
137pub use weather_data::error::WeatherDataError;