Skip to content

Commit 86665d0

Browse files
committed
0.1.2: no more num dependency, multidispatched addition.
- `num` dependency is gone. It was only used for floored division and it is not hard to copy only that portion from num. - `Duration + Date` (or so) was blocked by rust-lang/rust#7590, which has been subsequently fixed. - Removed unused `unsafe` checks.
1 parent 0a04ae1 commit 86665d0

File tree

10 files changed

+95
-46
lines changed

10 files changed

+95
-46
lines changed

Cargo.toml

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[package]
22
name = "chrono"
3-
version = "0.1.1"
3+
version = "0.1.2"
44
authors = ["Kang Seonghoon <[email protected]>"]
55

66
description = "Date and time library for Rust"
@@ -13,9 +13,6 @@ license = "MIT/Apache-2.0"
1313
[lib]
1414
name = "chrono"
1515

16-
[dependencies.num]
17-
git = "https://github.com/rust-lang/num"
18-
1916
[dependencies.time]
2017
git = "https://github.com/rust-lang/time"
2118

src/date.rs

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -263,13 +263,10 @@ impl<Off:Offset> Add<Duration,Date<Off>> for Date<Off> {
263263
}
264264
}
265265

266-
/*
267-
// Rust issue #7590, the current coherence checker can't handle multiple Add impls
268266
impl<Off:Offset> Add<Date<Off>,Date<Off>> for Duration {
269267
#[inline]
270268
fn add(&self, rhs: &Date<Off>) -> Date<Off> { rhs.add(self) }
271269
}
272-
*/
273270

