DateTimeZ now supports arithmetic operations.
This commit is contained in:
parent
49737e992f
commit
c9ec9ee63f
|
@ -5,8 +5,10 @@
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
use duration::Duration;
|
use duration::Duration;
|
||||||
|
|
||||||
use self::internals::{Of, Mdf, YearFlags};
|
use self::internals::{DateImpl, Of, Mdf, YearFlags};
|
||||||
use self::internals::{DateImpl, MIN_YEAR, MAX_YEAR};
|
|
||||||
|
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).
|
/// The day of week (DOW).
|
||||||
#[deriving(Eq, TotalEq, FromPrimitive, Show)]
|
#[deriving(Eq, TotalEq, FromPrimitive, Show)]
|
||||||
|
@ -209,7 +211,7 @@ pub struct DateZ {
|
||||||
impl DateZ {
|
impl DateZ {
|
||||||
/// The internal constructor with the verification.
|
/// The internal constructor with the verification.
|
||||||
fn new(year: int, mdf: Mdf) -> Option<DateZ> {
|
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;
|
let Mdf(mdf) = mdf;
|
||||||
Some(DateZ { ymdf: ((year << 13) as DateImpl) | (mdf as DateImpl) })
|
Some(DateZ { ymdf: ((year << 13) as DateImpl) | (mdf as DateImpl) })
|
||||||
} else {
|
} else {
|
||||||
|
@ -294,6 +296,18 @@ impl DateZ {
|
||||||
None
|
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 {
|
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]
|
#[test]
|
||||||
fn test_date_add() {
|
fn test_date_add() {
|
||||||
fn check((y1,m1,d1): (int, uint, uint), rhs: Duration, (y,m,d): (int, uint, uint)) {
|
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 {
|
pub fn to_mdf(&self) -> Mdf {
|
||||||
Mdf::from_of(*self)
|
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 {
|
impl fmt::Show for Of {
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
|
use duration::Duration;
|
||||||
use time::{Timelike, TimeZ};
|
use time::{Timelike, TimeZ};
|
||||||
use date::{Datelike, DateZ, Weekday};
|
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 {
|
impl fmt::Show for DateTimeZ {
|
||||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||||
write!(f.buf, "{}T{}", self.date, self.time)
|
write!(f.buf, "{}T{}", self.date, self.time)
|
||||||
|
@ -136,9 +164,37 @@ impl fmt::Show for DateTimeZ {
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use super::*;
|
use super::*;
|
||||||
|
use duration::Duration;
|
||||||
|
|
||||||
#[test]
|
#[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 =
|
let to_timestamp =
|
||||||
|y,m,d,h,n,s| DateTimeZ::from_ymdhms(y,m,d,h,n,s).unwrap().nseconds_from_unix_epoch();
|
|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);
|
assert_eq!(to_timestamp(1969, 12, 31, 23, 59, 59), -1);
|
||||||
|
|
Loading…
Reference in New Issue