language changes: namespaced enums, no more std::num::{Zero,Bounded}.

This commit is contained in:
Kang Seonghoon 2014-11-19 10:59:32 +09:00
parent fdcaff7ce1
commit ec6c874042
7 changed files with 145 additions and 145 deletions

View File

@ -1,13 +1,19 @@
[package] [package]
name = "chrono" name = "chrono"
version = "0.1.0" version = "0.1.0"
authors = ["Kang Seonghoon <public+rust@mearie.org>"] authors = ["Kang Seonghoon <public+rust@mearie.org>"]
[dependencies.num] description = "Date and time library for Rust"
homepage = "https://github.com/lifthrasiir/rust-chrono"
git = "https://github.com/rust-lang/num" readme = "README.md"
license = "MIT/Apache-2.0"
[lib] [lib]
name = "chrono" name = "chrono"
[dependencies.num]
git = "https://github.com/rust-lang/num"
[dependencies.time]
git = "https://github.com/rust-lang/time"

View File

@ -6,7 +6,7 @@
* ISO 8601 calendar date with timezone. * ISO 8601 calendar date with timezone.
*/ */
use std::{fmt, num, hash}; use std::{fmt, hash};
use {Weekday, Datelike}; use {Weekday, Datelike};
use duration::Duration; use duration::Duration;
@ -232,11 +232,6 @@ impl<Off:Offset> Datelike for Date<Off> {
} }
} }
impl num::Bounded for Date<UTC> {
#[inline] fn min_value() -> Date<UTC> { MIN }
#[inline] fn max_value() -> Date<UTC> { MAX }
}
impl<Off:Offset> PartialEq for Date<Off> { impl<Off:Offset> PartialEq for Date<Off> {
fn eq(&self, other: &Date<Off>) -> bool { self.date == other.date } fn eq(&self, other: &Date<Off>) -> bool { self.date == other.date }
} }

View File

