switched the internal Date representation from Mdf to Of; made most Date operations representation-agnostic.
This commit is contained in:
parent
75c21b0c3e
commit
0f6ccf0728
|
@ -206,28 +206,32 @@ pub trait Datelike {
|
||||||
/// Also supports the conversion from ISO 8601 ordinal and week date.
|
/// Also supports the conversion from ISO 8601 ordinal and week date.
|
||||||
#[deriving(Eq, TotalEq, Ord, TotalOrd, Hash)]
|
#[deriving(Eq, TotalEq, Ord, TotalOrd, Hash)]
|
||||||
pub struct DateZ {
|
pub struct DateZ {
|
||||||
priv ymdf: DateImpl, // (year << 13) | mdf
|
priv ymdf: DateImpl, // (year << 13) | of
|
||||||
}
|
}
|
||||||
|
|
||||||
impl DateZ {
|
impl DateZ {
|
||||||
/// The internal constructor with the verification.
|
/// Makes a new `DateZ` from year and packed ordinal-flags, with a verification.
|
||||||
fn new(year: int, mdf: Mdf) -> Option<DateZ> {
|
fn from_of(year: int, of: Of) -> Option<DateZ> {
|
||||||
if year >= MIN_YEAR && year <= MAX_YEAR && mdf.valid() {
|
if year >= MIN_YEAR && year <= MAX_YEAR && of.valid() {
|
||||||
let Mdf(mdf) = mdf;
|
let Of(of) = of;
|
||||||
Some(DateZ { ymdf: ((year << 13) as DateImpl) | (mdf as DateImpl) })
|
Some(DateZ { ymdf: ((year << 13) as DateImpl) | (of as DateImpl) })
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Makes a new `DateZ` from year and packed month-day-flags, with a verification.
|
||||||
|
fn from_mdf(year: int, mdf: Mdf) -> Option<DateZ> {
|
||||||
|
DateZ::from_of(year, mdf.to_of())
|
||||||
|
}
|
||||||
|
|
||||||
/// Makes a new `DateZ` from year, month and day.
|
/// Makes a new `DateZ` from year, month and day.
|
||||||
/// This assumes the proleptic Gregorian calendar, with the year 0 being 1 BCE.
|
/// This assumes the proleptic Gregorian calendar, with the year 0 being 1 BCE.
|
||||||
///
|
///
|
||||||
/// Returns `None` on the out-of-range date, invalid month and/or day.
|
/// Returns `None` on the out-of-range date, invalid month and/or day.
|
||||||
pub fn from_ymd(year: int, month: uint, day: uint) -> Option<DateZ> {
|
pub fn from_ymd(year: int, month: uint, day: uint) -> Option<DateZ> {
|
||||||
let flags = YearFlags::from_year(year);
|
let flags = YearFlags::from_year(year);
|
||||||
let mdf = Mdf::new(month, day, flags);
|
DateZ::from_mdf(year, Mdf::new(month, day, flags))
|
||||||
DateZ::new(year, mdf)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Makes a new `DateZ` from year and day of year (DOY or "ordinal").
|
/// Makes a new `DateZ` from year and day of year (DOY or "ordinal").
|
||||||
|
@ -236,8 +240,7 @@ impl DateZ {
|
||||||
/// Returns `None` on the out-of-range date and/or invalid DOY.
|
/// Returns `None` on the out-of-range date and/or invalid DOY.
|
||||||
pub fn from_yo(year: int, ordinal: uint) -> Option<DateZ> {
|
pub fn from_yo(year: int, ordinal: uint) -> Option<DateZ> {
|
||||||
let flags = YearFlags::from_year(year);
|
let flags = YearFlags::from_year(year);
|
||||||
let mdf = Of::new(ordinal, flags).to_mdf();
|
DateZ::from_of(year, Of::new(ordinal, flags))
|
||||||
DateZ::new(year, mdf)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Makes a new `DateZ` from ISO week date (year and week number) and day of the week (DOW).
|
/// Makes a new `DateZ` from ISO week date (year and week number) and day of the week (DOW).
|
||||||
|
@ -254,18 +257,15 @@ impl DateZ {
|
||||||
let delta = flags.isoweek_delta();
|
let delta = flags.isoweek_delta();
|
||||||
if weekord <= delta { // ordinal < 1, previous year
|
if weekord <= delta { // ordinal < 1, previous year
|
||||||
let prevflags = YearFlags::from_year(year - 1);
|
let prevflags = YearFlags::from_year(year - 1);
|
||||||
let mdf = Of::new(weekord + prevflags.ndays() - delta, prevflags).to_mdf();
|
DateZ::from_of(year - 1, Of::new(weekord + prevflags.ndays() - delta, prevflags))
|
||||||
DateZ::new(year - 1, mdf)
|
|
||||||
} else {
|
} else {
|
||||||
let ordinal = weekord - delta;
|
let ordinal = weekord - delta;
|
||||||
let ndays = flags.ndays();
|
let ndays = flags.ndays();
|
||||||
if ordinal <= ndays { // this year
|
if ordinal <= ndays { // this year
|
||||||
let mdf = Of::new(ordinal, flags).to_mdf();
|
DateZ::from_of(year, Of::new(ordinal, flags))
|
||||||
DateZ::new(year, mdf)
|
|
||||||
} else { // ordinal > ndays, next year
|
} else { // ordinal > ndays, next year
|
||||||
let nextflags = YearFlags::from_year(year + 1);
|
let nextflags = YearFlags::from_year(year + 1);
|
||||||
let mdf = Of::new(ordinal - ndays, nextflags).to_mdf();
|
DateZ::from_of(year + 1, Of::new(ordinal - ndays, nextflags))
|
||||||
DateZ::new(year + 1, mdf)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
@ -273,26 +273,34 @@ impl DateZ {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns the packed month, day and year flags.
|
/// Returns the packed month-day-flags.
|
||||||
#[inline]
|
#[inline]
|
||||||
fn mdf(&self) -> Mdf {
|
fn mdf(&self) -> Mdf {
|
||||||
Mdf((self.ymdf & 0b1111_11111_1111) as uint)
|
self.of().to_mdf()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns the packed ordinal and year flags.
|
/// Returns the packed ordinal-flags.
|
||||||
#[inline]
|
#[inline]
|
||||||
fn of(&self) -> Of {
|
fn of(&self) -> Of {
|
||||||
self.mdf().to_of()
|
Of((self.ymdf & 0b1111_11111_1111) as uint)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Makes a new `DateZ` with the packed month, day and year flags changed.
|
/// Makes a new `DateZ` with the packed month-day-flags changed.
|
||||||
///
|
///
|
||||||
/// Returns `None` when the resulting `DateZ` would be invalid.
|
/// Returns `None` when the resulting `DateZ` would be invalid.
|
||||||
#[inline]
|
#[inline]
|
||||||
fn with_mdf(&self, mdf: Mdf) -> Option<DateZ> {
|
fn with_mdf(&self, mdf: Mdf) -> Option<DateZ> {
|
||||||
if mdf.valid() {
|
self.with_of(mdf.to_of())
|
||||||
let Mdf(mdf) = mdf;
|
}
|
||||||
Some(DateZ { ymdf: (self.ymdf & !0b1111_11111_1111) | mdf as DateImpl })
|
|
||||||
|
/// Makes a new `DateZ` with the packed ordinal-flags changed.
|
||||||
|
///
|
||||||
|
/// Returns `None` when the resulting `DateZ` would be invalid.
|
||||||
|
#[inline]
|
||||||
|
fn with_of(&self, of: Of) -> Option<DateZ> {
|
||||||
|
if of.valid() {
|
||||||
|
let Of(of) = of;
|
||||||
|
Some(DateZ { ymdf: (self.ymdf & !0b111111111_1111) | of as DateImpl })
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
|
@ -300,14 +308,12 @@ impl DateZ {
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn succ(&self) -> Option<DateZ> {
|
pub fn succ(&self) -> Option<DateZ> {
|
||||||
let mdf = self.of().succ().to_mdf();
|
self.with_of(self.of().succ()).or_else(|| DateZ::from_ymd(self.year() + 1, 1, 1))
|
||||||
self.with_mdf(mdf).or_else(|| DateZ::from_ymd(self.year() + 1, 1, 1))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn pred(&self) -> Option<DateZ> {
|
pub fn pred(&self) -> Option<DateZ> {
|
||||||
let mdf = self.of().pred().to_mdf();
|
self.with_of(self.of().pred()).or_else(|| DateZ::from_ymd(self.year() - 1, 12, 31))
|
||||||
self.with_mdf(mdf).or_else(|| DateZ::from_ymd(self.year() - 1, 12, 31))
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -340,10 +346,14 @@ impl Datelike for DateZ {
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn with_year(&self, year: int) -> Option<DateZ> {
|
fn with_year(&self, year: int) -> Option<DateZ> {
|
||||||
|
// we need to operate with `mdf` since we should keep the month and day number as is
|
||||||
|
let mdf = self.mdf();
|
||||||
|
|
||||||
// adjust the flags as needed
|
// adjust the flags as needed
|
||||||
let flags = YearFlags::from_year(year);
|
let flags = YearFlags::from_year(year);
|
||||||
let mdf = self.mdf().with_flags(flags);
|
let mdf = mdf.with_flags(flags);
|
||||||
DateZ::new(year, mdf)
|
|
||||||
|
DateZ::from_mdf(year, mdf)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
|
@ -368,12 +378,12 @@ impl Datelike for DateZ {
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn with_ordinal(&self, ordinal: uint) -> Option<DateZ> {
|
fn with_ordinal(&self, ordinal: uint) -> Option<DateZ> {
|
||||||
self.with_mdf(self.mdf().to_of().with_ordinal(ordinal).to_mdf())
|
self.with_of(self.of().with_ordinal(ordinal))
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn with_ordinal0(&self, ordinal0: uint) -> Option<DateZ> {
|
fn with_ordinal0(&self, ordinal0: uint) -> Option<DateZ> {
|
||||||
self.with_mdf(self.mdf().to_of().with_ordinal(ordinal0 + 1).to_mdf())
|
self.with_of(self.of().with_ordinal(ordinal0 + 1))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -383,15 +393,14 @@ impl Add<Duration,DateZ> for DateZ {
|
||||||
|
|
||||||
let year = self.year();
|
let year = self.year();
|
||||||
let (mut year_div_400, year_mod_400) = year.div_mod_floor(&400);
|
let (mut year_div_400, year_mod_400) = year.div_mod_floor(&400);
|
||||||
let cycle = internals::yo_to_cycle(year_mod_400 as uint, self.of().ordinal()) as int;
|
let cycle = internals::yo_to_cycle(year_mod_400 as uint, self.of().ordinal());
|
||||||
let cycle = cycle + rhs.ndays();
|
let cycle = cycle as int + rhs.ndays();
|
||||||
let (cycle_div_400y, cycle) = cycle.div_mod_floor(&146097);
|
let (cycle_div_400y, cycle) = cycle.div_mod_floor(&146097);
|
||||||
year_div_400 += cycle_div_400y;
|
year_div_400 += cycle_div_400y;
|
||||||
|
|
||||||
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) };
|
||||||
let mdf = Of::new(ordinal, flags).to_mdf();
|
DateZ::from_of(year_div_400 * 400 + year_mod_400 as int, Of::new(ordinal, flags)).unwrap()
|
||||||
DateZ::new(year_div_400 * 400 + year_mod_400 as int, mdf).unwrap()
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue