Add duration functions for calculating durations as integers (#257)

This commit is contained in:
Hugo Saracino 2022-09-23 01:48:49 +02:00 committed by GitHub
parent 825ccf0986
commit 58cffa2de6
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
6 changed files with 112 additions and 1 deletions

44
lib/src/fnc/duration.rs Normal file
View file

@ -0,0 +1,44 @@
use crate::err::Error;
use crate::sql::value::Value;
pub fn days((duration,): (Value,)) -> Result<Value, Error> {
Ok(match duration {
Value::Duration(d) => d.days(),
_ => Value::None,
})
}
pub fn hours((duration,): (Value,)) -> Result<Value, Error> {
Ok(match duration {
Value::Duration(d) => d.hours(),
_ => Value::None,
})
}
pub fn mins((duration,): (Value,)) -> Result<Value, Error> {
Ok(match duration {
Value::Duration(d) => d.mins(),
_ => Value::None,
})
}
pub fn secs((duration,): (Value,)) -> Result<Value, Error> {
Ok(match duration {
Value::Duration(d) => d.secs(),
_ => Value::None,
})
}
pub fn weeks((duration,): (Value,)) -> Result<Value, Error> {
Ok(match duration {
Value::Duration(d) => d.weeks(),
_ => Value::None,
})
}
pub fn years((duration,): (Value,)) -> Result<Value, Error> {
Ok(match duration {
Value::Duration(d) => d.years(),
_ => Value::None,
})
}

View file

@ -7,6 +7,7 @@ pub mod array;
pub mod cast; pub mod cast;
pub mod count; pub mod count;
pub mod crypto; pub mod crypto;
pub mod duration;
pub mod future; pub mod future;
pub mod geo; pub mod geo;
pub mod http; pub mod http;
@ -77,6 +78,13 @@ pub fn synchronous(ctx: &Context<'_>, name: &str, args: Vec<Value>) -> Result<Va
"crypto::sha256" => crypto::sha256, "crypto::sha256" => crypto::sha256,
"crypto::sha512" => crypto::sha512, "crypto::sha512" => crypto::sha512,
// //
"duration::days" => duration::days,
"duration::hours" => duration::hours,
"duration::mins" => duration::mins,
"duration::secs" => duration::secs,
"duration::weeks" => duration::weeks,
"duration::years" => duration::years,
//
"geo::area" => geo::area, "geo::area" => geo::area,
"geo::bearing" => geo::bearing, "geo::bearing" => geo::bearing,
"geo::centroid" => geo::centroid, "geo::centroid" => geo::centroid,

View file

@ -1,4 +1,5 @@
use crate::sql::common::{take_digits, take_digits_range, take_u32_len}; use crate::sql::common::{take_digits, take_digits_range, take_u32_len};
use crate::sql::duration::Duration;
use crate::sql::error::IResult; use crate::sql::error::IResult;
use crate::sql::serde::is_internal_serialization; use crate::sql::serde::is_internal_serialization;
use chrono::{DateTime, FixedOffset, TimeZone, Utc}; use chrono::{DateTime, FixedOffset, TimeZone, Utc};
@ -7,9 +8,9 @@ use nom::character::complete::char;
use nom::combinator::map; use nom::combinator::map;
use nom::sequence::delimited; use nom::sequence::delimited;
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use std::fmt;
use std::ops::Deref; use std::ops::Deref;
use std::str; use std::str;
use std::{fmt, ops};
const SINGLE: char = '\''; const SINGLE: char = '\'';
const DOUBLE: char = '"'; const DOUBLE: char = '"';
@ -70,6 +71,16 @@ impl Serialize for Datetime {
} }
} }
impl ops::Sub<Datetime> for Datetime {
type Output = Duration;
fn sub(self, other: Datetime) -> Duration {
match (self.0 - other.0).to_std() {
Ok(d) => Duration::from(d),
Err(_) => Duration::default(),
}
}
}
pub fn datetime(i: &str) -> IResult<&str, Datetime> { pub fn datetime(i: &str) -> IResult<&str, Datetime> {
alt(( alt((
delimited(char(DOUBLE), datetime_raw, char(DOUBLE)), delimited(char(DOUBLE), datetime_raw, char(DOUBLE)),

View file

@ -2,6 +2,7 @@ use crate::sql::common::take_u64;
use crate::sql::datetime::Datetime; use crate::sql::datetime::Datetime;
use crate::sql::error::IResult; use crate::sql::error::IResult;
use crate::sql::serde::is_internal_serialization; use crate::sql::serde::is_internal_serialization;
use crate::sql::value::Value;
use chrono::DurationRound; use chrono::DurationRound;
use nom::branch::alt; use nom::branch::alt;
use nom::bytes::complete::tag; use nom::bytes::complete::tag;
@ -54,6 +55,40 @@ impl Duration {
pub fn to_raw(&self) -> String { pub fn to_raw(&self) -> String {
self.to_string() self.to_string()
} }
pub fn secs(&self) -> Value {
self.0.as_secs().into()
}
pub fn mins(&self) -> Value {
let secs = self.0.as_secs();
let mins = secs / SECONDS_PER_MINUTE;
mins.into()
}
pub fn hours(&self) -> Value {
let secs = self.0.as_secs();
let hours = secs / SECONDS_PER_HOUR;
hours.into()
}
pub fn days(&self) -> Value {
let secs = self.0.as_secs();
let days = secs / SECONDS_PER_DAY;
days.into()
}
pub fn weeks(&self) -> Value {
let secs = self.0.as_secs();
let weeks = secs / SECONDS_PER_WEEK;
weeks.into()
}
pub fn years(&self) -> Value {
let secs = self.0.as_secs();
let years = secs / SECONDS_PER_YEAR;
years.into()
}
} }
impl fmt::Display for Duration { impl fmt::Display for Duration {

View file

@ -239,6 +239,7 @@ fn function_names(i: &str) -> IResult<&str, &str> {
function_array, function_array,
function_count, function_count,
function_crypto, function_crypto,
function_duration,
function_geo, function_geo,
function_http, function_http,
function_is, function_is,
@ -289,6 +290,17 @@ fn function_crypto(i: &str) -> IResult<&str, &str> {
))(i) ))(i)
} }
fn function_duration(i: &str) -> IResult<&str, &str> {
alt((
tag("duration::days"),
tag("duration::hours"),
tag("duration::mins"),
tag("duration::secs"),
tag("duration::weeks"),
tag("duration::years"),
))(i)
}
fn function_geo(i: &str) -> IResult<&str, &str> { fn function_geo(i: &str) -> IResult<&str, &str> {
alt(( alt((
tag("geo::area"), tag("geo::area"),

View file

@ -1199,6 +1199,7 @@ impl ops::Sub for Value {
fn sub(self, other: Self) -> Self { fn sub(self, other: Self) -> Self {
match (self, other) { match (self, other) {
(Value::Number(v), Value::Number(w)) => Value::Number(v - w), (Value::Number(v), Value::Number(w)) => Value::Number(v - w),
(Value::Datetime(v), Value::Datetime(w)) => Value::Duration(v - w),
(Value::Datetime(v), Value::Duration(w)) => Value::Datetime(w - v), (Value::Datetime(v), Value::Duration(w)) => Value::Datetime(w - v),
(Value::Duration(v), Value::Datetime(w)) => Value::Datetime(v - w), (Value::Duration(v), Value::Datetime(w)) => Value::Datetime(v - w),
(Value::Duration(v), Value::Duration(w)) => Value::Duration(v - w), (Value::Duration(v), Value::Duration(w)) => Value::Duration(v - w),