Add string to datetime to str plugin (#1381)

* Add string to datetime to str plugin

* Test string to date/time conversion
This commit is contained in:
Corvus Corax 2020-02-13 09:47:04 -06:00 committed by GitHub
parent 84927d52b5
commit 0961da406d
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
6 changed files with 70 additions and 20 deletions

1
Cargo.lock generated
View file

@ -2555,6 +2555,7 @@ dependencies = [
name = "nu_plugin_str"
version = "0.9.0"
dependencies = [
"chrono",
"nu-build",
"nu-errors",
"nu-plugin",

View file

@ -15,6 +15,7 @@ use crate::value::primitive::Primitive;
use crate::value::range::{Range, RangeInclusion};
use crate::{ColumnPath, PathMember};
use bigdecimal::BigDecimal;
use chrono::{DateTime, Utc};
use indexmap::IndexMap;
use nu_errors::ShellError;
use nu_source::{AnchorLocation, HasSpan, Span, Spanned, Tag};
@ -201,6 +202,10 @@ impl UntaggedValue {
UntaggedValue::Primitive(Primitive::Date(s.into()))
}
pub fn date(d: impl Into<DateTime<Utc>>) -> UntaggedValue {
UntaggedValue::Primitive(Primitive::Date(d.into()))
}
/// Helper for creating the Nothing value
pub fn nothing() -> UntaggedValue {
UntaggedValue::Primitive(Primitive::Nothing)

View file

@ -15,6 +15,7 @@ nu-protocol = { path = "../nu-protocol", version = "0.9.0" }
nu-source = { path = "../nu-source", version = "0.9.0" }
nu-errors = { path = "../nu-errors", version = "0.9.0" }
nu-value-ext = { path = "../nu-value-ext", version = "0.9.0" }
chrono = { version = "0.4.10", features = ["serde"] }
regex = "1"
num-bigint = "0.2.3"

View file

@ -36,6 +36,12 @@ impl Plugin for Str {
"convert string to portion of original, requires \"start,end\"",
Some('s'),
)
.named(
"to-date-time",
SyntaxShape::String,
"Convert string to Date/Time",
Some('D'),
)
.rest(SyntaxShape::ColumnPath, "the column(s) to convert")
.filter())
}
@ -117,6 +123,11 @@ impl Plugin for Str {
self.for_field(possible_field);
}
if let Some(dt) = args.get("to-date-time") {
let dt = dt.as_string()?;
self.for_date_time(dt);
}
match &self.error {
Some(reason) => Err(ShellError::untagged_runtime_error(format!(
"{}: {}",

View file

@ -7,7 +7,37 @@ mod integration {
unstructured_sample_record,
};
use nu_plugin::test_helpers::{expect_return_value_at, plugin, CallStub};
use nu_protocol::UntaggedValue;
use nu_protocol::{Primitive, UntaggedValue};
#[test]
fn picks_up_date_time() {
let run = plugin(&mut Str::new())
.args(
CallStub::new()
.with_named_parameter("to-date-time", string("%d.%m.%Y %H:%M %P %z"))
.create(),
)
.input(string("5.8.1994 8:00 am +0000"))
.input(string("6.9.1995 10:00 am +0000"))
.input(string("5.8.1994 20:00 pm +0000"))
.input(string("20.4.2020 8:00 am +0000"))
.setup(|_, _| {})
.test();
let ret_vals = run.unwrap();
for r in ret_vals {
let r = r
.as_ref()
.unwrap()
.raw_value()
.unwrap()
.as_primitive()
.unwrap();
match r {
Primitive::Date(_) => (),
_ => assert!(false, "failed to convert string to date"),
}
}
}
#[test]
fn picks_up_one_action_flag_only() {

View file

@ -1,3 +1,6 @@
extern crate chrono;
use chrono::DateTime;
use nu_errors::ShellError;
use nu_protocol::{did_you_mean, ColumnPath, Primitive, ShellTypeName, UntaggedValue, Value};
use nu_source::{span_for_spanned_list, Tagged};
@ -12,6 +15,7 @@ pub enum Action {
ToInteger,
Substring(usize, usize),
Replace(ReplaceAction),
ToDateTime(String),
}
#[derive(Debug, Eq, PartialEq)]
@ -70,6 +74,10 @@ impl Str {
Err(_) => UntaggedValue::string(input),
},
},
Some(Action::ToDateTime(dt)) => match DateTime::parse_from_str(input, dt) {
Ok(d) => UntaggedValue::date(d),
Err(_) => UntaggedValue::string(input),
},
None => UntaggedValue::string(input),
};
@ -89,27 +97,15 @@ impl Str {
}
pub fn for_to_int(&mut self) {
if self.permit() {
self.action = Some(Action::ToInteger);
} else {
self.log_error("can only apply one");
}
self.add_action(Action::ToInteger);
}
pub fn for_downcase(&mut self) {
if self.permit() {
self.action = Some(Action::Downcase);
} else {
self.log_error("can only apply one");
}
self.add_action(Action::Downcase);
}
pub fn for_upcase(&mut self) {
if self.permit() {
self.action = Some(Action::Upcase);
} else {
self.log_error("can only apply one");
}
self.add_action(Action::Upcase);
}
pub fn for_substring(&mut self, s: String) -> Result<(), ShellError> {
@ -130,18 +126,24 @@ impl Str {
};
if start > end {
self.log_error("End must be greater than or equal to Start");
} else if self.permit() {
self.action = Some(Action::Substring(start, end));
} else {
self.log_error("can only apply one");
self.add_action(Action::Substring(start, end));
}
Ok(())
}
pub fn for_replace(&mut self, mode: ReplaceAction) {
self.add_action(Action::Replace(mode));
}
pub fn for_date_time(&mut self, dt: String) {
self.add_action(Action::ToDateTime(dt));
}
fn add_action(&mut self, act: Action) {
if self.permit() {
self.action = Some(Action::Replace(mode));
self.action = Some(act);
} else {
self.log_error("can only apply one");
}