fixed some issues on negative division/modulo.
This commit is contained in:
parent
c9ec9ee63f
commit
75c21b0c3e
|
@ -3,6 +3,7 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
|
use num::Integer;
|
||||||
use duration::Duration;
|
use duration::Duration;
|
||||||
|
|
||||||
use self::internals::{DateImpl, Of, Mdf, YearFlags};
|
use self::internals::{DateImpl, Of, Mdf, YearFlags};
|
||||||
|
@ -381,16 +382,11 @@ impl Add<Duration,DateZ> for DateZ {
|
||||||
// TODO overflow
|
// TODO overflow
|
||||||
|
|
||||||
let year = self.year();
|
let year = self.year();
|
||||||
let mut year_div_400 = year / 400;
|
let (mut year_div_400, year_mod_400) = year.div_mod_floor(&400);
|
||||||
let year_mod_400 = (year % 400) as uint;
|
let cycle = internals::yo_to_cycle(year_mod_400 as uint, self.of().ordinal()) as int;
|
||||||
let mut cycle = internals::yo_to_cycle(year_mod_400, self.of().ordinal()) as int;
|
let cycle = cycle + rhs.ndays();
|
||||||
cycle += rhs.ndays();
|
let (cycle_div_400y, cycle) = cycle.div_mod_floor(&146097);
|
||||||
year_div_400 += cycle / 146097;
|
year_div_400 += cycle_div_400y;
|
||||||
cycle %= 146097;
|
|
||||||
if cycle < 0 {
|
|
||||||
cycle += 146097;
|
|
||||||
year_div_400 -= 400;
|
|
||||||
}
|
|
||||||
|
|
||||||
let (year_mod_400, ordinal) = internals::cycle_to_yo(cycle as uint);
|
let (year_mod_400, ordinal) = internals::cycle_to_yo(cycle as uint);
|
||||||
let flags = unsafe { YearFlags::from_year_mod_400(year_mod_400 as int) };
|
let flags = unsafe { YearFlags::from_year_mod_400(year_mod_400 as int) };
|
||||||
|
@ -411,8 +407,8 @@ impl Sub<DateZ,Duration> for DateZ {
|
||||||
fn sub(&self, rhs: &DateZ) -> Duration {
|
fn sub(&self, rhs: &DateZ) -> Duration {
|
||||||
let year1 = self.year();
|
let year1 = self.year();
|
||||||
let year2 = rhs.year();
|
let year2 = rhs.year();
|
||||||
let (year1_div_400, year1_mod_400) = (year1 / 400, year1 % 400);
|
let (year1_div_400, year1_mod_400) = year1.div_mod_floor(&400);
|
||||||
let (year2_div_400, year2_mod_400) = (year2 / 400, year2 % 400);
|
let (year2_div_400, year2_mod_400) = year2.div_mod_floor(&400);
|
||||||
let cycle1 = internals::yo_to_cycle(year1_mod_400 as uint, self.of().ordinal()) as int;
|
let cycle1 = internals::yo_to_cycle(year1_mod_400 as uint, self.of().ordinal()) as int;
|
||||||
let cycle2 = internals::yo_to_cycle(year2_mod_400 as uint, rhs.of().ordinal()) as int;
|
let cycle2 = internals::yo_to_cycle(year2_mod_400 as uint, rhs.of().ordinal()) as int;
|
||||||
Duration::days((year1_div_400 - year2_div_400) * 146097 + (cycle1 - cycle2))
|
Duration::days((year1_div_400 - year2_div_400) * 146097 + (cycle1 - cycle2))
|
||||||
|
@ -669,6 +665,8 @@ mod tests {
|
||||||
check((2014, 1, 1), Duration::days(364), (2014, 12, 31));
|
check((2014, 1, 1), Duration::days(364), (2014, 12, 31));
|
||||||
check((2014, 1, 1), Duration::days(365*4 + 1), (2018, 1, 1));
|
check((2014, 1, 1), Duration::days(365*4 + 1), (2018, 1, 1));
|
||||||
check((2014, 1, 1), Duration::days(365*400 + 97), (2414, 1, 1));
|
check((2014, 1, 1), Duration::days(365*400 + 97), (2414, 1, 1));
|
||||||
|
|
||||||
|
check((-7, 1, 1), Duration::days(365*12 + 3), (5, 1, 1));
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
@ -712,6 +710,7 @@ mod tests {
|
||||||
*/
|
*/
|
||||||
mod internals {
|
mod internals {
|
||||||
use std::{i32, num, fmt};
|
use std::{i32, num, fmt};
|
||||||
|
use num::Integer;
|
||||||
pub use super::{Weekday, Sun, Mon, Tue, Wed, Thu, Fri, Sat};
|
pub use super::{Weekday, Sun, Mon, Tue, Wed, Thu, Fri, Sat};
|
||||||
|
|
||||||
/// The internal date representation. This also includes the packed `Mdf` value.
|
/// The internal date representation. This also includes the packed `Mdf` value.
|
||||||
|
@ -786,8 +785,7 @@ mod internals {
|
||||||
];
|
];
|
||||||
|
|
||||||
pub fn cycle_to_yo(cycle: uint) -> (uint, uint) {
|
pub fn cycle_to_yo(cycle: uint) -> (uint, uint) {
|
||||||
let mut year_mod_400 = cycle / 365;
|
let (mut year_mod_400, mut ordinal0) = cycle.div_rem(&365);
|
||||||
let mut ordinal0 = cycle % 365;
|
|
||||||
let delta = YEAR_DELTAS[year_mod_400] as uint;
|
let delta = YEAR_DELTAS[year_mod_400] as uint;
|
||||||
if ordinal0 < delta {
|
if ordinal0 < delta {
|
||||||
year_mod_400 -= 1;
|
year_mod_400 -= 1;
|
||||||
|
@ -805,8 +803,7 @@ mod internals {
|
||||||
impl YearFlags {
|
impl YearFlags {
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn from_year(year: int) -> YearFlags {
|
pub fn from_year(year: int) -> YearFlags {
|
||||||
let mut year = year % 400;
|
let year = year.mod_floor(&400);
|
||||||
if year < 0 { year += 400; }
|
|
||||||
unsafe { YearFlags::from_year_mod_400(year) }
|
unsafe { YearFlags::from_year_mod_400(year) }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
use std::{fmt, num};
|
use std::{fmt, num};
|
||||||
|
use num::Integer;
|
||||||
|
|
||||||
static NANOS_PER_SEC: int = 1_000_000_000;
|
static NANOS_PER_SEC: int = 1_000_000_000;
|
||||||
static SECS_PER_DAY: int = 86400;
|
static SECS_PER_DAY: int = 86400;
|
||||||
|
@ -16,13 +17,9 @@ pub struct Duration {
|
||||||
|
|
||||||
impl Duration {
|
impl Duration {
|
||||||
pub fn new(days: int, secs: int, nanos: int) -> Option<Duration> {
|
pub fn new(days: int, secs: int, nanos: int) -> Option<Duration> {
|
||||||
let mut secs_ = nanos / NANOS_PER_SEC;
|
let (secs_, nanos) = nanos.div_mod_floor(&NANOS_PER_SEC);
|
||||||
let mut nanos = nanos % NANOS_PER_SEC;
|
|
||||||
if nanos < 0 { secs_ -= 1; nanos += NANOS_PER_SEC; }
|
|
||||||
let secs = match secs.checked_add(&secs_) { Some(v) => v, None => return None };
|
let secs = match secs.checked_add(&secs_) { Some(v) => v, None => return None };
|
||||||
let mut days_ = secs / SECS_PER_DAY;
|
let (days_, secs) = secs.div_mod_floor(&SECS_PER_DAY);
|
||||||
let mut secs = secs % SECS_PER_DAY;
|
|
||||||
if secs < 0 { days_ -= 1; secs += SECS_PER_DAY; }
|
|
||||||
let days = match days.checked_add(&days_) { Some(v) => v, None => return None };
|
let days = match days.checked_add(&days_) { Some(v) => v, None => return None };
|
||||||
Some(Duration { days: days, secs: secs as u32, nanos: nanos as u32 })
|
Some(Duration { days: days, secs: secs as u32, nanos: nanos as u32 })
|
||||||
}
|
}
|
||||||
|
@ -54,9 +51,7 @@ impl Duration {
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn seconds(secs: int) -> Duration {
|
pub fn seconds(secs: int) -> Duration {
|
||||||
let mut days = secs / SECS_PER_DAY;
|
let (days, secs) = secs.div_mod_floor(&SECS_PER_DAY);
|
||||||
let mut secs = secs % SECS_PER_DAY;
|
|
||||||
if secs < 0 { days -= 1; secs += SECS_PER_DAY; }
|
|
||||||
Duration { secs: secs as u32, ..Duration::days(days) }
|
Duration { secs: secs as u32, ..Duration::days(days) }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -72,9 +67,7 @@ impl Duration {
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn nanoseconds(nanos: int) -> Duration {
|
pub fn nanoseconds(nanos: int) -> Duration {
|
||||||
let mut secs = nanos / NANOS_PER_SEC;
|
let (secs, nanos) = nanos.div_mod_floor(&NANOS_PER_SEC);
|
||||||
let mut nanos = nanos % NANOS_PER_SEC;
|
|
||||||
if nanos < 0 { secs -= 1; nanos += NANOS_PER_SEC; }
|
|
||||||
Duration { nanos: nanos as u32, ..Duration::seconds(secs) }
|
Duration { nanos: nanos as u32, ..Duration::seconds(secs) }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,9 @@
|
||||||
#[crate_id = "chrono#0.1.0"];
|
#![crate_id = "chrono#0.1.0"]
|
||||||
#[crate_type = "lib"];
|
#![crate_type = "lib"]
|
||||||
|
|
||||||
#[feature(globs, macro_rules)];
|
#![feature(globs, macro_rules)]
|
||||||
|
|
||||||
|
extern crate num;
|
||||||
|
|
||||||
pub mod duration;
|
pub mod duration;
|
||||||
pub mod date;
|
pub mod date;
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
|
use num::Integer;
|
||||||
use duration::Duration;
|
use duration::Duration;
|
||||||
|
|
||||||
pub trait Timelike {
|
pub trait Timelike {
|
||||||
|
@ -146,8 +147,8 @@ impl Add<Duration,TimeZ> for TimeZ {
|
||||||
nanos -= maxnanos;
|
nanos -= maxnanos;
|
||||||
secs += 1;
|
secs += 1;
|
||||||
}
|
}
|
||||||
let (s, mins) = (secs % 60, secs / 60);
|
let (mins, s) = secs.div_rem(&60);
|
||||||
let (m, hours) = (mins % 60, mins / 60);
|
let (hours, m) = mins.div_rem(&60);
|
||||||
let h = hours % 24;
|
let h = hours % 24;
|
||||||
TimeZ { hour: h as u8, min: m as u8, sec: s as u8, frac: nanos }
|
TimeZ { hour: h as u8, min: m as u8, sec: s as u8, frac: nanos }
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue