fred_rs/release/series.rs
1//! Get the series on a release of economic data
2//!
3//! [https://research.stlouisfed.org/docs/api/fred/release_series.html](https://research.stlouisfed.org/docs/api/fred/release_series.html)
4//!
5//! ```
6//! use fred_rs::client::FredClient;
7//! use fred_rs::release::series::{Builder, OrderBy, SortOrder};
8//! use fred_rs::series::Response;
9//!
10//! let mut c = match FredClient::new() {
11//! Ok(c) => c,
12//! Err(msg) => {
13//! println!("{}", msg);
14//! assert_eq!(2, 1);
15//! return
16//! },
17//! };
18//!
19//! let mut builder = Builder::new();
20//! builder
21//! .limit(5)
22//! .sort_order(SortOrder::Descending)
23//! .order_by(OrderBy::Frequency);
24//!
25//! let resp: Response = match c.release_series(9, Some(builder)) {
26//! Ok(resp) => resp,
27//! Err(msg) => {
28//! println!("{}", msg);
29//! assert_eq!(2, 1);
30//! return
31//! },
32//! };
33//!
34//! for item in resp.seriess {
35//! println!(
36//! "{}: {} {}",
37//! item.id,
38//! item.title,
39//! item.frequency,
40//! );
41//! }
42//! ```
43
44/// Determines the order of search results
45///
46/// [https://research.stlouisfed.org/docs/api/fred/release_series.html#order_by](https://research.stlouisfed.org/docs/api/fred/release_series.html#order_by)
47pub enum OrderBy {
48 /// Default
49 SeriesId,
50 Title,
51 Units,
52 Frequency,
53 SeasonalAdjustment,
54 RealtimeStart,
55 RealtimeEnd,
56 LastUpdated,
57 ObservationStart,
58 ObservationEnd,
59 Popularity,
60 GroupPopularity,
61}
62
63/// Sort order options for the fred/release/series endpoint
64///
65/// [https://research.stlouisfed.org/docs/api/fred/release_series.html#sort_order](https://research.stlouisfed.org/docs/api/fred/release_series.html#sort_order)
66pub enum SortOrder {
67 /// Dates returned in ascending order (default)
68 Ascending,
69 /// Dates returned in descending order
70 Descending,
71}
72
73/// Apply result filter
74///
75/// This should be used in conjunction with the filter_value argument to filter results based on one (maybe more than one?) of the fields.
76///
77/// [https://research.stlouisfed.org/docs/api/fred/release_series.html#filter_variable](https://research.stlouisfed.org/docs/api/fred/release_series.html#filter_variable)
78pub enum FilterVariable {
79 Frequency,
80 Units,
81 SeasonalAdjustment,
82}
83
84pub struct Builder {
85 option_string: String,
86 include_tags: String,
87 exclude_tags: String,
88}
89
90impl Builder {
91
92 /// Initializes a new release::series::Builder that can be used to add commands to an API request
93 ///
94 /// The builder does not do validity checking of the arguments nor does it check for duplicates.
95 ///
96 /// ```
97 /// use fred_rs::release::series::Builder;
98 /// // Create a new builder
99 /// let mut builder = Builder::new();
100 /// // add arguments to the builder
101 /// builder
102 /// .realtime_start("1900-01-01")
103 /// .realtime_end("2000-01-01");
104 /// ```
105 pub fn new() -> Builder {
106 Builder {
107 option_string: String::new(),
108 include_tags: String::new(),
109 exclude_tags: String::new(),
110 }
111 }
112
113 /// Returns the current arguments as a URL formatted string
114 pub(crate) fn build(mut self) -> String {
115 if self.include_tags.len() > 0 {
116 self.option_string += format!("&tag_names={}", self.include_tags).as_str()
117 }
118 if self.exclude_tags.len() > 0 {
119 self.option_string += format!("&exclude_tag_names={}", self.exclude_tags).as_str()
120 }
121 self.option_string
122 }
123
124 /// Adds a realtime_start argument to the builder
125 ///
126 /// # Arguments
127 /// * `start_date` - date formatted as YYYY-MM-DD
128 ///
129 /// [https://research.stlouisfed.org/docs/api/fred/release_series.html#realtime_start](https://research.stlouisfed.org/docs/api/fred/release_series.html#realtime_start)
130 pub fn realtime_start(&mut self, start_date: &str) -> &mut Builder {
131 self.option_string += format!("&realtime_start={}", start_date).as_str();
132 self
133 }
134
135 /// Adds a realtime_end argument to the builder
136 ///
137 /// # Arguments
138 /// * `end_date` - date formatted as YYYY-MM-DD
139 ///
140 /// [https://research.stlouisfed.org/docs/api/fred/release_series.html#realtime_end](https://research.stlouisfed.org/docs/api/fred/release_series.html#realtime_end)
141 pub fn realtime_end(&mut self, end_date: &str) -> &mut Builder {
142 self.option_string += format!("&realtime_end={}", end_date).as_str();
143 self
144 }
145
146 /// Adds a limit argument to the builder
147 ///
148 /// The limit argument specifies a maximum number of observations to return.
149 ///
150 /// # Arguments
151 /// * `num_results` - Maximum number of results to return
152 ///
153 /// [https://research.stlouisfed.org/docs/api/fred/release_series.html#limit](https://research.stlouisfed.org/docs/api/fred/release_series.html#limit)
154 pub fn limit(&mut self, num_results: usize) -> &mut Builder {
155 let num_results = if num_results > 1000 { // max value is 1000
156 1000
157 } else {
158 num_results
159 };
160 self.option_string += format!("&limit={}", num_results).as_str();
161 self
162 }
163
164 /// Adds an offset argument to the builder
165 ///
166 /// 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.
167 ///
168 /// # Arguments
169 /// * `ofs` - the offset amount
170 ///
171 /// [https://research.stlouisfed.org/docs/api/fred/release_series.html#offset](https://research.stlouisfed.org/docs/api/fred/release_series.html#offset)
172 pub fn offset(&mut self, ofs: usize) -> &mut Builder {
173 self.option_string += format!("&offset={}", ofs).as_str();
174 self
175 }
176
177 /// Adds the search_type argument to the request
178 ///
179 /// # Arguments
180 /// * `order` - result ranking system
181 ///
182 /// [https://research.stlouisfed.org/docs/api/fred/release_series.html#order_by](https://research.stlouisfed.org/docs/api/fred/release_series.html#order_by)
183 pub fn order_by(&mut self, order: OrderBy) -> &mut Builder {
184 match order {
185 OrderBy::SeriesId => {
186 self.option_string += "&order_by=series_id";
187 },
188 OrderBy::Title => {
189 self.option_string += "&order_by=title";
190 },
191 OrderBy::Units => {
192 self.option_string += "&order_by=units";
193 },
194 OrderBy::Frequency => {
195 self.option_string += "&order_by=frequency";
196 },
197 OrderBy::SeasonalAdjustment => {
198 self.option_string += "&order_by=seasonal_adjustment";
199 },
200 OrderBy::RealtimeStart => {
201 self.option_string += "&order_by=realtime_start";
202 },
203 OrderBy::RealtimeEnd => {
204 self.option_string += "&order_by=realtime_end";
205 },
206 OrderBy::LastUpdated => {
207 self.option_string += "&order_by=last_updated";
208 },
209 OrderBy::ObservationStart => {
210 self.option_string += "&order_by=observation_start";
211 },
212 OrderBy::ObservationEnd => {
213 self.option_string += "&order_by=observation_end";
214 },
215 OrderBy::Popularity => {
216 self.option_string += "&order_by=popularity";
217 },
218 OrderBy::GroupPopularity => {
219 self.option_string += "&order_by=group_popularity";
220 },
221 };
222 self
223 }
224
225 /// Change the sort order of the data
226 ///
227 /// # Arguments
228 /// * `order` - Data sort order enum
229 ///
230 /// [https://research.stlouisfed.org/docs/api/fred/release_series.html#sort_order](https://research.stlouisfed.org/docs/api/fred/release_series.html#sort_order)
231 pub fn sort_order(&mut self, order: SortOrder) -> &mut Builder {
232 match order {
233 SortOrder::Descending => {
234 self.option_string += format!("&sort_order=desc").as_str()
235 },
236 _ => () // ASC is the default so do nothing
237 }
238 self
239 }
240
241 /// Adds the filter_variable argument to the request
242 ///
243 /// # Arguments
244 /// * `var` - the varible by which to filter
245 ///
246 /// [https://research.stlouisfed.org/docs/api/fred/release_series.html#filter_variable](https://research.stlouisfed.org/docs/api/fred/release_series.html#filter_variable)
247 pub fn filter_variable(&mut self, var: FilterVariable) -> &mut Builder {
248 match var {
249 FilterVariable::Frequency => {
250 self.option_string += "&filter_variable=frequency";
251 },
252 FilterVariable::Units => {
253 self.option_string += "&filter_variable=units";
254 },
255 FilterVariable::SeasonalAdjustment => {
256 self.option_string += "&filter_variable=seasonal_adjustment";
257 },
258 };
259 self
260 }
261
262 /// Sets the filter value for the specified filter variable
263 ///
264 /// Results will only include a subset of the original results that match this value for the filter_variable argument.
265 ///
266 /// # Arguments
267 /// * `val` - the filter value
268 ///
269 /// [https://research.stlouisfed.org/docs/api/fred/release_series.html#filter_value](https://research.stlouisfed.org/docs/api/fred/release_series.html#filter_value)
270 pub fn filter_value(&mut self, val: &str) -> &mut Builder {
271 self.option_string += format!("&filter_value={}", val).as_str();
272 self
273 }
274
275 /// Adds a tag name to include in the search
276 ///
277 /// Results must match all included tag names.
278 ///
279 /// # Arguments
280 /// * `tag` - tag name to add
281 ///
282 /// [https://research.stlouisfed.org/docs/api/fred/release_series.html#tag_names](https://research.stlouisfed.org/docs/api/fred/release_series.html#tag_names)
283 pub fn tag_name(&mut self, tag: &str) -> &mut Builder {
284 if self.include_tags.len() != 0 {
285 self.include_tags.push(';');
286 }
287 self.include_tags += tag;
288 self
289 }
290
291 /// Adds a tag name to exclude in the search
292 ///
293 /// Results must match no excluded tag names.
294 ///
295 /// # Arguments
296 /// * `tag` - tag name to add
297 ///
298 /// [https://research.stlouisfed.org/docs/api/fred/release_series.html#exclude_tag_names](https://research.stlouisfed.org/docs/api/fred/release_series.html#exclude_tag_names)
299 pub fn exclude_tag(&mut self, tag: &str) -> &mut Builder {
300 if self.exclude_tags.len() != 0 {
301 self.exclude_tags.push(';');
302 }
303 self.exclude_tags += tag;
304 self
305 }
306
307}
308
309#[cfg(test)]
310mod tests {
311 use super::*;
312 use crate::series::Response;
313 use crate::client::FredClient;
314
315 #[test]
316 fn release_series_with_options() {
317 let mut c = match FredClient::new() {
318 Ok(c) => c,
319 Err(msg) => {
320 println!("{}", msg);
321 assert_eq!(2, 1);
322 return
323 },
324 };
325
326 let mut builder = Builder::new();
327 builder
328 .limit(5)
329 .sort_order(SortOrder::Descending)
330 .order_by(OrderBy::Frequency);
331
332 let resp: Response = match c.release_series(9, Some(builder)) {
333 Ok(resp) => resp,
334 Err(msg) => {
335 println!("{}", msg);
336 assert_eq!(2, 1);
337 return
338 },
339 };
340
341 for item in resp.seriess {
342 println!(
343 "{}: {} {}",
344 item.id,
345 item.title,
346 item.frequency,
347 );
348 }
349 }
350}