Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Datetime support #1090

Draft
wants to merge 6 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .vscode/settings.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
"actix",
"bigdecimal",
"bindgen",
"dateparser",
"dbgjs",
"dcell",
"ddimaria",
Expand Down
13 changes: 13 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions quadratic-core/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ tabled = { version = "0.14.0", features = ["color"] }
pollster = "0.2.5"
uuid = { version = "1.4.0", features = ["v4", "serde"] }
chrono = { version = "0.4", features = ["serde", "wasmbind"] }
dateparser = "0.2.1"

# The `console_error_panic_hook` crate provides better debugging of panics by
# logging them with `console.error`. This is great for development, but requires
Expand Down
2 changes: 2 additions & 0 deletions quadratic-core/src/controller/operations/cell_value.rs
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,8 @@
)),
});
CellValue::Number(percent)
} else if let Some(cell_value) = CellValue::unpack_date_time(value) {
cell_value

Check warning on line 80 in quadratic-core/src/controller/operations/cell_value.rs

View check run for this annotation

Codecov / codecov/patch

quadratic-core/src/controller/operations/cell_value.rs#L80

Added line #L80 was not covered by tests
} else {
CellValue::Text(value.into())
};
Expand Down
2 changes: 2 additions & 0 deletions quadratic-core/src/formulas/criteria.rs
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@
| CellValue::Code(_)
| CellValue::Logical(_)
| CellValue::Instant(_)
| CellValue::DateTime(_)
| CellValue::Duration(_) => Ok(Criterion::Compare {
compare_fn: CompareFn::Eql,
rhs: value.inner.clone(),
Expand Down Expand Up @@ -102,6 +103,7 @@
CellValue::Duration(lhs) => compare_fn.compare(lhs, rhs),
_ => false,
},
CellValue::DateTime(_) => false,

Check warning on line 106 in quadratic-core/src/formulas/criteria.rs

View check run for this annotation

Codecov / codecov/patch

quadratic-core/src/formulas/criteria.rs#L106

Added line #L106 was not covered by tests
CellValue::Error(_) => false,
CellValue::Html(_) => false,
CellValue::Code(_) => false,
Expand Down
4 changes: 4 additions & 0 deletions quadratic-core/src/grid/file/current.rs
Original file line number Diff line number Diff line change
Expand Up @@ -182,6 +182,7 @@
current::CellValue::Error(error) => {
CellValue::Error(Box::new((*error).clone().into()))
}
current::CellValue::DateTime(dt) => CellValue::DateTime(dt.to_owned()),

Check warning on line 185 in quadratic-core/src/grid/file/current.rs

View check run for this annotation

Codecov / codecov/patch

quadratic-core/src/grid/file/current.rs#L185

Added line #L185 was not covered by tests
};
if let Ok(y) = y.parse::<i64>() {
col.values.insert(y, cell_value);
Expand Down Expand Up @@ -497,6 +498,9 @@
CellValue::Logical(logical) => {
current::CellValue::Logical(*logical)
}
CellValue::DateTime(dt) => {
current::CellValue::DateTime(dt.to_owned())

Check warning on line 502 in quadratic-core/src/grid/file/current.rs

View check run for this annotation

Codecov / codecov/patch

quadratic-core/src/grid/file/current.rs#L501-L502

Added lines #L501 - L502 were not covered by tests
}
CellValue::Instant(instant) => {
current::CellValue::Instant(instant.to_string())
}
Expand Down
1 change: 1 addition & 0 deletions quadratic-core/src/grid/file/v1_5/schema.rs
Original file line number Diff line number Diff line change
Expand Up @@ -157,6 +157,7 @@ pub enum CellValue {
Html(String),
Code(CodeCell),
Logical(bool),
DateTime(DateTime<Utc>),
Instant(String),
Duration(String),
Error(RunError),
Expand Down
32 changes: 27 additions & 5 deletions quadratic-core/src/values/cellvalue.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,3 @@
use std::{fmt, str::FromStr};

use bigdecimal::{BigDecimal, Signed, ToPrimitive, Zero};
use serde::{Deserialize, Serialize};

use super::{Duration, Instant, IsBlank};
use crate::{
controller::operations::operation::Operation,
Expand All @@ -12,6 +7,11 @@
},
CodeResult, Pos, RunError, RunLengthEncoding, SheetRect,
};
use bigdecimal::{BigDecimal, Signed, ToPrimitive, Zero};
use chrono::{DateTime, Utc};
use dateparser::parse_with_timezone;
use serde::{Deserialize, Serialize};
use std::{fmt, str::FromStr};

// todo: fill this out
const CURRENCY_SYMBOLS: &str = "$€£¥";
Expand Down Expand Up @@ -40,6 +40,9 @@
Number(BigDecimal),
/// Logical value.
Logical(bool),
#[cfg_attr(test, proptest(skip))]
/// DateTime based on UTC (w/o support for timezones)
DateTime(DateTime<Utc>),
/// Instant in time.
Instant(Instant),
/// Duration of time.
Expand All @@ -64,6 +67,7 @@
CellValue::Error(e) => write!(f, "{}", e.msg),
CellValue::Html(s) => write!(f, "{}", s),
CellValue::Code(code) => write!(f, "{:?}", code),
CellValue::DateTime(dt) => write!(f, "{:?}", dt),

Check warning on line 70 in quadratic-core/src/values/cellvalue.rs

View check run for this annotation

Codecov / codecov/patch

quadratic-core/src/values/cellvalue.rs#L70

Added line #L70 was not covered by tests
}
}
}
Expand All @@ -88,6 +92,7 @@
CellValue::Error(_) => "error",
CellValue::Html(_) => "html",
CellValue::Code(_) => "python",
CellValue::DateTime(_) => "datetime",

Check warning on line 95 in quadratic-core/src/values/cellvalue.rs

View check run for this annotation

Codecov / codecov/patch

quadratic-core/src/values/cellvalue.rs#L95

Added line #L95 was not covered by tests
}
}
/// Returns a formula-source-code representation of the value.
Expand All @@ -103,6 +108,7 @@
CellValue::Error(_) => "[error]".to_string(),
CellValue::Html(s) => s.clone(),
CellValue::Code(_) => todo!("repr of python"),
CellValue::DateTime(dt) => dt.date_naive().to_string(),

Check warning on line 111 in quadratic-core/src/values/cellvalue.rs

View check run for this annotation

Codecov / codecov/patch

quadratic-core/src/values/cellvalue.rs#L111

Added line #L111 was not covered by tests
}
}

Expand Down Expand Up @@ -211,6 +217,9 @@
CellValue::Duration(_) => todo!("repr of Duration"),
CellValue::Error(_) => "[error]".to_string(),

// todo: add formatting here...
CellValue::DateTime(dt) => dt.date_naive().to_string(),

Check warning on line 221 in quadratic-core/src/values/cellvalue.rs

View check run for this annotation

Codecov / codecov/patch

quadratic-core/src/values/cellvalue.rs#L221

Added line #L221 was not covered by tests

// this should not render
CellValue::Code(_) => String::new(),
}
Expand All @@ -227,6 +236,7 @@
CellValue::Instant(_) => todo!("repr of Instant"),
CellValue::Duration(_) => todo!("repr of Duration"),
CellValue::Error(_) => "[error]".to_string(),
CellValue::DateTime(dt) => dt.to_string(),

Check warning on line 239 in quadratic-core/src/values/cellvalue.rs

View check run for this annotation

Codecov / codecov/patch

quadratic-core/src/values/cellvalue.rs#L239

Added line #L239 was not covered by tests

// this should not be editable
CellValue::Code(_) => String::new(),
Expand Down Expand Up @@ -283,6 +293,12 @@
})
}

pub fn unpack_date_time(value: &str) -> Option<CellValue> {
parse_with_timezone(value, &Utc)
.ok()
.map(|dt| CellValue::DateTime(dt))
}

pub fn is_blank_or_empty_string(&self) -> bool {
self.is_blank() || *self == CellValue::Text(String::new())
}
Expand Down Expand Up @@ -319,6 +335,7 @@
a.cmp(&b)
}
(CellValue::Logical(a), CellValue::Logical(b)) => a.cmp(b),
(CellValue::DateTime(dt), CellValue::DateTime(other_dt)) => dt.cmp(&other_dt),

Check warning on line 338 in quadratic-core/src/values/cellvalue.rs

View check run for this annotation

Codecov / codecov/patch

quadratic-core/src/values/cellvalue.rs#L338

Added line #L338 was not covered by tests
(CellValue::Instant(a), CellValue::Instant(b)) => a.cmp(b),
(CellValue::Duration(a), CellValue::Duration(b)) => a.cmp(b),
(CellValue::Blank, CellValue::Blank) => std::cmp::Ordering::Equal,
Expand All @@ -330,6 +347,7 @@
| (CellValue::Duration(_), _)
| (CellValue::Html(_), _)
| (CellValue::Code(_), _)
| (CellValue::DateTime(_), _)
| (CellValue::Blank, _) => return Ok(None),
}))
}
Expand All @@ -352,6 +370,7 @@
CellValue::Blank => 6,
CellValue::Html(_) => 7,
CellValue::Code(_) => 8,
CellValue::DateTime(_) => 9,
}
}

Expand Down Expand Up @@ -421,6 +440,7 @@
}

// todo: this needs to be reworked under the new paradigm

// compare to operations/cell_value.rs, which has a very similar functions, except for the decimal check (which requires Sheet access)
/// Converts a string to a CellValue, updates number formatting, and returns reverse Ops
pub fn from_string(s: &String, pos: Pos, sheet: &mut Sheet) -> (CellValue, Vec<Operation>) {
Expand Down Expand Up @@ -486,6 +506,8 @@
} else if s.to_lowercase().starts_with("<html>") || s.to_lowercase().starts_with("<div>") {
// todo: probably use a crate here to detect html
value = CellValue::Html(s.to_string());
} else if let Ok(dt) = parse_with_timezone(&s, &chrono::Utc) {
value = CellValue::DateTime(dt);

Check warning on line 510 in quadratic-core/src/values/cellvalue.rs

View check run for this annotation

Codecov / codecov/patch

quadratic-core/src/values/cellvalue.rs#L510

Added line #L510 was not covered by tests
} else if let Some(boolean) = CellValue::unpack_boolean(&s) {
value = boolean;
} else {
Expand Down
7 changes: 7 additions & 0 deletions quadratic-core/src/values/convert.rs
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,8 @@
* CONVERSIONS (Value -> specific type)
*/

// todo: not sure where or if this is used anymore

impl<'a> TryFrom<&'a CellValue> for String {
type Error = RunErrorMsg;

Expand All @@ -94,9 +96,13 @@
CellValue::Error(e) => Err(e.msg.clone()),
CellValue::Html(s) => Ok(s.clone()),
CellValue::Code(_) => Ok(String::new()),
CellValue::DateTime(dt) => Ok(dt.to_string()),

Check warning on line 99 in quadratic-core/src/values/convert.rs

View check run for this annotation

Codecov / codecov/patch

quadratic-core/src/values/convert.rs#L99

Added line #L99 was not covered by tests
}
}
}

// todo: not sure where or if this is used anymore

impl<'a> TryFrom<&'a CellValue> for f64 {
type Error = RunErrorMsg;

Expand Down Expand Up @@ -125,6 +131,7 @@
expected: "number".into(),
got: Some(value.type_name().into()),
}),
CellValue::DateTime(_) => Ok(0.0),

Check warning on line 134 in quadratic-core/src/values/convert.rs

View check run for this annotation

Codecov / codecov/patch

quadratic-core/src/values/convert.rs#L134

Added line #L134 was not covered by tests
CellValue::Error(e) => Err(e.msg.clone()),
CellValue::Html(_) => Ok(0.0),
CellValue::Code(_) => Ok(0.0),
Expand Down
2 changes: 1 addition & 1 deletion quadratic-core/src/values/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ pub mod cell_values;
mod cellvalue;
mod convert;
mod isblank;
mod time;
pub mod time;

pub use array::Array;
pub use array_size::{ArraySize, Axis};
Expand Down
Loading