Skip to main content

ferric_fred/
series_group.rs

1use chrono::NaiveDate;
2use serde::{Deserialize, Serialize};
3
4use crate::SeriesGroupId;
5
6/// Metadata for a GeoFRED / Maps series group (the `geofred/series/group`
7/// endpoint) — the descriptive header for a group of regional series, and the
8/// span of dates it covers.
9///
10/// `region_type`, `season`, `units`, and `frequency` are kept as `String`: FRED
11/// returns them as display/code text here, and this crate mirrors the wire
12/// rather than parsing them into enums (ADR-0025).
13#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
14#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
15pub struct SeriesGroup {
16    /// The group's descriptive title, e.g. `"All Employees: Total Private"`.
17    pub title: String,
18
19    /// The group's identifier (FRED's own `series_group` field), e.g. `1223`.
20    #[serde(rename = "series_group")]
21    pub id: SeriesGroupId,
22
23    /// The region granularity as a display label, e.g. `"state"`.
24    pub region_type: String,
25
26    /// The seasonality, as FRED reports it here (a short code, e.g. `"NSA"`).
27    pub season: String,
28
29    /// The units as a display label, e.g. `"Thousands of Persons"`.
30    pub units: String,
31
32    /// The frequency as a display label, e.g. `"Monthly"`.
33    pub frequency: String,
34
35    /// The earliest date the group has data for.
36    pub min_date: NaiveDate,
37
38    /// The latest date the group has data for.
39    pub max_date: NaiveDate,
40}
41
42#[cfg(test)]
43mod tests {
44    use super::*;
45
46    const SERIES_GROUP: &str = r#"{
47        "title": "All Employees: Total Private",
48        "region_type": "state",
49        "series_group": "1223",
50        "season": "NSA",
51        "units": "Thousands of Persons",
52        "frequency": "Monthly",
53        "min_date": "1990-01-01",
54        "max_date": "2026-05-01"
55    }"#;
56
57    #[test]
58    fn parses_group_metadata() {
59        let group: SeriesGroup = serde_json::from_str(SERIES_GROUP).expect("series group parses");
60        assert_eq!(group.id, SeriesGroupId::new("1223"));
61        assert_eq!(group.title, "All Employees: Total Private");
62        assert_eq!(group.region_type, "state");
63        assert_eq!(group.season, "NSA");
64        assert_eq!(group.min_date, NaiveDate::from_ymd_opt(1990, 1, 1).unwrap());
65        assert_eq!(group.max_date, NaiveDate::from_ymd_opt(2026, 5, 1).unwrap());
66    }
67}