mirror of
https://github.com/chronotope/chrono.git
synced 2025-09-30 06:21:56 +00:00
Merge pull request #457 from robyoung/pr/209
Add days and weeks iterators for `NaiveDate`
This commit is contained in:
commit
53e63c3709
@ -10,7 +10,11 @@ Versions with only mechanical changes will be omitted from the following list.
|
||||
|
||||
## 0.4.14 (unreleased)
|
||||
|
||||
## Improvements
|
||||
### Features
|
||||
|
||||
* Added day and week iterators for `NaiveDate` (@gnzlbg & @robyoung)
|
||||
|
||||
### Improvements
|
||||
|
||||
* Added MIN and MAX values for `NaiveTime`, `NaiveDateTime` and `DateTime<Utc>`.
|
||||
|
||||
|
@ -1048,6 +1048,58 @@ impl NaiveDate {
|
||||
pub fn format<'a>(&self, fmt: &'a str) -> DelayedFormat<StrftimeItems<'a>> {
|
||||
self.format_with_items(StrftimeItems::new(fmt))
|
||||
}
|
||||
|
||||
/// Returns an iterator that steps by days until the last representable date.
|
||||
///
|
||||
/// # Example
|
||||
///
|
||||
/// ```
|
||||
/// # use chrono::NaiveDate;
|
||||
///
|
||||
/// let expected = [
|
||||
/// NaiveDate::from_ymd(2016, 2, 27),
|
||||
/// NaiveDate::from_ymd(2016, 2, 28),
|
||||
/// NaiveDate::from_ymd(2016, 2, 29),
|
||||
/// NaiveDate::from_ymd(2016, 3, 1),
|
||||
/// ];
|
||||
///
|
||||
/// let mut count = 0;
|
||||
/// for (idx, d) in NaiveDate::from_ymd(2016, 2, 27).iter_days().take(4).enumerate() {
|
||||
/// assert_eq!(d, expected[idx]);
|
||||
/// count += 1;
|
||||
/// }
|
||||
/// assert_eq!(count, 4);
|
||||
/// ```
|
||||
#[inline]
|
||||
pub fn iter_days(&self) -> NaiveDateDaysIterator {
|
||||
NaiveDateDaysIterator { value: *self }
|
||||
}
|
||||
|
||||
/// Returns an iterator that steps by weeks until the last representable date.
|
||||
///
|
||||
/// # Example
|
||||
///
|
||||
/// ```
|
||||
/// # use chrono::NaiveDate;
|
||||
///
|
||||
/// let expected = [
|
||||
/// NaiveDate::from_ymd(2016, 2, 27),
|
||||
/// NaiveDate::from_ymd(2016, 3, 5),
|
||||
/// NaiveDate::from_ymd(2016, 3, 12),
|
||||
/// NaiveDate::from_ymd(2016, 3, 19),
|
||||
/// ];
|
||||
///
|
||||
/// let mut count = 0;
|
||||
/// for (idx, d) in NaiveDate::from_ymd(2016, 2, 27).iter_weeks().take(4).enumerate() {
|
||||
/// assert_eq!(d, expected[idx]);
|
||||
/// count += 1;
|
||||
/// }
|
||||
/// assert_eq!(count, 4);
|
||||
/// ```
|
||||
#[inline]
|
||||
pub fn iter_weeks(&self) -> NaiveDateWeeksIterator {
|
||||
NaiveDateWeeksIterator { value: *self }
|
||||
}
|
||||
}
|
||||
|
||||
impl Datelike for NaiveDate {
|
||||
@ -1511,6 +1563,63 @@ impl Sub<NaiveDate> for NaiveDate {
|
||||
}
|
||||
}
|
||||
|
||||
/// Iterator over `NaiveDate` with a step size of one day.
|
||||
#[derive(Debug, Copy, Clone, Hash, PartialEq, PartialOrd, Eq, Ord)]
|
||||
pub struct NaiveDateDaysIterator {
|
||||
value: NaiveDate,
|
||||
}
|
||||
|
||||
impl Iterator for NaiveDateDaysIterator {
|
||||
type Item = NaiveDate;
|
||||
|
||||
fn next(&mut self) -> Option<Self::Item> {
|
||||
if self.value == MAX_DATE {
|
||||
return None;
|
||||
}
|
||||
// current < MAX_DATE from here on:
|
||||
let current = self.value;
|
||||
// This can't panic because current is < MAX_DATE:
|
||||
self.value = current.succ();
|
||||
Some(current)
|
||||
}
|
||||
|
||||
fn size_hint(&self) -> (usize, Option<usize>) {
|
||||
let exact_size = MAX_DATE.signed_duration_since(self.value).num_days();
|
||||
(exact_size as usize, Some(exact_size as usize))
|
||||
}
|
||||
}
|
||||
|
||||
impl ExactSizeIterator for NaiveDateDaysIterator {}
|
||||
|
||||
#[derive(Debug, Copy, Clone, Hash, PartialEq, PartialOrd, Eq, Ord)]
|
||||
pub struct NaiveDateWeeksIterator {
|
||||
value: NaiveDate,
|
||||
}
|
||||
|
||||
impl Iterator for NaiveDateWeeksIterator {
|
||||
type Item = NaiveDate;
|
||||
|
||||
fn next(&mut self) -> Option<Self::Item> {
|
||||
if MAX_DATE - self.value < OldDuration::weeks(1) {
|
||||
return None;
|
||||
}
|
||||
let current = self.value;
|
||||
self.value = current + OldDuration::weeks(1);
|
||||
Some(current)
|
||||
}
|
||||
|
||||
fn size_hint(&self) -> (usize, Option<usize>) {
|
||||
let exact_size = MAX_DATE.signed_duration_since(self.value).num_weeks();
|
||||
(exact_size as usize, Some(exact_size as usize))
|
||||
}
|
||||
}
|
||||
|
||||
impl ExactSizeIterator for NaiveDateWeeksIterator {}
|
||||
|
||||
// TODO: NaiveDateDaysIterator and NaiveDateWeeksIterator should implement FusedIterator,
|
||||
// TrustedLen, and Step once they becomes stable.
|
||||
// See: https://github.com/chronotope/chrono/issues/208
|
||||
|
||||
/// The `Debug` output of the naive date `d` is the same as
|
||||
/// [`d.format("%Y-%m-%d")`](../format/strftime/index.html).
|
||||
///
|
||||
@ -2270,4 +2379,20 @@ mod tests {
|
||||
"2009,09,01,00,53"
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_day_iterator_limit() {
|
||||
assert_eq!(
|
||||
NaiveDate::from_ymd(262143, 12, 29).iter_days().take(4).collect::<Vec<_>>().len(),
|
||||
2
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_week_iterator_limit() {
|
||||
assert_eq!(
|
||||
NaiveDate::from_ymd(262143, 12, 12).iter_weeks().take(4).collect::<Vec<_>>().len(),
|
||||
2
|
||||
);
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user