Add comparison between dates

This commit is contained in:
Jonathan Turner 2019-11-16 14:36:51 +13:00
parent bcecd08825
commit 3c3637b674
3 changed files with 100 additions and 32 deletions

View file

@ -856,6 +856,7 @@ enum CompareValues {
Ints(BigInt, BigInt),
Decimals(BigDecimal, BigDecimal),
String(String, String),
Date(DateTime<Utc>, DateTime<Utc>),
}
impl CompareValues {
@ -864,6 +865,7 @@ impl CompareValues {
CompareValues::Ints(left, right) => left.cmp(right),
CompareValues::Decimals(left, right) => left.cmp(right),
CompareValues::String(left, right) => left.cmp(right),
CompareValues::Date(left, right) => right.cmp(left),
}
}
}
@ -900,6 +902,7 @@ fn coerce_compare_primitive(
CompareValues::Decimals(BigDecimal::from(*left), right.clone())
}
(String(left), String(right)) => CompareValues::String(left.clone(), right.clone()),
(Date(left), Date(right)) => CompareValues::Date(left.clone(), right.clone()),
_ => return Err((left.type_name(), right.type_name())),
})
}

View file

@ -86,12 +86,19 @@ fn unit_size(input: &str, bare_span: Span) -> IResult<&str, (Spanned<RawNumber>,
};
let (input, unit) = all_consuming(alt((
value(Unit::B, alt((tag("B"), tag("b")))),
value(Unit::KB, alt((tag("KB"), tag("kb"), tag("Kb")))),
value(Unit::MB, alt((tag("MB"), tag("mb"), tag("Mb")))),
value(Unit::GB, alt((tag("GB"), tag("gb"), tag("Gb")))),
value(Unit::TB, alt((tag("TB"), tag("tb"), tag("Tb")))),
value(Unit::PB, alt((tag("PB"), tag("pb"), tag("Pb")))),
value(Unit::Byte, alt((tag("B"), tag("b")))),
value(Unit::Kilobyte, alt((tag("KB"), tag("kb"), tag("Kb")))),
value(Unit::Megabyte, alt((tag("MB"), tag("mb"), tag("Mb")))),
value(Unit::Gigabyte, alt((tag("GB"), tag("gb"), tag("Gb")))),
value(Unit::Terabyte, alt((tag("TB"), tag("tb"), tag("Tb")))),
value(Unit::Petabyte, alt((tag("PB"), tag("pb"), tag("Pb")))),
value(Unit::Second, tag("s")),
value(Unit::Minute, tag("m")),
value(Unit::Hour, tag("h")),
value(Unit::Day, tag("d")),
value(Unit::Week, tag("w")),
value(Unit::Month, tag("M")),
value(Unit::Year, tag("y")),
)))(input)?;
let start_span = number.span.end();

View file

