fred_rs/releases/dates.rs
1//! Get release dates for all releases of economic data
2//!
3//! [https://research.stlouisfed.org/docs/api/fred/releases_dates.html](https://research.stlouisfed.org/docs/api/fred/releases_dates.html)
4//!
5//! ```
6//! use fred_rs::client::FredClient;
7//! use fred_rs::releases::dates::{Builder, Response, OrderBy, SortOrder};
8//!
9//! // Create the client object
10//! let mut c = match FredClient::new() {
11//! Ok(c) => c,
12//! Err(msg) => {
13//! println!("{}", msg);
14//! return
15//! },
16//! };
17//!
18//! // Create the argument builder
19//! let mut builder = Builder::new();
20//! builder
21//! .limit(5)
22//! .sort_order(SortOrder::Ascending)
23//! .order_by(OrderBy::ReleaseId);
24//!
25//! // Make the request and pass in the builder to apply the arguments
26//! let resp: Response = match c.releases_dates(Some(builder)) {
27//! Ok(resp) => resp,
28//! Err(msg) => {
29//! println!("{}", msg);
30//! return
31//! },
32//! };
33//! ```
34
35use serde::Deserialize;
36use std::fmt::{self, Display, Formatter};
37
38#[derive(Deserialize, Clone, Debug, Default)]
39/// Response data structure for the fred/releases/dates endpoint
40///
41/// [https://research.stlouisfed.org/docs/api/fred/releases_dates.html] (https://research.stlouisfed.org/docs/api/fred/releases_dates.html)
42pub struct Response {
43 /// The Real Time start date for the request
44 pub realtime_start: String,
45 /// The Real Time end data for the request
46 pub realtime_end: String,
47 /// How the results are ordered
48 pub order_by: String,
49 // Results are listed in ascending or descending order
50 pub sort_order: String,
51 /// Number of results returned
52 pub count: usize,
53 /// First result returned
54 pub offset: usize,
55 /// Maximum number of results to return
56 pub limit: usize,
57 /// List of release dates for a release
58 pub release_dates: Vec<ReleaseDate>,
59}
60
61impl Display for Response {
62 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
63 for item in self.release_dates.iter() {
64 match item.fmt(f) {
65 Ok(_) => (),
66 Err(e) => return Err(e),
67 }
68 match writeln!(f, "") {
69 Ok(_) => (),
70 Err(e) => return Err(e),
71 }
72 }
73 Ok(())
74 }
75}
76
77#[derive(Deserialize, Clone, Debug, Default)]
78/// Data structure containing infomation about a particular release
79///
80/// [https://research.stlouisfed.org/docs/api/fred/releases_dates.html](https://research.stlouisfed.org/docs/api/fred/releases_dates.html)
81pub struct ReleaseDate {
82 /// The release ID number
83 pub release_id: usize,
84 /// The name of the release
85 pub release_name: Option<String>,
86 /// The date of the release
87 pub date: String,
88}
89
90impl Display for ReleaseDate {
91 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
92 write!(f, "Release Date {}: {}", self.release_id, self.date)
93 }
94}
95
96/// Determines the order of search results
97///
98/// [https://research.stlouisfed.org/docs/api/fred/releases_dates.html#order_by](https://research.stlouisfed.org/docs/api/fred/releases_dates.html#order_by)
99pub enum OrderBy {
100 /// Default
101 ReleaseDate,
102 ReleaseId,
103 ReleaseName,
104}
105
106/// Sort order options for the fred/releases/dates endpoint
107///
108/// [https://research.stlouisfed.org/docs/api/fred/releases_dates.html#sort_order](https://research.stlouisfed.org/docs/api/fred/releases_dates.html#sort_order)
109pub enum SortOrder {
110 /// Dates returned in ascending order
111 Ascending,
112 /// Dates returned in descending order (default)
113 Descending,
114}
115
116pub struct Builder {
117 option_string: String
118}
119
120impl Builder {
121
122 /// Initializes a new releases::Builder that can be used to add commands to an API request
123 ///
124 /// The builder does not do validity checking of the arguments nor does it check for duplicates.
125 ///
126 /// ```
127 /// use fred_rs::releases::dates::Builder;
128 /// // Create a new builder
129 /// let mut builder = Builder::new();
130 /// // add arguments to the builder
131 /// builder
132 /// .realtime_start("1900-01-01")
133 /// .realtime_end("2000-01-01");
134 /// ```
135 pub fn new() -> Builder {
136 Builder {
137 option_string: String::new(),
138 }
139 }
140
141 /// Returns the current arguments as a URL formatted string
142 pub(crate) fn build(self) -> String {
143 self.option_string
144 }
145
146 /// Adds a realtime_start argument to the builder
147 ///
148 /// # Arguments
149 /// * `start_date` - date formatted as YYYY-MM-DD
150 ///
151 /// [https://research.stlouisfed.org/docs/api/fred/releases_dates.html#realtime_start](https://research.stlouisfed.org/docs/api/fred/releases_dates.html#realtime_start)
152 pub fn realtime_start(&mut self, start_date: &str) -> &mut Builder {
153 self.option_string += format!("&realtime_start={}", start_date).as_str();
154 self
155 }
156
157 /// Adds a realtime_end argument to the builder
158 ///
159 /// # Arguments
160 /// * `end_date` - date formatted as YYYY-MM-DD
161 ///
162 /// [https://research.stlouisfed.org/docs/api/fred/releases_dates.html#realtime_end](https://research.stlouisfed.org/docs/api/fred/releases_dates.html#realtime_end)
163 pub fn realtime_end(&mut self, end_date: &str) -> &mut Builder {
164 self.option_string += format!("&realtime_end={}", end_date).as_str();
165 self
166 }
167
168 /// Adds a limit argument to the builder
169 ///
170 /// The limit argument specifies a maximum number of observations to return.
171 ///
172 /// # Arguments
173 /// * `num_results` - Maximum number of results to return
174 ///
175 /// [https://research.stlouisfed.org/docs/api/fred/releases_dates.html#limit](https://research.stlouisfed.org/docs/api/fred/releases_dates.html#limit)
176 pub fn limit(&mut self, num_results: usize) -> &mut Builder {
177 let num_results = if num_results > 1000 { // max value is 1000
178 1000
179 } else {
180 num_results
181 };
182 self.option_string += format!("&limit={}", num_results).as_str();
183 self
184 }
185
186 /// Adds an offset argument to the builder
187 ///
188 /// 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.
189 ///
190 /// # Arguments
191 /// * `ofs` - the offset amount
192 ///
193 /// [https://research.stlouisfed.org/docs/api/fred/releases_dates.html#offset](https://research.stlouisfed.org/docs/api/fred/releases_dates.html#offset)
194 pub fn offset(&mut self, ofs: usize) -> &mut Builder {
195 self.option_string += format!("&offset={}", ofs).as_str();
196 self
197 }
198
199 /// Adds the search_type argument to the request
200 ///
201 /// # Arguments
202 /// * `order` - result ranking system
203 ///
204 /// [https://research.stlouisfed.org/docs/api/fred/releases_dates.html#order_by](https://research.stlouisfed.org/docs/api/fred/releases_dates.html#order_by)
205 pub fn order_by(&mut self, order: OrderBy) -> &mut Builder {
206 match order {
207 OrderBy::ReleaseDate => {
208 self.option_string += "&order_by=release_name";
209 },
210 OrderBy::ReleaseId => {
211 self.option_string += "&order_by=release_id";
212 },
213 OrderBy::ReleaseName => {
214 self.option_string += "&order_by=name";
215 },
216 };
217 self
218 }
219
220 /// Change the sort order of the data
221 ///
222 /// # Arguments
223 /// * `order` - Data sort order enum
224 ///
225 /// [https://research.stlouisfed.org/docs/api/fred/releases_dates.html#sort_order](https://research.stlouisfed.org/docs/api/fred/releases_dates.html#sort_order)
226 pub fn sort_order(&mut self, order: SortOrder) -> &mut Builder {
227 match order {
228 SortOrder::Ascending => {
229 self.option_string += format!("&sort_order=asc").as_str()
230 },
231 _ => () // DESC is the default so do nothing
232 }
233 self
234 }
235
236 /// Include release dates with no data available
237 ///
238 /// The default is false. Calling this will set the argument to true.
239 ///
240 /// [https://research.stlouisfed.org/docs/api/fred/releases_dates.html#include_release_dates_with_no_data](https://research.stlouisfed.org/docs/api/fred/releases_dates.html#include_release_dates_with_no_data)
241 pub fn include_release_dates_with_no_data(&mut self) -> &mut Builder {
242 self.option_string += format!(
243 "&include_release_dates_with_no_data=true"
244 ).as_str();
245 self
246 }
247}
248
249#[cfg(test)]
250mod tests {
251 use super::*;
252 use crate::client::FredClient;
253
254 #[test]
255 fn releases_dates_with_options() {
256 let mut c = match FredClient::new() {
257 Ok(c) => c,
258 Err(msg) => {
259 println!("{}", msg);
260 assert_eq!(2, 1);
261 return
262 },
263 };
264
265 let mut builder = Builder::new();
266 builder
267 .limit(5)
268 .sort_order(SortOrder::Ascending)
269 .order_by(OrderBy::ReleaseId);
270
271 let resp: Response = match c.releases_dates(Some(builder)) {
272 Ok(resp) => resp,
273 Err(msg) => {
274 println!("{}", msg);
275 assert_eq!(2, 1);
276 return
277 },
278 };
279
280 for item in resp.release_dates {
281 println!("{}: {} -> {}", item.date, item.release_id, item.release_name.unwrap());
282 }
283 }
284}