From 6231367bc848e5eddf5562c3194a46b66c5ed3f4 Mon Sep 17 00:00:00 2001 From: Jonathan Turner Date: Sun, 17 Nov 2019 18:48:48 +1300 Subject: [PATCH] Make duration its own primitive --- src/commands/to_bson.rs | 1 + src/commands/to_json.rs | 3 +++ src/commands/to_sqlite.rs | 1 + src/commands/to_toml.rs | 1 + src/commands/to_yaml.rs | 3 +++ src/data/base.rs | 25 ++++++++++++++++++++++++- src/parser/parse/unit.rs | 34 +++++++--------------------------- 7 files changed, 40 insertions(+), 28 deletions(-) diff --git a/src/commands/to_bson.rs b/src/commands/to_bson.rs index eabf8381ec..afcd198cf4 100644 --- a/src/commands/to_bson.rs +++ b/src/commands/to_bson.rs @@ -41,6 +41,7 @@ pub fn value_to_bson_value(v: &Tagged) -> Result { .to_f64() .expect("Unimplemented BUG: What about big decimals?"), ), + Value::Primitive(Primitive::Duration(secs)) => Bson::I64(*secs as i64), Value::Primitive(Primitive::Date(d)) => Bson::UtcDatetime(*d), Value::Primitive(Primitive::EndOfStream) => Bson::Null, Value::Primitive(Primitive::BeginningOfStream) => Bson::Null, diff --git a/src/commands/to_json.rs b/src/commands/to_json.rs index 40edc5aeb8..62a3476307 100644 --- a/src/commands/to_json.rs +++ b/src/commands/to_json.rs @@ -32,6 +32,9 @@ pub fn value_to_json_value(v: &Tagged) -> Result serde_json::Value::Number( serde_json::Number::from(b.to_u64().expect("What about really big numbers")), ), + Value::Primitive(Primitive::Duration(secs)) => { + serde_json::Value::Number(serde_json::Number::from(*secs)) + } Value::Primitive(Primitive::Date(d)) => serde_json::Value::String(d.to_string()), Value::Primitive(Primitive::EndOfStream) => serde_json::Value::Null, Value::Primitive(Primitive::BeginningOfStream) => serde_json::Value::Null, diff --git a/src/commands/to_sqlite.rs b/src/commands/to_sqlite.rs index 4f9181ec7c..2bc7a6a675 100644 --- a/src/commands/to_sqlite.rs +++ b/src/commands/to_sqlite.rs @@ -88,6 +88,7 @@ fn nu_value_to_sqlite_string(v: Value) -> String { Value::Primitive(p) => match p { Primitive::Nothing => "NULL".into(), Primitive::Int(i) => format!("{}", i), + Primitive::Duration(u) => format!("{}", u), Primitive::Decimal(f) => format!("{}", f), Primitive::Bytes(u) => format!("{}", u), Primitive::Pattern(s) => format!("'{}'", s.replace("'", "''")), diff --git a/src/commands/to_toml.rs b/src/commands/to_toml.rs index 778fdd2561..92e2c54ea9 100644 --- a/src/commands/to_toml.rs +++ b/src/commands/to_toml.rs @@ -30,6 +30,7 @@ pub fn value_to_toml_value(v: &Tagged) -> Result Ok(match v.item() { Value::Primitive(Primitive::Boolean(b)) => toml::Value::Boolean(*b), Value::Primitive(Primitive::Bytes(b)) => toml::Value::Integer(*b as i64), + Value::Primitive(Primitive::Duration(d)) => toml::Value::Integer(*d as i64), Value::Primitive(Primitive::Date(d)) => toml::Value::String(d.to_string()), Value::Primitive(Primitive::EndOfStream) => { toml::Value::String("".to_string()) diff --git a/src/commands/to_yaml.rs b/src/commands/to_yaml.rs index 6019561d66..737ef81f86 100644 --- a/src/commands/to_yaml.rs +++ b/src/commands/to_yaml.rs @@ -32,6 +32,9 @@ pub fn value_to_yaml_value(v: &Tagged) -> Result { serde_yaml::Value::Number(serde_yaml::Number::from(b.to_f64().unwrap())) } + Value::Primitive(Primitive::Duration(secs)) => { + serde_yaml::Value::Number(serde_yaml::Number::from(secs.to_f64().unwrap())) + } Value::Primitive(Primitive::Date(d)) => serde_yaml::Value::String(d.to_string()), Value::Primitive(Primitive::EndOfStream) => serde_yaml::Value::Null, Value::Primitive(Primitive::BeginningOfStream) => serde_yaml::Value::Null, diff --git a/src/data/base.rs b/src/data/base.rs index 4baa8f1d67..f4138941fc 100644 --- a/src/data/base.rs +++ b/src/data/base.rs @@ -79,6 +79,7 @@ pub enum Primitive { Pattern(String), Boolean(bool), Date(DateTime), + Duration(u64), // Duration in seconds Path(PathBuf), #[serde(with = "serde_bytes")] Binary(Vec), @@ -111,6 +112,7 @@ impl Primitive { Path(_) => "path", Int(_) => "int", Decimal(_) => "decimal", + Duration(_) => "duration", Bytes(_) => "bytes", Pattern(_) => "pattern", String(_) => "string", @@ -131,6 +133,7 @@ impl Primitive { Int(int) => write!(f, "{}", int), Path(path) => write!(f, "{}", path.display()), Decimal(decimal) => write!(f, "{}", decimal), + Duration(secs) => write!(f, "{}", secs), Bytes(bytes) => write!(f, "{}", bytes), Pattern(string) => write!(f, "{:?}", string), String(string) => write!(f, "{:?}", string), @@ -169,6 +172,13 @@ impl Primitive { _ => format!("{}", byte.format(1)), } } + Primitive::Duration(sec) => { + if *sec == 1 { + format!("{} sec", sec) + } else { + format!("{} secs", sec) + } + } //FIXME: make nicer duration output Primitive::Int(i) => format!("{}", i), Primitive::Decimal(decimal) => format!("{}", decimal), Primitive::Pattern(s) => format!("{}", s), @@ -785,6 +795,10 @@ impl Value { Value::Primitive(Primitive::Boolean(s.into())) } + pub fn duration(secs: u64) -> Value { + Value::Primitive(Primitive::Duration(secs)) + } + pub fn system_date(s: SystemTime) -> Value { Value::Primitive(Primitive::Date(s.into())) } @@ -857,6 +871,7 @@ enum CompareValues { Decimals(BigDecimal, BigDecimal), String(String, String), Date(DateTime, DateTime), + DateDuration(DateTime, u64), } impl CompareValues { @@ -865,7 +880,14 @@ 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), + CompareValues::Date(left, right) => left.cmp(right), + CompareValues::DateDuration(left, right) => { + use std::time::Duration; + + // Create the datetime we're comparing against, as duration is an offset from now + let right: DateTime = (SystemTime::now() - Duration::from_secs(*right)).into(); + right.cmp(left) + } } } } @@ -903,6 +925,7 @@ fn coerce_compare_primitive( } (String(left), String(right)) => CompareValues::String(left.clone(), right.clone()), (Date(left), Date(right)) => CompareValues::Date(left.clone(), right.clone()), + (Date(left), Duration(right)) => CompareValues::DateDuration(left.clone(), right.clone()), _ => return Err((left.type_name(), right.type_name())), }) } diff --git a/src/parser/parse/unit.rs b/src/parser/parse/unit.rs index e98a5cdbcb..3bb263d827 100644 --- a/src/parser/parse/unit.rs +++ b/src/parser/parse/unit.rs @@ -3,8 +3,6 @@ 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 { @@ -68,31 +66,13 @@ impl Unit { 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)), - ), + Unit::Second => Value::duration(convert_number_to_u64(&size)), + Unit::Minute => Value::duration(60 * convert_number_to_u64(&size)), + Unit::Hour => Value::duration(60 * 60 * convert_number_to_u64(&size)), + Unit::Day => Value::duration(24 * 60 * 60 * convert_number_to_u64(&size)), + Unit::Week => Value::duration(7 * 24 * 60 * 60 * convert_number_to_u64(&size)), + Unit::Month => Value::duration(30 * 24 * 60 * 60 * convert_number_to_u64(&size)), + Unit::Year => Value::duration(365 * 24 * 60 * 60 * convert_number_to_u64(&size)), } } }