Skip to main content

ferric_fred/
release_date.rs

1use chrono::NaiveDate;
2use serde::{Deserialize, Serialize};
3
4use crate::ReleaseId;
5
6/// A single scheduled or historical release date, from the
7/// `fred/releases/dates` and `fred/release/dates` endpoints — the date a
8/// release was (or is scheduled to be) published.
9#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
10#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
11pub struct ReleaseDate {
12    /// The release this date belongs to.
13    pub release_id: ReleaseId,
14
15    /// The release's name. `releases/dates` (which spans every release)
16    /// includes it; `release/dates` omits it, since the release is already
17    /// fixed by the request.
18    #[serde(default)]
19    pub release_name: Option<String>,
20
21    /// The date the release was, or is scheduled to be, published.
22    pub date: NaiveDate,
23}
24
25/// A page of release dates with pagination metadata, shared by the
26/// `fred/releases/dates` and `fred/release/dates` endpoints.
27#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
28#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
29pub struct ReleaseDatesResults {
30    /// Total number of release dates available (across all pages).
31    pub count: u32,
32
33    /// The offset (number of dates skipped) for this page.
34    pub offset: u32,
35
36    /// The page-size limit that was applied.
37    pub limit: u32,
38
39    /// The release dates on this page.
40    pub release_dates: Vec<ReleaseDate>,
41}
42
43#[cfg(test)]
44mod tests {
45    use super::*;
46
47    #[test]
48    fn deserializes_a_named_release_date() {
49        // `releases/dates` entries carry the release name.
50        let date: ReleaseDate = serde_json::from_str(
51            r#"{"release_id":9,"release_name":"Advance Monthly Sales for Retail and Food Services","date":"2013-08-13"}"#,
52        )
53        .unwrap();
54        assert_eq!(date.release_id, ReleaseId::new(9));
55        assert_eq!(
56            date.release_name.as_deref(),
57            Some("Advance Monthly Sales for Retail and Food Services")
58        );
59        assert_eq!(date.date, NaiveDate::from_ymd_opt(2013, 8, 13).unwrap());
60    }
61
62    #[test]
63    fn release_date_without_name_defaults_to_none() {
64        // `release/dates` entries omit the name (the release is fixed).
65        let date: ReleaseDate =
66            serde_json::from_str(r#"{"release_id":82,"date":"1997-02-10"}"#).unwrap();
67        assert_eq!(date.release_id, ReleaseId::new(82));
68        assert!(date.release_name.is_none());
69        assert_eq!(date.date, NaiveDate::from_ymd_opt(1997, 2, 10).unwrap());
70    }
71
72    #[test]
73    fn results_carry_pagination() {
74        let results: ReleaseDatesResults = serde_json::from_str(
75            r#"{"count":2,"offset":0,"limit":1000,"release_dates":[
76                {"release_id":9,"release_name":"Advance Monthly Sales","date":"2013-08-13"},
77                {"release_id":10,"release_name":"Consumer Price Index","date":"2013-08-15"}
78            ]}"#,
79        )
80        .unwrap();
81        assert_eq!(results.count, 2);
82        assert_eq!(results.release_dates.len(), 2);
83        assert_eq!(results.release_dates[1].release_id, ReleaseId::new(10));
84    }
85}