summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMatthias Beyer <mail@beyermatthias.de>2017-09-09 18:25:31 +0200
committerMatthias Beyer <mail@beyermatthias.de>2017-09-12 18:06:49 +0200
commit2ad17c444e964d44de3ac2bdf51a28edba9266ce (patch)
tree91dcfd9e0d1383610654319ec29a7867f55de5c2
parent4ea2a3ca2c5b1aafe5bd8fff509f0a523a234b8b (diff)
Add function to adjust times
-rw-r--r--src/timetype.rs233
1 files changed, 231 insertions, 2 deletions
diff --git a/src/timetype.rs b/src/timetype.rs
index 9231d59..55dc5f2 100644
--- a/src/timetype.rs
+++ b/src/timetype.rs
@@ -468,6 +468,32 @@ fn add_to_years(amount: i64, tt: TimeType) -> Result<TimeType> {
}
}
+#[inline]
+fn adjust_times_add(mut y: i64, mut mo: i64, mut d: i64, mut h: i64, mut mi: i64, mut s: i64)
+ -> (i64, i64, i64, i64, i64, i64)
+{
+ macro_rules! fix {
+ {
+ $base:ident,
+ $border:expr,
+ $next:ident
+ } => {
+ while $base >= $border {
+ $next += 1;
+ $base -= $border;
+ }
+ }
+ }
+
+ fix! { s , 60, mi }
+ fix! { mi, 60, h }
+ fix! { h , 24, d }
+ fix! { d , 30, mo }
+ fix! { mo, 12, y }
+
+ (y, mo, d, h, mi, s)
+}
+
fn add_to_moment(mom: NaiveDateTime, tt: TimeType) -> Result<TimeType> {
use timetype::TimeType as TT;
@@ -479,6 +505,9 @@ fn add_to_moment(mom: NaiveDateTime, tt: TimeType) -> Result<TimeType> {
let h = mom.hour() as i64;
let mi = mom.minute() as i64;
let s = mom.second() as i64 + a;
+
+ let (y, mo, d, h, mi, s) = adjust_times_add(y, mo, d, h, mi, s);
+
let tt = NaiveDate::from_ymd(y as i32, mo as u32, d as u32)
.and_hms(h as u32, mi as u32, s as u32);
Ok(TimeType::moment(tt))
@@ -490,6 +519,9 @@ fn add_to_moment(mom: NaiveDateTime, tt: TimeType) -> Result<TimeType> {
let h = mom.hour() as i64;
let mi = mom.minute() as i64 + a;
let s = mom.second() as i64;
+
+ let (y, mo, d, h, mi, s) = adjust_times_add(y, mo, d, h, mi, s);
+
let tt = NaiveDate::from_ymd(y as i32, mo as u32, d as u32)
.and_hms(h as u32, mi as u32, s as u32);
Ok(TimeType::moment(tt))
@@ -501,6 +533,9 @@ fn add_to_moment(mom: NaiveDateTime, tt: TimeType) -> Result<TimeType> {
let h = mom.hour() as i64 + a;
let mi = mom.minute() as i64;
let s = mom.second() as i64;
+
+ let (y, mo, d, h, mi, s) = adjust_times_add(y, mo, d, h, mi, s);
+
let tt = NaiveDate::from_ymd(y as i32, mo as u32, d as u32)
.and_hms(h as u32, mi as u32, s as u32);
Ok(TimeType::moment(tt))
@@ -512,6 +547,9 @@ fn add_to_moment(mom: NaiveDateTime, tt: TimeType) -> Result<TimeType> {
let h = mom.hour() as i64;
let mi = mom.minute() as i64;
let s = mom.second() as i64;
+
+ let (y, mo, d, h, mi, s) = adjust_times_add(y, mo, d, h, mi, s);
+
let tt = NaiveDate::from_ymd(y as i32, mo as u32, d as u32)
.and_hms(h as u32, mi as u32, s as u32);
Ok(TimeType::moment(tt))
@@ -523,6 +561,9 @@ fn add_to_moment(mom: NaiveDateTime, tt: TimeType) -> Result<TimeType> {
let h = mom.hour() as i64;
let mi = mom.minute() as i64;
let s = mom.second() as i64;
+
+ let (y, mo, d, h, mi, s) = adjust_times_add(y, mo, d, h, mi, s);
+
let tt = NaiveDate::from_ymd(y as i32, mo as u32, d as u32)
.and_hms(h as u32, mi as u32, s as u32);
Ok(TimeType::moment(tt))
@@ -534,6 +575,9 @@ fn add_to_moment(mom: NaiveDateTime, tt: TimeType) -> Result<TimeType> {
let h = mom.hour() as i64;
let mi = mom.minute() as i64;
let s = mom.second() as i64;
+
+ let (y, mo, d, h, mi, s) = adjust_times_add(y, mo, d, h, mi, s);
+
let tt = NaiveDate::from_ymd(y as i32, mo as u32, d as u32)
.and_hms(h as u32, mi as u32, s as u32);
Ok(TimeType::moment(tt))
@@ -682,17 +726,45 @@ fn sub_from_years(amount: i64, tt: TimeType) -> Result<TimeType> {
}
}
+#[inline]
+fn adjust_times_sub(mut y: i64, mut mo: i64, mut d: i64, mut h: i64, mut mi: i64, mut s: i64)
+ -> (i64, i64, i64, i64, i64, i64)
+{
+ macro_rules! fix {
+ {
+ $base:ident,
+ $next:ident
+ } => {
+ if $base < 0 {
+ $next += $base;
+ $base = 0;
+ }
+ }
+ }
+
+ fix! { s , mi }
+ fix! { mi, h }
+ fix! { h , d }
+ fix! { d , mo }
+ fix! { mo, y }
+
+ (y, mo, d, h, mi, s)
+}
+
fn sub_from_moment(mom: NaiveDateTime, tt: TimeType) -> Result<TimeType> {
use timetype::TimeType as TT;
match tt {
TT::Seconds(a) => {
let y = mom.year() as i64;
- let mo = mom.month();
+ let mo = mom.month() as i64;
let d = mom.day() as i64;
- let h = mom.hour();
+ let h = mom.hour() as i64;
let mi = mom.minute() as i64;
let s = mom.second() as i64 - a;
+
+ let (y, mo, d, h, mi, s) = adjust_times_sub(y, mo, d, h, mi, s);
+
let tt = NaiveDate::from_ymd(y as i32, mo as u32, d as u32)
.and_hms(h as u32, mi as u32, s as u32);
Ok(TimeType::moment(tt))
@@ -704,6 +776,9 @@ fn sub_from_moment(mom: NaiveDateTime, tt: TimeType) -> Result<TimeType> {
let h = mom.hour() as i64;
let mi = mom.minute() as i64 - a;
let s = mom.second() as i64;
+
+ let (y, mo, d, h, mi, s) = adjust_times_sub(y, mo, d, h, mi, s);
+
let tt = NaiveDate::from_ymd(y as i32, mo as u32, d as u32)
.and_hms(h as u32, mi as u32, s as u32);
Ok(TimeType::moment(tt))
@@ -715,6 +790,9 @@ fn sub_from_moment(mom: NaiveDateTime, tt: TimeType) -> Result<TimeType> {
let h = mom.hour() as i64 - a;
let mi = mom.minute() as i64;
let s = mom.second() as i64;
+
+ let (y, mo, d, h, mi, s) = adjust_times_sub(y, mo, d, h, mi, s);
+
let tt = NaiveDate::from_ymd(y as i32, mo as u32, d as u32)
.and_hms(h as u32, mi as u32, s as u32);
Ok(TimeType::moment(tt))
@@ -726,6 +804,9 @@ fn sub_from_moment(mom: NaiveDateTime, tt: TimeType) -> Result<TimeType> {
let h = mom.hour() as i64;
let mi = mom.minute() as i64;
let s = mom.second() as i64;
+
+ let (y, mo, d, h, mi, s) = adjust_times_sub(y, mo, d, h, mi, s);
+
let tt = NaiveDate::from_ymd(y as i32, mo as u32, d as u32)
.and_hms(h as u32, mi as u32, s as u32);
Ok(TimeType::moment(tt))
@@ -737,6 +818,9 @@ fn sub_from_moment(mom: NaiveDateTime, tt: TimeType) -> Result<TimeType> {
let h = mom.hour() as i64;
let mi = mom.minute() as i64;
let s = mom.second() as i64;
+
+ let (y, mo, d, h, mi, s) = adjust_times_sub(y, mo, d, h, mi, s);
+
let tt = NaiveDate::from_ymd(y as i32, mo as u32, d as u32)
.and_hms(h as u32, mi as u32, s as u32);
Ok(TimeType::moment(tt))
@@ -748,6 +832,9 @@ fn sub_from_moment(mom: NaiveDateTime, tt: TimeType) -> Result<TimeType> {
let h = mom.hour() as i64;
let mi = mom.minute() as i64;
let s = mom.second() as i64;
+
+ let (y, mo, d, h, mi, s) = adjust_times_sub(y, mo, d, h, mi, s);
+
let tt = NaiveDate::from_ymd(y as i32, mo as u32, d as u32)
.and_hms(h as u32, mi as u32, s as u32);
Ok(TimeType::moment(tt))
@@ -1695,6 +1782,13 @@ mod moment_plus_amount_tests {
}
generate_test_moment_plus_amount! {
+ name = test_moment_plus_too_much_seconds;
+ base = NaiveDate::from_ymd(2000, 1, 1).and_hms(0, 0, 0);
+ amount = TT::seconds(62);
+ expected = NaiveDate::from_ymd(2000, 1, 1).and_hms(0, 1, 2);
+ }
+
+ generate_test_moment_plus_amount! {
name = test_moment_plus_minutes;
base = NaiveDate::from_ymd(2000, 1, 1).and_hms(0, 0, 0);
amount = TT::minutes(2);
@@ -1702,6 +1796,13 @@ mod moment_plus_amount_tests {
}
generate_test_moment_plus_amount! {
+ name = test_moment_plus_too_much_minutes;
+ base = NaiveDate::from_ymd(2000, 1, 1).and_hms(0, 0, 0);
+ amount = TT::minutes(65);
+ expected = NaiveDate::from_ymd(2000, 1, 1).and_hms(1, 5, 0);
+ }
+
+ generate_test_moment_plus_amount! {
name = test_moment_plus_minutes_in_seconds;
base = NaiveDate::from_ymd(2000, 1, 1).and_hms(0, 0, 0);
amount = TT::seconds(62);
@@ -1709,11 +1810,139 @@ mod moment_plus_amount_tests {
}
generate_test_moment_plus_amount! {
+ name = test_moment_plus_months;
+ base = NaiveDate::from_ymd(2000, 1, 1).and_hms(0, 0, 0);
+ amount = TT::months(14);
+ expected = NaiveDate::from_ymd(2001, 3, 1).and_hms(0, 0, 0);
+ }
+
+ generate_test_moment_plus_amount! {
name = test_moment_plus_years;
base = NaiveDate::from_ymd(2000, 1, 1).and_hms(0, 0, 0);
amount = TT::years(62);
expected = NaiveDate::from_ymd(2062, 1, 1).and_hms(0, 0, 0);
}
+ generate_test_moment_minus_amount! {
+ name = test_moment_minus_nothing;
+ base = NaiveDate::from_ymd(2000, 1, 1).and_hms(0, 0, 0);
+ amount = TT::seconds(0);
+ expected = NaiveDate::from_ymd(2000, 1, 1).and_hms(0, 0, 0);
+ }
+
+ generate_test_moment_minus_amount! {
+ name = test_moment_minus_seconds;
+ base = NaiveDate::from_ymd(2000, 1, 1).and_hms(0, 0, 0);
+ amount = TT::seconds(1);
+ expected = NaiveDate::from_ymd(1999, 12, 31).and_hms(23, 59, 59);
+ }
+
+}
+
+#[cfg(test)]
+mod test_time_adjustments {
+ use super::adjust_times_add;
+ use super::adjust_times_sub;
+
+ macro_rules! generate_test_add {
+ {
+ y : $y :expr => $then_y :expr;
+ mo: $mo :expr => $then_mo :expr;
+ d : $d :expr => $then_d :expr;
+ h : $h :expr => $then_h :expr;
+ m : $m :expr => $then_m :expr;
+ s : $s :expr => $then_s :expr;
+ } => {
+ let (y, mo, d, h, mi, s) = adjust_times_add($y, $mo, $d, $h, $m, $s);
+
+ assert_eq!($then_y , y );
+ assert_eq!($then_mo, mo);
+ assert_eq!($then_d , d );
+ assert_eq!($then_h , h );
+ assert_eq!($then_m , mi);
+ assert_eq!($then_s , s );
+ }
+ }
+
+ macro_rules! generate_test_sub {
+ {
+ y : $y :expr => $then_y :expr;
+ mo: $mo :expr => $then_mo :expr;
+ d : $d :expr => $then_d :expr;
+ h : $h :expr => $then_h :expr;
+ m : $m :expr => $then_m :expr;
+ s : $s :expr => $then_s :expr;
+ } => {
+ let (y, mo, d, h, mi, s) = adjust_times_sub($y, $mo, $d, $h, $m, $s);
+
+ assert_eq!($then_y , y );
+ assert_eq!($then_mo, mo);
+ assert_eq!($then_d , d );
+ assert_eq!($then_h , h );
+ assert_eq!($then_m , mi);
+ assert_eq!($then_s , s );
+ }
+ }
+
+ #[test]
+ fn test_adjust_times_add_seconds() {
+ generate_test_add! {
+ y : 0 => 0;
+ mo : 0 => 0;
+ d : 0 => 0;
+ h : 0 => 0;
+ m : 0 => 1;
+ s : 62 => 2;
+ }
+ }
+
+ #[test]
+ fn test_adjust_times_add_minutes() {
+ generate_test_add! {
+ y : 0 => 0;
+ mo : 0 => 0;
+ d : 0 => 0;
+ h : 0 => 1;
+ m : 62 => 2;
+ s : 0 => 0;
+ }
+ }
+
+ #[test]
+ fn test_adjust_times_add_hours() {
+ generate_test_add! {
+ y : 0 => 0;
+ mo : 0 => 0;
+ d : 0 => 1;
+ h : 26 => 2;
+ m : 0 => 0;
+ s : 0 => 0;
+ }
+ }
+
+ #[test]
+ fn test_adjust_times_add_days() {
+ generate_test_add! {
+ y : 0 => 0;
+ mo : 0 => 1;
+ d : 32 => 2;
+ h : 0 => 0;
+ m : 0 => 0;
+ s : 0 => 0;
+ }
+ }
+
+ #[test]
+ fn test_adjust_times_add_months() {
+ generate_test_add! {
+ y : 0 => 1;
+ mo : 14 => 2;
+ d : 0 => 0;
+ h : 0 => 0;
+ m : 0 => 0;
+ s : 0 => 0;
+ }
+ }
+
}