1747 add ns to duration (#2128)

* Added nanos to Duration

* Removed unwraps

* Added nanos to Duration

* Removed unwraps

* Fixed errors

* Removed unwraps

* Changed serialization to String

* Fixed Date and Duration comparison
This commit is contained in:
Pierre-André Gagnon
2020-07-10 13:48:11 -04:00
committed by GitHub
parent 6a89b1b010
commit e07a9e4ee7
18 changed files with 263 additions and 98 deletions

View File

@ -46,7 +46,7 @@ pub fn value_to_bson_value(v: &Value) -> Result<Bson, ShellError> {
.to_f64()
.expect("Unimplemented BUG: What about big decimals?"),
),
UntaggedValue::Primitive(Primitive::Duration(secs)) => Bson::I64(*secs as i64),
UntaggedValue::Primitive(Primitive::Duration(i)) => Bson::String(i.to_string()),
UntaggedValue::Primitive(Primitive::Date(d)) => Bson::UtcDatetime(*d),
UntaggedValue::Primitive(Primitive::EndOfStream) => Bson::Null,
UntaggedValue::Primitive(Primitive::BeginningOfStream) => Bson::Null,

View File

@ -65,8 +65,8 @@ pub fn value_to_json_value(v: &Value) -> Result<serde_json::Value, ShellError> {
UntaggedValue::Primitive(Primitive::Bytes(b)) => serde_json::Value::Number(
serde_json::Number::from(b.to_u64().expect("What about really big numbers")),
),
UntaggedValue::Primitive(Primitive::Duration(secs)) => {
serde_json::Value::Number(serde_json::Number::from(*secs))
UntaggedValue::Primitive(Primitive::Duration(i)) => {
serde_json::Value::String(i.to_string())
}
UntaggedValue::Primitive(Primitive::Date(d)) => serde_json::Value::String(d.to_string()),
UntaggedValue::Primitive(Primitive::EndOfStream) => serde_json::Value::Null,

View File

@ -91,7 +91,7 @@ fn nu_value_to_sqlite_string(v: Value) -> String {
UntaggedValue::Primitive(p) => match p {
Primitive::Nothing => "NULL".into(),
Primitive::Int(i) => format!("{}", i),
Primitive::Duration(u) => format!("{}", u),
Primitive::Duration(i) => format!("{}", i),
Primitive::Decimal(f) => format!("{}", f),
Primitive::Bytes(u) => format!("{}", u),
Primitive::Pattern(s) => format!("'{}'", s.replace("'", "''")),

View File

@ -45,7 +45,7 @@ fn helper(v: &Value) -> Result<toml::Value, ShellError> {
Ok(match &v.value {
UntaggedValue::Primitive(Primitive::Boolean(b)) => toml::Value::Boolean(*b),
UntaggedValue::Primitive(Primitive::Bytes(b)) => toml::Value::Integer(*b as i64),
UntaggedValue::Primitive(Primitive::Duration(d)) => toml::Value::Integer(*d as i64),
UntaggedValue::Primitive(Primitive::Duration(i)) => toml::Value::String(i.to_string()),
UntaggedValue::Primitive(Primitive::Date(d)) => toml::Value::String(d.to_string()),
UntaggedValue::Primitive(Primitive::EndOfStream) => {
toml::Value::String("<End of Stream>".to_string())

View File

@ -40,15 +40,9 @@ pub fn value_to_yaml_value(v: &Value) -> Result<serde_yaml::Value, ShellError> {
)
})?))
}
UntaggedValue::Primitive(Primitive::Duration(secs)) => serde_yaml::Value::Number(
serde_yaml::Number::from(secs.to_f64().ok_or_else(|| {
ShellError::labeled_error(
"Could not convert to duration",
"could not convert to duration",
&v.tag,
)
})?),
),
UntaggedValue::Primitive(Primitive::Duration(i)) => {
serde_yaml::Value::String(i.to_string())
}
UntaggedValue::Primitive(Primitive::Date(d)) => serde_yaml::Value::String(d.to_string()),
UntaggedValue::Primitive(Primitive::EndOfStream) => serde_yaml::Value::Null,
UntaggedValue::Primitive(Primitive::BeginningOfStream) => serde_yaml::Value::Null,

View File

@ -7,13 +7,12 @@ use nu_errors::ShellError;
use nu_protocol::{
hir, Primitive, ShellTypeName, SpannedTypeName, TaggedDictBuilder, UntaggedValue, Value,
};
use nu_source::Tag;
use nu_source::{Span, Tag};
use nu_value_ext::ValueExt;
use num_bigint::BigInt;
use num_traits::Zero;
use query_interface::{interfaces, vtable_for, ObjectHash};
use serde::{Deserialize, Serialize};
use std::time::SystemTime;
#[derive(Debug, Ord, PartialOrd, Eq, PartialEq, Clone, new, Serialize)]
pub struct Operation {
@ -87,7 +86,7 @@ pub(crate) enum CompareValues {
Decimals(BigDecimal, BigDecimal),
String(String, String),
Date(DateTime<Utc>, DateTime<Utc>),
DateDuration(DateTime<Utc>, i64),
DateDuration(DateTime<Utc>, BigInt),
Booleans(bool, bool),
}
@ -99,14 +98,15 @@ impl CompareValues {
CompareValues::String(left, right) => left.cmp(right),
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<Utc> = if *right < 0 {
(SystemTime::now() + Duration::from_secs((*right * -1) as u64)).into()
} else {
(SystemTime::now() - Duration::from_secs(*right as u64)).into()
};
// FIXME: Not sure if I could do something better with the Span.
let duration = Primitive::into_chrono_duration(
Primitive::Duration(right.clone()),
Span::unknown(),
)
.expect("Could not convert nushell Duration into chrono Duration.");
let right: DateTime<Utc> = Utc::now()
.checked_sub_signed(duration)
.expect("Data overflow");
right.cmp(left)
}
CompareValues::Booleans(left, right) => left.cmp(right),
@ -159,7 +159,7 @@ fn coerce_compare_primitive(
(String(left), Line(right)) => CompareValues::String(left.clone(), right.clone()),
(Line(left), Line(right)) => CompareValues::String(left.clone(), right.clone()),
(Date(left), Date(right)) => CompareValues::Date(*left, *right),
(Date(left), Duration(right)) => CompareValues::DateDuration(*left, *right),
(Date(left), Duration(right)) => CompareValues::DateDuration(*left, right.clone()),
(Boolean(left), Boolean(right)) => CompareValues::Booleans(*left, *right),
_ => return Err((left.type_name(), right.type_name())),
})

View File

@ -27,7 +27,7 @@ pub enum InlineShape {
Pattern(String),
Boolean(bool),
Date(DateTime<Utc>),
Duration(i64),
Duration(BigInt),
Path(PathBuf),
Binary(usize),
@ -71,7 +71,7 @@ impl InlineShape {
Primitive::Pattern(pattern) => InlineShape::Pattern(pattern.clone()),
Primitive::Boolean(boolean) => InlineShape::Boolean(*boolean),
Primitive::Date(date) => InlineShape::Date(*date),
Primitive::Duration(duration) => InlineShape::Duration(*duration),
Primitive::Duration(duration) => InlineShape::Duration(duration.clone()),
Primitive::Path(path) => InlineShape::Path(path.clone()),
Primitive::Binary(b) => InlineShape::Binary(b.len()),
Primitive::BeginningOfStream => InlineShape::BeginningOfStream,
@ -178,9 +178,10 @@ impl PrettyDebug for FormatInlineShape {
.to_owned(),
),
InlineShape::Date(date) => b::primitive(nu_protocol::format_date(date)),
InlineShape::Duration(duration) => {
b::description(format_primitive(&Primitive::Duration(*duration), None))
}
InlineShape::Duration(duration) => b::description(format_primitive(
&Primitive::Duration(duration.clone()),
None,
)),
InlineShape::Path(path) => b::primitive(path.display()),
InlineShape::Binary(length) => b::opaque(format!("<binary: {} bytes>", length)),
InlineShape::Row(row) => b::delimit(

View File

@ -6,7 +6,7 @@ use nu_errors::ShellError;
use nu_protocol::hir::Operator;
use nu_protocol::ShellTypeName;
use nu_protocol::{Primitive, Type, UntaggedValue};
use nu_source::{DebugDocBuilder, PrettyDebug, Tagged};
use nu_source::{DebugDocBuilder, PrettyDebug, Span, Tagged};
use nu_table::TextStyle;
use num_traits::Zero;
@ -118,18 +118,20 @@ pub fn compute_values(
}?;
Ok(UntaggedValue::Primitive(Primitive::Decimal(result)))
}
(Primitive::Date(x), Primitive::Date(y)) => {
(Primitive::Date(x), Primitive::Date(y)) => match operator {
Operator::Minus => Ok(UntaggedValue::Primitive(Primitive::from(
x.signed_duration_since(*y),
))),
_ => Err((left.type_name(), right.type_name())),
},
(Primitive::Date(x), Primitive::Duration(_)) => {
let result = match operator {
Operator::Minus => Ok(x.signed_duration_since(*y).num_seconds()),
_ => Err((left.type_name(), right.type_name())),
}?;
Ok(UntaggedValue::Primitive(Primitive::Duration(result)))
}
(Primitive::Date(x), Primitive::Duration(y)) => {
let result = match operator {
Operator::Plus => Ok(x
.checked_add_signed(chrono::Duration::seconds(*y as i64))
.expect("Overflowing add of duration")),
Operator::Plus => {
// FIXME: Not sure if I could do something better with the Span.
let y = Primitive::into_chrono_duration(rhs.clone(), Span::unknown())
.expect("Could not convert nushell Duration into chrono Duration.");
Ok(x.checked_add_signed(y).expect("Data overflow."))
}
_ => Err((left.type_name(), right.type_name())),
}?;
Ok(UntaggedValue::Primitive(Primitive::Date(result)))