Add duration functions for calculating durations as integers (#257)
This commit is contained in:
parent
825ccf0986
commit
58cffa2de6
6 changed files with 112 additions and 1 deletions
44
lib/src/fnc/duration.rs
Normal file
44
lib/src/fnc/duration.rs
Normal 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,
|
||||||
|
})
|
||||||
|
}
|
|
@ -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,
|
||||||
|
|
|
@ -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)),
|
||||||
|
|
|
@ -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 {
|
||||||
|
|
|
@ -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"),
|
||||||
|
|
|
@ -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),
|
||||||
|
|
Loading…
Reference in a new issue