DateTimeZ now supports arithmetic operations.
This commit is contained in:
parent
49737e992f
commit
c9ec9ee63f
|
@ -5,8 +5,10 @@
|
|||
use std::fmt;
|
||||
use duration::Duration;
|
||||
|
||||
use self::internals::{Of, Mdf, YearFlags};
|
||||
use self::internals::{DateImpl, MIN_YEAR, MAX_YEAR};
|
||||
use self::internals::{DateImpl, Of, Mdf, YearFlags};
|
||||
|
||||
pub static MAX_YEAR: int = internals::MAX_YEAR as int;
|
||||
pub static MIN_YEAR: int = internals::MIN_YEAR as int;
|
||||
|
||||
/// The day of week (DOW).
|
||||
#[deriving(Eq, TotalEq, FromPrimitive, Show)]
|
||||
|
@ -209,7 +211,7 @@ pub struct DateZ {
|
|||
impl DateZ {
|
||||
/// The internal constructor with the verification.
|
||||
fn new(year: int, mdf: Mdf) -> Option<DateZ> {
|
||||
if year >= MIN_YEAR as int && year <= MAX_YEAR as int && mdf.valid() {
|
||||
if year >= MIN_YEAR && year <= MAX_YEAR && mdf.valid() {
|
||||
let Mdf(mdf) = mdf;
|
||||
Some(DateZ { ymdf: ((year << 13) as DateImpl) | (mdf as DateImpl) })
|
||||
} else {
|
||||
|
@ -294,6 +296,18 @@ impl DateZ {
|
|||
None
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn succ(&self) -> Option<DateZ> {
|
||||
let mdf = self.of().succ().to_mdf();
|
||||
self.with_mdf(mdf).or_else(|| DateZ::from_ymd(self.year() + 1, 1, 1))
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn pred(&self) -> Option<DateZ> {
|
||||
let mdf = self.of().pred().to_mdf();
|
||||
self.with_mdf(mdf).or_else(|| DateZ::from_ymd(self.year() - 1, 12, 31))
|
||||
}
|
||||
}
|
||||
|
||||
impl Datelike for DateZ {
|
||||
|
@ -621,6 +635,24 @@ mod tests {
|
|||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_date_succ() {
|
||||
assert_eq!(DateZ::from_ymd(2014, 5, 6).unwrap().succ(), DateZ::from_ymd(2014, 5, 7));
|
||||
assert_eq!(DateZ::from_ymd(2014, 5, 31).unwrap().succ(), DateZ::from_ymd(2014, 6, 1));
|
||||
assert_eq!(DateZ::from_ymd(2014, 12, 31).unwrap().succ(), DateZ::from_ymd(2015, 1, 1));
|
||||
assert_eq!(DateZ::from_ymd(2016, 2, 28).unwrap().succ(), DateZ::from_ymd(2016, 2, 29));
|
||||
assert_eq!(DateZ::from_ymd(MAX_YEAR, 12, 31).unwrap().succ(), None);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_date_pred() {
|
||||
assert_eq!(DateZ::from_ymd(2016, 3, 1).unwrap().pred(), DateZ::from_ymd(2016, 2, 29));
|
||||
assert_eq!(DateZ::from_ymd(2015, 1, 1).unwrap().pred(), DateZ::from_ymd(2014, 12, 31));
|
||||
assert_eq!(DateZ::from_ymd(2014, 6, 1).unwrap().pred(), DateZ::from_ymd(2014, 5, 31));
|
||||
assert_eq!(DateZ::from_ymd(2014, 5, 7).unwrap().pred(), DateZ::from_ymd(2014, 5, 6));
|
||||
assert_eq!(DateZ::from_ymd(MIN_YEAR, 1, 1).unwrap().pred(), None);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_date_add() {
|
||||
fn check((y1,m1,d1): (int, uint, uint), rhs: Duration, (y,m,d): (int, uint, uint)) {
|
||||
|
@ -1012,6 +1044,18 @@ mod internals {
|
|||
pub fn to_mdf(&self) -> Mdf {
|
||||
Mdf::from_of(*self)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn succ(&self) -> Of {
|
||||
let Of(of) = *self;
|
||||
Of(of + (1 << 4))
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn pred(&self) -> Of {
|
||||
let Of(of) = *self;
|
||||
Of(of - (1 << 4))
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Show for Of {
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
*/
|
||||
|
||||
use std::fmt;
|
||||
use duration::Duration;
|
||||
use time::{Timelike, TimeZ};
|
||||
use date::{Datelike, DateZ, Weekday};
|
||||
|
||||
|
@ -127,6 +128,33 @@ impl Timelike for DateTimeZ {
|
|||
}
|
||||
}
|
||||
|
||||
impl Add<Duration,DateTimeZ> for DateTimeZ {
|
||||
fn add(&self, rhs: &Duration) -> DateTimeZ {
|
||||
let mut date = self.date + *rhs;
|
||||
let time = self.time + *rhs;
|
||||
if time < self.time {
|
||||
// since the time portion of the duration is always positive and bounded,
|
||||
// this condition always means that the time part has been overflowed.
|
||||
date = date.succ().unwrap();
|
||||
}
|
||||
DateTimeZ { date: date, time: time }
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
// Rust issue #7590, the current coherence checker can't handle multiple Add impls
|
||||
impl Add<DateTimeZ,DateTimeZ> for Duration {
|
||||
#[inline]
|
||||
fn add(&self, rhs: &DateTimeZ) -> DateTimeZ { rhs.add(self) }
|
||||
}
|
||||
*/
|
||||
|
||||
impl Sub<DateTimeZ,Duration> for DateTimeZ {
|
||||
fn sub(&self, rhs: &DateTimeZ) -> Duration {
|
||||
(self.date - rhs.date) + (self.time - rhs.time)
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Show for DateTimeZ {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
write!(f.buf, "{}T{}", self.date, self.time)
|
||||
|
@ -136,9 +164,37 @@ impl fmt::Show for DateTimeZ {
|
|||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use duration::Duration;
|
||||
|
||||
#[test]
|
||||
fn test_time_nseconds_from_unix_epoch() {
|
||||
fn test_datetime_add() {
|
||||
let ymdhms = |y,m,d,h,n,s| DateTimeZ::from_ymdhms(y,m,d,h,n,s).unwrap();
|
||||
assert_eq!(ymdhms(2014, 5, 6, 7, 8, 9) + Duration::seconds(3600 + 60 + 1),
|
||||
ymdhms(2014, 5, 6, 8, 9, 10));
|
||||
assert_eq!(ymdhms(2014, 5, 6, 7, 8, 9) + Duration::seconds(86399),
|
||||
ymdhms(2014, 5, 7, 7, 8, 8));
|
||||
assert_eq!(ymdhms(2014, 5, 6, 7, 8, 9) + Duration::seconds(86400 * 10),
|
||||
ymdhms(2014, 5, 16, 7, 8, 9));
|
||||
assert_eq!(ymdhms(2014, 5, 6, 7, 8, 9) + Duration::seconds(-86400 * 10),
|
||||
ymdhms(2014, 4, 26, 7, 8, 9));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_datetime_sub() {
|
||||
let ymdhms = |y,m,d,h,n,s| DateTimeZ::from_ymdhms(y,m,d,h,n,s).unwrap();
|
||||
assert_eq!(ymdhms(2014, 5, 6, 7, 8, 9) - ymdhms(2014, 5, 6, 7, 8, 9), Duration::zero());
|
||||
assert_eq!(ymdhms(2014, 5, 6, 7, 8, 10) - ymdhms(2014, 5, 6, 7, 8, 9),
|
||||
Duration::seconds(1));
|
||||
assert_eq!(ymdhms(2014, 5, 6, 7, 8, 9) - ymdhms(2014, 5, 6, 7, 8, 10),
|
||||
Duration::seconds(-1));
|
||||
assert_eq!(ymdhms(2014, 5, 7, 7, 8, 9) - ymdhms(2014, 5, 6, 7, 8, 10),
|
||||
Duration::seconds(86399));
|
||||
assert_eq!(ymdhms(2001, 9, 9, 1, 46, 39) - ymdhms(1970, 1, 1, 0, 0, 0),
|
||||
Duration::seconds(999_999_999));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_datetime_nseconds_from_unix_epoch() {
|
||||
let to_timestamp =
|
||||
|y,m,d,h,n,s| DateTimeZ::from_ymdhms(y,m,d,h,n,s).unwrap().nseconds_from_unix_epoch();
|
||||
assert_eq!(to_timestamp(1969, 12, 31, 23, 59, 59), -1);
|
||||
|
|
Loading…
Reference in New Issue