274271
impl<Off:Offset, Off2:Offset> Sub<Date<Off2>,Duration> for Date<Off> {
275272
fn sub(&self, rhs: &Date<Off2>) -> Duration {

src/datetime.rs

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -185,13 +185,10 @@ impl<Off:Offset> Add<Duration,DateTime<Off>> for DateTime<Off> {
185185
}
186186
}
187187

188-
/*
189-
// Rust issue #7590, the current coherence checker can't handle multiple Add impls
190188
impl<Off:Offset> Add<DateTime<Off>,DateTime<Off>> for Duration {
191189
#[inline]
192190
fn add(&self, rhs: &DateTime<Off>) -> DateTime<Off> { rhs.add(self) }
193191
}
194-
*/
195192

196193
impl<Off:Offset, Off2:Offset> Sub<DateTime<Off2>,Duration> for DateTime<Off> {
197194
fn sub(&self, rhs: &DateTime<Off2>) -> Duration {

src/div.rs

Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
// This is a part of rust-chrono.
2+
// Copyright (c) 2014, Kang Seonghoon.
3+
// Copyright 2013-2014 The Rust Project Developers.
4+
// See README.md and LICENSE.txt for details.
5+
6+
//! Integer division utilities. (Shamelessly copied from [num](https://github.com/rust-lang/num/))
7+
8+
// Algorithm from [Daan Leijen. _Division and Modulus for Computer Scientists_,
9+
// December 2001](http://research.microsoft.com/pubs/151917/divmodnote-letter.pdf)
10+
11+
use std::num::Int;
12+
13+
/// Same as `(a / b, a % b)`.
14+
#[inline]
15+
pub fn div_rem<T: Int>(a: T, b: T) -> (T, T) {
16+
(a / b, a % b)
17+
}
18+
19+
/// Same as `let (q, r) = div_mod_floor(a, b); r`.
20+
#[inline]
21+
pub fn mod_floor<T: Int>(a: T, b: T) -> T {
22+
let zero = Int::zero();
23+
match a % b {
24+
r if (r > zero && b < zero) || (r < zero && b > zero) => r + b,
25+
r => r,
26+
}
27+
}
28+
29+
/// Calculates a floored integer quotient and modulo.
30+
#[inline]
31+
pub fn div_mod_floor<T: Int>(a: T, b: T) -> (T, T) {
32+
let zero = Int::zero();
33+
let one = Int::one();
34+
match (a / b, a % b) {
35+
(d, r) if (r > zero && b < zero) || (r < zero && b > zero) => (d - one, r + b),
36+
(d, r) => (d, r),
37+
}
38+
}
39+
40+
#[cfg(test)]
41+
mod tests {
42+
use super::{mod_floor, div_mod_floor};
43+
44+
#[test]
45+
fn test_mod_floor() {
46+
assert_eq!(mod_floor( 8i, 3), 2);
47+
assert_eq!(mod_floor( 8i, -3), -1);
48+
assert_eq!(mod_floor(-8i, 3), 1);
49+
assert_eq!(mod_floor(-8i, -3), -2);
50+
51+
assert_eq!(mod_floor( 1i, 2), 1);
52+
assert_eq!(mod_floor( 1i, -2), -1);
53+
assert_eq!(mod_floor(-1i, 2), 1);
54+
assert_eq!(mod_floor(-1i, -2), -1);
55+
}
56+
57+
#[test]
58+
fn test_div_mod_floor() {
59+
assert_eq!(div_mod_floor( 8i, 3), ( 2, 2));
60+
assert_eq!(div_mod_floor( 8i, -3), (-3, -1));
61+
assert_eq!(div_mod_floor(-8i, 3), (-3, 1));
62+
assert_eq!(div_mod_floor(-8i, -3), ( 2, -2));
63+
64+
assert_eq!(div_mod_floor( 1i, 2), ( 0, 1));
65+
assert_eq!(div_mod_floor( 1i, -2), (-1, -1));
66+
assert_eq!(div_mod_floor(-1i, 2), (-1, 1));
67+
assert_eq!(div_mod_floor(-1i, -2), ( 0, -1));
68+
}
69+
}
70+

src/lib.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,6 @@ Experimental date and time handling for Rust.
1313
#![feature(macro_rules)]
1414
#![deny(missing_docs)]
1515

16-
extern crate num;
1716
extern crate "time" as stdtime;
1817

1918
pub use duration::Duration;
@@ -26,6 +25,7 @@ pub use date::Date;
2625
pub use time::Time;
2726
pub use datetime::DateTime;
2827

28+
mod div;
2929
pub mod duration {
3030
//! ISO 8601 duration.
3131
//!

src/naive/date.rs

Lines changed: 14 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -8,9 +8,9 @@
88

99
use std::fmt;
1010
use std::num::Int;
11-
use num::Integer;
1211

1312
use {Weekday, Datelike};
13+
use div::div_mod_floor;
1414
use duration::Duration;
1515
use naive::time::NaiveTime;
1616
use naive::datetime::NaiveDateTime;
@@ -148,9 +148,9 @@ impl NaiveDate {
148148
/// Returns `None` on the out-of-range date.
149149
pub fn from_num_days_from_ce_opt(days: i32) -> Option<NaiveDate> {
150150
let days = days + 365; // make January 1, 1 BCE equal to day 0
151-
let (year_div_400, cycle) = days.div_mod_floor(&146097);
151+
let (year_div_400, cycle) = div_mod_floor(days, 146097);
152152
let (year_mod_400, ordinal) = internals::cycle_to_yo(cycle as u32);
153-
let flags = unsafe { YearFlags::from_year_mod_400(year_mod_400 as i32) };
153+
let flags = YearFlags::from_year_mod_400(year_mod_400 as i32);
154154
NaiveDate::from_of(year_div_400 * 400 + year_mod_400 as i32,
155155
Of::new(ordinal, flags))
156156
}
@@ -382,33 +382,30 @@ impl Add<Duration,NaiveDate> for NaiveDate {
382382
// TODO overflow currently fails
383383

384384
let year = self.year();
385-
let (mut year_div_400, year_mod_400) = year.div_mod_floor(&400);
385+
let (mut year_div_400, year_mod_400) = div_mod_floor(year, 400);
386386
let cycle = internals::yo_to_cycle(year_mod_400 as u32, self.of().ordinal());
387387
let cycle = (cycle as i32).checked_add(rhs.num_days().to_i32().unwrap()).unwrap();
388-
let (cycle_div_400y, cycle) = cycle.div_mod_floor(&146097);
388+
let (cycle_div_400y, cycle) = div_mod_floor(cycle, 146097);
389389
year_div_400 += cycle_div_400y;
390390

391391
let (year_mod_400, ordinal) = internals::cycle_to_yo(cycle as u32);
392-
let flags = unsafe { YearFlags::from_year_mod_400(year_mod_400 as i32) };
392+
let flags = YearFlags::from_year_mod_400(year_mod_400 as i32);
393393
NaiveDate::from_of(year_div_400 * 400 + year_mod_400 as i32,
394394
Of::new(ordinal, flags)).unwrap()
395395
}
396396
}
397397

398-
/*
399-
// Rust issue #7590, the current coherence checker can't handle multiple Add impls
400398
impl Add<NaiveDate,NaiveDate> for Duration {
401399
#[inline]
402400
fn add(&self, rhs: &NaiveDate) -> NaiveDate { rhs.add(self) }
403401
}
404-
*/
405402

406403
impl Sub<NaiveDate,Duration> for NaiveDate {
407404
fn sub(&self, rhs: &NaiveDate) -> Duration {
408405
let year1 = self.year();
409406
let year2 = rhs.year();
410-
let (year1_div_400, year1_mod_400) = year1.div_mod_floor(&400);
411-
let (year2_div_400, year2_mod_400) = year2.div_mod_floor(&400);
407+
let (year1_div_400, year1_mod_400) = div_mod_floor(year1, 400);
408+
let (year2_div_400, year2_mod_400) = div_mod_floor(year2, 400);
412409
let cycle1 = internals::yo_to_cycle(year1_mod_400 as u32, self.of().ordinal()) as i64;
413410
let cycle2 = internals::yo_to_cycle(year2_mod_400 as u32, rhs.of().ordinal()) as i64;
414411
Duration::days((year1_div_400 as i64 - year2_div_400 as i64) * 146097 + (cycle1 - cycle2))
@@ -698,7 +695,7 @@ mod tests {
698695
let lhs = NaiveDate::from_ymd(y1, m1, d1);
699696
let sum = NaiveDate::from_ymd(y, m, d);
700697
assert_eq!(lhs + rhs, sum);
701-
//assert_eq!(rhs + lhs, sum);
698+
assert_eq!(rhs + lhs, sum);
702699
}
703700

704701
check((2014, 1, 1), Duration::zero(), (2014, 1, 1));
@@ -780,8 +777,8 @@ mod tests {
780777
#[allow(dead_code)] // some internal methods have been left for consistency
781778
mod internals {
782779
use std::{i32, num, fmt};
783-
use num::Integer;
784780
use Weekday;
781+
use div::{div_rem, mod_floor};
785782

786783
/// The internal date representation. This also includes the packed `Mdf` value.
787784
pub type DateImpl = i32;
@@ -855,7 +852,7 @@ mod internals {
855852
];
856853

857854
pub fn cycle_to_yo(cycle: u32) -> (u32, u32) {
858-
let (mut year_mod_400, mut ordinal0) = cycle.div_rem(&365);
855+
let (mut year_mod_400, mut ordinal0) = div_rem(cycle, 365);
859856
let delta = YEAR_DELTAS[year_mod_400 as uint] as u32;
860857
if ordinal0 < delta {
861858
year_mod_400 -= 1;
@@ -873,12 +870,12 @@ mod internals {
873870
impl YearFlags {
874871
#[inline]
875872
pub fn from_year(year: i32) -> YearFlags {
876-
let year = year.mod_floor(&400);
877-
unsafe { YearFlags::from_year_mod_400(year) }
873+
let year = mod_floor(year, 400);
874+
YearFlags::from_year_mod_400(year)
878875
}
879876

880877
#[inline]
881-
pub unsafe fn from_year_mod_400(year: i32) -> YearFlags {
878+
pub fn from_year_mod_400(year: i32) -> YearFlags {
882879
YEAR_TO_FLAGS[year as uint]
883880
}
884881

src/naive/datetime.rs

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -8,9 +8,9 @@
88

99
use std::fmt;
1010
use std::num::Int;
11-
use num::Integer;
1211

1312
use {Weekday, Timelike, Datelike};
13+
use div::div_mod_floor;
1414
use duration::Duration;
1515
use naive::time::NaiveTime;
1616
use naive::date::NaiveDate;
@@ -49,7 +49,7 @@ impl NaiveDateTime {
4949
/// Returns `None` on the out-of-range number of seconds and/or invalid nanosecond.
5050
#[inline]
5151
pub fn from_num_seconds_from_unix_epoch_opt(secs: i64, nsecs: u32) -> Option<NaiveDateTime> {
52-
let (days, secs) = secs.div_mod_floor(&86400);
52+
let (days, secs) = div_mod_floor(secs, 86400);
5353
let date = days.to_i32().and_then(|days| days.checked_add(719163))
5454
.and_then(|days_ce| NaiveDate::from_num_days_from_ce_opt(days_ce));
5555
let time = NaiveTime::from_num_seconds_from_midnight_opt(secs as u32, nsecs);
@@ -183,13 +183,10 @@ impl Add<Duration,NaiveDateTime> for NaiveDateTime {
183183
}
184184
}
185185

186-
/*
187-
// Rust issue #7590, the current coherence checker can't handle multiple Add impls
188186
impl Add<NaiveDateTime,NaiveDateTime> for Duration {
189187
#[inline]
190188
fn add(&self, rhs: &NaiveDateTime) -> NaiveDateTime { rhs.add(self) }
191189
}
192-
*/
193190

194191
impl Sub<NaiveDateTime,Duration> for NaiveDateTime {
195192
fn sub(&self, rhs: &NaiveDateTime) -> Duration {

src/naive/time.rs

Lines changed: 4 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -8,9 +8,9 @@
88

99
use std::fmt;
1010
use std::num::Int;
11-
use num::Integer;
1211

1312
use Timelike;
13+
use div::div_mod_floor;
1414
use offset::Offset;
1515
use duration::Duration;
1616
use format::DelayedFormat;
@@ -126,8 +126,8 @@ impl NaiveTime {
126126

127127
/// Returns a triple of the hour, minute and second numbers.
128128
fn hms(&self) -> (u32, u32, u32) {
129-
let (mins, sec) = self.secs.div_mod_floor(&60);
130-
let (hour, min) = mins.div_mod_floor(&60);
129+
let (mins, sec) = div_mod_floor(self.secs, 60);
130+
let (hour, min) = div_mod_floor(mins, 60);
131131
(hour, min, sec)
132132
}
133133
}
@@ -190,13 +190,10 @@ impl Add<Duration,NaiveTime> for NaiveTime {
190190
}
191191
}
192192

193-
/*
194-
// Rust issue #7590, the current coherence checker can't handle multiple Add impls
195193
impl Add<NaiveTime,NaiveTime> for Duration {
196194
#[inline]
197195
fn add(&self, rhs: &NaiveTime) -> NaiveTime { rhs.add(self) }
198196
}
199-
*/
200197

201198
impl Sub<NaiveTime,Duration> for NaiveTime {
202199
fn sub(&self, rhs: &NaiveTime) -> Duration {
@@ -303,7 +300,7 @@ mod tests {
303300
fn test_time_add() {
304301
fn check(lhs: NaiveTime, rhs: Duration, sum: NaiveTime) {
305302
assert_eq!(lhs + rhs, sum);
306-
//assert_eq!(rhs + lhs, sum);
303+
assert_eq!(rhs + lhs, sum);
307304
}
308305

309306
let hmsm = |h,m,s,mi| NaiveTime::from_hms_milli(h, m, s, mi);

src/offset.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,9 +9,9 @@
99
use std::fmt;
1010
use std::str::MaybeOwned;
1111
use stdtime;
12-
use num::Integer;
1312

1413
use {Weekday, Datelike, Timelike};
14+
use div::div_mod_floor;
1515
use duration::Duration;
1616
use naive::date::NaiveDate;
1717
use naive::time::NaiveTime;
@@ -365,8 +365,8 @@ impl fmt::Show for FixedOffset {
365365
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
366366
let offset = self.local_minus_utc;
367367
let (sign, offset) = if offset < 0 {('-', -offset)} else {('+', offset)};
368-
let (mins, sec) = offset.div_mod_floor(&60);
369-
let (hour, min) = mins.div_mod_floor(&60);
368+
let (mins, sec) = div_mod_floor(offset, 60);
369+
let (hour, min) = div_mod_floor(mins, 60);
370370
if sec == 0 {
371371
write!(f, "{}{:02}:{:02}", sign, hour, min)
372372
} else {

src/time.rs

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -113,13 +113,10 @@ impl<Off:Offset> Add<Duration,Time<Off>> for Time<Off> {
113113
}
114114
}
115115

116-
/*
117-
// Rust issue #7590, the current coherence checker can't handle multiple Add impls
118116
impl<Off:Offset> Add<Time<Off>,Time<Off>> for Duration {
119117
#[inline]
120118
fn add(&self, rhs: &Time<Off>) -> Time<Off> { rhs.add(self) }
121119
}
122-
*/
123120

124121
impl<Off:Offset, Off2:Offset> Sub<Time<Off2>,Duration> for Time<Off> {
125122
fn sub(&self, rhs: &Time<Off2>) -> Duration {

0 commit comments

Comments
 (0)