all functions implemented

This commit is contained in:
pedrocarlo
2025-01-31 22:44:00 -03:00
parent 65b43614e3
commit e1733ca31e
2 changed files with 215 additions and 25 deletions

View File

@@ -14,7 +14,6 @@ use time::*;
register_extension! {
scalars: {
time_now,
time_fmt_iso,
time_date,
make_date,
make_timestamp,
@@ -43,6 +42,7 @@ register_extension! {
time_before,
time_compare,
time_equal,
dur_ns,
dur_us,
dur_ms,
dur_s,
@@ -53,7 +53,13 @@ register_extension! {
time_sub,
time_since,
time_until,
time_trunc
time_trunc,
time_round,
time_fmt_iso,
time_fmt_datetime,
time_fmt_date,
time_fmt_time,
time_parse,
},
}
@@ -121,29 +127,6 @@ fn time_now(args: &[Value]) -> Value {
t.into_blob()
}
#[scalar(name = "time_fmt_iso")]
fn time_fmt_iso(args: &[Value]) -> Value {
if args.len() != 1 && args.len() != 2 {
return Value::error(ResultCode::InvalidArgs);
}
let blob = ok_tri!(args[0].to_blob());
let t = tri!(Time::try_from(blob));
let offset_sec = {
if args.len() == 2 {
value_tri!(args[1].value_type(), ValueType::Integer);
ok_tri!(args[1].to_integer()) as i32
} else {
0
}
};
let fmt_str = tri!(t.fmt_iso(offset_sec));
Value::from_text(fmt_str)
}
/// ```text
/// time_date(year, month, day[, hour, min, sec[, nsec[, offset_sec]]])
/// ```
@@ -614,6 +597,16 @@ fn time_equal(args: &[Value]) -> Value {
// Duration Constants
/// 1 nanosecond
#[scalar(name = "dur_ns")]
fn dur_ns(args: &[Value]) -> Value {
if args.len() != 0 {
return Value::error(ResultCode::InvalidArgs);
}
Value::from_integer(ok_tri!(chrono::Duration::nanoseconds(1).num_nanoseconds()))
}
/// 1 microsecond
#[scalar(name = "dur_us")]
fn dur_us(args: &[Value]) -> Value {
@@ -810,3 +803,152 @@ fn time_trunc(args: &[Value]) -> Value {
_ => Value::error(ResultCode::Error),
}
}
#[scalar(name = "time_round")]
fn time_round(args: &[Value]) -> Value {
if args.len() != 2 {
return Value::error(ResultCode::InvalidArgs);
}
let blob = ok_tri!(args[0].to_blob());
let t = tri!(Time::try_from(blob));
value_tri!(args[1].value_type(), ValueType::Integer);
let duration = ok_tri!(args[1].to_integer());
let duration = Duration::from(duration);
tri!(t.round_duration(duration)).into_blob()
}
// Formatting
#[scalar(name = "time_fmt_iso")]
fn time_fmt_iso(args: &[Value]) -> Value {
if args.len() != 1 && args.len() != 2 {
return Value::error(ResultCode::InvalidArgs);
}
let blob = ok_tri!(args[0].to_blob());
let t = tri!(Time::try_from(blob));
let offset_sec = {
if args.len() == 2 {
value_tri!(args[1].value_type(), ValueType::Integer);
ok_tri!(args[1].to_integer()) as i32
} else {
0
}
};
let fmt_str = tri!(t.fmt_iso(offset_sec));
Value::from_text(fmt_str)
}
#[scalar(name = "time_fmt_datetime")]
fn time_fmt_datetime(args: &[Value]) -> Value {
if args.len() != 1 && args.len() != 2 {
return Value::error(ResultCode::InvalidArgs);
}
let blob = ok_tri!(args[0].to_blob());
let t = tri!(Time::try_from(blob));
let offset_sec = {
if args.len() == 2 {
value_tri!(args[1].value_type(), ValueType::Integer);
ok_tri!(args[1].to_integer()) as i32
} else {
0
}
};
let fmt_str = tri!(t.fmt_datetime(offset_sec));
Value::from_text(fmt_str)
}
#[scalar(name = "time_fmt_date")]
fn time_fmt_date(args: &[Value]) -> Value {
if args.len() != 1 && args.len() != 2 {
return Value::error(ResultCode::InvalidArgs);
}
let blob = ok_tri!(args[0].to_blob());
let t = tri!(Time::try_from(blob));
let offset_sec = {
if args.len() == 2 {
value_tri!(args[1].value_type(), ValueType::Integer);
ok_tri!(args[1].to_integer()) as i32
} else {
0
}
};
let fmt_str = tri!(t.fmt_date(offset_sec));
Value::from_text(fmt_str)
}
#[scalar(name = "time_fmt_time")]
fn time_fmt_time(args: &[Value]) -> Value {
if args.len() != 1 && args.len() != 2 {
return Value::error(ResultCode::InvalidArgs);
}
let blob = ok_tri!(args[0].to_blob());
let t = tri!(Time::try_from(blob));
let offset_sec = {
if args.len() == 2 {
value_tri!(args[1].value_type(), ValueType::Integer);
ok_tri!(args[1].to_integer()) as i32
} else {
0
}
};
let fmt_str = tri!(t.fmt_time(offset_sec));
Value::from_text(fmt_str)
}
#[scalar(name = "time_parse")]
fn time_parse(args: &[Value]) -> Value {
if args.len() != 1 {
return Value::error(ResultCode::InvalidArgs);
}
let dt_str = ok_tri!(args[0].to_text());
if let Ok(dt) = chrono::DateTime::parse_from_rfc3339(&dt_str) {
return Time::from_datetime(dt.to_utc()).into_blob();
}
if let Ok(mut dt) = chrono::NaiveDateTime::parse_from_str(&dt_str, "%Y-%m-%d %H:%M:%S") {
// Unwrap is safe here
dt = dt.with_nanosecond(0).unwrap();
return Time::from_datetime(dt.and_utc()).into_blob();
}
if let Ok(date) = chrono::NaiveDate::parse_from_str(&dt_str, "%Y-%m-%d") {
// Unwrap is safe here
let dt = date
.and_hms_opt(0, 0, 0)
.unwrap()
.with_nanosecond(0)
.unwrap();
return Time::from_datetime(dt.and_utc()).into_blob();
}
let time = tri!(chrono::NaiveTime::parse_from_str(&dt_str, "%H:%M:%S"));
let dt = NaiveDateTime::new(NaiveDate::from_ymd_opt(1, 1, 1).unwrap(), time)
.with_nanosecond(0)
.unwrap();
Time::from_datetime(dt.and_utc()).into_blob()
}

View File

@@ -134,6 +134,48 @@ impl Time {
}
}
pub fn fmt_datetime(&self, offset_sec: i32) -> Result<String> {
let fmt = "%F %T";
if offset_sec == 0 {
return Ok(self.inner.format(fmt).to_string());
}
// I do not see how this can error
let offset = &FixedOffset::east_opt(offset_sec).ok_or(TimeError::InvalidFormat)?;
let timezone_date = self.inner.with_timezone(offset);
return Ok(timezone_date.format(fmt).to_string());
}
pub fn fmt_date(&self, offset_sec: i32) -> Result<String> {
let fmt = "%F";
if offset_sec == 0 {
return Ok(self.inner.format(fmt).to_string());
}
// I do not see how this can error
let offset = &FixedOffset::east_opt(offset_sec).ok_or(TimeError::InvalidFormat)?;
let timezone_date = self.inner.with_timezone(offset);
return Ok(timezone_date.format(fmt).to_string());
}
pub fn fmt_time(&self, offset_sec: i32) -> Result<String> {
let fmt = "%T";
if offset_sec == 0 {
return Ok(self.inner.format(fmt).to_string());
}
// I do not see how this can error
let offset = &FixedOffset::east_opt(offset_sec).ok_or(TimeError::InvalidFormat)?;
let timezone_date = self.inner.with_timezone(offset);
return Ok(timezone_date.format(fmt).to_string());
}
/// Adjust the datetime to the offset
pub fn from_datetime(dt: DateTime<Utc>) -> Self {
Self { inner: dt }
@@ -361,6 +403,12 @@ impl Time {
Ok(ret)
}
pub fn round_duration(&self, d: Duration) -> Result<Self> {
Ok(Self {
inner: self.inner.duration_round(d.inner)?,
})
}
pub fn time_get(&self, field: TimeField) -> Value {
use TimeField::*;