Skip to main content

all_examples/
all_examples.rs

1//! Comprehensive examples showcasing the partial-date library with 22+ different use cases.
2//!
3//! Run with: `cargo run --example all_examples`
4
5use partial_date::extract::extract;
6use partial_date::models::*;
7
8fn main() {
9    println!("======================================================================");
10    println!("partial-date: 22+ Examples");
11    println!("======================================================================\n");
12
13    example_1_basic_dmy();
14    example_2_basic_mdy();
15    example_3_basic_ymd();
16    example_4_partial_day_and_month();
17    example_5_partial_month_and_year();
18    example_6_day_only();
19    example_7_month_name_full();
20    example_8_month_name_abbreviated();
21    example_9_month_name_fuzzy();
22    example_10_year_two_digit_sliding_window();
23    example_11_year_two_digit_always_2000s();
24    example_12_year_two_digit_literal();
25    example_13_ordinal_day_st();
26    example_14_ordinal_day_varied();
27    example_15_ordinal_day_in_context();
28    example_16_custom_min_max();
29    example_17_default_values();
30    example_18_no_separator_concat();
31    example_19_messy_input();
32    example_20_boundary_dates();
33    example_21_fuzzy_month_name();
34    example_22_all_component_orders();
35}
36
37// ============================================================================
38// EXAMPLE 1: Basic DMY (Day-Month-Year) Format
39// ============================================================================
40fn example_1_basic_dmy() {
41    println!("1️⃣  BASIC DMY FORMAT");
42    println!("   Input: '25/12/2024'");
43    println!("   Config: Day-Month-Year order\n");
44
45    let input = Input {
46        utterance: "25/12/2024".to_string(),
47        config: Some(Config {
48            component_order: ComponentOrder {
49                first: DateComponent::Day,
50                second: DateComponent::Month,
51                third: DateComponent::Year,
52            },
53            ..Default::default()
54        }),
55    };
56
57    let result = extract(input);
58    println!("   ✓ Day:   {:?}", result.day.value);
59    println!("   ✓ Month: {:?}", result.month.number);
60    println!("   ✓ Year:  {:?}\n", result.year.value);
61}
62
63// ============================================================================
64// EXAMPLE 2: Basic MDY (Month-Day-Year) Format
65// ============================================================================
66fn example_2_basic_mdy() {
67    println!("2️⃣  BASIC MDY FORMAT");
68    println!("   Input: '12/25/2024'");
69    println!("   Config: Month-Day-Year order\n");
70
71    let input = Input {
72        utterance: "12/25/2024".to_string(),
73        config: Some(Config {
74            component_order: ComponentOrder {
75                first: DateComponent::Month,
76                second: DateComponent::Day,
77                third: DateComponent::Year,
78            },
79            ..Default::default()
80        }),
81    };
82
83    let result = extract(input);
84    println!("   ✓ Day:   {:?}", result.day.value);
85    println!("   ✓ Month: {:?}", result.month.number);
86    println!("   ✓ Year:  {:?}\n", result.year.value);
87}
88
89// ============================================================================
90// EXAMPLE 3: Basic YMD (Year-Month-Day) Format
91// ============================================================================
92fn example_3_basic_ymd() {
93    println!("3️⃣  BASIC YMD FORMAT");
94    println!("   Input: '2024/12/25'");
95    println!("   Config: Year-Month-Day order\n");
96
97    let input = Input {
98        utterance: "2024/12/25".to_string(),
99        config: Some(Config {
100            component_order: ComponentOrder {
101                first: DateComponent::Year,
102                second: DateComponent::Month,
103                third: DateComponent::Day,
104            },
105            ..Default::default()
106        }),
107    };
108
109    let result = extract(input);
110    println!("   ✓ Day:   {:?}", result.day.value);
111    println!("   ✓ Month: {:?}", result.month.number);
112    println!("   ✓ Year:  {:?}\n", result.year.value);
113}
114
115// ============================================================================
116// EXAMPLE 4: Partial Date - Day + Month Only
117// ============================================================================
118fn example_4_partial_day_and_month() {
119    println!("4️⃣  PARTIAL DATE: Day + Month");
120    println!("   Input: '15/06'");
121    println!("   Config: DMY order, Day=Yes, Month=Yes, Year=No\n");
122
123    let input = Input {
124        utterance: "15/06".to_string(),
125        config: Some(Config {
126            component_order: ComponentOrder {
127                first: DateComponent::Day,
128                second: DateComponent::Month,
129                third: DateComponent::Year,
130            },
131            year: YearConfig {
132                expected: IsExpected::No,
133                ..Default::default()
134            },
135            ..Default::default()
136        }),
137    };
138
139    let result = extract(input);
140    println!("   ✓ Day:   {:?}", result.day.value);
141    println!("   ✓ Month: {:?}", result.month.number);
142    println!("   ✓ Year:  {:?} (not expected)\n", result.year.value);
143}
144
145// ============================================================================
146// EXAMPLE 5: Partial Date - Month + Year Only
147// ============================================================================
148fn example_5_partial_month_and_year() {
149    println!("5️⃣  PARTIAL DATE: Month + Year");
150    println!("   Input: 'June 2025'");
151    println!("   Config: Day=No, Month=Yes, Year=Yes\n");
152
153    let input = Input {
154        utterance: "June 2025".to_string(),
155        config: Some(Config {
156            day: DayConfig {
157                expected: IsExpected::No,
158                ..Default::default()
159            },
160            ..Default::default()
161        }),
162    };
163
164    let result = extract(input);
165    println!("   ✓ Day:   {:?} (not expected)", result.day.value);
166    println!("   ✓ Month: {:?}", result.month.number);
167    println!("   ✓ Year:  {:?}\n", result.year.value);
168}
169
170// ============================================================================
171// EXAMPLE 6: Day Only
172// ============================================================================
173fn example_6_day_only() {
174    println!("6️⃣  PARTIAL DATE: Day Only");
175    println!("   Input: 'the 15th'");
176    println!("   Config: Day=Yes, Month=No, Year=No\n");
177
178    let input = Input {
179        utterance: "the 15th".to_string(),
180        config: Some(Config {
181            month: MonthConfig {
182                expected: IsExpected::No,
183                ..Default::default()
184            },
185            year: YearConfig {
186                expected: IsExpected::No,
187                ..Default::default()
188            },
189            ..Default::default()
190        }),
191    };
192
193    let result = extract(input);
194    println!("   ✓ Day:   {:?}", result.day.value);
195    println!("   ✓ Month: {:?} (not expected)", result.month.number);
196    println!("   ✓ Year:  {:?} (not expected)\n", result.year.value);
197}
198
199// ============================================================================
200// EXAMPLE 7: Month Name - Full Name
201// ============================================================================
202fn example_7_month_name_full() {
203    println!("7️⃣  NATURAL LANGUAGE: Full Month Name");
204    println!("   Input: '25 December 2024'");
205    println!("   Config: Default (accepts month names)\n");
206
207    let input = Input {
208        utterance: "25 December 2024".to_string(),
209        config: None, // Uses default config
210    };
211
212    let result = extract(input);
213    println!("   ✓ Day:   {:?}", result.day.value);
214    println!("   ✓ Month: {:?}", result.month.number);
215    println!("   ✓ Month Name: {:?}", result.month.name);
216    println!("   ✓ Year:  {:?}\n", result.year.value);
217}
218
219// ============================================================================
220// EXAMPLE 8: Month Name - Abbreviated (3-letter)
221// ============================================================================
222fn example_8_month_name_abbreviated() {
223    println!("8️⃣  NATURAL LANGUAGE: Abbreviated Month Name");
224    println!("   Input: '15 Dec 2025'");
225    println!("   Config: Default\n");
226
227    let input = Input {
228        utterance: "15 Dec 2025".to_string(),
229        config: None,
230    };
231
232    let result = extract(input);
233    println!("   ✓ Day:   {:?}", result.day.value);
234    println!("   ✓ Month: {:?}", result.month.number);
235    println!("   ✓ Month Name: {:?}", result.month.name);
236    println!("   ✓ Year:  {:?}\n", result.year.value);
237}
238
239// ============================================================================
240// EXAMPLE 9: Month Name - Fuzzy Matching (Misspelled)
241// ============================================================================
242fn example_9_month_name_fuzzy() {
243    println!("9️⃣  NATURAL LANGUAGE: Fuzzy Misspelled Month");
244    println!("   Input: '31 Decmber 2024' (typo: 'Decmber')");
245    println!("   Config: Default (uses Levenshtein fuzzy matching)\n");
246
247    let input = Input {
248        utterance: "31 Decmber 2024".to_string(),
249        config: None,
250    };
251
252    let result = extract(input);
253    println!("   ✓ Day:   {:?}", result.day.value);
254    println!("   ✓ Month: {:?}", result.month.number);
255    println!(
256        "   ✓ Month Name: {:?} (correctly matched!)",
257        result.month.name
258    );
259    println!("   ✓ Year:  {:?}\n", result.year.value);
260}
261
262// ============================================================================
263// EXAMPLE 10: Two-Digit Year - Sliding Window (Default)
264// ============================================================================
265fn example_10_year_two_digit_sliding_window() {
266    println!("🔟 TWO-DIGIT YEAR: Sliding Window Expansion");
267    println!("   Input: '25/12/24'");
268    println!("   Config: Default (00-49→2000-2049, 50-99→1950-1999)\n");
269
270    let cases = vec![
271        ("25/12/24", 2024),
272        ("15/06/99", 1999),
273        ("01/01/00", 2000),
274        ("31/12/50", 1950),
275    ];
276
277    for (input_str, _expected_year) in cases {
278        let input = Input {
279            utterance: input_str.to_string(),
280            config: Some(Config {
281                component_order: ComponentOrder {
282                    first: DateComponent::Day,
283                    second: DateComponent::Month,
284                    third: DateComponent::Year,
285                },
286                ..Default::default()
287            }),
288        };
289        let result = extract(input);
290        println!("   '{:12}' → Year: {:?}", input_str, result.year.value);
291    }
292    println!();
293}
294
295// ============================================================================
296// EXAMPLE 11: Two-Digit Year - Always(Century)
297// ============================================================================
298fn example_11_year_two_digit_always_2000s() {
299    println!("1️⃣1️⃣  TWO-DIGIT YEAR: Always(Century(2000))");
300    println!("   Input: '25/12/99'");
301    println!("   Config: Two-digit expansion = Always(Century(2000)) (all become 2000-2099)\n");
302
303    let input = Input {
304        utterance: "25/12/99".to_string(),
305        config: Some(Config {
306            component_order: ComponentOrder {
307                first: DateComponent::Day,
308                second: DateComponent::Month,
309                third: DateComponent::Year,
310            },
311            year: YearConfig {
312                expected: IsExpected::Yes,
313                two_digit_expansion: TwoDigitYearExpansion::Always(Century::new(2000)),
314                ..Default::default()
315            },
316            ..Default::default()
317        }),
318    };
319
320    let result = extract(input);
321    println!("   ✓ Input '99' expands to: {:?}", result.year.value);
322    println!("   (Note: normally 99 → 1999, here → 2099)\n");
323}
324
325// ============================================================================
326// EXAMPLE 12: Two-Digit Year - Literal (No Expansion)
327// ============================================================================
328fn example_12_year_two_digit_literal() {
329    println!("1️⃣2️⃣  TWO-DIGIT YEAR: Literal (No Expansion)");
330    println!("   Input: '25/12/24'");
331    println!("   Config: Two-digit expansion = Literal (keep as-is)\n");
332
333    let input = Input {
334        utterance: "25/12/24".to_string(),
335        config: Some(Config {
336            component_order: ComponentOrder {
337                first: DateComponent::Day,
338                second: DateComponent::Month,
339                third: DateComponent::Year,
340            },
341            year: YearConfig {
342                expected: IsExpected::Yes,
343                two_digit_expansion: TwoDigitYearExpansion::Literal,
344                ..Default::default()
345            },
346            ..Default::default()
347        }),
348    };
349
350    let result = extract(input);
351    println!("   ✓ Input '24' stays as: {:?}", result.year.value);
352    println!("   (Normally 24 → 2024, here → 24)\n");
353}
354
355// ============================================================================
356// EXAMPLE 13: Ordinal Day - 'st' Suffix
357// ============================================================================
358fn example_13_ordinal_day_st() {
359    println!("1️⃣3️⃣  ORDINAL DAY: 'st' Suffix");
360    println!("   Input: '1st December 2024'");
361    println!("   Config: Default\n");
362
363    let input = Input {
364        utterance: "1st December 2024".to_string(),
365        config: None,
366    };
367
368    let result = extract(input);
369    println!("   ✓ Day:   {:?}", result.day.value);
370    println!("   ✓ Month: {:?}", result.month.number);
371    println!("   ✓ Year:  {:?}\n", result.year.value);
372}
373
374// ============================================================================
375// EXAMPLE 14: Ordinal Day - Varied Suffixes
376// ============================================================================
377fn example_14_ordinal_day_varied() {
378    println!("1️⃣4️⃣  ORDINAL DAY: Various Suffixes");
379    println!("   Inputs: '21st', '22nd', '23rd', '24th'\n");
380
381    let cases = vec![
382        "21st June 2024",
383        "22nd June 2024",
384        "23rd June 2024",
385        "24th June 2024",
386    ];
387
388    for input_str in cases {
389        let input = Input {
390            utterance: input_str.to_string(),
391            config: None,
392        };
393        let result = extract(input);
394        println!("   '{}' → Day: {:?}", input_str, result.day.value);
395    }
396    println!();
397}
398
399// ============================================================================
400// EXAMPLE 15: Ordinal Day in Natural Language Context
401// ============================================================================
402fn example_15_ordinal_day_in_context() {
403    println!("1️⃣5️⃣  ORDINAL DAY: In Context");
404    println!("   Input: 'Meeting on the 15th of June'");
405    println!("   Config: Default\n");
406
407    let input = Input {
408        utterance: "Meeting on the 15th of June".to_string(),
409        config: None,
410    };
411
412    let result = extract(input);
413    println!("   ✓ Day:   {:?}", result.day.value);
414    println!("   ✓ Month: {:?}", result.month.number);
415    println!("   ✓ Year:  {:?}\n", result.year.value);
416}
417
418// ============================================================================
419// EXAMPLE 16: Custom Min/Max Validation
420// ============================================================================
421fn example_16_custom_min_max() {
422    println!("1️⃣6️⃣  CUSTOM CONFIG: Min/Max Validation");
423    println!("   Input: '15/06/2024'");
424    println!("   Config: Day min=10, max=20 (only days 10-20 valid)\n");
425
426    let input = Input {
427        utterance: "15/06/2024".to_string(),
428        config: Some(Config {
429            component_order: ComponentOrder {
430                first: DateComponent::Day,
431                second: DateComponent::Month,
432                third: DateComponent::Year,
433            },
434            day: DayConfig {
435                min: 10,
436                max: 20,
437                expected: IsExpected::Yes,
438                ..Default::default()
439            },
440            ..Default::default()
441        }),
442    };
443
444    let result = extract(input);
445    println!("   ✓ Day 15 (in range 10-20): {:?}", result.day.value);
446    println!("   ✓ Month: {:?}", result.month.number);
447    println!("   ✓ Year:  {:?}\n", result.year.value);
448}
449
450// ============================================================================
451// EXAMPLE 17: Default Values
452// ============================================================================
453fn example_17_default_values() {
454    println!("1️⃣7️⃣  DEFAULT VALUES");
455    println!("   Input: 'June 2024' (no day)");
456    println!("   Config: Default day = 15\n");
457
458    let input = Input {
459        utterance: "June 2024".to_string(),
460        config: Some(Config {
461            day: DayConfig {
462                expected: IsExpected::Yes,
463                default: Some(15),
464                ..Default::default()
465            },
466            ..Default::default()
467        }),
468    };
469
470    let result = extract(input);
471    println!("   ✓ Day:   {:?} (from default)", result.day.value);
472    println!("   ✓ Month: {:?}", result.month.number);
473    println!("   ✓ Year:  {:?}\n", result.year.value);
474}
475
476// ============================================================================
477// EXAMPLE 18: No-Separator Concatenated Dates
478// ============================================================================
479fn example_18_no_separator_concat() {
480    println!("1️⃣8️⃣  NO-SEPARATOR CONCATENATED DATES");
481    println!("   Input: '25122024' (DDMMYYYY with no separators)");
482    println!("   Config: no_separator=true, DMY order\n");
483
484    let input = Input {
485        utterance: "25122024".to_string(),
486        config: Some(Config {
487            component_order: ComponentOrder {
488                first: DateComponent::Day,
489                second: DateComponent::Month,
490                third: DateComponent::Year,
491            },
492            no_separator: true,
493            ..Default::default()
494        }),
495    };
496
497    let result = extract(input);
498    println!("   ✓ Day:   {:?}", result.day.value);
499    println!("   ✓ Month: {:?}", result.month.number);
500    println!("   ✓ Year:  {:?}\n", result.year.value);
501}
502
503// ============================================================================
504// EXAMPLE 19: Messy Input with Extra Spacing & Mixed Separators
505// ============================================================================
506fn example_19_messy_input() {
507    println!("1️⃣9️⃣  MESSY INPUT: Extra spacing & mixed separators");
508    println!("   Input: '25  /  12 - 2024'");
509    println!("   Config: Default (handles various separators)\n");
510
511    let input = Input {
512        utterance: "25  /  12 - 2024".to_string(),
513        config: Some(Config {
514            component_order: ComponentOrder {
515                first: DateComponent::Day,
516                second: DateComponent::Month,
517                third: DateComponent::Year,
518            },
519            ..Default::default()
520        }),
521    };
522
523    let result = extract(input);
524    println!("   ✓ Day:   {:?}", result.day.value);
525    println!("   ✓ Month: {:?}", result.month.number);
526    println!("   ✓ Year:  {:?}\n", result.year.value);
527}
528
529// ============================================================================
530// EXAMPLE 20: Boundary Dates
531// ============================================================================
532fn example_20_boundary_dates() {
533    println!("2️⃣0️⃣  BOUNDARY DATES");
534    println!("   Testing edge cases: first/last day of month/year\n");
535
536    let cases = vec![
537        ("01/01/2024", "First day of year"),
538        ("31/12/2024", "Last day of year"),
539        ("29/02/2024", "Leap day"),
540    ];
541
542    for (input_str, description) in cases {
543        let input = Input {
544            utterance: input_str.to_string(),
545            config: Some(Config {
546                component_order: ComponentOrder {
547                    first: DateComponent::Day,
548                    second: DateComponent::Month,
549                    third: DateComponent::Year,
550                },
551                ..Default::default()
552            }),
553        };
554        let result = extract(input);
555        println!(
556            "   {} ({}): Day={:?}, Month={:?}, Year={:?}",
557            input_str, description, result.day.value, result.month.number, result.year.value
558        );
559    }
560    println!();
561}
562
563// ============================================================================
564// EXAMPLE 21: Fuzzy Month Matching with Various Misspellings
565// ============================================================================
566fn example_21_fuzzy_month_name() {
567    println!("2️⃣1️⃣  FUZZY MONTH MATCHING: Misspellings");
568    println!("   Testing Levenshtein distance fuzzy matching\n");
569
570    let cases = vec![
571        ("25 Januray 2024", "Januray (transposition)"),
572        ("15 Decmber 2024", "Decmber (missing letter)"),
573        ("31 Ocotber 2024", "Ocotber (swap)"),
574    ];
575
576    for (input_str, description) in cases {
577        let input = Input {
578            utterance: input_str.to_string(),
579            config: None,
580        };
581        let result = extract(input);
582        println!(
583            "   {} → {:?} {}",
584            description,
585            result.month.name,
586            if result.month.number.is_found() {
587                "✓"
588            } else {
589                "✗"
590            }
591        );
592    }
593    println!();
594}
595
596// ============================================================================
597// EXAMPLE 22: All Component Orders (DMY, MDY, YMD, YDM, MYD, DYM)
598// ============================================================================
599fn example_22_all_component_orders() {
600    println!("2️⃣2️⃣  ALL COMPONENT ORDERS");
601    println!("   Same input '01 06 24', different interpretations based on order\n");
602
603    let input_str = "01 06 24";
604    let orders = vec![
605        (
606            "DMY",
607            ComponentOrder {
608                first: DateComponent::Day,
609                second: DateComponent::Month,
610                third: DateComponent::Year,
611            },
612        ),
613        (
614            "MDY",
615            ComponentOrder {
616                first: DateComponent::Month,
617                second: DateComponent::Day,
618                third: DateComponent::Year,
619            },
620        ),
621        (
622            "YMD",
623            ComponentOrder {
624                first: DateComponent::Year,
625                second: DateComponent::Month,
626                third: DateComponent::Day,
627            },
628        ),
629        (
630            "YDM",
631            ComponentOrder {
632                first: DateComponent::Year,
633                second: DateComponent::Day,
634                third: DateComponent::Month,
635            },
636        ),
637        (
638            "MYD",
639            ComponentOrder {
640                first: DateComponent::Month,
641                second: DateComponent::Year,
642                third: DateComponent::Day,
643            },
644        ),
645        (
646            "DYM",
647            ComponentOrder {
648                first: DateComponent::Day,
649                second: DateComponent::Year,
650                third: DateComponent::Month,
651            },
652        ),
653    ];
654
655    for (order_name, order) in orders {
656        let input = Input {
657            utterance: input_str.to_string(),
658            config: Some(Config {
659                component_order: order,
660                year: YearConfig {
661                    expected: IsExpected::Yes,
662                    two_digit_expansion: TwoDigitYearExpansion::SlidingWindow {
663                        earliest_year: 1950,
664                        pivot: SlidingWindowPivot::new(50),
665                    },
666                    ..Default::default()
667                },
668                ..Default::default()
669            }),
670        };
671
672        let result = extract(input);
673        println!(
674            "   {} → Day: {:?}, Month: {:?}, Year: {:?}",
675            order_name, result.day.value, result.month.number, result.year.value
676        );
677    }
678    println!();
679}