mirror of
https://github.com/nushell/nushell
synced 2024-12-28 14:03:09 +00:00
Use native toml datetime type in to toml
(#13018)
# Description Makes `to toml` use the `toml::value::Datetime` type, so that `to toml` serializes dates properly. # User-Facing Changes `to toml` will now encode dates differently, in a native format instead of a string. This could, in theory, break some workflows: ```Nushell # Before: ~> {datetime: 2024-05-31} | to toml | from toml | get datetime | into datetime Fri, 31 May 2024 00:00:00 +0000 (10 hours ago) # After: ~> {datetime: 2024-05-31} | to toml | from toml | get datetime | into datetime Error: nu:🐚:only_supports_this_input_type × Input type not supported. ╭─[entry #13:1:36] 1 │ {datetime: 2024-05-31} | to toml | from toml | get datetime | into datetime · ────┬──── ──────┬────── · │ ╰── only string and int input data is supported · ╰── input type: date ╰──── ``` Fix #11751
This commit is contained in:
parent
83cf212e20
commit
2d0a60ac67
1 changed files with 53 additions and 5 deletions
|
@ -1,4 +1,4 @@
|
||||||
use chrono::SecondsFormat;
|
use chrono::{DateTime, Datelike, FixedOffset, Timelike};
|
||||||
use nu_engine::command_prelude::*;
|
use nu_engine::command_prelude::*;
|
||||||
use nu_protocol::ast::PathMember;
|
use nu_protocol::ast::PathMember;
|
||||||
|
|
||||||
|
@ -49,9 +49,7 @@ fn helper(engine_state: &EngineState, v: &Value) -> Result<toml::Value, ShellErr
|
||||||
Value::Int { val, .. } => toml::Value::Integer(*val),
|
Value::Int { val, .. } => toml::Value::Integer(*val),
|
||||||
Value::Filesize { val, .. } => toml::Value::Integer(*val),
|
Value::Filesize { val, .. } => toml::Value::Integer(*val),
|
||||||
Value::Duration { val, .. } => toml::Value::String(val.to_string()),
|
Value::Duration { val, .. } => toml::Value::String(val.to_string()),
|
||||||
Value::Date { val, .. } => {
|
Value::Date { val, .. } => toml::Value::Datetime(to_toml_datetime(val)),
|
||||||
toml::Value::String(val.to_rfc3339_opts(SecondsFormat::AutoSi, false))
|
|
||||||
}
|
|
||||||
Value::Range { .. } => toml::Value::String("<Range>".to_string()),
|
Value::Range { .. } => toml::Value::String("<Range>".to_string()),
|
||||||
Value::Float { val, .. } => toml::Value::Float(*val),
|
Value::Float { val, .. } => toml::Value::Float(*val),
|
||||||
Value::String { val, .. } | Value::Glob { val, .. } => toml::Value::String(val.clone()),
|
Value::String { val, .. } | Value::Glob { val, .. } => toml::Value::String(val.clone()),
|
||||||
|
@ -157,6 +155,43 @@ fn to_toml(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Convert chrono datetime into a toml::Value datetime. The latter uses its
|
||||||
|
/// own ad-hoc datetime types, which makes this somewhat convoluted.
|
||||||
|
fn to_toml_datetime(datetime: &DateTime<FixedOffset>) -> toml::value::Datetime {
|
||||||
|
let date = toml::value::Date {
|
||||||
|
// TODO: figure out what to do with BC dates, because the toml
|
||||||
|
// crate doesn't support them. Same for large years, which
|
||||||
|
// don't fit in u16.
|
||||||
|
year: datetime.year_ce().1 as u16,
|
||||||
|
// Panic: this is safe, because chrono guarantees that the month
|
||||||
|
// value will be between 1 and 12 and the day will be between 1
|
||||||
|
// and 31
|
||||||
|
month: datetime.month() as u8,
|
||||||
|
day: datetime.day() as u8,
|
||||||
|
};
|
||||||
|
|
||||||
|
let time = toml::value::Time {
|
||||||
|
// Panic: same as before, chorono guarantees that all of the following 3
|
||||||
|
// methods return values less than 65'000
|
||||||
|
hour: datetime.hour() as u8,
|
||||||
|
minute: datetime.minute() as u8,
|
||||||
|
second: datetime.second() as u8,
|
||||||
|
nanosecond: datetime.nanosecond(),
|
||||||
|
};
|
||||||
|
|
||||||
|
let offset = toml::value::Offset::Custom {
|
||||||
|
// Panic: minute timezone offset fits into i16 (that's more than
|
||||||
|
// 1000 hours)
|
||||||
|
minutes: (-datetime.timezone().utc_minus_local() / 60) as i16,
|
||||||
|
};
|
||||||
|
|
||||||
|
toml::value::Datetime {
|
||||||
|
date: Some(date),
|
||||||
|
time: Some(time),
|
||||||
|
offset: Some(offset),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use super::*;
|
use super::*;
|
||||||
|
@ -181,7 +216,20 @@ mod tests {
|
||||||
Span::test_data(),
|
Span::test_data(),
|
||||||
);
|
);
|
||||||
|
|
||||||
let reference_date = toml::Value::String(String::from("1980-10-12T10:12:44+02:00"));
|
let reference_date = toml::Value::Datetime(toml::value::Datetime {
|
||||||
|
date: Some(toml::value::Date {
|
||||||
|
year: 1980,
|
||||||
|
month: 10,
|
||||||
|
day: 12,
|
||||||
|
}),
|
||||||
|
time: Some(toml::value::Time {
|
||||||
|
hour: 10,
|
||||||
|
minute: 12,
|
||||||
|
second: 44,
|
||||||
|
nanosecond: 0,
|
||||||
|
}),
|
||||||
|
offset: Some(toml::value::Offset::Custom { minutes: 120 }),
|
||||||
|
});
|
||||||
|
|
||||||
let result = helper(&engine_state, &test_date);
|
let result = helper(&engine_state, &test_date);
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue