pubmed_client/pubmed/query/
dates.rs1use super::{PubDate, SearchQuery};
4
5impl SearchQuery {
6 pub fn date_range(mut self, start_year: u32, end_year: Option<u32>) -> Self {
23 let date_filter = match end_year {
24 Some(end) => format!("{start_year}:{end}[pdat]"),
25 None => format!("{start_year}:3000[pdat]"), };
27 self.filters.push(date_filter);
28 self
29 }
30
31 pub fn published_between<S, E>(mut self, start: S, end: Option<E>) -> Self
64 where
65 S: Into<PubDate>,
66 E: Into<PubDate>,
67 {
68 let start_date = start.into();
69 let date_filter = match end {
70 Some(end_date) => {
71 let end_date = end_date.into();
72 format!(
73 "{}:{}[pdat]",
74 start_date.to_pubmed_string(),
75 end_date.to_pubmed_string()
76 )
77 }
78 None => format!("{}:3000[pdat]", start_date.to_pubmed_string()),
79 };
80 self.filters.push(date_filter);
81 self
82 }
83
84 pub fn published_in_year(mut self, year: u32) -> Self {
100 self.filters.push(format!("{year}[pdat]"));
101 self
102 }
103
104 pub fn entry_date_between<S, E>(mut self, start: S, end: Option<E>) -> Self
121 where
122 S: Into<PubDate>,
123 E: Into<PubDate>,
124 {
125 let start_date = start.into();
126 let date_filter = match end {
127 Some(end_date) => {
128 let end_date = end_date.into();
129 format!(
130 "{}:{}[edat]",
131 start_date.to_pubmed_string(),
132 end_date.to_pubmed_string()
133 )
134 }
135 None => format!("{}:3000[edat]", start_date.to_pubmed_string()),
136 };
137 self.filters.push(date_filter);
138 self
139 }
140
141 pub fn modification_date_between<S, E>(mut self, start: S, end: Option<E>) -> Self
158 where
159 S: Into<PubDate>,
160 E: Into<PubDate>,
161 {
162 let start_date = start.into();
163 let date_filter = match end {
164 Some(end_date) => {
165 let end_date = end_date.into();
166 format!(
167 "{}:{}[mdat]",
168 start_date.to_pubmed_string(),
169 end_date.to_pubmed_string()
170 )
171 }
172 None => format!("{}:3000[mdat]", start_date.to_pubmed_string()),
173 };
174 self.filters.push(date_filter);
175 self
176 }
177
178 pub fn published_after<D>(self, date: D) -> Self
205 where
206 D: Into<PubDate>,
207 {
208 self.published_between(date, None::<u32>)
209 }
210
211 pub fn published_before<D>(self, date: D) -> Self
238 where
239 D: Into<PubDate>,
240 {
241 self.published_between(1900, Some(date))
242 }
243}
244
245#[cfg(test)]
246mod tests {
247 use super::*;
248
249 #[test]
250 fn test_date_range_with_end_year() {
251 let query = SearchQuery::new().date_range(2020, Some(2023));
252 assert_eq!(query.build(), "2020:2023[pdat]");
253 }
254
255 #[test]
256 fn test_date_range_without_end_year() {
257 let query = SearchQuery::new().date_range(2020, None);
258 assert_eq!(query.build(), "2020:3000[pdat]");
259 }
260
261 #[test]
262 fn test_published_in_year() {
263 let query = SearchQuery::new().published_in_year(2023);
264 assert_eq!(query.build(), "2023[pdat]");
265 }
266
267 #[test]
268 fn test_published_between_years() {
269 let query = SearchQuery::new().published_between(2020, Some(2023));
270 assert_eq!(query.build(), "2020:2023[pdat]");
271 }
272
273 #[test]
274 fn test_published_between_months() {
275 let query = SearchQuery::new().published_between((2020, 3), Some((2021, 12)));
276 assert_eq!(query.build(), "2020/03:2021/12[pdat]");
277 }
278
279 #[test]
280 fn test_published_between_days() {
281 let query = SearchQuery::new().published_between((2020, 3, 15), Some((2020, 12, 31)));
282 assert_eq!(query.build(), "2020/03/15:2020/12/31[pdat]");
283 }
284
285 #[test]
286 fn test_published_after_year() {
287 let query = SearchQuery::new().published_after(2020);
288 assert_eq!(query.build(), "2020:3000[pdat]");
289 }
290
291 #[test]
292 fn test_published_after_month() {
293 let query = SearchQuery::new().published_after((2020, 3));
294 assert_eq!(query.build(), "2020/03:3000[pdat]");
295 }
296
297 #[test]
298 fn test_published_after_day() {
299 let query = SearchQuery::new().published_after((2020, 3, 15));
300 assert_eq!(query.build(), "2020/03/15:3000[pdat]");
301 }
302
303 #[test]
304 fn test_published_before_year() {
305 let query = SearchQuery::new().published_before(2020);
306 assert_eq!(query.build(), "1900:2020[pdat]");
307 }
308
309 #[test]
310 fn test_published_before_month() {
311 let query = SearchQuery::new().published_before((2020, 3));
312 assert_eq!(query.build(), "1900:2020/03[pdat]");
313 }
314
315 #[test]
316 fn test_published_before_day() {
317 let query = SearchQuery::new().published_before((2020, 3, 15));
318 assert_eq!(query.build(), "1900:2020/03/15[pdat]");
319 }
320
321 #[test]
322 fn test_entry_date_between() {
323 let query = SearchQuery::new().entry_date_between(2023, Some(2024));
324 assert_eq!(query.build(), "2023:2024[edat]");
325 }
326
327 #[test]
328 fn test_entry_date_between_open_ended() {
329 let query = SearchQuery::new().entry_date_between((2023, 6), None::<u32>);
330 assert_eq!(query.build(), "2023/06:3000[edat]");
331 }
332
333 #[test]
334 fn test_modification_date_between() {
335 let query =
336 SearchQuery::new().modification_date_between((2023, 1, 1), Some((2023, 12, 31)));
337 assert_eq!(query.build(), "2023/01/01:2023/12/31[mdat]");
338 }
339
340 #[test]
341 fn test_modification_date_between_open_ended() {
342 let query = SearchQuery::new().modification_date_between(2023, None::<u32>);
343 assert_eq!(query.build(), "2023:3000[mdat]");
344 }
345
346 #[test]
347 fn test_combined_date_filters() {
348 let query = SearchQuery::new()
349 .query("covid-19")
350 .published_between(2020, Some(2023))
351 .entry_date_between((2023, 1), None::<u32>);
352
353 assert_eq!(
354 query.build(),
355 "covid-19 AND 2020:2023[pdat] AND 2023/01:3000[edat]"
356 );
357 }
358
359 #[test]
360 fn test_multiple_date_ranges() {
361 let query = SearchQuery::new()
362 .date_range(2020, Some(2021))
363 .date_range(2022, Some(2023));
364
365 assert_eq!(query.build(), "2020:2021[pdat] AND 2022:2023[pdat]");
366 }
367
368 #[test]
369 fn test_date_precision_mixing() {
370 let query = SearchQuery::new()
371 .published_between(2020, Some((2023, 6, 15)))
372 .entry_date_between((2023, 1), Some(2024));
373
374 let built = query.build();
375 assert!(built.contains("2020:2023/06/15[pdat]"));
376 assert!(built.contains("2023/01:2024[edat]"));
377 }
378
379 #[test]
380 fn test_multiple_date_types() {
381 let query = SearchQuery::new()
382 .query("research")
383 .published_between(2020, Some(2023))
384 .entry_date_between((2023, 1), Some((2023, 12)))
385 .modification_date_between((2023, 6), None::<u32>);
386
387 let built = query.build();
388 assert!(built.contains("2020:2023[pdat]"));
389 assert!(built.contains("2023/01:2023/12[edat]"));
390 assert!(built.contains("2023/06:3000[mdat]"));
391 }
392
393 #[test]
394 fn test_edge_year_values() {
395 let query = SearchQuery::new().date_range(1, Some(9999));
396 assert_eq!(query.build(), "1:9999[pdat]");
397 }
398
399 #[test]
400 fn test_same_start_end_date() {
401 let query = SearchQuery::new().published_between(2023, Some(2023));
402 assert_eq!(query.build(), "2023:2023[pdat]");
403 }
404
405 #[test]
406 fn test_published_between_none_end() {
407 let query = SearchQuery::new().published_between(2020, None::<u32>);
408 assert_eq!(query.build(), "2020:3000[pdat]");
409 }
410}