@ -3,15 +3,34 @@ use crate::prelude::*;
use serde::{Deserialize, Serialize};
use std::fmt;
use std::str::FromStr;
use std::time::Duration;
use std::time::SystemTime;
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Deserialize, Serialize)]
pub enum Unit {
B,
KB,
MB,
GB,
TB,
PB,
// Filesize units
Byte,
Kilobyte,
Megabyte,
Gigabyte,
Terabyte,
Petabyte,
// Duration units
Second,
Minute,
Hour,
Day,
Week,
Month,
Year,
}
fn convert_number_to_u64(number: &Number) -> u64 {
match number {
Number::Int(big_int) => big_int.to_u64().unwrap(),
Number::Decimal(big_decimal) => big_decimal.to_u64().unwrap(),
}
}
impl FormatDebug for Spanned<Unit> {
@ -23,26 +42,58 @@ impl FormatDebug for Spanned<Unit> {
impl Unit {
pub fn as_str(&self) -> &str {
match *self {
Unit::B => "B",
Unit::KB => "KB",
Unit::MB => "MB",
Unit::GB => "GB",
Unit::TB => "TB",
Unit::PB => "PB",
Unit::Byte => "B",
Unit::Kilobyte => "KB",
Unit::Megabyte => "MB",
Unit::Gigabyte => "GB",
Unit::Terabyte => "TB",
Unit::Petabyte => "PB",
Unit::Second => "s",
Unit::Minute => "m",
Unit::Hour => "h",
Unit::Day => "d",
Unit::Week => "w",
Unit::Month => "M",
Unit::Year => "y",
}
}
pub(crate) fn compute(&self, size: &Number) -> Value {
let size = size.clone();
Value::number(match self {
Unit::B => size,
Unit::KB => size * 1024,
Unit::MB => size * 1024 * 1024,
Unit::GB => size * 1024 * 1024 * 1024,
Unit::TB => size * 1024 * 1024 * 1024 * 1024,
Unit::PB => size * 1024 * 1024 * 1024 * 1024 * 1024,
})
match self {
Unit::Byte => Value::number(size),
Unit::Kilobyte => Value::number(size * 1024),
Unit::Megabyte => Value::number(size * 1024 * 1024),
Unit::Gigabyte => Value::number(size * 1024 * 1024 * 1024),
Unit::Terabyte => Value::number(size * 1024 * 1024 * 1024 * 1024),
Unit::Petabyte => Value::number(size * 1024 * 1024 * 1024 * 1024 * 1024),
Unit::Second => Value::system_date(
SystemTime::now() - Duration::from_secs(convert_number_to_u64(&size)),
),
Unit::Minute => Value::system_date(
SystemTime::now() - Duration::from_secs(60 * convert_number_to_u64(&size)),
),
Unit::Hour => Value::system_date(
SystemTime::now() - Duration::from_secs(60 * 60 * convert_number_to_u64(&size)),
),
Unit::Day => Value::system_date(
SystemTime::now()
- Duration::from_secs(24 * 60 * 60 * convert_number_to_u64(&size)),
),
Unit::Week => Value::system_date(
SystemTime::now()
- Duration::from_secs(7 * 24 * 60 * 60 * convert_number_to_u64(&size)),
),
Unit::Month => Value::system_date(
SystemTime::now()
- Duration::from_secs(30 * 24 * 60 * 60 * convert_number_to_u64(&size)),
),
Unit::Year => Value::system_date(
SystemTime::now()
- Duration::from_secs(365 * 24 * 60 * 60 * convert_number_to_u64(&size)),
),
}
}
}
@ -50,12 +101,19 @@ impl FromStr for Unit {
type Err = ();
fn from_str(input: &str) -> Result<Self, <Self as std::str::FromStr>::Err> {
match input {
"B" | "b" => Ok(Unit::B),
"KB" | "kb" | "Kb" | "K" | "k" => Ok(Unit::KB),
"MB" | "mb" | "Mb" => Ok(Unit::MB),
"GB" | "gb" | "Gb" => Ok(Unit::GB),
"TB" | "tb" | "Tb" => Ok(Unit::TB),
"PB" | "pb" | "Pb" => Ok(Unit::PB),
"B" | "b" => Ok(Unit::Byte),
"KB" | "kb" | "Kb" | "K" | "k" => Ok(Unit::Kilobyte),
"MB" | "mb" | "Mb" => Ok(Unit::Megabyte),
"GB" | "gb" | "Gb" => Ok(Unit::Gigabyte),
"TB" | "tb" | "Tb" => Ok(Unit::Terabyte),
"PB" | "pb" | "Pb" => Ok(Unit::Petabyte),
"s" => Ok(Unit::Second),
"m" => Ok(Unit::Minute),
"h" => Ok(Unit::Hour),
"d" => Ok(Unit::Day),
"w" => Ok(Unit::Week),
"M" => Ok(Unit::Month),
"y" => Ok(Unit::Year),
_ => Err(()),
}
}