fred_rs/series/
updates.rs

1//! Get economic data series sorted by when observations were updated on the FREDĀ® server
2//! 
3//! [https://research.stlouisfed.org/docs/api/fred/series_updates.html](https://research.stlouisfed.org/docs/api/fred/series_updates.html)
4//! 
5//! ```
6//! use fred_rs::client::FredClient;
7//! use fred_rs::series::updates::{Builder, Response};
8//! 
9//! let mut c = match FredClient::new() {
10//!     Ok(c) => c,
11//!     Err(msg) => {
12//!         println!("{}", msg);
13//!         assert_eq!(2, 1);
14//!         return
15//!     },
16//! };
17//! 
18//! let mut builder = Builder::new();
19//! builder
20//!     .limit(5);
21//! 
22//! let resp: Response = match c.series_updates(Some(builder)) {
23//!     Ok(resp) => resp,
24//!     Err(msg) => {
25//!         println!("{}", msg);
26//!         assert_eq!(2, 1);
27//!         return
28//!     },
29//! };
30//! 
31//! for item in resp.seriess {
32//!     println!(
33//!         "{}: {} {}",
34//!         item.title,
35//!         item.id,
36//!         item.popularity,
37//!     );
38//! }
39//! ```
40
41use serde::Deserialize;
42use std::fmt::{self, Display, Formatter};
43
44use crate::series::Series;
45
46#[derive(Deserialize, Clone, Debug, Default)]
47/// Response data structure for the fred/series/updates endpoint
48/// 
49/// [https://research.stlouisfed.org/docs/api/fred/series_updates.html] (https://research.stlouisfed.org/docs/api/fred/series_updates.html)
50pub struct Response {
51    /// The Real Time start date for the request
52    pub realtime_start: String,
53    /// The Real Time end data for the request
54    pub realtime_end: String,
55    /// What variable the requested wass filtered with
56    pub filter_variable: String,
57    /// Value that must match the filter field to include a result
58    pub filter_value: String,
59    /// How the results are ordered
60    pub order_by: String,
61    // Results are listed in ascending or descending
62    pub sort_order: String,
63    /// Number of results returned
64    pub count: usize,
65    /// ???
66    pub offset: usize,
67    /// Maximum number of results to return
68    pub limit: usize,
69    /// Series returned by the search
70    pub seriess: Vec<Series>,
71}
72
73impl Display for Response {
74    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
75        for item in self.seriess.iter() {
76            match item.fmt(f) {
77                Ok(_) => (),
78                Err(e) => return Err(e),
79            }
80            match writeln!(f, "") {
81                Ok(_) => (),
82                Err(e) => return Err(e),
83            }
84        }
85        Ok(())
86    }
87}
88
89/// Used to filter series included in the results
90/// 
91/// [https://research.stlouisfed.org/docs/api/fred/series_updates.html#filter_value](https://research.stlouisfed.org/docs/api/fred/series_updates.html#filter_value)
92pub enum FilterValue {
93    /// Macroeconomic data series
94    Macro,
95    /// Regional data series
96    Regional,
97    /// (Default) All data series
98    All,
99}
100
101pub struct Builder {
102    option_string: String,
103}
104
105impl Builder {
106
107    /// Initializes a new series::updates::Builder that can be used to add commands to an API request
108    /// 
109    /// The builder does not do validity checking of the arguments nor does it check for duplicates.
110    /// 
111    /// ```
112    /// use fred_rs::series::updates::Builder;
113    /// // Create a new builder
114    /// let mut builder = Builder::new();
115    /// // add arguments to the builder
116    /// builder
117    ///     .realtime_start("1900-01-01")
118    ///     .realtime_end("2000-01-01");
119    /// ```
120    pub fn new() -> Builder {
121        Builder {
122            option_string: String::new(),
123        }
124    }
125
126    /// Returns the current arguments as a URL formatted string
127    /// 
128    /// Returns Err if there are no tag names specified using tag_name().
129    pub(crate) fn build(self) -> String {
130        self.option_string
131    }
132
133    /// Adds a realtime_start argument to the builder
134    /// 
135    /// # Arguments
136    /// * `start_date` - date formatted as YYYY-MM-DD
137    /// 
138    /// [https://research.stlouisfed.org/docs/api/fred/series_updates.html#realtime_start](https://research.stlouisfed.org/docs/api/fred/series_updates.html#realtime_start)
139    pub fn realtime_start(&mut self, start_date: &str) -> &mut Builder {
140        self.option_string += format!("&realtime_start={}", start_date).as_str();
141        self
142    }
143
144    /// Adds a realtime_end argument to the builder
145    /// 
146    /// # Arguments
147    /// * `end_date` - date formatted as YYYY-MM-DD
148    pub fn realtime_end(&mut self, end_date: &str) -> &mut Builder {
149        self.option_string += format!("&realtime_end={}", end_date).as_str();
150        self
151    }
152
153    /// Adds a limit argument to the builder
154    /// 
155    /// The limit argument specifies a maximum number of observations to return.
156    /// 
157    /// # Arguments
158    /// * `num_results` - Maximum number of results to return
159    /// 
160    /// [https://research.stlouisfed.org/docs/api/fred/series_updates.html#realtime_end](https://research.stlouisfed.org/docs/api/fred/series_updates.html#realtime_end)
161    pub fn limit(&mut self, num_results: usize) -> &mut Builder {
162        let num_results = if num_results > 1000 { // max value is 1000
163            1000
164        } else {
165            num_results
166        };
167        self.option_string += format!("&limit={}", num_results).as_str();
168        self
169    }
170
171    /// Adds an offset argument to the builder
172    /// 
173    /// Adding an offset shifts the starting result number.  For example, if limit is 5 and offset is 0 then results 1-5 will be returned, but if offset was 5 then results 6-10 would be returned.
174    /// 
175    /// # Arguments
176    /// * `ofs` - the offset amount
177    /// 
178    /// [https://research.stlouisfed.org/docs/api/fred/series_updates.html#offset](https://research.stlouisfed.org/docs/api/fred/series_updates.html#offset)
179    pub fn offset(&mut self, ofs: usize) -> &mut Builder {
180        self.option_string += format!("&offset={}", ofs).as_str();
181        self
182    }
183
184    /// Adds the filter_value argument to the request
185    /// 
186    /// # Arguments
187    /// * `value` - value with which to filter results
188    /// 
189    /// [https://research.stlouisfed.org/docs/api/fred/series_updates.html#filter_value](https://research.stlouisfed.org/docs/api/fred/series_updates.html#filter_value)
190    pub fn filter_value(&mut self, value: FilterValue) -> &mut Builder {
191        match value {
192            FilterValue::Macro => {
193                self.option_string += "&filter_value=macro";
194            },
195            FilterValue::Regional => {
196                self.option_string += "&filter_value=regional";
197            },
198            _ => (), // All is default so do nothing
199        };
200        self
201    }
202
203    /// Limit results to a certian time range
204    /// 
205    /// Both a start and end time must be specified together as per the API docs.
206    /// 
207    /// # Arguments
208    /// * `start_time` - Start time to limit results to (YYYYMMDDHhmm format)
209    /// * `end_time` - End time to limit results to (YYYYMMDDHhmm format)
210    /// 
211    /// [https://research.stlouisfed.org/docs/api/fred/series_updates.html#start_time](https://research.stlouisfed.org/docs/api/fred/series_updates.html#start_time)
212    /// 
213    /// [https://research.stlouisfed.org/docs/api/fred/series_updates.html#end_time](https://research.stlouisfed.org/docs/api/fred/series_updates.html#end_time)
214    pub fn time_range(&mut self, start_time: &str, end_time: &str) -> &mut Builder {
215        self.option_string += format!(
216            "&start_time={}&end_time={}",
217            start_time,
218            end_time
219        ).as_str();
220        self
221    }
222
223}
224
225#[cfg(test)]
226mod tests {
227    use super::*;
228    use crate::client::FredClient;
229
230    #[test]
231    fn series_updates_with_options() {
232        let mut c = match FredClient::new() {
233            Ok(c) => c,
234            Err(msg) => {
235                println!("{}", msg);
236                assert_eq!(2, 1);
237                return
238            },
239        };
240
241        let mut builder = Builder::new();
242        builder
243            .limit(5);
244
245        let resp: Response = match c.series_updates(Some(builder)) {
246            Ok(resp) => resp,
247            Err(msg) => {
248                println!("{}", msg);
249                assert_eq!(2, 1);
250                return
251            },
252        };
253
254        for item in resp.seriess {
255            println!(
256                "{}: {} {}",
257                item.title,
258                item.id,
259                item.popularity,
260            );
261        }
262    } 
263}