2022-02-28 01:21:46 +00:00
|
|
|
use crate::date::utils::parse_date_from_string;
|
2021-10-31 06:54:51 +00:00
|
|
|
use chrono::{DateTime, Datelike, FixedOffset, Local, Timelike};
|
|
|
|
use nu_protocol::ast::Call;
|
|
|
|
use nu_protocol::engine::{Command, EngineState, Stack};
|
2022-02-28 01:21:46 +00:00
|
|
|
use nu_protocol::{
|
Standardise the use of ShellError::UnsupportedInput and ShellError::TypeMismatch and add spans to every instance of the former (#7217)
# Description
* I was dismayed to discover recently that UnsupportedInput and
TypeMismatch are used *extremely* inconsistently across the codebase.
UnsupportedInput is sometimes used for input type-checks (as per the
name!!), but *also* used for argument type-checks. TypeMismatch is also
used for both.
I thus devised the following standard: input type-checking *only* uses
UnsupportedInput, and argument type-checking *only* uses TypeMismatch.
Moreover, to differentiate them, UnsupportedInput now has *two* error
arrows (spans), one pointing at the command and the other at the input
origin, while TypeMismatch only has the one (because the command should
always be nearby)
* In order to apply that standard, a very large number of
UnsupportedInput uses were changed so that the input's span could be
retrieved and delivered to it.
* Additionally, I noticed many places where **errors are not propagated
correctly**: there are lots of `match` sites which take a Value::Error,
then throw it away and replace it with a new Value::Error with
less/misleading information (such as reporting the error as an
"incorrect type"). I believe that the earliest errors are the most
important, and should always be propagated where possible.
* Also, to standardise one broad subset of UnsupportedInput error
messages, who all used slightly different wordings of "expected
`<type>`, got `<type>`", I created OnlySupportsThisInputType as a
variant of it.
* Finally, a bunch of error sites that had "repeated spans" - i.e. where
an error expected two spans, but `call.head` was given for both - were
fixed to use different spans.
# Example
BEFORE
```
〉20b | str starts-with 'a'
Error: nu::shell::unsupported_input (link)
× Unsupported input
╭─[entry #31:1:1]
1 │ 20b | str starts-with 'a'
· ┬
· ╰── Input's type is filesize. This command only works with strings.
╰────
〉'a' | math cos
Error: nu::shell::unsupported_input (link)
× Unsupported input
╭─[entry #33:1:1]
1 │ 'a' | math cos
· ─┬─
· ╰── Only numerical values are supported, input type: String
╰────
〉0x[12] | encode utf8
Error: nu::shell::unsupported_input (link)
× Unsupported input
╭─[entry #38:1:1]
1 │ 0x[12] | encode utf8
· ───┬──
· ╰── non-string input
╰────
```
AFTER
```
〉20b | str starts-with 'a'
Error: nu::shell::pipeline_mismatch (link)
× Pipeline mismatch.
╭─[entry #1:1:1]
1 │ 20b | str starts-with 'a'
· ┬ ───────┬───────
· │ ╰── only string input data is supported
· ╰── input type: filesize
╰────
〉'a' | math cos
Error: nu::shell::pipeline_mismatch (link)
× Pipeline mismatch.
╭─[entry #2:1:1]
1 │ 'a' | math cos
· ─┬─ ────┬───
· │ ╰── only numeric input data is supported
· ╰── input type: string
╰────
〉0x[12] | encode utf8
Error: nu::shell::pipeline_mismatch (link)
× Pipeline mismatch.
╭─[entry #3:1:1]
1 │ 0x[12] | encode utf8
· ───┬── ───┬──
· │ ╰── only string input data is supported
· ╰── input type: binary
╰────
```
# User-Facing Changes
Various error messages suddenly make more sense (i.e. have two arrows
instead of one).
# Tests + Formatting
Don't forget to add tests that cover your changes.
Make sure you've run and fixed any issues with these commands:
- `cargo fmt --all -- --check` to check standard code formatting (`cargo
fmt --all` applies these changes)
- `cargo clippy --workspace -- -D warnings -D clippy::unwrap_used -A
clippy::needless_collect` to check that you're using the standard code
style
- `cargo test --workspace` to check that all tests pass
# After Submitting
If your PR had any user-facing changes, update [the
documentation](https://github.com/nushell/nushell.github.io) after the
PR is merged, if necessary. This will help us keep the docs up to date.
2022-12-23 06:48:53 +00:00
|
|
|
Category, Example, PipelineData, ShellError::DatetimeParseError, ShellError::PipelineEmpty,
|
|
|
|
Signature, Span, Value,
|
2022-02-28 01:21:46 +00:00
|
|
|
};
|
2023-02-05 21:17:46 +00:00
|
|
|
use nu_protocol::{ShellError, Type};
|
2021-10-31 06:54:51 +00:00
|
|
|
|
|
|
|
#[derive(Clone)]
|
|
|
|
pub struct SubCommand;
|
|
|
|
|
|
|
|
impl Command for SubCommand {
|
|
|
|
fn name(&self) -> &str {
|
|
|
|
"date to-table"
|
|
|
|
}
|
|
|
|
|
|
|
|
fn signature(&self) -> Signature {
|
2022-11-09 21:55:05 +00:00
|
|
|
Signature::build("date to-table")
|
|
|
|
.input_output_types(vec![
|
|
|
|
(Type::Date, Type::Table(vec![])),
|
|
|
|
(Type::String, Type::Table(vec![])),
|
|
|
|
])
|
|
|
|
.allow_variants_without_examples(true) // https://github.com/nushell/nushell/issues/7032
|
|
|
|
.category(Category::Date)
|
2021-10-31 06:54:51 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
fn usage(&self) -> &str {
|
2022-04-01 08:09:30 +00:00
|
|
|
"Convert the date into a structured table."
|
2021-10-31 06:54:51 +00:00
|
|
|
}
|
|
|
|
|
2022-04-23 13:54:03 +00:00
|
|
|
fn search_terms(&self) -> Vec<&str> {
|
2022-08-24 09:16:47 +00:00
|
|
|
vec!["structured"]
|
2022-04-23 13:54:03 +00:00
|
|
|
}
|
|
|
|
|
2021-10-31 06:54:51 +00:00
|
|
|
fn run(
|
|
|
|
&self,
|
|
|
|
engine_state: &EngineState,
|
|
|
|
_stack: &mut Stack,
|
|
|
|
call: &Call,
|
|
|
|
input: PipelineData,
|
2023-02-05 21:17:46 +00:00
|
|
|
) -> Result<PipelineData, ShellError> {
|
2021-10-31 06:54:51 +00:00
|
|
|
let head = call.head;
|
Standardise the use of ShellError::UnsupportedInput and ShellError::TypeMismatch and add spans to every instance of the former (#7217)
# Description
* I was dismayed to discover recently that UnsupportedInput and
TypeMismatch are used *extremely* inconsistently across the codebase.
UnsupportedInput is sometimes used for input type-checks (as per the
name!!), but *also* used for argument type-checks. TypeMismatch is also
used for both.
I thus devised the following standard: input type-checking *only* uses
UnsupportedInput, and argument type-checking *only* uses TypeMismatch.
Moreover, to differentiate them, UnsupportedInput now has *two* error
arrows (spans), one pointing at the command and the other at the input
origin, while TypeMismatch only has the one (because the command should
always be nearby)
* In order to apply that standard, a very large number of
UnsupportedInput uses were changed so that the input's span could be
retrieved and delivered to it.
* Additionally, I noticed many places where **errors are not propagated
correctly**: there are lots of `match` sites which take a Value::Error,
then throw it away and replace it with a new Value::Error with
less/misleading information (such as reporting the error as an
"incorrect type"). I believe that the earliest errors are the most
important, and should always be propagated where possible.
* Also, to standardise one broad subset of UnsupportedInput error
messages, who all used slightly different wordings of "expected
`<type>`, got `<type>`", I created OnlySupportsThisInputType as a
variant of it.
* Finally, a bunch of error sites that had "repeated spans" - i.e. where
an error expected two spans, but `call.head` was given for both - were
fixed to use different spans.
# Example
BEFORE
```
〉20b | str starts-with 'a'
Error: nu::shell::unsupported_input (link)
× Unsupported input
╭─[entry #31:1:1]
1 │ 20b | str starts-with 'a'
· ┬
· ╰── Input's type is filesize. This command only works with strings.
╰────
〉'a' | math cos
Error: nu::shell::unsupported_input (link)
× Unsupported input
╭─[entry #33:1:1]
1 │ 'a' | math cos
· ─┬─
· ╰── Only numerical values are supported, input type: String
╰────
〉0x[12] | encode utf8
Error: nu::shell::unsupported_input (link)
× Unsupported input
╭─[entry #38:1:1]
1 │ 0x[12] | encode utf8
· ───┬──
· ╰── non-string input
╰────
```
AFTER
```
〉20b | str starts-with 'a'
Error: nu::shell::pipeline_mismatch (link)
× Pipeline mismatch.
╭─[entry #1:1:1]
1 │ 20b | str starts-with 'a'
· ┬ ───────┬───────
· │ ╰── only string input data is supported
· ╰── input type: filesize
╰────
〉'a' | math cos
Error: nu::shell::pipeline_mismatch (link)
× Pipeline mismatch.
╭─[entry #2:1:1]
1 │ 'a' | math cos
· ─┬─ ────┬───
· │ ╰── only numeric input data is supported
· ╰── input type: string
╰────
〉0x[12] | encode utf8
Error: nu::shell::pipeline_mismatch (link)
× Pipeline mismatch.
╭─[entry #3:1:1]
1 │ 0x[12] | encode utf8
· ───┬── ───┬──
· │ ╰── only string input data is supported
· ╰── input type: binary
╰────
```
# User-Facing Changes
Various error messages suddenly make more sense (i.e. have two arrows
instead of one).
# Tests + Formatting
Don't forget to add tests that cover your changes.
Make sure you've run and fixed any issues with these commands:
- `cargo fmt --all -- --check` to check standard code formatting (`cargo
fmt --all` applies these changes)
- `cargo clippy --workspace -- -D warnings -D clippy::unwrap_used -A
clippy::needless_collect` to check that you're using the standard code
style
- `cargo test --workspace` to check that all tests pass
# After Submitting
If your PR had any user-facing changes, update [the
documentation](https://github.com/nushell/nushell.github.io) after the
PR is merged, if necessary. This will help us keep the docs up to date.
2022-12-23 06:48:53 +00:00
|
|
|
// This doesn't match explicit nulls
|
|
|
|
if matches!(input, PipelineData::Empty) {
|
2023-03-01 19:34:48 +00:00
|
|
|
return Err(PipelineEmpty { dst_span: head });
|
Standardise the use of ShellError::UnsupportedInput and ShellError::TypeMismatch and add spans to every instance of the former (#7217)
# Description
* I was dismayed to discover recently that UnsupportedInput and
TypeMismatch are used *extremely* inconsistently across the codebase.
UnsupportedInput is sometimes used for input type-checks (as per the
name!!), but *also* used for argument type-checks. TypeMismatch is also
used for both.
I thus devised the following standard: input type-checking *only* uses
UnsupportedInput, and argument type-checking *only* uses TypeMismatch.
Moreover, to differentiate them, UnsupportedInput now has *two* error
arrows (spans), one pointing at the command and the other at the input
origin, while TypeMismatch only has the one (because the command should
always be nearby)
* In order to apply that standard, a very large number of
UnsupportedInput uses were changed so that the input's span could be
retrieved and delivered to it.
* Additionally, I noticed many places where **errors are not propagated
correctly**: there are lots of `match` sites which take a Value::Error,
then throw it away and replace it with a new Value::Error with
less/misleading information (such as reporting the error as an
"incorrect type"). I believe that the earliest errors are the most
important, and should always be propagated where possible.
* Also, to standardise one broad subset of UnsupportedInput error
messages, who all used slightly different wordings of "expected
`<type>`, got `<type>`", I created OnlySupportsThisInputType as a
variant of it.
* Finally, a bunch of error sites that had "repeated spans" - i.e. where
an error expected two spans, but `call.head` was given for both - were
fixed to use different spans.
# Example
BEFORE
```
〉20b | str starts-with 'a'
Error: nu::shell::unsupported_input (link)
× Unsupported input
╭─[entry #31:1:1]
1 │ 20b | str starts-with 'a'
· ┬
· ╰── Input's type is filesize. This command only works with strings.
╰────
〉'a' | math cos
Error: nu::shell::unsupported_input (link)
× Unsupported input
╭─[entry #33:1:1]
1 │ 'a' | math cos
· ─┬─
· ╰── Only numerical values are supported, input type: String
╰────
〉0x[12] | encode utf8
Error: nu::shell::unsupported_input (link)
× Unsupported input
╭─[entry #38:1:1]
1 │ 0x[12] | encode utf8
· ───┬──
· ╰── non-string input
╰────
```
AFTER
```
〉20b | str starts-with 'a'
Error: nu::shell::pipeline_mismatch (link)
× Pipeline mismatch.
╭─[entry #1:1:1]
1 │ 20b | str starts-with 'a'
· ┬ ───────┬───────
· │ ╰── only string input data is supported
· ╰── input type: filesize
╰────
〉'a' | math cos
Error: nu::shell::pipeline_mismatch (link)
× Pipeline mismatch.
╭─[entry #2:1:1]
1 │ 'a' | math cos
· ─┬─ ────┬───
· │ ╰── only numeric input data is supported
· ╰── input type: string
╰────
〉0x[12] | encode utf8
Error: nu::shell::pipeline_mismatch (link)
× Pipeline mismatch.
╭─[entry #3:1:1]
1 │ 0x[12] | encode utf8
· ───┬── ───┬──
· │ ╰── only string input data is supported
· ╰── input type: binary
╰────
```
# User-Facing Changes
Various error messages suddenly make more sense (i.e. have two arrows
instead of one).
# Tests + Formatting
Don't forget to add tests that cover your changes.
Make sure you've run and fixed any issues with these commands:
- `cargo fmt --all -- --check` to check standard code formatting (`cargo
fmt --all` applies these changes)
- `cargo clippy --workspace -- -D warnings -D clippy::unwrap_used -A
clippy::needless_collect` to check that you're using the standard code
style
- `cargo test --workspace` to check that all tests pass
# After Submitting
If your PR had any user-facing changes, update [the
documentation](https://github.com/nushell/nushell.github.io) after the
PR is merged, if necessary. This will help us keep the docs up to date.
2022-12-23 06:48:53 +00:00
|
|
|
}
|
2021-10-31 06:54:51 +00:00
|
|
|
input.map(move |value| helper(value, head), engine_state.ctrlc.clone())
|
|
|
|
}
|
|
|
|
|
|
|
|
fn examples(&self) -> Vec<Example> {
|
2022-11-09 21:55:05 +00:00
|
|
|
let example_result_1 = || {
|
|
|
|
let span = Span::test_data();
|
|
|
|
let cols = vec![
|
|
|
|
"year".into(),
|
|
|
|
"month".into(),
|
|
|
|
"day".into(),
|
|
|
|
"hour".into(),
|
|
|
|
"minute".into(),
|
|
|
|
"second".into(),
|
Fix 8244 -- store timestamps with nanosecond resolution (consistently) (#8337)
# Description
Fix for data ambiguity noted in #8244.
Basic change is to use nanosecond resolution for unix timestamps (stored
in type Int). Previously, a timestamp might have seconds, milliseconds
or nanoseconds, but it turned out there were overlaps in data ranges
between different resolutions, so there wasn't always a unique mapping
back to date/time.
Due to higher precision, the *range* of dates that timestamps can map to
is restricted. Unix timestamps with seconds resolution and 64 bit
storage can cover all dates from the Big Bang to eternity. Timestamps
with seconds resolution and 32 bit storage can only represent dates from
1901-12-13 through 2038-01-19. The nanoseconds resolution and 64 bit
storage used with this fix can represent dates from 1677-09-21T00:12:44
to 2262-04-11T23:47:16, something of a compromise.
# User-Facing Changes
_(List of all changes that impact the user experience here. This helps
us keep track of breaking changes.)_
## `<datetime> | into int`
Converts to nanosecond resolution
```rust
〉date now | into int
1678084730502126846
```
This is the number of non-leap nanoseconds after the unix epoch date:
1970-01-01T00:00:00+00:00.
Conversion fails for dates outside the supported range:
```rust
〉1492-10-12 | into int
Error: nu::shell::incorrect_value
× Incorrect value.
╭─[entry #51:1:1]
1 │ 1492-10-12 | into int
· ────┬───
· ╰── DateTime out of timestamp range 1677-09-21T00:12:43 and 2262-04-11T23:47:16
╰────
```
## `<int> | into datetime`
Can no longer fail or produce incorrect results for any 64-bit input:
```rust
〉0 | into datetime
Thu, 01 Jan 1970 00:00:00 +0000 (53 years ago)
〉"7fffffffffffffff" | into int -r 16 | into datetime
Fri, 11 Apr 2262 23:47:16 +0000 (in 239 years)
〉("7fffffffffffffff" | into int -r 16) * -1 | into datetime
Tue, 21 Sep 1677 00:12:43 +0000 (345 years ago)
```
## `<date> | date to-record` and `<date> | date to-table`
Now both have a `nanosecond` field.
```rust
〉"7fffffffffffffff" | into int -r 16 | into datetime | date to-record
╭────────────┬───────────╮
│ year │ 2262 │
│ month │ 4 │
│ day │ 11 │
│ hour │ 23 │
│ minute │ 47 │
│ second │ 16 │
│ nanosecond │ 854775807 │
│ timezone │ +00:00 │
╰────────────┴───────────╯
〉"7fffffffffffffff" | into int -r 16 | into datetime | date to-table
╭───┬──────┬───────┬─────┬──────┬────────┬────────┬────────────┬──────────╮
│ # │ year │ month │ day │ hour │ minute │ second │ nanosecond │ timezone │
├───┼──────┼───────┼─────┼──────┼────────┼────────┼────────────┼──────────┤
│ 0 │ 2262 │ 4 │ 11 │ 23 │ 47 │ 16 │ 854775807 │ +00:00 │
╰───┴──────┴───────┴─────┴──────┴────────┴────────┴────────────┴──────────╯
```
This change was not mandated by the OP problem, but it is nice to be
able to see the nanosecond bits that were present in Nushell `date` type
all along.
# Tests + Formatting
Don't forget to add tests that cover your changes.
Make sure you've run and fixed any issues with these commands:
- `cargo fmt --all -- --check` to check standard code formatting (`cargo
fmt --all` applies these changes)
- `cargo clippy --workspace -- -D warnings -D clippy::unwrap_used -A
clippy::needless_collect` to check that you're using the standard code
style
- `cargo test --workspace` to check that all tests pass
# After Submitting
If your PR had any user-facing changes, update [the
documentation](https://github.com/nushell/nushell.github.io) after the
PR is merged, if necessary. This will help us keep the docs up to date.
2023-03-07 23:02:15 +00:00
|
|
|
"nanosecond".into(),
|
2022-11-09 21:55:05 +00:00
|
|
|
"timezone".into(),
|
|
|
|
];
|
|
|
|
let vals = vec![
|
|
|
|
Value::Int { val: 2020, span },
|
|
|
|
Value::Int { val: 4, span },
|
|
|
|
Value::Int { val: 12, span },
|
|
|
|
Value::Int { val: 22, span },
|
|
|
|
Value::Int { val: 10, span },
|
|
|
|
Value::Int { val: 57, span },
|
Fix 8244 -- store timestamps with nanosecond resolution (consistently) (#8337)
# Description
Fix for data ambiguity noted in #8244.
Basic change is to use nanosecond resolution for unix timestamps (stored
in type Int). Previously, a timestamp might have seconds, milliseconds
or nanoseconds, but it turned out there were overlaps in data ranges
between different resolutions, so there wasn't always a unique mapping
back to date/time.
Due to higher precision, the *range* of dates that timestamps can map to
is restricted. Unix timestamps with seconds resolution and 64 bit
storage can cover all dates from the Big Bang to eternity. Timestamps
with seconds resolution and 32 bit storage can only represent dates from
1901-12-13 through 2038-01-19. The nanoseconds resolution and 64 bit
storage used with this fix can represent dates from 1677-09-21T00:12:44
to 2262-04-11T23:47:16, something of a compromise.
# User-Facing Changes
_(List of all changes that impact the user experience here. This helps
us keep track of breaking changes.)_
## `<datetime> | into int`
Converts to nanosecond resolution
```rust
〉date now | into int
1678084730502126846
```
This is the number of non-leap nanoseconds after the unix epoch date:
1970-01-01T00:00:00+00:00.
Conversion fails for dates outside the supported range:
```rust
〉1492-10-12 | into int
Error: nu::shell::incorrect_value
× Incorrect value.
╭─[entry #51:1:1]
1 │ 1492-10-12 | into int
· ────┬───
· ╰── DateTime out of timestamp range 1677-09-21T00:12:43 and 2262-04-11T23:47:16
╰────
```
## `<int> | into datetime`
Can no longer fail or produce incorrect results for any 64-bit input:
```rust
〉0 | into datetime
Thu, 01 Jan 1970 00:00:00 +0000 (53 years ago)
〉"7fffffffffffffff" | into int -r 16 | into datetime
Fri, 11 Apr 2262 23:47:16 +0000 (in 239 years)
〉("7fffffffffffffff" | into int -r 16) * -1 | into datetime
Tue, 21 Sep 1677 00:12:43 +0000 (345 years ago)
```
## `<date> | date to-record` and `<date> | date to-table`
Now both have a `nanosecond` field.
```rust
〉"7fffffffffffffff" | into int -r 16 | into datetime | date to-record
╭────────────┬───────────╮
│ year │ 2262 │
│ month │ 4 │
│ day │ 11 │
│ hour │ 23 │
│ minute │ 47 │
│ second │ 16 │
│ nanosecond │ 854775807 │
│ timezone │ +00:00 │
╰────────────┴───────────╯
〉"7fffffffffffffff" | into int -r 16 | into datetime | date to-table
╭───┬──────┬───────┬─────┬──────┬────────┬────────┬────────────┬──────────╮
│ # │ year │ month │ day │ hour │ minute │ second │ nanosecond │ timezone │
├───┼──────┼───────┼─────┼──────┼────────┼────────┼────────────┼──────────┤
│ 0 │ 2262 │ 4 │ 11 │ 23 │ 47 │ 16 │ 854775807 │ +00:00 │
╰───┴──────┴───────┴─────┴──────┴────────┴────────┴────────────┴──────────╯
```
This change was not mandated by the OP problem, but it is nice to be
able to see the nanosecond bits that were present in Nushell `date` type
all along.
# Tests + Formatting
Don't forget to add tests that cover your changes.
Make sure you've run and fixed any issues with these commands:
- `cargo fmt --all -- --check` to check standard code formatting (`cargo
fmt --all` applies these changes)
- `cargo clippy --workspace -- -D warnings -D clippy::unwrap_used -A
clippy::needless_collect` to check that you're using the standard code
style
- `cargo test --workspace` to check that all tests pass
# After Submitting
If your PR had any user-facing changes, update [the
documentation](https://github.com/nushell/nushell.github.io) after the
PR is merged, if necessary. This will help us keep the docs up to date.
2023-03-07 23:02:15 +00:00
|
|
|
Value::Int { val: 789, span },
|
2022-11-09 21:55:05 +00:00
|
|
|
Value::String {
|
|
|
|
val: "+02:00".to_string(),
|
|
|
|
span,
|
|
|
|
},
|
|
|
|
];
|
|
|
|
Some(Value::List {
|
|
|
|
vals: vec![Value::Record { cols, vals, span }],
|
|
|
|
span,
|
|
|
|
})
|
|
|
|
};
|
|
|
|
|
2021-10-31 06:54:51 +00:00
|
|
|
vec![
|
|
|
|
Example {
|
2022-11-09 21:55:05 +00:00
|
|
|
description: "Convert the current date into a table.",
|
2021-10-31 06:54:51 +00:00
|
|
|
example: "date to-table",
|
|
|
|
result: None,
|
|
|
|
},
|
|
|
|
Example {
|
2022-11-09 21:55:05 +00:00
|
|
|
description: "Convert the date into a table.",
|
2021-10-31 06:54:51 +00:00
|
|
|
example: "date now | date to-table",
|
|
|
|
result: None,
|
|
|
|
},
|
|
|
|
Example {
|
2022-11-09 21:55:05 +00:00
|
|
|
description: "Convert a given date into a table.",
|
Fix 8244 -- store timestamps with nanosecond resolution (consistently) (#8337)
# Description
Fix for data ambiguity noted in #8244.
Basic change is to use nanosecond resolution for unix timestamps (stored
in type Int). Previously, a timestamp might have seconds, milliseconds
or nanoseconds, but it turned out there were overlaps in data ranges
between different resolutions, so there wasn't always a unique mapping
back to date/time.
Due to higher precision, the *range* of dates that timestamps can map to
is restricted. Unix timestamps with seconds resolution and 64 bit
storage can cover all dates from the Big Bang to eternity. Timestamps
with seconds resolution and 32 bit storage can only represent dates from
1901-12-13 through 2038-01-19. The nanoseconds resolution and 64 bit
storage used with this fix can represent dates from 1677-09-21T00:12:44
to 2262-04-11T23:47:16, something of a compromise.
# User-Facing Changes
_(List of all changes that impact the user experience here. This helps
us keep track of breaking changes.)_
## `<datetime> | into int`
Converts to nanosecond resolution
```rust
〉date now | into int
1678084730502126846
```
This is the number of non-leap nanoseconds after the unix epoch date:
1970-01-01T00:00:00+00:00.
Conversion fails for dates outside the supported range:
```rust
〉1492-10-12 | into int
Error: nu::shell::incorrect_value
× Incorrect value.
╭─[entry #51:1:1]
1 │ 1492-10-12 | into int
· ────┬───
· ╰── DateTime out of timestamp range 1677-09-21T00:12:43 and 2262-04-11T23:47:16
╰────
```
## `<int> | into datetime`
Can no longer fail or produce incorrect results for any 64-bit input:
```rust
〉0 | into datetime
Thu, 01 Jan 1970 00:00:00 +0000 (53 years ago)
〉"7fffffffffffffff" | into int -r 16 | into datetime
Fri, 11 Apr 2262 23:47:16 +0000 (in 239 years)
〉("7fffffffffffffff" | into int -r 16) * -1 | into datetime
Tue, 21 Sep 1677 00:12:43 +0000 (345 years ago)
```
## `<date> | date to-record` and `<date> | date to-table`
Now both have a `nanosecond` field.
```rust
〉"7fffffffffffffff" | into int -r 16 | into datetime | date to-record
╭────────────┬───────────╮
│ year │ 2262 │
│ month │ 4 │
│ day │ 11 │
│ hour │ 23 │
│ minute │ 47 │
│ second │ 16 │
│ nanosecond │ 854775807 │
│ timezone │ +00:00 │
╰────────────┴───────────╯
〉"7fffffffffffffff" | into int -r 16 | into datetime | date to-table
╭───┬──────┬───────┬─────┬──────┬────────┬────────┬────────────┬──────────╮
│ # │ year │ month │ day │ hour │ minute │ second │ nanosecond │ timezone │
├───┼──────┼───────┼─────┼──────┼────────┼────────┼────────────┼──────────┤
│ 0 │ 2262 │ 4 │ 11 │ 23 │ 47 │ 16 │ 854775807 │ +00:00 │
╰───┴──────┴───────┴─────┴──────┴────────┴────────┴────────────┴──────────╯
```
This change was not mandated by the OP problem, but it is nice to be
able to see the nanosecond bits that were present in Nushell `date` type
all along.
# Tests + Formatting
Don't forget to add tests that cover your changes.
Make sure you've run and fixed any issues with these commands:
- `cargo fmt --all -- --check` to check standard code formatting (`cargo
fmt --all` applies these changes)
- `cargo clippy --workspace -- -D warnings -D clippy::unwrap_used -A
clippy::needless_collect` to check that you're using the standard code
style
- `cargo test --workspace` to check that all tests pass
# After Submitting
If your PR had any user-facing changes, update [the
documentation](https://github.com/nushell/nushell.github.io) after the
PR is merged, if necessary. This will help us keep the docs up to date.
2023-03-07 23:02:15 +00:00
|
|
|
//todo: resolve https://github.com/bspeice/dtparse/issues/40, which truncates nanosec bits
|
|
|
|
// for now, change the example to use date literal rather than string conversion, as workaround
|
|
|
|
example: "2020-04-12T22:10:57.000000789+02:00 | date to-table",
|
2022-11-09 21:55:05 +00:00
|
|
|
result: example_result_1(),
|
2021-10-31 06:54:51 +00:00
|
|
|
},
|
2022-11-09 21:55:05 +00:00
|
|
|
// TODO: This should work but does not; see https://github.com/nushell/nushell/issues/7032
|
|
|
|
// Example {
|
|
|
|
// description: "Convert a given date into a table.",
|
|
|
|
// example: "'2020-04-12 22:10:57 +0200' | into datetime | date to-table",
|
|
|
|
// result: example_result_1(),
|
|
|
|
// },
|
2021-10-31 06:54:51 +00:00
|
|
|
]
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
fn parse_date_into_table(date: Result<DateTime<FixedOffset>, Value>, head: Span) -> Value {
|
|
|
|
let cols = vec![
|
|
|
|
"year".into(),
|
|
|
|
"month".into(),
|
|
|
|
"day".into(),
|
|
|
|
"hour".into(),
|
|
|
|
"minute".into(),
|
|
|
|
"second".into(),
|
Fix 8244 -- store timestamps with nanosecond resolution (consistently) (#8337)
# Description
Fix for data ambiguity noted in #8244.
Basic change is to use nanosecond resolution for unix timestamps (stored
in type Int). Previously, a timestamp might have seconds, milliseconds
or nanoseconds, but it turned out there were overlaps in data ranges
between different resolutions, so there wasn't always a unique mapping
back to date/time.
Due to higher precision, the *range* of dates that timestamps can map to
is restricted. Unix timestamps with seconds resolution and 64 bit
storage can cover all dates from the Big Bang to eternity. Timestamps
with seconds resolution and 32 bit storage can only represent dates from
1901-12-13 through 2038-01-19. The nanoseconds resolution and 64 bit
storage used with this fix can represent dates from 1677-09-21T00:12:44
to 2262-04-11T23:47:16, something of a compromise.
# User-Facing Changes
_(List of all changes that impact the user experience here. This helps
us keep track of breaking changes.)_
## `<datetime> | into int`
Converts to nanosecond resolution
```rust
〉date now | into int
1678084730502126846
```
This is the number of non-leap nanoseconds after the unix epoch date:
1970-01-01T00:00:00+00:00.
Conversion fails for dates outside the supported range:
```rust
〉1492-10-12 | into int
Error: nu::shell::incorrect_value
× Incorrect value.
╭─[entry #51:1:1]
1 │ 1492-10-12 | into int
· ────┬───
· ╰── DateTime out of timestamp range 1677-09-21T00:12:43 and 2262-04-11T23:47:16
╰────
```
## `<int> | into datetime`
Can no longer fail or produce incorrect results for any 64-bit input:
```rust
〉0 | into datetime
Thu, 01 Jan 1970 00:00:00 +0000 (53 years ago)
〉"7fffffffffffffff" | into int -r 16 | into datetime
Fri, 11 Apr 2262 23:47:16 +0000 (in 239 years)
〉("7fffffffffffffff" | into int -r 16) * -1 | into datetime
Tue, 21 Sep 1677 00:12:43 +0000 (345 years ago)
```
## `<date> | date to-record` and `<date> | date to-table`
Now both have a `nanosecond` field.
```rust
〉"7fffffffffffffff" | into int -r 16 | into datetime | date to-record
╭────────────┬───────────╮
│ year │ 2262 │
│ month │ 4 │
│ day │ 11 │
│ hour │ 23 │
│ minute │ 47 │
│ second │ 16 │
│ nanosecond │ 854775807 │
│ timezone │ +00:00 │
╰────────────┴───────────╯
〉"7fffffffffffffff" | into int -r 16 | into datetime | date to-table
╭───┬──────┬───────┬─────┬──────┬────────┬────────┬────────────┬──────────╮
│ # │ year │ month │ day │ hour │ minute │ second │ nanosecond │ timezone │
├───┼──────┼───────┼─────┼──────┼────────┼────────┼────────────┼──────────┤
│ 0 │ 2262 │ 4 │ 11 │ 23 │ 47 │ 16 │ 854775807 │ +00:00 │
╰───┴──────┴───────┴─────┴──────┴────────┴────────┴────────────┴──────────╯
```
This change was not mandated by the OP problem, but it is nice to be
able to see the nanosecond bits that were present in Nushell `date` type
all along.
# Tests + Formatting
Don't forget to add tests that cover your changes.
Make sure you've run and fixed any issues with these commands:
- `cargo fmt --all -- --check` to check standard code formatting (`cargo
fmt --all` applies these changes)
- `cargo clippy --workspace -- -D warnings -D clippy::unwrap_used -A
clippy::needless_collect` to check that you're using the standard code
style
- `cargo test --workspace` to check that all tests pass
# After Submitting
If your PR had any user-facing changes, update [the
documentation](https://github.com/nushell/nushell.github.io) after the
PR is merged, if necessary. This will help us keep the docs up to date.
2023-03-07 23:02:15 +00:00
|
|
|
"nanosecond".into(),
|
2021-10-31 06:54:51 +00:00
|
|
|
"timezone".into(),
|
|
|
|
];
|
|
|
|
match date {
|
|
|
|
Ok(x) => {
|
|
|
|
let vals = vec![
|
Reduced LOC by replacing several instances of `Value::Int {}`, `Value::Float{}`, `Value::Bool {}`, and `Value::String {}` with `Value::int()`, `Value::float()`, `Value::boolean()` and `Value::string()` (#7412)
# Description
While perusing Value.rs, I noticed the `Value::int()`, `Value::float()`,
`Value::boolean()` and `Value::string()` constructors, which seem
designed to make it easier to construct various Values, but which aren't
used often at all in the codebase. So, using a few find-replaces
regexes, I increased their usage. This reduces overall LOC because
structures like this:
```
Value::Int {
val: a,
span: head
}
```
are changed into
```
Value::int(a, head)
```
and are respected as such by the project's formatter.
There are little readability concerns because the second argument to all
of these is `span`, and it's almost always extremely obvious which is
the span at every callsite.
# User-Facing Changes
None.
# Tests + Formatting
Don't forget to add tests that cover your changes.
Make sure you've run and fixed any issues with these commands:
- `cargo fmt --all -- --check` to check standard code formatting (`cargo
fmt --all` applies these changes)
- `cargo clippy --workspace -- -D warnings -D clippy::unwrap_used -A
clippy::needless_collect` to check that you're using the standard code
style
- `cargo test --workspace` to check that all tests pass
# After Submitting
If your PR had any user-facing changes, update [the
documentation](https://github.com/nushell/nushell.github.io) after the
PR is merged, if necessary. This will help us keep the docs up to date.
2022-12-09 16:37:51 +00:00
|
|
|
Value::int(x.year() as i64, head),
|
|
|
|
Value::int(x.month() as i64, head),
|
|
|
|
Value::int(x.day() as i64, head),
|
|
|
|
Value::int(x.hour() as i64, head),
|
|
|
|
Value::int(x.minute() as i64, head),
|
|
|
|
Value::int(x.second() as i64, head),
|
Fix 8244 -- store timestamps with nanosecond resolution (consistently) (#8337)
# Description
Fix for data ambiguity noted in #8244.
Basic change is to use nanosecond resolution for unix timestamps (stored
in type Int). Previously, a timestamp might have seconds, milliseconds
or nanoseconds, but it turned out there were overlaps in data ranges
between different resolutions, so there wasn't always a unique mapping
back to date/time.
Due to higher precision, the *range* of dates that timestamps can map to
is restricted. Unix timestamps with seconds resolution and 64 bit
storage can cover all dates from the Big Bang to eternity. Timestamps
with seconds resolution and 32 bit storage can only represent dates from
1901-12-13 through 2038-01-19. The nanoseconds resolution and 64 bit
storage used with this fix can represent dates from 1677-09-21T00:12:44
to 2262-04-11T23:47:16, something of a compromise.
# User-Facing Changes
_(List of all changes that impact the user experience here. This helps
us keep track of breaking changes.)_
## `<datetime> | into int`
Converts to nanosecond resolution
```rust
〉date now | into int
1678084730502126846
```
This is the number of non-leap nanoseconds after the unix epoch date:
1970-01-01T00:00:00+00:00.
Conversion fails for dates outside the supported range:
```rust
〉1492-10-12 | into int
Error: nu::shell::incorrect_value
× Incorrect value.
╭─[entry #51:1:1]
1 │ 1492-10-12 | into int
· ────┬───
· ╰── DateTime out of timestamp range 1677-09-21T00:12:43 and 2262-04-11T23:47:16
╰────
```
## `<int> | into datetime`
Can no longer fail or produce incorrect results for any 64-bit input:
```rust
〉0 | into datetime
Thu, 01 Jan 1970 00:00:00 +0000 (53 years ago)
〉"7fffffffffffffff" | into int -r 16 | into datetime
Fri, 11 Apr 2262 23:47:16 +0000 (in 239 years)
〉("7fffffffffffffff" | into int -r 16) * -1 | into datetime
Tue, 21 Sep 1677 00:12:43 +0000 (345 years ago)
```
## `<date> | date to-record` and `<date> | date to-table`
Now both have a `nanosecond` field.
```rust
〉"7fffffffffffffff" | into int -r 16 | into datetime | date to-record
╭────────────┬───────────╮
│ year │ 2262 │
│ month │ 4 │
│ day │ 11 │
│ hour │ 23 │
│ minute │ 47 │
│ second │ 16 │
│ nanosecond │ 854775807 │
│ timezone │ +00:00 │
╰────────────┴───────────╯
〉"7fffffffffffffff" | into int -r 16 | into datetime | date to-table
╭───┬──────┬───────┬─────┬──────┬────────┬────────┬────────────┬──────────╮
│ # │ year │ month │ day │ hour │ minute │ second │ nanosecond │ timezone │
├───┼──────┼───────┼─────┼──────┼────────┼────────┼────────────┼──────────┤
│ 0 │ 2262 │ 4 │ 11 │ 23 │ 47 │ 16 │ 854775807 │ +00:00 │
╰───┴──────┴───────┴─────┴──────┴────────┴────────┴────────────┴──────────╯
```
This change was not mandated by the OP problem, but it is nice to be
able to see the nanosecond bits that were present in Nushell `date` type
all along.
# Tests + Formatting
Don't forget to add tests that cover your changes.
Make sure you've run and fixed any issues with these commands:
- `cargo fmt --all -- --check` to check standard code formatting (`cargo
fmt --all` applies these changes)
- `cargo clippy --workspace -- -D warnings -D clippy::unwrap_used -A
clippy::needless_collect` to check that you're using the standard code
style
- `cargo test --workspace` to check that all tests pass
# After Submitting
If your PR had any user-facing changes, update [the
documentation](https://github.com/nushell/nushell.github.io) after the
PR is merged, if necessary. This will help us keep the docs up to date.
2023-03-07 23:02:15 +00:00
|
|
|
Value::int(x.nanosecond() as i64, head),
|
Reduced LOC by replacing several instances of `Value::Int {}`, `Value::Float{}`, `Value::Bool {}`, and `Value::String {}` with `Value::int()`, `Value::float()`, `Value::boolean()` and `Value::string()` (#7412)
# Description
While perusing Value.rs, I noticed the `Value::int()`, `Value::float()`,
`Value::boolean()` and `Value::string()` constructors, which seem
designed to make it easier to construct various Values, but which aren't
used often at all in the codebase. So, using a few find-replaces
regexes, I increased their usage. This reduces overall LOC because
structures like this:
```
Value::Int {
val: a,
span: head
}
```
are changed into
```
Value::int(a, head)
```
and are respected as such by the project's formatter.
There are little readability concerns because the second argument to all
of these is `span`, and it's almost always extremely obvious which is
the span at every callsite.
# User-Facing Changes
None.
# Tests + Formatting
Don't forget to add tests that cover your changes.
Make sure you've run and fixed any issues with these commands:
- `cargo fmt --all -- --check` to check standard code formatting (`cargo
fmt --all` applies these changes)
- `cargo clippy --workspace -- -D warnings -D clippy::unwrap_used -A
clippy::needless_collect` to check that you're using the standard code
style
- `cargo test --workspace` to check that all tests pass
# After Submitting
If your PR had any user-facing changes, update [the
documentation](https://github.com/nushell/nushell.github.io) after the
PR is merged, if necessary. This will help us keep the docs up to date.
2022-12-09 16:37:51 +00:00
|
|
|
Value::string(x.offset().to_string(), head),
|
2021-10-31 06:54:51 +00:00
|
|
|
];
|
2021-10-31 19:53:23 +00:00
|
|
|
Value::List {
|
|
|
|
vals: vec![Value::Record {
|
|
|
|
cols,
|
|
|
|
vals,
|
|
|
|
span: head,
|
|
|
|
}],
|
2021-10-31 06:54:51 +00:00
|
|
|
span: head,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
Err(e) => e,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
fn helper(val: Value, head: Span) -> Value {
|
|
|
|
match val {
|
2021-12-19 07:46:13 +00:00
|
|
|
Value::String {
|
|
|
|
val,
|
|
|
|
span: val_span,
|
|
|
|
} => {
|
2022-02-28 01:21:46 +00:00
|
|
|
let date = parse_date_from_string(&val, val_span);
|
2021-10-31 06:54:51 +00:00
|
|
|
parse_date_into_table(date, head)
|
|
|
|
}
|
|
|
|
Value::Nothing { span: _ } => {
|
|
|
|
let now = Local::now();
|
|
|
|
let n = now.with_timezone(now.offset());
|
|
|
|
parse_date_into_table(Ok(n), head)
|
|
|
|
}
|
|
|
|
Value::Date { val, span: _ } => parse_date_into_table(Ok(val), head),
|
2022-02-28 01:21:46 +00:00
|
|
|
_ => Value::Error {
|
2023-02-06 20:17:07 +00:00
|
|
|
error: DatetimeParseError(val.debug_value(), head),
|
2022-02-28 01:21:46 +00:00
|
|
|
},
|
2021-10-31 06:54:51 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#[cfg(test)]
|
|
|
|
mod test {
|
|
|
|
use super::*;
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn test_examples() {
|
|
|
|
use crate::test_examples;
|
|
|
|
|
|
|
|
test_examples(SubCommand {})
|
|
|
|
}
|
|
|
|
}
|