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
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
mod timestamp;
mod timevalue;
mod timeinterval;
mod timeset;
mod format;
mod convert;

pub use timevalue::TimeValue;
pub use timestamp::{Timestamp,Timestamped};
pub use timeinterval::*;
pub use timeset::*;
pub use format::{TimeSetFormat,TimePointFormat};
pub use convert::IntoTimeValue;
use crate::iter::TimeConvexIterator;


use crate::TimePoint;


/// # The envelope (the bounds) of a time window
///
/// A trait which describes the envelope of a time window.
pub trait TimeBounds {

    /// The type of the underlying time data.
    ///
    /// This is also the type of the element managed by a time window.
    /// Typically, the timepoint is [`Timestamp`] when dealing with dates and
    /// [`TimeValue`]  when dealing with durations.
    type TimePoint: TimePoint;

    /// Checks if this time window is empty
    fn is_empty(&self) -> bool;

    /// Checks if this time window contains exactly one value
    ///
    /// A singleton is not empty and its lower bound equals its upper bound.
    #[inline]
    fn is_singleton(&self) -> bool {
        !self.is_empty() && self.lower_bound() == self.upper_bound()
    }

    /// Checks if this time window is bounded
    ///
    /// It returns also `false` if this time window is empty.
    #[inline]
    fn is_bounded(&self) -> bool { self.is_low_bounded() && self.is_up_bounded() }

    /// Checks if this time window has a finite lower bound
    ///
    /// It returns also `false` if this time window is empty.
    fn is_low_bounded(&self) -> bool;

    /// Checks if this time window has a finite upper bound
    ///
    /// It returns also `false` if this time window is empty.
    fn is_up_bounded(&self) -> bool;

    /// The lower bound of the time window
    ///
    /// The behavior is undefined if the time window is empty
    fn lower_bound(&self) -> Self::TimePoint;

    /// The upper bound of the time window
    ///
    /// The behavior is undefined if the time window is empty
    fn upper_bound(&self) -> Self::TimePoint;
}

/// # An arbitrary set of timepoints
///
/// This traits describes the structure of the time window.
pub trait TimeWindow : TimeBounds {

    #[inline]
    fn is_all(&self) -> bool {
        self.is_convex() && !self.is_low_bounded() && !self.is_up_bounded()
    }

    /// Checks if this time window is an interval
    ///
    /// Note that the empty set is convex.
    #[inline] fn is_convex(&self) -> bool { self.convex_count() <= 1 }

    /// The number of convex parts
    ///
    /// An empty set has 0 convex part.
    /// A _non-empty_ interval has exactly 1 convex part.
    fn convex_count(&self) -> usize;

    /// Convex envelope of the time window
    ///
    /// Formally, the convex envelope is the smallest convex which
    /// contains the time window.
    /// In practise, it is the interval defined by the lower and upper
    /// bounds of the time window.
    ///
    /// If the time window is already convex, then the envelope is itself.
    #[inline] fn convex_envelope(&self) -> TimeInterval<Self::TimePoint> {
        TimeInterval { lower: self.lower_bound(), upper: self.upper_bound() }
    }


    type ConvexIter: TimeConvexIterator<TimePoint=Self::TimePoint>;
    fn iter(&self) -> Self::ConvexIter;
}


/// # A marker of convex (interval) time set
///
/// If a time window implements this trait, it is sure
/// that it is a time interval (bounded or not) or an empty set.
///
/// Some computations will be optimized for convex windows.
pub trait TimeConvex : TimeBounds+Sized+Into<TimeInterval<Self::TimePoint>> { }

impl<TW:TimeConvex> TimeWindow for TW {

    /// Checks if the time window is convex or not
    ///
    /// A time window is convex if it is a single time interval
    /// (or if it is empty)
    #[inline] fn is_convex(&self) -> bool { true }

    /// Gets the number of convex parts of the time window
    ///
    /// It returns `0` for empty time windows and `1` for non-empty interval.
    #[inline] fn convex_count(&self) -> usize {
        if self.is_empty() { 0 } else { 1 }
    }

    type ConvexIter = std::option::IntoIter<TimeInterval<Self::TimePoint>>;

    #[inline]
    fn iter(&self) -> Self::ConvexIter
    {
        if self.is_empty() {
            None.into_iter()
        } else {
            Some(TimeInterval {
                lower:self.lower_bound(),
                upper:self.upper_bound()
            }).into_iter()
        }
    }
}