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;