1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
//! Generic time-window generation for recurring, overlapping, and metadata-rich
//! intervals.
//!
//! A window is a half-open UTC interval `[start, end)` paired with arbitrary
//! metadata.
//!
//! This crate is designed for systems that need to model:
//!
//! - recurring or rule-generated intervals
//! - overlapping events
//! - active and upcoming windows
//! - arbitrary metadata attached to time periods
//! - source composition and adaptation
//!
//! # Core types
//!
//! - [`Window`] represents a single time interval with metadata.
//! - [`WindowSource`] produces active and upcoming windows.
//! - [`WindowSourceExt`] provides iterator helpers for upcoming windows.
//! - [`DerivedWindowSource`] adapts one source into another by mapping windows.
//!
//! # Built-in sources
//!
//! When the `sources` feature is enabled, the crate also provides common source
//! implementations under [`sources`].
//!
//! # Interval semantics
//!
//! Windows are half-open intervals: a window is active when
//! `start <= now && now < end`.
//!
//! This means:
//!
//! - the start time is included
//! - the end time is excluded
//!
//! # Overlap
//!
//! Sources may produce overlapping windows. This crate does not assume
//! exclusivity or a calendar-like event model.
//!
//! As a result:
//!
//! - multiple windows may be active at the same instant
//! - upcoming windows are ordered by start time
//! - iterator helpers preserve overlapping schedules rather than skipping ahead
//! to the previous window's end
//!
//! # Metadata
//!
//! Each [`Window`] carries metadata of type `M`, allowing callers to associate
//! arbitrary context such as IDs, slugs, labels, or structured payloads.
//!
//! # Extensibility
//!
//! You can extend the crate in two primary ways:
//!
//! - implement [`WindowSource`] for a custom generator
//! - implement [`DerivedWindowSource`] to adapt an existing source
//!
//! # Timezone
//!
//! All times are represented as `DateTime<Utc>`.
//!
//! # Example
//!
//! ```rust
//! use chrono::{Duration, TimeZone, Utc};
//! use timewindow::{WindowSource, WindowSourceExt};
//! use timewindow::sources::IntervalSource;
//!
//! let anchor = Utc.with_ymd_and_hms(2026, 3, 20, 0, 0, 0).unwrap();
//! let source = IntervalSource::single(
//! anchor,
//! Duration::hours(9), // recurrence point
//! Duration::zero(), // offset from recurrence point
//! Duration::days(1), // repeat every day
//! Duration::hours(2), // window duration
//! "morning",
//! )
//! .unwrap();
//!
//! let windows: Vec<_> = source
//! .next_windows_from(Utc.with_ymd_and_hms(2026, 3, 20, 8, 0, 0).unwrap())
//! .take(2)
//! .collect();
//!
//! assert_eq!(windows.len(), 2);
//! assert_eq!(windows[0].meta, "morning");
//! assert_eq!(windows[0].start, Utc.with_ymd_and_hms(2026, 3, 20, 9, 0, 0).unwrap());
//! assert_eq!(windows[1].start, Utc.with_ymd_and_hms(2026, 3, 21, 9, 0, 0).unwrap());
//! ```
pub use DerivedWindowSource;
pub use ;
pub use WindowSource;
pub use Window;