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