zer_blocking/keys/
date.rs1use zer_core::{record::Record, schema::Schema};
2use super::BlockingKey;
3
4#[derive(Debug, Clone, Copy)]
6pub enum DateGranularity {
7 Year,
8 YearMonth,
9 YearMonthDay,
10}
11
12pub struct DateFragmentKey {
14 dob_field: String,
15 granularity: DateGranularity,
16}
17
18impl DateFragmentKey {
19 pub fn new(dob_field: &str, granularity: DateGranularity) -> Self {
20 Self { dob_field: dob_field.into(), granularity }
21 }
22
23 fn fragment_len(granularity: DateGranularity) -> usize {
24 match granularity {
25 DateGranularity::Year => 4,
26 DateGranularity::YearMonth => 7,
27 DateGranularity::YearMonthDay => 10,
28 }
29 }
30}
31
32impl BlockingKey for DateFragmentKey {
33 fn name(&self) -> &str {
34 "date_fragment"
35 }
36
37 fn extract(&self, record: &Record, _schema: &Schema) -> Vec<String> {
38 let cow = record.field_as_str(&self.dob_field);
39 let raw = match cow.as_deref() {
40 Some(s) => s.trim(),
41 None => return vec![],
42 };
43
44 let len = Self::fragment_len(self.granularity);
45 if raw.len() < len {
46 return vec![];
47 }
48
49 let fragment = &raw[..len];
50 if !fragment.chars().next().map(|c| c.is_ascii_digit()).unwrap_or(false) {
51 return vec![];
52 }
53
54 vec![fragment.to_string()]
55 }
56}
57
58#[cfg(test)]
59mod tests {
60 use super::*;
61 use zer_core::{record::FieldValue, schema::{SchemaBuilder, FieldKind}};
62
63 fn schema() -> Schema {
64 SchemaBuilder::new().field("dob", FieldKind::Date).build().unwrap()
65 }
66
67 #[test]
68 fn year_fragment() {
69 let k = DateFragmentKey::new("dob", DateGranularity::Year);
70 let r = Record::new(1).insert("dob", FieldValue::Text("1985-06-23".into()));
71 assert_eq!(k.extract(&r, &schema()), vec!["1985"]);
72 }
73
74 #[test]
75 fn year_month_fragment() {
76 let k = DateFragmentKey::new("dob", DateGranularity::YearMonth);
77 let r = Record::new(1).insert("dob", FieldValue::Text("1985-06-23".into()));
78 assert_eq!(k.extract(&r, &schema()), vec!["1985-06"]);
79 }
80
81 #[test]
82 fn year_month_day_fragment() {
83 let k = DateFragmentKey::new("dob", DateGranularity::YearMonthDay);
84 let r = Record::new(1).insert("dob", FieldValue::Text("1985-06-23".into()));
85 assert_eq!(k.extract(&r, &schema()), vec!["1985-06-23"]);
86 }
87
88 #[test]
89 fn missing_field_returns_empty() {
90 let k = DateFragmentKey::new("dob", DateGranularity::Year);
91 let r = Record::new(1);
92 assert!(k.extract(&r, &schema()).is_empty());
93 }
94
95 #[test]
96 fn short_value_returns_empty() {
97 let k = DateFragmentKey::new("dob", DateGranularity::YearMonth);
98 let r = Record::new(1).insert("dob", FieldValue::Text("1985".into()));
99 assert!(k.extract(&r, &schema()).is_empty());
100 }
101}