forked from extern/nushell
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:
committed by
GitHub
parent
6a89b1b010
commit
e07a9e4ee7
@ -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,
|
||||
|
@ -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,
|
||||
|
@ -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("'", "''")),
|
||||
|
@ -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())
|
||||
|
@ -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,
|
||||
|
@ -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())),
|
||||
})
|
||||
|
@ -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(
|
||||
|
@ -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)))
|
||||
|
@ -168,7 +168,31 @@ fn duration_math() {
|
||||
"#
|
||||
));
|
||||
|
||||
assert_eq!(actual.out, "8:00:00:00");
|
||||
assert_eq!(actual.out, "8:00:00:00.0");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn duration_math_with_nanoseconds() {
|
||||
let actual = nu!(
|
||||
cwd: "tests/fixtures/formats", pipeline(
|
||||
r#"
|
||||
= 1w + 10ns
|
||||
"#
|
||||
));
|
||||
|
||||
assert_eq!(actual.out, "7:00:00:00.00000001");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn duration_math_with_negative() {
|
||||
let actual = nu!(
|
||||
cwd: "tests/fixtures/formats", pipeline(
|
||||
r#"
|
||||
= 1d - 1w
|
||||
"#
|
||||
));
|
||||
|
||||
assert_eq!(actual.out, "-6:00:00:00.0");
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
Reference in New Issue
Block a user