@ -74,13 +74,13 @@ impl Weekday {
#[inline] #[inline]
pub fn succ(&self) -> Weekday { pub fn succ(&self) -> Weekday {
match *self { match *self {
Mon => Tue, Weekday::Mon => Weekday::Tue,
Tue => Wed, Weekday::Tue => Weekday::Wed,
Wed => Thu, Weekday::Wed => Weekday::Thu,
Thu => Fri, Weekday::Thu => Weekday::Fri,
Fri => Sat, Weekday::Fri => Weekday::Sat,
Sat => Sun, Weekday::Sat => Weekday::Sun,
Sun => Mon, Weekday::Sun => Weekday::Mon,
} }
} }
@ -88,13 +88,13 @@ impl Weekday {
#[inline] #[inline]
pub fn pred(&self) -> Weekday { pub fn pred(&self) -> Weekday {
match *self { match *self {
Mon => Sun, Weekday::Mon => Weekday::Sun,
Tue => Mon, Weekday::Tue => Weekday::Mon,
Wed => Tue, Weekday::Wed => Weekday::Tue,
Thu => Wed, Weekday::Thu => Weekday::Wed,
Fri => Thu, Weekday::Fri => Weekday::Thu,
Sat => Fri, Weekday::Sat => Weekday::Fri,
Sun => Sat, Weekday::Sun => Weekday::Sat,
} }
} }
@ -102,13 +102,13 @@ impl Weekday {
#[inline] #[inline]
pub fn number_from_monday(&self) -> u32 { pub fn number_from_monday(&self) -> u32 {
match *self { match *self {
Mon => 1, Weekday::Mon => 1,
Tue => 2, Weekday::Tue => 2,
Wed => 3, Weekday::Wed => 3,
Thu => 4, Weekday::Thu => 4,
Fri => 5, Weekday::Fri => 5,
Sat => 6, Weekday::Sat => 6,
Sun => 7, Weekday::Sun => 7,
} }
} }
@ -116,13 +116,13 @@ impl Weekday {
#[inline] #[inline]
pub fn number_from_sunday(&self) -> u32 { pub fn number_from_sunday(&self) -> u32 {
match *self { match *self {
Mon => 2, Weekday::Mon => 2,
Tue => 3, Weekday::Tue => 3,
Wed => 4, Weekday::Wed => 4,
Thu => 5, Weekday::Thu => 5,
Fri => 6, Weekday::Fri => 6,
Sat => 7, Weekday::Sat => 7,
Sun => 1, Weekday::Sun => 1,
} }
} }
@ -130,13 +130,13 @@ impl Weekday {
#[inline] #[inline]
pub fn num_days_from_monday(&self) -> u32 { pub fn num_days_from_monday(&self) -> u32 {
match *self { match *self {
Mon => 0, Weekday::Mon => 0,
Tue => 1, Weekday::Tue => 1,
Wed => 2, Weekday::Wed => 2,
Thu => 3, Weekday::Thu => 3,
Fri => 4, Weekday::Fri => 4,
Sat => 5, Weekday::Sat => 5,
Sun => 6, Weekday::Sun => 6,
} }
} }
@ -144,13 +144,13 @@ impl Weekday {
#[inline] #[inline]
pub fn num_days_from_sunday(&self) -> u32 { pub fn num_days_from_sunday(&self) -> u32 {
match *self { match *self {
Mon => 1, Weekday::Mon => 1,
Tue => 2, Weekday::Tue => 2,
Wed => 3, Weekday::Wed => 3,
Thu => 4, Weekday::Thu => 4,
Fri => 5, Weekday::Fri => 5,
Sat => 6, Weekday::Sat => 6,
Sun => 0, Weekday::Sun => 0,
} }
} }
} }

View File

@ -6,7 +6,8 @@
* ISO 8601 calendar date without timezone. * ISO 8601 calendar date without timezone.
*/ */
use std::{fmt, num}; use std::fmt;
use std::num::Int;
use num::Integer; use num::Integer;
use {Weekday, Datelike}; use {Weekday, Datelike};
@ -376,11 +377,6 @@ impl Datelike for NaiveDate {
} }
} }
impl num::Bounded for NaiveDate {
#[inline] fn min_value() -> NaiveDate { MIN }
#[inline] fn max_value() -> NaiveDate { MAX }
}
impl Add<Duration,NaiveDate> for NaiveDate { impl Add<Duration,NaiveDate> for NaiveDate {
fn add(&self, rhs: &Duration) -> NaiveDate { fn add(&self, rhs: &Duration) -> NaiveDate {
// TODO overflow currently fails // TODO overflow currently fails
@ -388,7 +384,7 @@ impl Add<Duration,NaiveDate> for NaiveDate {
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 u32, self.of().ordinal()); let cycle = internals::yo_to_cycle(year_mod_400 as u32, self.of().ordinal());
let cycle = (cycle as i32).checked_add(&rhs.num_days().to_i32().unwrap()).unwrap(); let cycle = (cycle as i32).checked_add(rhs.num_days().to_i32().unwrap()).unwrap();
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;
@ -435,11 +431,9 @@ impl fmt::Show for NaiveDate {
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use super::{NaiveDate, MIN, MAX}; use super::{NaiveDate, MIN, MAX};
use Datelike; use {Datelike, Weekday};
use {Sun, Mon, Tue, Wed, Thu, Fri, Sat};
use duration::Duration; use duration::Duration;
use std::{i32, u32}; use std::{i32, u32};
use std::num::Zero;
use std::iter::{range_inclusive, range_step_inclusive}; use std::iter::{range_inclusive, range_step_inclusive};
#[test] #[test]
@ -493,35 +487,36 @@ mod tests {
let isoywd_opt = |y,w,d| NaiveDate::from_isoywd_opt(y, w, d); let isoywd_opt = |y,w,d| NaiveDate::from_isoywd_opt(y, w, d);
let ymd = |y,m,d| NaiveDate::from_ymd(y, m, d); let ymd = |y,m,d| NaiveDate::from_ymd(y, m, d);
assert_eq!(isoywd_opt(2004, 0, Sun), None); assert_eq!(isoywd_opt(2004, 0, Weekday::Sun), None);
assert_eq!(isoywd_opt(2004, 1, Mon), Some(ymd(2003, 12, 29))); assert_eq!(isoywd_opt(2004, 1, Weekday::Mon), Some(ymd(2003, 12, 29)));
assert_eq!(isoywd_opt(2004, 1, Sun), Some(ymd(2004, 1, 4))); assert_eq!(isoywd_opt(2004, 1, Weekday::Sun), Some(ymd(2004, 1, 4)));
assert_eq!(isoywd_opt(2004, 2, Mon), Some(ymd(2004, 1, 5))); assert_eq!(isoywd_opt(2004, 2, Weekday::Mon), Some(ymd(2004, 1, 5)));
assert_eq!(isoywd_opt(2004, 2, Sun), Some(ymd(2004, 1, 11))); assert_eq!(isoywd_opt(2004, 2, Weekday::Sun), Some(ymd(2004, 1, 11)));
assert_eq!(isoywd_opt(2004, 52, Mon), Some(ymd(2004, 12, 20))); assert_eq!(isoywd_opt(2004, 52, Weekday::Mon), Some(ymd(2004, 12, 20)));
assert_eq!(isoywd_opt(2004, 52, Sun), Some(ymd(2004, 12, 26))); assert_eq!(isoywd_opt(2004, 52, Weekday::Sun), Some(ymd(2004, 12, 26)));
assert_eq!(isoywd_opt(2004, 53, Mon), Some(ymd(2004, 12, 27))); assert_eq!(isoywd_opt(2004, 53, Weekday::Mon), Some(ymd(2004, 12, 27)));
assert_eq!(isoywd_opt(2004, 53, Sun), Some(ymd(2005, 1, 2))); assert_eq!(isoywd_opt(2004, 53, Weekday::Sun), Some(ymd(2005, 1, 2)));
assert_eq!(isoywd_opt(2004, 54, Mon), None); assert_eq!(isoywd_opt(2004, 54, Weekday::Mon), None);
assert_eq!(isoywd_opt(2011, 0, Sun), None); assert_eq!(isoywd_opt(2011, 0, Weekday::Sun), None);
assert_eq!(isoywd_opt(2011, 1, Mon), Some(ymd(2011, 1, 3))); assert_eq!(isoywd_opt(2011, 1, Weekday::Mon), Some(ymd(2011, 1, 3)));
assert_eq!(isoywd_opt(2011, 1, Sun), Some(ymd(2011, 1, 9))); assert_eq!(isoywd_opt(2011, 1, Weekday::Sun), Some(ymd(2011, 1, 9)));
assert_eq!(isoywd_opt(2011, 2, Mon), Some(ymd(2011, 1, 10))); assert_eq!(isoywd_opt(2011, 2, Weekday::Mon), Some(ymd(2011, 1, 10)));
assert_eq!(isoywd_opt(2011, 2, Sun), Some(ymd(2011, 1, 16))); assert_eq!(isoywd_opt(2011, 2, Weekday::Sun), Some(ymd(2011, 1, 16)));
assert_eq!(isoywd_opt(2018, 51, Mon), Some(ymd(2018, 12, 17))); assert_eq!(isoywd_opt(2018, 51, Weekday::Mon), Some(ymd(2018, 12, 17)));
assert_eq!(isoywd_opt(2018, 51, Sun), Some(ymd(2018, 12, 23))); assert_eq!(isoywd_opt(2018, 51, Weekday::Sun), Some(ymd(2018, 12, 23)));
assert_eq!(isoywd_opt(2018, 52, Mon), Some(ymd(2018, 12, 24))); assert_eq!(isoywd_opt(2018, 52, Weekday::Mon), Some(ymd(2018, 12, 24)));
assert_eq!(isoywd_opt(2018, 52, Sun), Some(ymd(2018, 12, 30))); assert_eq!(isoywd_opt(2018, 52, Weekday::Sun), Some(ymd(2018, 12, 30)));
assert_eq!(isoywd_opt(2018, 53, Mon), None); assert_eq!(isoywd_opt(2018, 53, Weekday::Mon), None);
} }
#[test] #[test]
fn test_date_from_isoymd_and_isoweekdate() { fn test_date_from_isoymd_and_isoweekdate() {
for year in range_inclusive(2000i32, 2400) { for year in range_inclusive(2000i32, 2400) {
for week in range_inclusive(1u32, 53) { for week in range_inclusive(1u32, 53) {
for &weekday in [Mon, Tue, Wed, Thu, Fri, Sat, Sun].iter() { for &weekday in [Weekday::Mon, Weekday::Tue, Weekday::Wed, Weekday::Thu,
Weekday::Fri, Weekday::Sat, Weekday::Sun].iter() {
let d = NaiveDate::from_isoywd_opt(year, week, weekday); let d = NaiveDate::from_isoywd_opt(year, week, weekday);
if d.is_some() { if d.is_some() {
let d = d.unwrap(); let d = d.unwrap();
@ -622,9 +617,10 @@ mod tests {
#[test] #[test]
fn test_date_weekday() { fn test_date_weekday() {
assert_eq!(NaiveDate::from_ymd(1582, 10, 15).weekday(), Fri); assert_eq!(NaiveDate::from_ymd(1582, 10, 15).weekday(), Weekday::Fri);
assert_eq!(NaiveDate::from_ymd(1875, 5, 20).weekday(), Thu); // ISO 8601 reference date // May 20, 1875 = ISO 8601 reference date
assert_eq!(NaiveDate::from_ymd(2000, 1, 1).weekday(), Sat); assert_eq!(NaiveDate::from_ymd(1875, 5, 20).weekday(), Weekday::Thu);
assert_eq!(NaiveDate::from_ymd(2000, 1, 1).weekday(), Weekday::Sat);
} }
#[test] #[test]
@ -705,7 +701,7 @@ mod tests {
//assert_eq!(rhs + lhs, sum); //assert_eq!(rhs + lhs, sum);
} }
check((2014, 1, 1), Zero::zero(), (2014, 1, 1)); check((2014, 1, 1), Duration::zero(), (2014, 1, 1));
check((2014, 1, 1), Duration::seconds(86399), (2014, 1, 1)); check((2014, 1, 1), Duration::seconds(86399), (2014, 1, 1));
check((2014, 1, 1), Duration::seconds(-86399), (2014, 1, 1)); // always round towards zero check((2014, 1, 1), Duration::seconds(-86399), (2014, 1, 1)); // always round towards zero
check((2014, 1, 1), Duration::days(1), (2014, 1, 2)); check((2014, 1, 1), Duration::days(1), (2014, 1, 2));
@ -726,7 +722,7 @@ mod tests {
assert_eq!(rhs - lhs, -diff); assert_eq!(rhs - lhs, -diff);
} }
check((2014, 1, 1), (2014, 1, 1), Zero::zero()); check((2014, 1, 1), (2014, 1, 1), Duration::zero());
check((2014, 1, 2), (2014, 1, 1), Duration::days(1)); check((2014, 1, 2), (2014, 1, 1), Duration::days(1));
check((2014, 12, 31), (2014, 1, 1), Duration::days(364)); check((2014, 12, 31), (2014, 1, 1), Duration::days(364));
check((2015, 1, 3), (2014, 1, 1), Duration::days(365 + 2)); check((2015, 1, 3), (2014, 1, 1), Duration::days(365 + 2));
@ -1238,9 +1234,9 @@ mod internals {
mod tests { mod tests {
extern crate test; extern crate test;
use Weekday;
use super::{Of, Mdf}; use super::{Of, Mdf};
use super::{YearFlags, A, B, C, D, E, F, G, AG, BA, CB, DC, ED, FE, GF}; use super::{YearFlags, A, B, C, D, E, F, G, AG, BA, CB, DC, ED, FE, GF};
use {Sun, Mon, Tue, Wed, Thu, Fri, Sat};
use std::iter::range_inclusive; use std::iter::range_inclusive;
use std::u32; use std::u32;
@ -1413,20 +1409,20 @@ mod internals {
#[test] #[test]
fn test_of_weekday() { fn test_of_weekday() {
assert_eq!(Of::new(1, A).weekday(), Sun); assert_eq!(Of::new(1, A).weekday(), Weekday::Sun);
assert_eq!(Of::new(1, B).weekday(), Sat); assert_eq!(Of::new(1, B).weekday(), Weekday::Sat);
assert_eq!(Of::new(1, C).weekday(), Fri); assert_eq!(Of::new(1, C).weekday(), Weekday::Fri);
assert_eq!(Of::new(1, D).weekday(), Thu); assert_eq!(Of::new(1, D).weekday(), Weekday::Thu);
assert_eq!(Of::new(1, E).weekday(), Wed); assert_eq!(Of::new(1, E).weekday(), Weekday::Wed);
assert_eq!(Of::new(1, F).weekday(), Tue); assert_eq!(Of::new(1, F).weekday(), Weekday::Tue);
assert_eq!(Of::new(1, G).weekday(), Mon); assert_eq!(Of::new(1, G).weekday(), Weekday::Mon);
assert_eq!(Of::new(1, AG).weekday(), Sun); assert_eq!(Of::new(1, AG).weekday(), Weekday::Sun);
assert_eq!(Of::new(1, BA).weekday(), Sat); assert_eq!(Of::new(1, BA).weekday(), Weekday::Sat);
assert_eq!(Of::new(1, CB).weekday(), Fri); assert_eq!(Of::new(1, CB).weekday(), Weekday::Fri);
assert_eq!(Of::new(1, DC).weekday(), Thu); assert_eq!(Of::new(1, DC).weekday(), Weekday::Thu);
assert_eq!(Of::new(1, ED).weekday(), Wed); assert_eq!(Of::new(1, ED).weekday(), Weekday::Wed);
assert_eq!(Of::new(1, FE).weekday(), Tue); assert_eq!(Of::new(1, FE).weekday(), Weekday::Tue);
assert_eq!(Of::new(1, GF).weekday(), Mon); assert_eq!(Of::new(1, GF).weekday(), Weekday::Mon);
for &flags in FLAGS.iter() { for &flags in FLAGS.iter() {
let mut prev = Of::new(1, flags).weekday(); let mut prev = Of::new(1, flags).weekday();

View File

@ -7,6 +7,7 @@
*/ */
use std::fmt; use std::fmt;
use std::num::Int;
use num::Integer; use num::Integer;
use {Weekday, Timelike, Datelike}; use {Weekday, Timelike, Datelike};
@ -49,7 +50,7 @@ impl NaiveDateTime {
#[inline] #[inline]
pub fn from_num_seconds_from_unix_epoch_opt(secs: i64, nsecs: u32) -> Option<NaiveDateTime> { pub fn from_num_seconds_from_unix_epoch_opt(secs: i64, nsecs: u32) -> Option<NaiveDateTime> {
let (days, secs) = secs.div_mod_floor(&86400); let (days, secs) = secs.div_mod_floor(&86400);
let date = days.to_i32().and_then(|days| days.checked_add(&719163)) let date = days.to_i32().and_then(|days| days.checked_add(719163))
.and_then(|days_ce| NaiveDate::from_num_days_from_ce_opt(days_ce)); .and_then(|days_ce| NaiveDate::from_num_days_from_ce_opt(days_ce));
let time = NaiveTime::from_num_seconds_from_midnight_opt(secs as u32, nsecs); let time = NaiveTime::from_num_seconds_from_midnight_opt(secs as u32, nsecs);
match (date, time) { match (date, time) {
@ -208,7 +209,6 @@ mod tests {
use duration::Duration; use duration::Duration;
use naive::date::NaiveDate; use naive::date::NaiveDate;
use std::i64; use std::i64;
use std::num::Zero;
#[test] #[test]
fn test_datetime_from_num_seconds_from_unix_epoch() { fn test_datetime_from_num_seconds_from_unix_epoch() {
@ -241,7 +241,7 @@ mod tests {
#[test] #[test]
fn test_datetime_sub() { fn test_datetime_sub() {
let ymdhms = |y,m,d,h,n,s| NaiveDate::from_ymd(y,m,d).and_hms(h,n,s); let ymdhms = |y,m,d,h,n,s| NaiveDate::from_ymd(y,m,d).and_hms(h,n,s);
assert_eq!(ymdhms(2014, 5, 6, 7, 8, 9) - ymdhms(2014, 5, 6, 7, 8, 9), Zero::zero()); 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), assert_eq!(ymdhms(2014, 5, 6, 7, 8, 10) - ymdhms(2014, 5, 6, 7, 8, 9),
Duration::seconds(1)); Duration::seconds(1));
assert_eq!(ymdhms(2014, 5, 6, 7, 8, 9) - ymdhms(2014, 5, 6, 7, 8, 10), assert_eq!(ymdhms(2014, 5, 6, 7, 8, 9) - ymdhms(2014, 5, 6, 7, 8, 10),

View File

@ -7,6 +7,7 @@
*/ */
use std::fmt; use std::fmt;
use std::num::Int;
use num::Integer; use num::Integer;
use Timelike; use Timelike;
@ -54,7 +55,7 @@ impl NaiveTime {
/// 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_opt(hour: u32, min: u32, sec: u32, milli: u32) -> Option<NaiveTime> { pub fn from_hms_milli_opt(hour: u32, min: u32, sec: u32, milli: u32) -> Option<NaiveTime> {
milli.checked_mul(&1_000_000) milli.checked_mul(1_000_000)
.and_then(|nano| NaiveTime::from_hms_nano_opt(hour, min, sec, nano)) .and_then(|nano| NaiveTime::from_hms_nano_opt(hour, min, sec, nano))
} }
@ -73,7 +74,7 @@ impl NaiveTime {
/// 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_opt(hour: u32, min: u32, sec: u32, micro: u32) -> Option<NaiveTime> { pub fn from_hms_micro_opt(hour: u32, min: u32, sec: u32, micro: u32) -> Option<NaiveTime> {
micro.checked_mul(&1_000) micro.checked_mul(1_000)
.and_then(|nano| NaiveTime::from_hms_nano_opt(hour, min, sec, nano)) .and_then(|nano| NaiveTime::from_hms_nano_opt(hour, min, sec, nano))
} }
@ -242,7 +243,6 @@ mod tests {
use Timelike; use Timelike;
use duration::Duration; use duration::Duration;
use std::u32; use std::u32;
use std::num::Zero;
#[test] #[test]
fn test_time_from_hms_milli() { fn test_time_from_hms_milli() {
@ -308,7 +308,7 @@ mod tests {
let hmsm = |h,m,s,mi| NaiveTime::from_hms_milli(h, m, s, mi); let hmsm = |h,m,s,mi| NaiveTime::from_hms_milli(h, m, s, mi);
check(hmsm(3, 5, 7, 900), Zero::zero(), hmsm(3, 5, 7, 900)); check(hmsm(3, 5, 7, 900), Duration::zero(), hmsm(3, 5, 7, 900));
check(hmsm(3, 5, 7, 900), Duration::milliseconds(100), hmsm(3, 5, 8, 0)); check(hmsm(3, 5, 7, 900), Duration::milliseconds(100), hmsm(3, 5, 8, 0));
check(hmsm(3, 5, 7, 1_300), Duration::milliseconds(800), hmsm(3, 5, 8, 100)); check(hmsm(3, 5, 7, 1_300), Duration::milliseconds(800), hmsm(3, 5, 8, 100));
check(hmsm(3, 5, 7, 900), Duration::seconds(86399), hmsm(3, 5, 6, 900)); // overwrap check(hmsm(3, 5, 7, 900), Duration::seconds(86399), hmsm(3, 5, 6, 900)); // overwrap
@ -326,7 +326,7 @@ mod tests {
let hmsm = |h,m,s,mi| NaiveTime::from_hms_milli(h, m, s, mi); let hmsm = |h,m,s,mi| NaiveTime::from_hms_milli(h, m, s, mi);
check(hmsm(3, 5, 7, 900), hmsm(3, 5, 7, 900), Zero::zero()); check(hmsm(3, 5, 7, 900), hmsm(3, 5, 7, 900), Duration::zero());
check(hmsm(3, 5, 7, 900), hmsm(3, 5, 7, 600), Duration::milliseconds(300)); check(hmsm(3, 5, 7, 900), hmsm(3, 5, 7, 600), Duration::milliseconds(300));
check(hmsm(3, 5, 7, 200), hmsm(2, 4, 6, 200), Duration::seconds(3600 + 60 + 1)); check(hmsm(3, 5, 7, 200), hmsm(2, 4, 6, 200), Duration::seconds(3600 + 60 + 1));
check(hmsm(3, 5, 7, 200), hmsm(2, 4, 6, 300), check(hmsm(3, 5, 7, 200), hmsm(2, 4, 6, 300),

View File

@ -8,7 +8,6 @@
use std::fmt; use std::fmt;
use std::str::MaybeOwned; use std::str::MaybeOwned;
use std::num::Zero;
use stdtime; use stdtime;
use num::Integer; use num::Integer;
@ -25,7 +24,7 @@ use datetime::DateTime;
pub enum LocalResult<T> { pub enum LocalResult<T> {
/// Given local time representation is invalid. /// Given local time representation is invalid.
/// This can occur when, for example, the positive timezone transition. /// This can occur when, for example, the positive timezone transition.
NoResult, None,
/// Given local time representation has a single unique result. /// Given local time representation has a single unique result.
Single(T), Single(T),
/// Given local time representation has multiple results and thus ambiguous. /// Given local time representation has multiple results and thus ambiguous.
@ -36,17 +35,17 @@ pub enum LocalResult<T> {
impl<T> LocalResult<T> { impl<T> LocalResult<T> {
/// Returns `Some` only when the conversion result is unique, or `None` otherwise. /// Returns `Some` only when the conversion result is unique, or `None` otherwise.
pub fn single(self) -> Option<T> { pub fn single(self) -> Option<T> {
match self { Single(t) => Some(t), _ => None } match self { LocalResult::Single(t) => Some(t), _ => None }
} }
/// Returns `Some` for the earliest possible conversion result, or `None` if none. /// Returns `Some` for the earliest possible conversion result, or `None` if none.
pub fn earliest(self) -> Option<T> { pub fn earliest(self) -> Option<T> {
match self { Single(t) | Ambiguous(t,_) => Some(t), _ => None } match self { LocalResult::Single(t) | LocalResult::Ambiguous(t,_) => Some(t), _ => None }
} }
/// Returns `Some` for the latest possible conversion result, or `None` if none. /// Returns `Some` for the latest possible conversion result, or `None` if none.
pub fn latest(self) -> Option<T> { pub fn latest(self) -> Option<T> {
match self { Single(t) | Ambiguous(_,t) => Some(t), _ => None } match self { LocalResult::Single(t) | LocalResult::Ambiguous(_,t) => Some(t), _ => None }
} }
} }
@ -54,9 +53,11 @@ impl<T:fmt::Show> LocalResult<T> {
/// Returns the single unique conversion result, or fails accordingly. /// Returns the single unique conversion result, or fails accordingly.
pub fn unwrap(self) -> T { pub fn unwrap(self) -> T {
match self { match self {
NoResult => panic!("No such local time"), LocalResult::None => panic!("No such local time"),
Single(t) => t, LocalResult::Single(t) => t,
Ambiguous(t1,t2) => panic!("Ambiguous local time, ranging from {} to {}", t1, t2), LocalResult::Ambiguous(t1,t2) => {
panic!("Ambiguous local time, ranging from {} to {}", t1, t2)
}
} }
} }
} }
@ -84,7 +85,7 @@ pub trait Offset: Clone + fmt::Show {
fn ymd_opt(&self, year: i32, month: u32, day: u32) -> LocalResult<Date<Self>> { fn ymd_opt(&self, year: i32, month: u32, day: u32) -> LocalResult<Date<Self>> {
match NaiveDate::from_ymd_opt(year, month, day) { match NaiveDate::from_ymd_opt(year, month, day) {
Some(d) => self.from_local_date(&d), Some(d) => self.from_local_date(&d),
None => NoResult, None => LocalResult::None,
} }
} }
@ -109,7 +110,7 @@ pub trait Offset: Clone + fmt::Show {
fn yo_opt(&self, year: i32, ordinal: u32) -> LocalResult<Date<Self>> { fn yo_opt(&self, year: i32, ordinal: u32) -> LocalResult<Date<Self>> {
match NaiveDate::from_yo_opt(year, ordinal) { match NaiveDate::from_yo_opt(year, ordinal) {
Some(d) => self.from_local_date(&d), Some(d) => self.from_local_date(&d),
None => NoResult, None => LocalResult::None,
} }
} }
@ -138,7 +139,7 @@ pub trait Offset: Clone + fmt::Show {
fn isoywd_opt(&self, year: i32, week: u32, weekday: Weekday) -> LocalResult<Date<Self>> { fn isoywd_opt(&self, year: i32, week: u32, weekday: Weekday) -> LocalResult<Date<Self>> {
match NaiveDate::from_isoywd_opt(year, week, weekday) { match NaiveDate::from_isoywd_opt(year, week, weekday) {
Some(d) => self.from_local_date(&d), Some(d) => self.from_local_date(&d),
None => NoResult, None => LocalResult::None,
} }
} }
@ -155,7 +156,7 @@ pub trait Offset: Clone + fmt::Show {
fn hms_opt(&self, hour: u32, min: u32, sec: u32) -> LocalResult<Time<Self>> { fn hms_opt(&self, hour: u32, min: u32, sec: u32) -> LocalResult<Time<Self>> {
match NaiveTime::from_hms_opt(hour, min, sec) { match NaiveTime::from_hms_opt(hour, min, sec) {
Some(t) => self.from_local_time(&t), Some(t) => self.from_local_time(&t),
None => NoResult, None => LocalResult::None,
} }
} }
@ -174,7 +175,7 @@ pub trait Offset: Clone + fmt::Show {
fn hms_milli_opt(&self, hour: u32, min: u32, sec: u32, milli: u32) -> LocalResult<Time<Self>> { fn hms_milli_opt(&self, hour: u32, min: u32, sec: u32, milli: u32) -> LocalResult<Time<Self>> {
match NaiveTime::from_hms_milli_opt(hour, min, sec, milli) { match NaiveTime::from_hms_milli_opt(hour, min, sec, milli) {
Some(t) => self.from_local_time(&t), Some(t) => self.from_local_time(&t),
None => NoResult, None => LocalResult::None,
} }
} }
@ -193,7 +194,7 @@ pub trait Offset: Clone + fmt::Show {
fn hms_micro_opt(&self, hour: u32, min: u32, sec: u32, micro: u32) -> LocalResult<Time<Self>> { fn hms_micro_opt(&self, hour: u32, min: u32, sec: u32, micro: u32) -> LocalResult<Time<Self>> {
match NaiveTime::from_hms_micro_opt(hour, min, sec, micro) { match NaiveTime::from_hms_micro_opt(hour, min, sec, micro) {
Some(t) => self.from_local_time(&t), Some(t) => self.from_local_time(&t),
None => NoResult, None => LocalResult::None,
} }
} }
@ -212,7 +213,7 @@ pub trait Offset: Clone + fmt::Show {
fn hms_nano_opt(&self, hour: u32, min: u32, sec: u32, nano: u32) -> LocalResult<Time<Self>> { fn hms_nano_opt(&self, hour: u32, min: u32, sec: u32, nano: u32) -> LocalResult<Time<Self>> {
match NaiveTime::from_hms_nano_opt(hour, min, sec, nano) { match NaiveTime::from_hms_nano_opt(hour, min, sec, nano) {
Some(t) => self.from_local_time(&t), Some(t) => self.from_local_time(&t),
None => NoResult, None => LocalResult::None,
} }
} }
@ -262,16 +263,16 @@ impl UTC {
impl Offset for UTC { impl Offset for UTC {
fn name(&self) -> MaybeOwned<'static> { "UTC".into_maybe_owned() } fn name(&self) -> MaybeOwned<'static> { "UTC".into_maybe_owned() }
fn local_minus_utc(&self) -> Duration { Zero::zero() } fn local_minus_utc(&self) -> Duration { Duration::zero() }
fn from_local_date(&self, local: &NaiveDate) -> LocalResult<Date<UTC>> { fn from_local_date(&self, local: &NaiveDate) -> LocalResult<Date<UTC>> {
Single(Date::from_utc(local.clone(), UTC)) LocalResult::Single(Date::from_utc(local.clone(), UTC))
} }
fn from_local_time(&self, local: &NaiveTime) -> LocalResult<Time<UTC>> { fn from_local_time(&self, local: &NaiveTime) -> LocalResult<Time<UTC>> {
Single(Time::from_utc(local.clone(), UTC)) LocalResult::Single(Time::from_utc(local.clone(), UTC))
} }
fn from_local_datetime(&self, local: &NaiveDateTime) -> LocalResult<DateTime<UTC>> { fn from_local_datetime(&self, local: &NaiveDateTime) -> LocalResult<DateTime<UTC>> {
Single(DateTime::from_utc(local.clone(), UTC)) LocalResult::Single(DateTime::from_utc(local.clone(), UTC))
} }
fn to_local_date(&self, utc: &NaiveDate) -> NaiveDate { utc.clone() } fn to_local_date(&self, utc: &NaiveDate) -> NaiveDate { utc.clone() }
@ -336,15 +337,17 @@ impl Offset for FixedOffset {
fn local_minus_utc(&self) -> Duration { Duration::seconds(self.local_minus_utc as i64) } fn local_minus_utc(&self) -> Duration { Duration::seconds(self.local_minus_utc as i64) }
fn from_local_date(&self, local: &NaiveDate) -> LocalResult<Date<FixedOffset>> { fn from_local_date(&self, local: &NaiveDate) -> LocalResult<Date<FixedOffset>> {
Single(Date::from_utc(local.clone(), self.clone())) LocalResult::Single(Date::from_utc(local.clone(), self.clone()))
} }
fn from_local_time(&self, local: &NaiveTime) -> LocalResult<Time<FixedOffset>> { fn from_local_time(&self, local: &NaiveTime) -> LocalResult<Time<FixedOffset>> {
Single(Time::from_utc(*local + Duration::seconds(-self.local_minus_utc as i64), let t = Time::from_utc(*local + Duration::seconds(-self.local_minus_utc as i64),
self.clone())) self.clone());
LocalResult::Single(t)
} }
fn from_local_datetime(&self, local: &NaiveDateTime) -> LocalResult<DateTime<FixedOffset>> { fn from_local_datetime(&self, local: &NaiveDateTime) -> LocalResult<DateTime<FixedOffset>> {
Single(DateTime::from_utc(*local + Duration::seconds(-self.local_minus_utc as i64), let dt = DateTime::from_utc(*local + Duration::seconds(-self.local_minus_utc as i64),
self.clone())) self.clone());
LocalResult::Single(dt)
} }
fn to_local_date(&self, utc: &NaiveDate) -> NaiveDate { fn to_local_date(&self, utc: &NaiveDate) -> NaiveDate {
@ -391,8 +394,8 @@ impl Local {
let date = NaiveDate::from_yo(tm.tm_year + 1900, tm.tm_yday as u32 + 1); let date = NaiveDate::from_yo(tm.tm_year + 1900, tm.tm_yday as u32 + 1);
let time = NaiveTime::from_hms_nano(tm.tm_hour as u32, tm.tm_min as u32, let time = NaiveTime::from_hms_nano(tm.tm_hour as u32, tm.tm_min as u32,
tm.tm_sec as u32, tm.tm_nsec as u32); tm.tm_sec as u32, tm.tm_nsec as u32);
let offset = Local { cached: FixedOffset::east(tm.tm_gmtoff) }; let offset = Local { cached: FixedOffset::east(tm.tm_utcoff) };
DateTime::from_utc(date.and_time(time) + Duration::seconds(-tm.tm_gmtoff as i64), offset) DateTime::from_utc(date.and_time(time) + Duration::seconds(-tm.tm_utcoff as i64), offset)
} }
/// Converts a local `NaiveDateTime` to the `time::Timespec`. /// Converts a local `NaiveDateTime` to the `time::Timespec`.
@ -407,7 +410,7 @@ impl Local {
tm_wday: 0, // to_local ignores this tm_wday: 0, // to_local ignores this
tm_yday: 0, // and this tm_yday: 0, // and this
tm_isdst: -1, tm_isdst: -1,
tm_gmtoff: 1, // this is arbitrary but should be nonzero tm_utcoff: 1, // this is arbitrary but should be nonzero
// in order to make `to_timespec` use `rust_mktime` internally. // in order to make `to_timespec` use `rust_mktime` internally.
tm_nsec: d.nanosecond() as i32, tm_nsec: d.nanosecond() as i32,
}; };
@ -431,24 +434,24 @@ impl Offset for Local {
fn from_local_date(&self, local: &NaiveDate) -> LocalResult<Date<Local>> { fn from_local_date(&self, local: &NaiveDate) -> LocalResult<Date<Local>> {
match self.from_local_datetime(&local.and_hms(0, 0, 0)) { match self.from_local_datetime(&local.and_hms(0, 0, 0)) {
NoResult => NoResult, LocalResult::None => LocalResult::None,
Single(dt) => Single(dt.date()), LocalResult::Single(dt) => LocalResult::Single(dt.date()),
Ambiguous(min, max) => { LocalResult::Ambiguous(min, max) => {
let min = min.date(); let min = min.date();
let max = max.date(); let max = max.date();
if min == max {Single(min)} else {Ambiguous(min, max)} if min == max {LocalResult::Single(min)} else {LocalResult::Ambiguous(min, max)}
} }
} }
} }
fn from_local_time(&self, local: &NaiveTime) -> LocalResult<Time<Local>> { fn from_local_time(&self, local: &NaiveTime) -> LocalResult<Time<Local>> {
// XXX we don't have enough information here, so we assume that the timezone remains same // XXX we don't have enough information here, so we assume that the timezone remains same
Single(Time::from_utc(local.clone(), self.clone())) LocalResult::Single(Time::from_utc(local.clone(), self.clone()))
} }
fn from_local_datetime(&self, local: &NaiveDateTime) -> LocalResult<DateTime<Local>> { fn from_local_datetime(&self, local: &NaiveDateTime) -> LocalResult<DateTime<Local>> {
let timespec = Local::datetime_to_timespec(local); let timespec = Local::datetime_to_timespec(local);
Single(Local::tm_to_datetime(stdtime::at(timespec))) LocalResult::Single(Local::tm_to_datetime(stdtime::at(timespec)))
} }
fn to_local_date(&self, utc: &NaiveDate) -> NaiveDate { self.cached.to_local_date(utc) } fn to_local_date(&self, utc: &NaiveDate) -> NaiveDate { self.cached.to_local_date(utc) }