{Date,Time,DateTime} -> {DateZ,TimeZ,DateTimeZ}, in order to distinguish them from the timezone-aware types.
This commit is contained in:
parent
646b6c27b9
commit
715a35caa6
|
@ -105,50 +105,143 @@ impl Weekday {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// ISO 8601 calendar date. Also supports the conversion from ISO 8601 ordinal and week date.
|
pub trait Datelike {
|
||||||
|
/// Returns the year number.
|
||||||
|
fn year(&self) -> int;
|
||||||
|
|
||||||
|
/// Returns the absolute year number starting from 1 with a boolean flag,
|
||||||
|
/// which is false when the year predates the epoch (BCE/BC) and true otherwise (CE/AD).
|
||||||
|
#[inline]
|
||||||
|
fn year_ce(&self) -> (bool, uint) {
|
||||||
|
let year = self.year();
|
||||||
|
if year < 1 {
|
||||||
|
(false, (1 - year) as uint)
|
||||||
|
} else {
|
||||||
|
(true, year as uint)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns the month number starting from 1.
|
||||||
|
fn month(&self) -> uint;
|
||||||
|
|
||||||
|
/// Returns the month number starting from 0.
|
||||||
|
fn month0(&self) -> uint;
|
||||||
|
|
||||||
|
/// Returns the day of month starting from 1.
|
||||||
|
fn day(&self) -> uint;
|
||||||
|
|
||||||
|
/// Returns the day of month starting from 0.
|
||||||
|
fn day0(&self) -> uint;
|
||||||
|
|
||||||
|
/// Returns the day of year starting from 1.
|
||||||
|
fn ordinal(&self) -> uint;
|
||||||
|
|
||||||
|
/// Returns the day of year starting from 0.
|
||||||
|
fn ordinal0(&self) -> uint;
|
||||||
|
|
||||||
|
/// Returns the day of week.
|
||||||
|
fn weekday(&self) -> Weekday;
|
||||||
|
|
||||||
|
/// Returns the ISO week date: an adjusted year, week number and day of week.
|
||||||
|
/// The adjusted year may differ from that of the calendar date.
|
||||||
|
fn isoweekdate(&self) -> (int, uint, Weekday);
|
||||||
|
|
||||||
|
/// Makes a new value with the year number changed.
|
||||||
|
///
|
||||||
|
/// Returns `None` when the resulting value would be invalid.
|
||||||
|
fn with_year(&self, year: int) -> Option<Self>;
|
||||||
|
|
||||||
|
/// Makes a new value with the month number (starting from 1) changed.
|
||||||
|
///
|
||||||
|
/// Returns `None` when the resulting value would be invalid.
|
||||||
|
fn with_month(&self, month: uint) -> Option<Self>;
|
||||||
|
|
||||||
|
/// Makes a new value with the month number (starting from 0) changed.
|
||||||
|
///
|
||||||
|
/// Returns `None` when the resulting value would be invalid.
|
||||||
|
fn with_month0(&self, month0: uint) -> Option<Self>;
|
||||||
|
|
||||||
|
/// Makes a new value with the day of month (starting from 1) changed.
|
||||||
|
///
|
||||||
|
/// Returns `None` when the resulting value would be invalid.
|
||||||
|
fn with_day(&self, day: uint) -> Option<Self>;
|
||||||
|
|
||||||
|
/// Makes a new value with the day of month (starting from 0) changed.
|
||||||
|
///
|
||||||
|
/// Returns `None` when the resulting value would be invalid.
|
||||||
|
fn with_day0(&self, day0: uint) -> Option<Self>;
|
||||||
|
|
||||||
|
/// Makes a new value with the day of year (starting from 1) changed.
|
||||||
|
///
|
||||||
|
/// Returns `None` when the resulting value would be invalid.
|
||||||
|
fn with_ordinal(&self, ordinal: uint) -> Option<Self>;
|
||||||
|
|
||||||
|
/// Makes a new value with the day of year (starting from 0) changed.
|
||||||
|
///
|
||||||
|
/// Returns `None` when the resulting value would be invalid.
|
||||||
|
fn with_ordinal0(&self, ordinal0: uint) -> Option<Self>;
|
||||||
|
|
||||||
|
/// Returns the number of days since January 1, 1 (Day 1) in the proleptic Gregorian calendar.
|
||||||
|
fn ndays_from_ce(&self) -> int {
|
||||||
|
// we know this wouldn't overflow since year is limited to 1/2^13 of i32's full range.
|
||||||
|
let mut year = self.year() - 1;
|
||||||
|
let mut ndays = 0;
|
||||||
|
if year < 0 {
|
||||||
|
let excess = 1 + (-year) / 400;
|
||||||
|
year += excess * 400;
|
||||||
|
ndays -= excess * 146097;
|
||||||
|
}
|
||||||
|
let div_100 = year / 100;
|
||||||
|
ndays += ((year * 1461) >> 2) - div_100 + (div_100 >> 2);
|
||||||
|
ndays + self.ordinal() as int
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// ISO 8601 calendar date without timezone.
|
||||||
/// Allows for every proleptic Gregorian date from Jan 1, 262145 BCE to Dec 31, 262143 CE.
|
/// Allows for every proleptic Gregorian date from Jan 1, 262145 BCE to Dec 31, 262143 CE.
|
||||||
|
/// 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 Date {
|
pub struct DateZ {
|
||||||
priv ymdf: DateImpl, // (year << 13) | mdf
|
priv ymdf: DateImpl, // (year << 13) | mdf
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Date {
|
impl DateZ {
|
||||||
/// The internal constructor with the verification.
|
/// The internal constructor with the verification.
|
||||||
fn new(year: int, mdf: Mdf) -> Option<Date> {
|
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 as int && year <= MAX_YEAR as int && mdf.valid() {
|
||||||
let Mdf(mdf) = mdf;
|
let Mdf(mdf) = mdf;
|
||||||
Some(Date { ymdf: ((year << 13) as DateImpl) | (mdf as DateImpl) })
|
Some(DateZ { ymdf: ((year << 13) as DateImpl) | (mdf as DateImpl) })
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Makes a new `Date` 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<Date> {
|
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);
|
let mdf = Mdf::new(month, day, flags);
|
||||||
Date::new(year, mdf)
|
DateZ::new(year, mdf)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Makes a new `Date` from year and day of year (DOY or "ordinal").
|
/// Makes a new `DateZ` from year and day of year (DOY or "ordinal").
|
||||||
/// 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 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<Date> {
|
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();
|
let mdf = Of::new(ordinal, flags).to_mdf();
|
||||||
Date::new(year, mdf)
|
DateZ::new(year, mdf)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Makes a new `Date` 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).
|
||||||
/// 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.
|
||||||
/// The resulting `Date` may have a different year from the input year.
|
/// The resulting `DateZ` may have a different year from the input year.
|
||||||
///
|
///
|
||||||
/// Returns `None` on the out-of-range date and/or invalid week number.
|
/// Returns `None` on the out-of-range date and/or invalid week number.
|
||||||
pub fn from_isoywd(year: int, week: uint, weekday: Weekday) -> Option<Date> {
|
pub fn from_isoywd(year: int, week: uint, weekday: Weekday) -> Option<DateZ> {
|
||||||
let flags = YearFlags::from_year(year);
|
let flags = YearFlags::from_year(year);
|
||||||
let nweeks = flags.nisoweeks();
|
let nweeks = flags.nisoweeks();
|
||||||
if 1 <= week && week <= nweeks {
|
if 1 <= week && week <= nweeks {
|
||||||
|
@ -158,17 +251,17 @@ impl Date {
|
||||||
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();
|
let mdf = Of::new(weekord + prevflags.ndays() - delta, prevflags).to_mdf();
|
||||||
Date::new(year - 1, mdf)
|
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();
|
let mdf = Of::new(ordinal, flags).to_mdf();
|
||||||
Date::new(year, mdf)
|
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();
|
let mdf = Of::new(ordinal - ndays, nextflags).to_mdf();
|
||||||
Date::new(year + 1, mdf)
|
DateZ::new(year + 1, mdf)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
@ -188,69 +281,31 @@ impl Date {
|
||||||
self.mdf().to_of()
|
self.mdf().to_of()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns the year number.
|
/// Makes a new `DateZ` with the packed month, day and year flags changed.
|
||||||
|
///
|
||||||
|
/// Returns `None` when the resulting `DateZ` would be invalid.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn year(&self) -> int {
|
fn with_mdf(&self, mdf: Mdf) -> Option<DateZ> {
|
||||||
(self.ymdf >> 13) as int
|
if mdf.valid() {
|
||||||
}
|
let Mdf(mdf) = mdf;
|
||||||
|
Some(DateZ { ymdf: (self.ymdf & !0b1111_11111_1111) | mdf as DateImpl })
|
||||||
/// Returns the absolute year number starting from 1 with a boolean flag,
|
|
||||||
/// which is false when the year predates the epoch (BCE/BC) and true otherwise (CE/AD).
|
|
||||||
#[inline]
|
|
||||||
pub fn year_ce(&self) -> (bool, uint) {
|
|
||||||
let year = self.year();
|
|
||||||
if year < 1 {
|
|
||||||
(false, (1 - year) as uint)
|
|
||||||
} else {
|
} else {
|
||||||
(true, year as uint)
|
None
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns the month number starting from 1.
|
impl Datelike for DateZ {
|
||||||
#[inline]
|
#[inline] fn year(&self) -> int { (self.ymdf >> 13) as int }
|
||||||
pub fn month(&self) -> uint {
|
#[inline] fn month(&self) -> uint { self.mdf().month() }
|
||||||
self.mdf().month()
|
#[inline] fn month0(&self) -> uint { self.mdf().month() - 1 }
|
||||||
}
|
#[inline] fn day(&self) -> uint { self.mdf().day() }
|
||||||
|
#[inline] fn day0(&self) -> uint { self.mdf().day() - 1 }
|
||||||
|
#[inline] fn ordinal(&self) -> uint { self.of().ordinal() }
|
||||||
|
#[inline] fn ordinal0(&self) -> uint { self.of().ordinal() - 1 }
|
||||||
|
#[inline] fn weekday(&self) -> Weekday { self.of().weekday() }
|
||||||
|
|
||||||
/// Returns the month number starting from 0.
|
fn isoweekdate(&self) -> (int, uint, Weekday) {
|
||||||
#[inline]
|
|
||||||
pub fn month0(&self) -> uint {
|
|
||||||
self.mdf().month() - 1
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Returns the day of month starting from 1.
|
|
||||||
#[inline]
|
|
||||||
pub fn day(&self) -> uint {
|
|
||||||
self.mdf().day()
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Returns the day of month starting from 0.
|
|
||||||
#[inline]
|
|
||||||
pub fn day0(&self) -> uint {
|
|
||||||
self.mdf().day() - 1
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Returns the day of year starting from 1.
|
|
||||||
#[inline]
|
|
||||||
pub fn ordinal(&self) -> uint {
|
|
||||||
self.of().ordinal()
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Returns the day of year starting from 0.
|
|
||||||
#[inline]
|
|
||||||
pub fn ordinal0(&self) -> uint {
|
|
||||||
self.of().ordinal() - 1
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Returns the day of week.
|
|
||||||
#[inline]
|
|
||||||
pub fn weekday(&self) -> Weekday {
|
|
||||||
self.of().weekday()
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Returns the ISO week date: an adjusted year, week number and day of week.
|
|
||||||
/// The adjusted year may differ from that of the calendar date.
|
|
||||||
pub fn isoweekdate(&self) -> (int, uint, Weekday) {
|
|
||||||
let of = self.of();
|
let of = self.of();
|
||||||
let year = self.year();
|
let year = self.year();
|
||||||
let (rawweek, weekday) = of.isoweekdate_raw();
|
let (rawweek, weekday) = of.isoweekdate_raw();
|
||||||
|
@ -267,95 +322,46 @@ impl Date {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Makes a new `Date` with the year number changed.
|
|
||||||
///
|
|
||||||
/// Returns `None` when the resulting `Date` would be invalid.
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn with_year(&self, year: int) -> Option<Date> {
|
fn with_year(&self, year: int) -> Option<DateZ> {
|
||||||
// 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 = self.mdf().with_flags(flags);
|
||||||
Date::new(year, mdf)
|
DateZ::new(year, mdf)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Makes a new `Date` with the packed month, day and year flags changed.
|
|
||||||
///
|
|
||||||
/// Returns `None` when the resulting `Date` would be invalid.
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn with_mdf(&self, mdf: Mdf) -> Option<Date> {
|
fn with_month(&self, month: uint) -> Option<DateZ> {
|
||||||
if mdf.valid() {
|
|
||||||
let Mdf(mdf) = mdf;
|
|
||||||
Some(Date { ymdf: (self.ymdf & !0b1111_11111_1111) | mdf as DateImpl })
|
|
||||||
} else {
|
|
||||||
None
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Makes a new `Date` with the month number (starting from 1) changed.
|
|
||||||
///
|
|
||||||
/// Returns `None` when the resulting `Date` would be invalid.
|
|
||||||
#[inline]
|
|
||||||
pub fn with_month(&self, month: uint) -> Option<Date> {
|
|
||||||
self.with_mdf(self.mdf().with_month(month))
|
self.with_mdf(self.mdf().with_month(month))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Makes a new `Date` with the month number (starting from 0) changed.
|
|
||||||
///
|
|
||||||
/// Returns `None` when the resulting `Date` would be invalid.
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn with_month0(&self, month0: uint) -> Option<Date> {
|
fn with_month0(&self, month0: uint) -> Option<DateZ> {
|
||||||
self.with_mdf(self.mdf().with_month(month0 + 1))
|
self.with_mdf(self.mdf().with_month(month0 + 1))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Makes a new `Date` with the day of month (starting from 1) changed.
|
|
||||||
///
|
|
||||||
/// Returns `None` when the resulting `Date` would be invalid.
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn with_day(&self, day: uint) -> Option<Date> {
|
fn with_day(&self, day: uint) -> Option<DateZ> {
|
||||||
self.with_mdf(self.mdf().with_day(day))
|
self.with_mdf(self.mdf().with_day(day))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Makes a new `Date` with the day of month (starting from 0) changed.
|
|
||||||
///
|
|
||||||
/// Returns `None` when the resulting `Date` would be invalid.
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn with_day0(&self, day0: uint) -> Option<Date> {
|
fn with_day0(&self, day0: uint) -> Option<DateZ> {
|
||||||
self.with_mdf(self.mdf().with_day(day0 + 1))
|
self.with_mdf(self.mdf().with_day(day0 + 1))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Makes a new `Date` with the day of year (starting from 1) changed.
|
|
||||||
///
|
|
||||||
/// Returns `None` when the resulting `Date` would be invalid.
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn with_ordinal(&self, ordinal: uint) -> Option<Date> {
|
fn with_ordinal(&self, ordinal: uint) -> Option<DateZ> {
|
||||||
self.with_mdf(self.mdf().to_of().with_ordinal(ordinal).to_mdf())
|
self.with_mdf(self.mdf().to_of().with_ordinal(ordinal).to_mdf())
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Makes a new `Date` with the day of year (starting from 0) changed.
|
|
||||||
///
|
|
||||||
/// Returns `None` when the resulting `Date` would be invalid.
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn with_ordinal0(&self, ordinal0: uint) -> Option<Date> {
|
fn with_ordinal0(&self, ordinal0: uint) -> Option<DateZ> {
|
||||||
self.with_mdf(self.mdf().to_of().with_ordinal(ordinal0 + 1).to_mdf())
|
self.with_mdf(self.mdf().to_of().with_ordinal(ordinal0 + 1).to_mdf())
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns the number of days since January 1, 1 (Day 1) in the proleptic Gregorian calendar.
|
|
||||||
pub fn ndays_from_ce(&self) -> int {
|
|
||||||
// we know this wouldn't overflow since year is limited to 1/2^13 of i32's full range.
|
|
||||||
let mut year = self.year() - 1;
|
|
||||||
let mut ndays = 0;
|
|
||||||
if year < 0 {
|
|
||||||
let excess = 1 + (-year) / 400;
|
|
||||||
year += excess * 400;
|
|
||||||
ndays -= excess * 146097;
|
|
||||||
}
|
|
||||||
let div_100 = year / 100;
|
|
||||||
ndays += ((year * 1461) >> 2) - div_100 + (div_100 >> 2);
|
|
||||||
ndays + self.of().ordinal() as int
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl fmt::Show for Date {
|
impl fmt::Show for DateZ {
|
||||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||||
write!(f.buf, "{:04}-{:02}-{:02}", self.year(), self.month(), self.day())
|
write!(f.buf, "{:04}-{:02}-{:02}", self.year(), self.month(), self.day())
|
||||||
}
|
}
|
||||||
|
@ -369,69 +375,69 @@ mod tests {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_date_from_ymd() {
|
fn test_date_from_ymd() {
|
||||||
assert!(Date::from_ymd(2012, 0, 1).is_none());
|
assert!(DateZ::from_ymd(2012, 0, 1).is_none());
|
||||||
assert!(Date::from_ymd(2012, 1, 1).is_some());
|
assert!(DateZ::from_ymd(2012, 1, 1).is_some());
|
||||||
assert!(Date::from_ymd(2012, 2, 29).is_some());
|
assert!(DateZ::from_ymd(2012, 2, 29).is_some());
|
||||||
assert!(Date::from_ymd(2014, 2, 29).is_none());
|
assert!(DateZ::from_ymd(2014, 2, 29).is_none());
|
||||||
assert!(Date::from_ymd(2014, 3, 0).is_none());
|
assert!(DateZ::from_ymd(2014, 3, 0).is_none());
|
||||||
assert!(Date::from_ymd(2014, 3, 1).is_some());
|
assert!(DateZ::from_ymd(2014, 3, 1).is_some());
|
||||||
assert!(Date::from_ymd(2014, 3, 31).is_some());
|
assert!(DateZ::from_ymd(2014, 3, 31).is_some());
|
||||||
assert!(Date::from_ymd(2014, 3, 32).is_none());
|
assert!(DateZ::from_ymd(2014, 3, 32).is_none());
|
||||||
assert!(Date::from_ymd(2014, 12, 31).is_some());
|
assert!(DateZ::from_ymd(2014, 12, 31).is_some());
|
||||||
assert!(Date::from_ymd(2014, 13, 1).is_none());
|
assert!(DateZ::from_ymd(2014, 13, 1).is_none());
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_date_from_yo() {
|
fn test_date_from_yo() {
|
||||||
assert!(Date::from_yo(2012, 0).is_none());
|
assert!(DateZ::from_yo(2012, 0).is_none());
|
||||||
assert_eq!(Date::from_yo(2012, 1), Date::from_ymd(2012, 1, 1));
|
assert_eq!(DateZ::from_yo(2012, 1), DateZ::from_ymd(2012, 1, 1));
|
||||||
assert_eq!(Date::from_yo(2012, 2), Date::from_ymd(2012, 1, 2));
|
assert_eq!(DateZ::from_yo(2012, 2), DateZ::from_ymd(2012, 1, 2));
|
||||||
assert_eq!(Date::from_yo(2012, 32), Date::from_ymd(2012, 2, 1));
|
assert_eq!(DateZ::from_yo(2012, 32), DateZ::from_ymd(2012, 2, 1));
|
||||||
assert_eq!(Date::from_yo(2012, 60), Date::from_ymd(2012, 2, 29));
|
assert_eq!(DateZ::from_yo(2012, 60), DateZ::from_ymd(2012, 2, 29));
|
||||||
assert_eq!(Date::from_yo(2012, 61), Date::from_ymd(2012, 3, 1));
|
assert_eq!(DateZ::from_yo(2012, 61), DateZ::from_ymd(2012, 3, 1));
|
||||||
assert_eq!(Date::from_yo(2012, 100), Date::from_ymd(2012, 4, 9));
|
assert_eq!(DateZ::from_yo(2012, 100), DateZ::from_ymd(2012, 4, 9));
|
||||||
assert_eq!(Date::from_yo(2012, 200), Date::from_ymd(2012, 7, 18));
|
assert_eq!(DateZ::from_yo(2012, 200), DateZ::from_ymd(2012, 7, 18));
|
||||||
assert_eq!(Date::from_yo(2012, 300), Date::from_ymd(2012, 10, 26));
|
assert_eq!(DateZ::from_yo(2012, 300), DateZ::from_ymd(2012, 10, 26));
|
||||||
assert_eq!(Date::from_yo(2012, 366), Date::from_ymd(2012, 12, 31));
|
assert_eq!(DateZ::from_yo(2012, 366), DateZ::from_ymd(2012, 12, 31));
|
||||||
assert!(Date::from_yo(2012, 367).is_none());
|
assert!(DateZ::from_yo(2012, 367).is_none());
|
||||||
|
|
||||||
assert!(Date::from_yo(2014, 0).is_none());
|
assert!(DateZ::from_yo(2014, 0).is_none());
|
||||||
assert_eq!(Date::from_yo(2014, 1), Date::from_ymd(2014, 1, 1));
|
assert_eq!(DateZ::from_yo(2014, 1), DateZ::from_ymd(2014, 1, 1));
|
||||||
assert_eq!(Date::from_yo(2014, 2), Date::from_ymd(2014, 1, 2));
|
assert_eq!(DateZ::from_yo(2014, 2), DateZ::from_ymd(2014, 1, 2));
|
||||||
assert_eq!(Date::from_yo(2014, 32), Date::from_ymd(2014, 2, 1));
|
assert_eq!(DateZ::from_yo(2014, 32), DateZ::from_ymd(2014, 2, 1));
|
||||||
assert_eq!(Date::from_yo(2014, 59), Date::from_ymd(2014, 2, 28));
|
assert_eq!(DateZ::from_yo(2014, 59), DateZ::from_ymd(2014, 2, 28));
|
||||||
assert_eq!(Date::from_yo(2014, 60), Date::from_ymd(2014, 3, 1));
|
assert_eq!(DateZ::from_yo(2014, 60), DateZ::from_ymd(2014, 3, 1));
|
||||||
assert_eq!(Date::from_yo(2014, 100), Date::from_ymd(2014, 4, 10));
|
assert_eq!(DateZ::from_yo(2014, 100), DateZ::from_ymd(2014, 4, 10));
|
||||||
assert_eq!(Date::from_yo(2014, 200), Date::from_ymd(2014, 7, 19));
|
assert_eq!(DateZ::from_yo(2014, 200), DateZ::from_ymd(2014, 7, 19));
|
||||||
assert_eq!(Date::from_yo(2014, 300), Date::from_ymd(2014, 10, 27));
|
assert_eq!(DateZ::from_yo(2014, 300), DateZ::from_ymd(2014, 10, 27));
|
||||||
assert_eq!(Date::from_yo(2014, 365), Date::from_ymd(2014, 12, 31));
|
assert_eq!(DateZ::from_yo(2014, 365), DateZ::from_ymd(2014, 12, 31));
|
||||||
assert!(Date::from_yo(2014, 366).is_none());
|
assert!(DateZ::from_yo(2014, 366).is_none());
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_date_from_isoywd() {
|
fn test_date_from_isoywd() {
|
||||||
assert!(Date::from_isoywd(2004, 0, Sun).is_none());
|
assert!(DateZ::from_isoywd(2004, 0, Sun).is_none());
|
||||||
assert_eq!(Date::from_isoywd(2004, 1, Mon), Date::from_ymd(2003, 12, 29));
|
assert_eq!(DateZ::from_isoywd(2004, 1, Mon), DateZ::from_ymd(2003, 12, 29));
|
||||||
assert_eq!(Date::from_isoywd(2004, 1, Sun), Date::from_ymd(2004, 1, 4));
|
assert_eq!(DateZ::from_isoywd(2004, 1, Sun), DateZ::from_ymd(2004, 1, 4));
|
||||||
assert_eq!(Date::from_isoywd(2004, 2, Mon), Date::from_ymd(2004, 1, 5));
|
assert_eq!(DateZ::from_isoywd(2004, 2, Mon), DateZ::from_ymd(2004, 1, 5));
|
||||||
assert_eq!(Date::from_isoywd(2004, 2, Sun), Date::from_ymd(2004, 1, 11));
|
assert_eq!(DateZ::from_isoywd(2004, 2, Sun), DateZ::from_ymd(2004, 1, 11));
|
||||||
assert_eq!(Date::from_isoywd(2004, 52, Mon), Date::from_ymd(2004, 12, 20));
|
assert_eq!(DateZ::from_isoywd(2004, 52, Mon), DateZ::from_ymd(2004, 12, 20));
|
||||||
assert_eq!(Date::from_isoywd(2004, 52, Sun), Date::from_ymd(2004, 12, 26));
|
assert_eq!(DateZ::from_isoywd(2004, 52, Sun), DateZ::from_ymd(2004, 12, 26));
|
||||||
assert_eq!(Date::from_isoywd(2004, 53, Mon), Date::from_ymd(2004, 12, 27));
|
assert_eq!(DateZ::from_isoywd(2004, 53, Mon), DateZ::from_ymd(2004, 12, 27));
|
||||||
assert_eq!(Date::from_isoywd(2004, 53, Sun), Date::from_ymd(2005, 1, 2));
|
assert_eq!(DateZ::from_isoywd(2004, 53, Sun), DateZ::from_ymd(2005, 1, 2));
|
||||||
assert!(Date::from_isoywd(2004, 54, Mon).is_none());
|
assert!(DateZ::from_isoywd(2004, 54, Mon).is_none());
|
||||||
|
|
||||||
assert!(Date::from_isoywd(2011, 0, Sun).is_none());
|
assert!(DateZ::from_isoywd(2011, 0, Sun).is_none());
|
||||||
assert_eq!(Date::from_isoywd(2011, 1, Mon), Date::from_ymd(2011, 1, 3));
|
assert_eq!(DateZ::from_isoywd(2011, 1, Mon), DateZ::from_ymd(2011, 1, 3));
|
||||||
assert_eq!(Date::from_isoywd(2011, 1, Sun), Date::from_ymd(2011, 1, 9));
|
assert_eq!(DateZ::from_isoywd(2011, 1, Sun), DateZ::from_ymd(2011, 1, 9));
|
||||||
assert_eq!(Date::from_isoywd(2011, 2, Mon), Date::from_ymd(2011, 1, 10));
|
assert_eq!(DateZ::from_isoywd(2011, 2, Mon), DateZ::from_ymd(2011, 1, 10));
|
||||||
assert_eq!(Date::from_isoywd(2011, 2, Sun), Date::from_ymd(2011, 1, 16));
|
assert_eq!(DateZ::from_isoywd(2011, 2, Sun), DateZ::from_ymd(2011, 1, 16));
|
||||||
|
|
||||||
assert_eq!(Date::from_isoywd(2018, 51, Mon), Date::from_ymd(2018, 12, 17));
|
assert_eq!(DateZ::from_isoywd(2018, 51, Mon), DateZ::from_ymd(2018, 12, 17));
|
||||||
assert_eq!(Date::from_isoywd(2018, 51, Sun), Date::from_ymd(2018, 12, 23));
|
assert_eq!(DateZ::from_isoywd(2018, 51, Sun), DateZ::from_ymd(2018, 12, 23));
|
||||||
assert_eq!(Date::from_isoywd(2018, 52, Mon), Date::from_ymd(2018, 12, 24));
|
assert_eq!(DateZ::from_isoywd(2018, 52, Mon), DateZ::from_ymd(2018, 12, 24));
|
||||||
assert_eq!(Date::from_isoywd(2018, 52, Sun), Date::from_ymd(2018, 12, 30));
|
assert_eq!(DateZ::from_isoywd(2018, 52, Sun), DateZ::from_ymd(2018, 12, 30));
|
||||||
assert!(Date::from_isoywd(2018, 53, Mon).is_none());
|
assert!(DateZ::from_isoywd(2018, 53, Mon).is_none());
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
@ -439,7 +445,7 @@ mod tests {
|
||||||
for year in range_inclusive(2000i, 2400) {
|
for year in range_inclusive(2000i, 2400) {
|
||||||
for week in range_inclusive(1u, 53) {
|
for week in range_inclusive(1u, 53) {
|
||||||
for &weekday in [Mon, Tue, Wed, Thu, Fri, Sat, Sun].iter() {
|
for &weekday in [Mon, Tue, Wed, Thu, Fri, Sat, Sun].iter() {
|
||||||
let d = Date::from_isoywd(year, week, weekday);
|
let d = DateZ::from_isoywd(year, week, weekday);
|
||||||
if d.is_some() {
|
if d.is_some() {
|
||||||
let d = d.unwrap();
|
let d = d.unwrap();
|
||||||
assert_eq!(d.weekday(), weekday);
|
assert_eq!(d.weekday(), weekday);
|
||||||
|
@ -455,11 +461,11 @@ mod tests {
|
||||||
for year in range_inclusive(2000i, 2400) {
|
for year in range_inclusive(2000i, 2400) {
|
||||||
for month in range_inclusive(1u, 12) {
|
for month in range_inclusive(1u, 12) {
|
||||||
for day in range_inclusive(1u, 31) {
|
for day in range_inclusive(1u, 31) {
|
||||||
let d = Date::from_ymd(year, month, day);
|
let d = DateZ::from_ymd(year, month, day);
|
||||||
if d.is_some() {
|
if d.is_some() {
|
||||||
let d = d.unwrap();
|
let d = d.unwrap();
|
||||||
let (year_, week_, weekday_) = d.isoweekdate();
|
let (year_, week_, weekday_) = d.isoweekdate();
|
||||||
let d_ = Date::from_isoywd(year_, week_, weekday_).unwrap();
|
let d_ = DateZ::from_isoywd(year_, week_, weekday_).unwrap();
|
||||||
assert_eq!(d, d_);
|
assert_eq!(d, d_);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -470,14 +476,14 @@ mod tests {
|
||||||
#[test]
|
#[test]
|
||||||
fn test_date_fields() {
|
fn test_date_fields() {
|
||||||
fn check(year: int, month: uint, day: uint, ordinal: uint) {
|
fn check(year: int, month: uint, day: uint, ordinal: uint) {
|
||||||
let d1 = Date::from_ymd(year, month, day);
|
let d1 = DateZ::from_ymd(year, month, day);
|
||||||
assert!(d1.is_some());
|
assert!(d1.is_some());
|
||||||
assert_eq!(d1.unwrap().year(), year);
|
assert_eq!(d1.unwrap().year(), year);
|
||||||
assert_eq!(d1.unwrap().month(), month);
|
assert_eq!(d1.unwrap().month(), month);
|
||||||
assert_eq!(d1.unwrap().day(), day);
|
assert_eq!(d1.unwrap().day(), day);
|
||||||
assert_eq!(d1.unwrap().ordinal(), ordinal);
|
assert_eq!(d1.unwrap().ordinal(), ordinal);
|
||||||
|
|
||||||
let d2 = Date::from_yo(year, ordinal);
|
let d2 = DateZ::from_yo(year, ordinal);
|
||||||
assert!(d2.is_some());
|
assert!(d2.is_some());
|
||||||
assert_eq!(d2.unwrap().year(), year);
|
assert_eq!(d2.unwrap().year(), year);
|
||||||
assert_eq!(d2.unwrap().month(), month);
|
assert_eq!(d2.unwrap().month(), month);
|
||||||
|
@ -510,57 +516,57 @@ mod tests {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_date_weekday() {
|
fn test_date_weekday() {
|
||||||
assert_eq!(Date::from_ymd(1582, 10, 15).unwrap().weekday(), Fri);
|
assert_eq!(DateZ::from_ymd(1582, 10, 15).unwrap().weekday(), Fri);
|
||||||
assert_eq!(Date::from_ymd(1875, 5, 20).unwrap().weekday(), Thu); // ISO 8601 reference date
|
assert_eq!(DateZ::from_ymd(1875, 5, 20).unwrap().weekday(), Thu); // ISO 8601 reference date
|
||||||
assert_eq!(Date::from_ymd(2000, 1, 1).unwrap().weekday(), Sat);
|
assert_eq!(DateZ::from_ymd(2000, 1, 1).unwrap().weekday(), Sat);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_date_with_fields() {
|
fn test_date_with_fields() {
|
||||||
let d = Date::from_ymd(2000, 2, 29).unwrap();
|
let d = DateZ::from_ymd(2000, 2, 29).unwrap();
|
||||||
assert_eq!(d.with_year(-400), Date::from_ymd(-400, 2, 29));
|
assert_eq!(d.with_year(-400), DateZ::from_ymd(-400, 2, 29));
|
||||||
assert_eq!(d.with_year(-100), None);
|
assert_eq!(d.with_year(-100), None);
|
||||||
assert_eq!(d.with_year(1600), Date::from_ymd(1600, 2, 29));
|
assert_eq!(d.with_year(1600), DateZ::from_ymd(1600, 2, 29));
|
||||||
assert_eq!(d.with_year(1900), None);
|
assert_eq!(d.with_year(1900), None);
|
||||||
assert_eq!(d.with_year(2000), Date::from_ymd(2000, 2, 29));
|
assert_eq!(d.with_year(2000), DateZ::from_ymd(2000, 2, 29));
|
||||||
assert_eq!(d.with_year(2001), None);
|
assert_eq!(d.with_year(2001), None);
|
||||||
assert_eq!(d.with_year(2004), Date::from_ymd(2004, 2, 29));
|
assert_eq!(d.with_year(2004), DateZ::from_ymd(2004, 2, 29));
|
||||||
assert_eq!(d.with_year(int::MAX), None);
|
assert_eq!(d.with_year(int::MAX), None);
|
||||||
|
|
||||||
let d = Date::from_ymd(2000, 4, 30).unwrap();
|
let d = DateZ::from_ymd(2000, 4, 30).unwrap();
|
||||||
assert_eq!(d.with_month(0), None);
|
assert_eq!(d.with_month(0), None);
|
||||||
assert_eq!(d.with_month(1), Date::from_ymd(2000, 1, 30));
|
assert_eq!(d.with_month(1), DateZ::from_ymd(2000, 1, 30));
|
||||||
assert_eq!(d.with_month(2), None);
|
assert_eq!(d.with_month(2), None);
|
||||||
assert_eq!(d.with_month(3), Date::from_ymd(2000, 3, 30));
|
assert_eq!(d.with_month(3), DateZ::from_ymd(2000, 3, 30));
|
||||||
assert_eq!(d.with_month(4), Date::from_ymd(2000, 4, 30));
|
assert_eq!(d.with_month(4), DateZ::from_ymd(2000, 4, 30));
|
||||||
assert_eq!(d.with_month(12), Date::from_ymd(2000, 12, 30));
|
assert_eq!(d.with_month(12), DateZ::from_ymd(2000, 12, 30));
|
||||||
assert_eq!(d.with_month(13), None);
|
assert_eq!(d.with_month(13), None);
|
||||||
assert_eq!(d.with_month(uint::MAX), None);
|
assert_eq!(d.with_month(uint::MAX), None);
|
||||||
|
|
||||||
let d = Date::from_ymd(2000, 2, 8).unwrap();
|
let d = DateZ::from_ymd(2000, 2, 8).unwrap();
|
||||||
assert_eq!(d.with_day(0), None);
|
assert_eq!(d.with_day(0), None);
|
||||||
assert_eq!(d.with_day(1), Date::from_ymd(2000, 2, 1));
|
assert_eq!(d.with_day(1), DateZ::from_ymd(2000, 2, 1));
|
||||||
assert_eq!(d.with_day(29), Date::from_ymd(2000, 2, 29));
|
assert_eq!(d.with_day(29), DateZ::from_ymd(2000, 2, 29));
|
||||||
assert_eq!(d.with_day(30), None);
|
assert_eq!(d.with_day(30), None);
|
||||||
assert_eq!(d.with_day(uint::MAX), None);
|
assert_eq!(d.with_day(uint::MAX), None);
|
||||||
|
|
||||||
let d = Date::from_ymd(2000, 5, 5).unwrap();
|
let d = DateZ::from_ymd(2000, 5, 5).unwrap();
|
||||||
assert_eq!(d.with_ordinal(0), None);
|
assert_eq!(d.with_ordinal(0), None);
|
||||||
assert_eq!(d.with_ordinal(1), Date::from_ymd(2000, 1, 1));
|
assert_eq!(d.with_ordinal(1), DateZ::from_ymd(2000, 1, 1));
|
||||||
assert_eq!(d.with_ordinal(60), Date::from_ymd(2000, 2, 29));
|
assert_eq!(d.with_ordinal(60), DateZ::from_ymd(2000, 2, 29));
|
||||||
assert_eq!(d.with_ordinal(61), Date::from_ymd(2000, 3, 1));
|
assert_eq!(d.with_ordinal(61), DateZ::from_ymd(2000, 3, 1));
|
||||||
assert_eq!(d.with_ordinal(366), Date::from_ymd(2000, 12, 31));
|
assert_eq!(d.with_ordinal(366), DateZ::from_ymd(2000, 12, 31));
|
||||||
assert_eq!(d.with_ordinal(367), None);
|
assert_eq!(d.with_ordinal(367), None);
|
||||||
assert_eq!(d.with_ordinal(uint::MAX), None);
|
assert_eq!(d.with_ordinal(uint::MAX), None);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_date_ndays_from_ce() {
|
fn test_date_ndays_from_ce() {
|
||||||
assert_eq!(Date::from_ymd(1, 1, 1).unwrap().ndays_from_ce(), 1);
|
assert_eq!(DateZ::from_ymd(1, 1, 1).unwrap().ndays_from_ce(), 1);
|
||||||
|
|
||||||
for year in range_inclusive(-9999i, 10000) {
|
for year in range_inclusive(-9999i, 10000) {
|
||||||
assert_eq!(Date::from_ymd(year, 1, 1).unwrap().ndays_from_ce(),
|
assert_eq!(DateZ::from_ymd(year, 1, 1).unwrap().ndays_from_ce(),
|
||||||
Date::from_ymd(year - 1, 12, 31).unwrap().ndays_from_ce() + 1);
|
DateZ::from_ymd(year - 1, 12, 31).unwrap().ndays_from_ce() + 1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -570,13 +576,13 @@ mod tests {
|
||||||
*
|
*
|
||||||
* The current implementation is optimized for determining year, month, day and day of week.
|
* The current implementation is optimized for determining year, month, day and day of week.
|
||||||
* 4-bit `YearFlags` map to one of 14 possible classes of year in the Gregorian calendar,
|
* 4-bit `YearFlags` map to one of 14 possible classes of year in the Gregorian calendar,
|
||||||
* which are included in every packed `Date` instance.
|
* which are included in every packed `DateZ` instance.
|
||||||
* The conversion between the packed calendar date (`Mdf`) and the ordinal date (`Of`) is
|
* The conversion between the packed calendar date (`Mdf`) and the ordinal date (`Of`) is
|
||||||
* based on the moderately-sized lookup table (~1.5KB)
|
* based on the moderately-sized lookup table (~1.5KB)
|
||||||
* and the packed representation is chosen for the efficient lookup.
|
* and the packed representation is chosen for the efficient lookup.
|
||||||
* Every internal data structure does not validate its input,
|
* Every internal data structure does not validate its input,
|
||||||
* but the conversion keeps the valid value valid and the invalid value invalid
|
* but the conversion keeps the valid value valid and the invalid value invalid
|
||||||
* so that the user-facing `Date` can validate the input as late as possible.
|
* so that the user-facing `DateZ` can validate the input as late as possible.
|
||||||
*/
|
*/
|
||||||
mod internals {
|
mod internals {
|
||||||
use std::{i32, num, fmt};
|
use std::{i32, num, fmt};
|
||||||
|
|
|
@ -3,242 +3,48 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
use time::Time;
|
use time::{Timelike, TimeZ};
|
||||||
use date::{Date, Weekday};
|
use date::{Datelike, DateZ, Weekday};
|
||||||
|
|
||||||
#[deriving(Eq, TotalEq, Ord, TotalOrd, Hash)]
|
#[deriving(Eq, TotalEq, Ord, TotalOrd, Hash)]
|
||||||
pub struct DateTime {
|
pub struct DateTimeZ {
|
||||||
date: Date,
|
date: DateZ,
|
||||||
time: Time,
|
time: TimeZ,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl DateTime {
|
impl DateTimeZ {
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn new(date: Date, time: Time) -> DateTime {
|
pub fn new(date: DateZ, time: TimeZ) -> DateTimeZ {
|
||||||
DateTime { date: date, time: time }
|
DateTimeZ { date: date, time: time }
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn from_ymdhms(year: int, month: uint, day: uint,
|
pub fn from_ymdhms(year: int, month: uint, day: uint,
|
||||||
hour: uint, min: uint, sec: uint) -> Option<DateTime> {
|
hour: uint, min: uint, sec: uint) -> Option<DateTimeZ> {
|
||||||
match (Date::from_ymd(year, month, day), Time::from_hms(hour, min, sec)) {
|
match (DateZ::from_ymd(year, month, day), TimeZ::from_hms(hour, min, sec)) {
|
||||||
(Some(d), Some(t)) => Some(DateTime::new(d, t)),
|
(Some(d), Some(t)) => Some(DateTimeZ::new(d, t)),
|
||||||
(_, _) => None,
|
(_, _) => None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn from_yohms(year: int, ordinal: uint,
|
pub fn from_yohms(year: int, ordinal: uint,
|
||||||
hour: uint, min: uint, sec: uint) -> Option<DateTime> {
|
hour: uint, min: uint, sec: uint) -> Option<DateTimeZ> {
|
||||||
match (Date::from_yo(year, ordinal), Time::from_hms(hour, min, sec)) {
|
match (DateZ::from_yo(year, ordinal), TimeZ::from_hms(hour, min, sec)) {
|
||||||
(Some(d), Some(t)) => Some(DateTime::new(d, t)),
|
(Some(d), Some(t)) => Some(DateTimeZ::new(d, t)),
|
||||||
(_, _) => None,
|
(_, _) => None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn from_isoywdhms(year: int, week: uint, weekday: Weekday,
|
pub fn from_isoywdhms(year: int, week: uint, weekday: Weekday,
|
||||||
hour: uint, min: uint, sec: uint) -> Option<DateTime> {
|
hour: uint, min: uint, sec: uint) -> Option<DateTimeZ> {
|
||||||
match (Date::from_isoywd(year, week, weekday), Time::from_hms(hour, min, sec)) {
|
match (DateZ::from_isoywd(year, week, weekday), TimeZ::from_hms(hour, min, sec)) {
|
||||||
(Some(d), Some(t)) => Some(DateTime::new(d, t)),
|
(Some(d), Some(t)) => Some(DateTimeZ::new(d, t)),
|
||||||
(_, _) => None,
|
(_, _) => None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns the year number.
|
|
||||||
#[inline]
|
|
||||||
pub fn year(&self) -> int {
|
|
||||||
self.date.year()
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Returns the absolute year number starting from 1 with a boolean flag,
|
|
||||||
/// which is false when the year predates the epoch (BCE/BC) and true otherwise (CE/AD).
|
|
||||||
#[inline]
|
|
||||||
pub fn year_ce(&self) -> (bool, uint) {
|
|
||||||
self.date.year_ce()
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Returns the month number starting from 1.
|
|
||||||
#[inline]
|
|
||||||
pub fn month(&self) -> uint {
|
|
||||||
self.date.month()
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Returns the month number starting from 0.
|
|
||||||
#[inline]
|
|
||||||
pub fn month0(&self) -> uint {
|
|
||||||
self.date.month0()
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Returns the day of month starting from 1.
|
|
||||||
#[inline]
|
|
||||||
pub fn day(&self) -> uint {
|
|
||||||
self.date.day()
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Returns the day of month starting from 0.
|
|
||||||
#[inline]
|
|
||||||
pub fn day0(&self) -> uint {
|
|
||||||
self.date.day0()
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Returns the day of year starting from 1.
|
|
||||||
#[inline]
|
|
||||||
pub fn ordinal(&self) -> uint {
|
|
||||||
self.date.ordinal()
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Returns the day of year starting from 0.
|
|
||||||
#[inline]
|
|
||||||
pub fn ordinal0(&self) -> uint {
|
|
||||||
self.date.ordinal0()
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Returns the day of week.
|
|
||||||
#[inline]
|
|
||||||
pub fn weekday(&self) -> Weekday {
|
|
||||||
self.date.weekday()
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Returns the ISO week date: an adjusted year, week number and day of week.
|
|
||||||
/// The adjusted year may differ from that of the calendar date.
|
|
||||||
#[inline]
|
|
||||||
pub fn isoweekdate(&self) -> (int, uint, Weekday) {
|
|
||||||
self.date.isoweekdate()
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Returns the hour number from 0 to 23.
|
|
||||||
#[inline]
|
|
||||||
pub fn hour(&self) -> uint {
|
|
||||||
self.time.hour()
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Returns the hour number from 1 to 12 with a boolean flag,
|
|
||||||
/// which is false for AM and true for PM.
|
|
||||||
#[inline]
|
|
||||||
pub fn hour12(&self) -> (bool, uint) {
|
|
||||||
self.time.hour12()
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Returns the minute number from 0 to 59.
|
|
||||||
#[inline]
|
|
||||||
pub fn minute(&self) -> uint {
|
|
||||||
self.time.minute()
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Returns the second number from 0 to 59.
|
|
||||||
#[inline]
|
|
||||||
pub fn second(&self) -> uint {
|
|
||||||
self.time.second()
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Returns the number of nanoseconds since the whole non-leap second.
|
|
||||||
/// The range from 1,000,000,000 to 1,999,999,999 represents the leap second.
|
|
||||||
#[inline]
|
|
||||||
pub fn nanosecond(&self) -> uint {
|
|
||||||
self.time.nanosecond()
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Makes a new `DateTime` with the year number changed.
|
|
||||||
///
|
|
||||||
/// Returns `None` when the resulting `DateTime` would be invalid.
|
|
||||||
#[inline]
|
|
||||||
pub fn with_year(&self, year: int) -> Option<DateTime> {
|
|
||||||
self.date.with_year(year).map(|d| DateTime { date: d, ..*self })
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Makes a new `DateTime` with the month number (starting from 1) changed.
|
|
||||||
///
|
|
||||||
/// Returns `None` when the resulting `DateTime` would be invalid.
|
|
||||||
#[inline]
|
|
||||||
pub fn with_month(&self, month: uint) -> Option<DateTime> {
|
|
||||||
self.date.with_month(month).map(|d| DateTime { date: d, ..*self })
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Makes a new `DateTime` with the month number (starting from 0) changed.
|
|
||||||
///
|
|
||||||
/// Returns `None` when the resulting `DateTime` would be invalid.
|
|
||||||
#[inline]
|
|
||||||
pub fn with_month0(&self, month0: uint) -> Option<DateTime> {
|
|
||||||
self.date.with_month0(month0).map(|d| DateTime { date: d, ..*self })
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Makes a new `DateTime` with the day of month (starting from 1) changed.
|
|
||||||
///
|
|
||||||
/// Returns `None` when the resulting `DateTime` would be invalid.
|
|
||||||
#[inline]
|
|
||||||
pub fn with_day(&self, day: uint) -> Option<DateTime> {
|
|
||||||
self.date.with_day(day).map(|d| DateTime { date: d, ..*self })
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Makes a new `DateTime` with the day of month (starting from 0) changed.
|
|
||||||
///
|
|
||||||
/// Returns `None` when the resulting `DateTime` would be invalid.
|
|
||||||
#[inline]
|
|
||||||
pub fn with_day0(&self, day0: uint) -> Option<DateTime> {
|
|
||||||
self.date.with_day0(day0).map(|d| DateTime { date: d, ..*self })
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Makes a new `DateTime` with the day of year (starting from 1) changed.
|
|
||||||
///
|
|
||||||
/// Returns `None` when the resulting `DateTime` would be invalid.
|
|
||||||
#[inline]
|
|
||||||
pub fn with_ordinal(&self, ordinal: uint) -> Option<DateTime> {
|
|
||||||
self.date.with_ordinal(ordinal).map(|d| DateTime { date: d, ..*self })
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Makes a new `DateTime` with the day of year (starting from 0) changed.
|
|
||||||
///
|
|
||||||
/// Returns `None` when the resulting `DateTime` would be invalid.
|
|
||||||
#[inline]
|
|
||||||
pub fn with_ordinal0(&self, ordinal0: uint) -> Option<DateTime> {
|
|
||||||
self.date.with_ordinal0(ordinal0).map(|d| DateTime { date: d, ..*self })
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Makes a new `Time` with the hour number changed.
|
|
||||||
///
|
|
||||||
/// Returns `None` when the resulting `Time` would be invalid.
|
|
||||||
#[inline]
|
|
||||||
pub fn with_hour(&self, hour: uint) -> Option<DateTime> {
|
|
||||||
self.time.with_hour(hour).map(|t| DateTime { time: t, ..*self })
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Makes a new `Time` with the minute number changed.
|
|
||||||
///
|
|
||||||
/// Returns `None` when the resulting `Time` would be invalid.
|
|
||||||
#[inline]
|
|
||||||
pub fn with_minute(&self, min: uint) -> Option<DateTime> {
|
|
||||||
self.time.with_minute(min).map(|t| DateTime { time: t, ..*self })
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Makes a new `Time` with the second number changed.
|
|
||||||
///
|
|
||||||
/// Returns `None` when the resulting `Time` would be invalid.
|
|
||||||
#[inline]
|
|
||||||
pub fn with_second(&self, sec: uint) -> Option<DateTime> {
|
|
||||||
self.time.with_second(sec).map(|t| DateTime { time: t, ..*self })
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Makes a new `Time` with nanoseconds since the whole non-leap second changed.
|
|
||||||
///
|
|
||||||
/// Returns `None` when the resulting `Time` would be invalid.
|
|
||||||
#[inline]
|
|
||||||
pub fn with_nanosecond(&self, nano: uint) -> Option<DateTime> {
|
|
||||||
self.time.with_nanosecond(nano).map(|t| DateTime { time: t, ..*self })
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Returns the number of days since January 1, 1 (Day 1) in the proleptic Gregorian calendar.
|
|
||||||
#[inline]
|
|
||||||
pub fn ndays_from_ce(&self) -> int {
|
|
||||||
self.date.ndays_from_ce()
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Returns the number of non-leap seconds past the last midnight.
|
|
||||||
#[inline]
|
|
||||||
pub fn nseconds_from_midnight(&self) -> uint {
|
|
||||||
self.time.nseconds_from_midnight()
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Returns the number of non-leap seconds since January 1, 1970 0:00:00.
|
/// Returns the number of non-leap seconds since January 1, 1970 0:00:00.
|
||||||
/// Note that this does *not* account for the timezone!
|
/// Note that this does *not* account for the timezone!
|
||||||
#[inline]
|
#[inline]
|
||||||
|
@ -247,7 +53,81 @@ impl DateTime {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl fmt::Show for DateTime {
|
impl Datelike for DateTimeZ {
|
||||||
|
#[inline] fn year(&self) -> int { self.date.year() }
|
||||||
|
#[inline] fn month(&self) -> uint { self.date.month() }
|
||||||
|
#[inline] fn month0(&self) -> uint { self.date.month0() }
|
||||||
|
#[inline] fn day(&self) -> uint { self.date.day() }
|
||||||
|
#[inline] fn day0(&self) -> uint { self.date.day0() }
|
||||||
|
#[inline] fn ordinal(&self) -> uint { self.date.ordinal() }
|
||||||
|
#[inline] fn ordinal0(&self) -> uint { self.date.ordinal0() }
|
||||||
|
#[inline] fn weekday(&self) -> Weekday { self.date.weekday() }
|
||||||
|
#[inline] fn isoweekdate(&self) -> (int, uint, Weekday) { self.date.isoweekdate() }
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn with_year(&self, year: int) -> Option<DateTimeZ> {
|
||||||
|
self.date.with_year(year).map(|d| DateTimeZ { date: d, ..*self })
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn with_month(&self, month: uint) -> Option<DateTimeZ> {
|
||||||
|
self.date.with_month(month).map(|d| DateTimeZ { date: d, ..*self })
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn with_month0(&self, month0: uint) -> Option<DateTimeZ> {
|
||||||
|
self.date.with_month0(month0).map(|d| DateTimeZ { date: d, ..*self })
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn with_day(&self, day: uint) -> Option<DateTimeZ> {
|
||||||
|
self.date.with_day(day).map(|d| DateTimeZ { date: d, ..*self })
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn with_day0(&self, day0: uint) -> Option<DateTimeZ> {
|
||||||
|
self.date.with_day0(day0).map(|d| DateTimeZ { date: d, ..*self })
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn with_ordinal(&self, ordinal: uint) -> Option<DateTimeZ> {
|
||||||
|
self.date.with_ordinal(ordinal).map(|d| DateTimeZ { date: d, ..*self })
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn with_ordinal0(&self, ordinal0: uint) -> Option<DateTimeZ> {
|
||||||
|
self.date.with_ordinal0(ordinal0).map(|d| DateTimeZ { date: d, ..*self })
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Timelike for DateTimeZ {
|
||||||
|
#[inline] fn hour(&self) -> uint { self.time.hour() }
|
||||||
|
#[inline] fn minute(&self) -> uint { self.time.minute() }
|
||||||
|
#[inline] fn second(&self) -> uint { self.time.second() }
|
||||||
|
#[inline] fn nanosecond(&self) -> uint { self.time.nanosecond() }
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn with_hour(&self, hour: uint) -> Option<DateTimeZ> {
|
||||||
|
self.time.with_hour(hour).map(|t| DateTimeZ { time: t, ..*self })
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn with_minute(&self, min: uint) -> Option<DateTimeZ> {
|
||||||
|
self.time.with_minute(min).map(|t| DateTimeZ { time: t, ..*self })
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn with_second(&self, sec: uint) -> Option<DateTimeZ> {
|
||||||
|
self.time.with_second(sec).map(|t| DateTimeZ { time: t, ..*self })
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn with_nanosecond(&self, nano: uint) -> Option<DateTimeZ> {
|
||||||
|
self.time.with_nanosecond(nano).map(|t| DateTimeZ { time: t, ..*self })
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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)
|
||||||
}
|
}
|
||||||
|
@ -260,7 +140,7 @@ mod tests {
|
||||||
#[test]
|
#[test]
|
||||||
fn test_time_nseconds_from_unix_epoch() {
|
fn test_time_nseconds_from_unix_epoch() {
|
||||||
let to_timestamp =
|
let to_timestamp =
|
||||||
|y,m,d,h,n,s| DateTime::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);
|
||||||
assert_eq!(to_timestamp(1970, 1, 1, 0, 0, 0), 0);
|
assert_eq!(to_timestamp(1970, 1, 1, 0, 0, 0), 0);
|
||||||
assert_eq!(to_timestamp(1970, 1, 1, 0, 0, 1), 1);
|
assert_eq!(to_timestamp(1970, 1, 1, 0, 0, 1), 1);
|
||||||
|
|
|
@ -4,129 +4,136 @@
|
||||||
|
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
|
|
||||||
/// ISO 8601 time. Allows for the nanosecond precision and optional leap second representation.
|
pub trait Timelike {
|
||||||
|
/// Returns the hour number from 0 to 23.
|
||||||
|
fn hour(&self) -> uint;
|
||||||
|
|
||||||
|
/// Returns the hour number from 1 to 12 with a boolean flag,
|
||||||
|
/// which is false for AM and true for PM.
|
||||||
|
#[inline]
|
||||||
|
fn hour12(&self) -> (bool, uint) {
|
||||||
|
let hour = self.hour();
|
||||||
|
let mut hour12 = hour % 12;
|
||||||
|
if hour12 == 0 { hour12 = 12; }
|
||||||
|
(hour >= 12, hour12)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns the minute number from 0 to 59.
|
||||||
|
fn minute(&self) -> uint;
|
||||||
|
|
||||||
|
/// Returns the second number from 0 to 59.
|
||||||
|
fn second(&self) -> uint;
|
||||||
|
|
||||||
|
/// Returns the number of nanoseconds since the whole non-leap second.
|
||||||
|
/// The range from 1,000,000,000 to 1,999,999,999 represents the leap second.
|
||||||
|
fn nanosecond(&self) -> uint;
|
||||||
|
|
||||||
|
/// Makes a new value with the hour number changed.
|
||||||
|
///
|
||||||
|
/// Returns `None` when the resulting value would be invalid.
|
||||||
|
fn with_hour(&self, hour: uint) -> Option<Self>;
|
||||||
|
|
||||||
|
/// Makes a new value with the minute number changed.
|
||||||
|
///
|
||||||
|
/// Returns `None` when the resulting value would be invalid.
|
||||||
|
fn with_minute(&self, min: uint) -> Option<Self>;
|
||||||
|
|
||||||
|
/// Makes a new value with the second number changed.
|
||||||
|
///
|
||||||
|
/// Returns `None` when the resulting value would be invalid.
|
||||||
|
fn with_second(&self, sec: uint) -> Option<Self>;
|
||||||
|
|
||||||
|
/// Makes a new value with nanoseconds since the whole non-leap second changed.
|
||||||
|
///
|
||||||
|
/// Returns `None` when the resulting value would be invalid.
|
||||||
|
fn with_nanosecond(&self, nano: uint) -> Option<Self>;
|
||||||
|
|
||||||
|
/// Returns the number of non-leap seconds past the last midnight.
|
||||||
|
#[inline]
|
||||||
|
fn nseconds_from_midnight(&self) -> uint {
|
||||||
|
self.hour() * 3600 + self.minute() * 60 + self.second()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// ISO 8601 time without timezone.
|
||||||
|
/// Allows for the nanosecond precision and optional leap second representation.
|
||||||
#[deriving(Eq, TotalEq, Ord, TotalOrd, Hash)]
|
#[deriving(Eq, TotalEq, Ord, TotalOrd, Hash)]
|
||||||
pub struct Time {
|
pub struct TimeZ {
|
||||||
priv hour: u8,
|
priv hour: u8,
|
||||||
priv min: u8,
|
priv min: u8,
|
||||||
priv sec: u8,
|
priv sec: u8,
|
||||||
priv frac: u32,
|
priv frac: u32,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Time {
|
impl TimeZ {
|
||||||
/// Makes a new `Time` from hour, minute and second.
|
/// Makes a new `TimeZ` from hour, minute and second.
|
||||||
///
|
///
|
||||||
/// Returns `None` on invalid hour, minute and/or second.
|
/// Returns `None` on invalid hour, minute and/or second.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn from_hms(hour: uint, min: uint, sec: uint) -> Option<Time> {
|
pub fn from_hms(hour: uint, min: uint, sec: uint) -> Option<TimeZ> {
|
||||||
Time::from_hms_nano(hour, min, sec, 0)
|
TimeZ::from_hms_nano(hour, min, sec, 0)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Makes a new `Time` from hour, minute, second and millisecond.
|
/// Makes a new `TimeZ` from hour, minute, second and millisecond.
|
||||||
/// The millisecond part can exceed 1,000 in order to represent the leap second.
|
/// The millisecond part can exceed 1,000 in order to represent the leap second.
|
||||||
///
|
///
|
||||||
/// Returns `None` on invalid hour, minute, second and/or millisecond.
|
/// Returns `None` on invalid hour, minute, second and/or millisecond.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn from_hms_milli(hour: uint, min: uint, sec: uint, milli: uint) -> Option<Time> {
|
pub fn from_hms_milli(hour: uint, min: uint, sec: uint, milli: uint) -> Option<TimeZ> {
|
||||||
Time::from_hms_nano(hour, min, sec, milli * 1_000_000)
|
TimeZ::from_hms_nano(hour, min, sec, milli * 1_000_000)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Makes a new `Time` from hour, minute, second and microsecond.
|
/// Makes a new `TimeZ` from hour, minute, second and microsecond.
|
||||||
/// The microsecond part can exceed 1,000,000 in order to represent the leap second.
|
/// The microsecond part can exceed 1,000,000 in order to represent the leap second.
|
||||||
///
|
///
|
||||||
/// Returns `None` on invalid hour, minute, second and/or microsecond.
|
/// Returns `None` on invalid hour, minute, second and/or microsecond.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn from_hms_micro(hour: uint, min: uint, sec: uint, micro: uint) -> Option<Time> {
|
pub fn from_hms_micro(hour: uint, min: uint, sec: uint, micro: uint) -> Option<TimeZ> {
|
||||||
Time::from_hms_nano(hour, min, sec, micro * 1_000)
|
TimeZ::from_hms_nano(hour, min, sec, micro * 1_000)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Makes a new `Time` from hour, minute, second and nanosecond.
|
/// Makes a new `TimeZ` from hour, minute, second and nanosecond.
|
||||||
/// The nanosecond part can exceed 1,000,000,000 in order to represent the leap second.
|
/// The nanosecond part can exceed 1,000,000,000 in order to represent the leap second.
|
||||||
///
|
///
|
||||||
/// Returns `None` on invalid hour, minute, second and/or nanosecond.
|
/// Returns `None` on invalid hour, minute, second and/or nanosecond.
|
||||||
pub fn from_hms_nano(hour: uint, min: uint, sec: uint, nano: uint) -> Option<Time> {
|
pub fn from_hms_nano(hour: uint, min: uint, sec: uint, nano: uint) -> Option<TimeZ> {
|
||||||
if hour >= 24 || min >= 60 || sec >= 60 || nano >= 2_000_000_000 { return None; }
|
if hour >= 24 || min >= 60 || sec >= 60 || nano >= 2_000_000_000 { return None; }
|
||||||
Some(Time { hour: hour as u8, min: min as u8, sec: sec as u8, frac: nano as u32 })
|
Some(TimeZ { hour: hour as u8, min: min as u8, sec: sec as u8, frac: nano as u32 })
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns the hour number from 0 to 23.
|
impl Timelike for TimeZ {
|
||||||
#[inline]
|
#[inline] fn hour(&self) -> uint { self.hour as uint }
|
||||||
pub fn hour(&self) -> uint {
|
#[inline] fn minute(&self) -> uint { self.min as uint }
|
||||||
self.hour as uint
|
#[inline] fn second(&self) -> uint { self.sec as uint }
|
||||||
}
|
#[inline] fn nanosecond(&self) -> uint { self.frac as uint }
|
||||||
|
|
||||||
/// Returns the hour number from 1 to 12 with a boolean flag,
|
|
||||||
/// which is false for AM and true for PM.
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn hour12(&self) -> (bool, uint) {
|
fn with_hour(&self, hour: uint) -> Option<TimeZ> {
|
||||||
let mut hour12 = self.hour % 12;
|
|
||||||
if hour12 == 0 { hour12 = 12; }
|
|
||||||
(self.hour >= 12, hour12 as uint)
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Returns the minute number from 0 to 59.
|
|
||||||
#[inline]
|
|
||||||
pub fn minute(&self) -> uint {
|
|
||||||
self.min as uint
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Returns the second number from 0 to 59.
|
|
||||||
#[inline]
|
|
||||||
pub fn second(&self) -> uint {
|
|
||||||
self.sec as uint
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Returns the number of nanoseconds since the whole non-leap second.
|
|
||||||
/// The range from 1,000,000,000 to 1,999,999,999 represents the leap second.
|
|
||||||
#[inline]
|
|
||||||
pub fn nanosecond(&self) -> uint {
|
|
||||||
self.frac as uint
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Makes a new `Time` with the hour number changed.
|
|
||||||
///
|
|
||||||
/// Returns `None` when the resulting `Time` would be invalid.
|
|
||||||
#[inline]
|
|
||||||
pub fn with_hour(&self, hour: uint) -> Option<Time> {
|
|
||||||
if hour >= 24 { return None; }
|
if hour >= 24 { return None; }
|
||||||
Some(Time { hour: hour as u8, ..*self })
|
Some(TimeZ { hour: hour as u8, ..*self })
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Makes a new `Time` with the minute number changed.
|
|
||||||
///
|
|
||||||
/// Returns `None` when the resulting `Time` would be invalid.
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn with_minute(&self, min: uint) -> Option<Time> {
|
fn with_minute(&self, min: uint) -> Option<TimeZ> {
|
||||||
if min >= 60 { return None; }
|
if min >= 60 { return None; }
|
||||||
Some(Time { min: min as u8, ..*self })
|
Some(TimeZ { min: min as u8, ..*self })
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Makes a new `Time` with the second number changed.
|
|
||||||
///
|
|
||||||
/// Returns `None` when the resulting `Time` would be invalid.
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn with_second(&self, sec: uint) -> Option<Time> {
|
fn with_second(&self, sec: uint) -> Option<TimeZ> {
|
||||||
if sec >= 60 { return None; }
|
if sec >= 60 { return None; }
|
||||||
Some(Time { sec: sec as u8, ..*self })
|
Some(TimeZ { sec: sec as u8, ..*self })
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Makes a new `Time` with nanoseconds since the whole non-leap second changed.
|
|
||||||
///
|
|
||||||
/// Returns `None` when the resulting `Time` would be invalid.
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn with_nanosecond(&self, nano: uint) -> Option<Time> {
|
fn with_nanosecond(&self, nano: uint) -> Option<TimeZ> {
|
||||||
if nano >= 2_000_000_000 { return None; }
|
if nano >= 2_000_000_000 { return None; }
|
||||||
Some(Time { frac: nano as u32, ..*self })
|
Some(TimeZ { frac: nano as u32, ..*self })
|
||||||
}
|
|
||||||
|
|
||||||
/// Returns the number of non-leap seconds past the last midnight.
|
|
||||||
#[inline]
|
|
||||||
pub fn nseconds_from_midnight(&self) -> uint {
|
|
||||||
self.hour as uint * 3600 + self.min as uint * 60 + self.sec as uint
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl fmt::Show for Time {
|
impl fmt::Show for TimeZ {
|
||||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||||
let (sec, nano) = if self.frac >= 1_000_000_000 {
|
let (sec, nano) = if self.frac >= 1_000_000_000 {
|
||||||
(self.sec + 1, self.frac - 1_000_000_000)
|
(self.sec + 1, self.frac - 1_000_000_000)
|
||||||
|
@ -153,9 +160,9 @@ mod tests {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_time_fmt() {
|
fn test_time_fmt() {
|
||||||
assert_eq!(Time::from_hms_milli(23, 59, 59, 999).unwrap().to_str(), ~"23:59:59,999");
|
assert_eq!(TimeZ::from_hms_milli(23, 59, 59, 999).unwrap().to_str(), ~"23:59:59,999");
|
||||||
assert_eq!(Time::from_hms_milli(23, 59, 59, 1_000).unwrap().to_str(), ~"23:59:60");
|
assert_eq!(TimeZ::from_hms_milli(23, 59, 59, 1_000).unwrap().to_str(), ~"23:59:60");
|
||||||
assert_eq!(Time::from_hms_milli(23, 59, 59, 1_001).unwrap().to_str(), ~"23:59:60,001");
|
assert_eq!(TimeZ::from_hms_milli(23, 59, 59, 1_001).unwrap().to_str(), ~"23:59:60,001");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue