use crate::datatypes::values::Value;
use crate::graph::schema::{InternedKey, NodeData, TemporalConfig};
use chrono::NaiveDate;
pub fn is_temporally_valid(
properties: &[(InternedKey, Value)],
config: &TemporalConfig,
reference: &NaiveDate,
) -> bool {
let from_key = InternedKey::from_str(&config.valid_from);
let to_key = InternedKey::from_str(&config.valid_to);
if let Some((_, Value::DateTime(d))) = properties.iter().find(|(k, _)| *k == from_key) {
if d > reference {
return false;
}
}
if let Some((_, Value::DateTime(d))) = properties.iter().find(|(k, _)| *k == to_key) {
if d < reference {
return false;
}
}
true
}
pub fn node_is_temporally_valid(
node: &NodeData,
config: &TemporalConfig,
reference: &NaiveDate,
) -> bool {
if let Some(val) = node.get_field_ref(&config.valid_from) {
if let Value::DateTime(d) = &*val {
if d > reference {
return false;
}
}
}
if let Some(val) = node.get_field_ref(&config.valid_to) {
if let Value::DateTime(d) = &*val {
if d < reference {
return false;
}
}
}
true
}
pub fn overlaps_range(
properties: &[(InternedKey, Value)],
config: &TemporalConfig,
start: &NaiveDate,
end: &NaiveDate,
) -> bool {
let from_key = InternedKey::from_str(&config.valid_from);
let to_key = InternedKey::from_str(&config.valid_to);
if let Some((_, Value::DateTime(d))) = properties.iter().find(|(k, _)| *k == from_key) {
if d > end {
return false;
}
}
if let Some((_, Value::DateTime(d))) = properties.iter().find(|(k, _)| *k == to_key) {
if d < start {
return false;
}
}
true
}
pub fn node_overlaps_range(
node: &NodeData,
config: &TemporalConfig,
start: &NaiveDate,
end: &NaiveDate,
) -> bool {
if let Some(val) = node.get_field_ref(&config.valid_from) {
if let Value::DateTime(d) = &*val {
if d > end {
return false;
}
}
}
if let Some(val) = node.get_field_ref(&config.valid_to) {
if let Value::DateTime(d) = &*val {
if d < start {
return false;
}
}
}
true
}
pub fn is_temporally_valid_multi(
properties: &[(InternedKey, Value)],
configs: &[TemporalConfig],
reference: &NaiveDate,
) -> bool {
for config in configs {
let from_key = InternedKey::from_str(&config.valid_from);
let to_key = InternedKey::from_str(&config.valid_to);
if properties
.iter()
.any(|(k, _)| *k == from_key || *k == to_key)
{
return is_temporally_valid(properties, config, reference);
}
}
true }
pub fn overlaps_range_multi(
properties: &[(InternedKey, Value)],
configs: &[TemporalConfig],
start: &NaiveDate,
end: &NaiveDate,
) -> bool {
for config in configs {
let from_key = InternedKey::from_str(&config.valid_from);
let to_key = InternedKey::from_str(&config.valid_to);
if properties
.iter()
.any(|(k, _)| *k == from_key || *k == to_key)
{
return overlaps_range(properties, config, start, end);
}
}
true
}
pub fn node_passes_context(
node: &NodeData,
config: &TemporalConfig,
context: &crate::graph::TemporalContext,
) -> bool {
use crate::graph::TemporalContext;
match context {
TemporalContext::All => true,
TemporalContext::Today => {
let today = chrono::Local::now().date_naive();
node_is_temporally_valid(node, config, &today)
}
TemporalContext::At(d) => node_is_temporally_valid(node, config, d),
TemporalContext::During(start, end) => node_overlaps_range(node, config, start, end),
}
}