mirror of
https://github.com/twonlyapp/twonly-app.git
synced 2026-10-09 02:54:14 +00:00
83 lines
2.3 KiB
Rust
83 lines
2.3 KiB
Rust
/*
|
|
* Copyright (c) 2026, Tobias Müller git@tsmr.eu
|
|
*
|
|
*/
|
|
|
|
use chrono::{DateTime, Local, TimeZone};
|
|
use std::sync::Arc;
|
|
use tokio::sync::{RwLock, RwLockReadGuard};
|
|
|
|
use crate::error::{Result, TwonlyError};
|
|
|
|
pub(crate) fn milliseconds_to_seconds(timestamp: i64) -> i64 {
|
|
timestamp.div_euclid(1_000)
|
|
}
|
|
|
|
pub(crate) fn current_time() -> DateTime<Local> {
|
|
Local::now()
|
|
}
|
|
|
|
pub(crate) fn is_today(timestamp: i64) -> bool {
|
|
Local
|
|
.timestamp_opt(timestamp, 0)
|
|
.single()
|
|
.is_some_and(|date| date.date_naive() == current_time().date_naive())
|
|
}
|
|
|
|
/// Midnight of the current day in the user's timezone. Flame counters roll over
|
|
/// at the local day boundary, so every comparison against "today" has to start
|
|
/// here instead of at a UTC boundary.
|
|
pub(crate) fn start_of_local_day() -> Result<i64> {
|
|
Ok(Local
|
|
.from_local_datetime(
|
|
¤t_time()
|
|
.date_naive()
|
|
.and_hms_opt(0, 0, 0)
|
|
.ok_or_else(|| TwonlyError::Generic("invalid local date".into()))?,
|
|
)
|
|
.earliest()
|
|
.ok_or_else(|| TwonlyError::Generic("local day has no midnight".into()))?
|
|
.timestamp())
|
|
}
|
|
|
|
pub(crate) fn new_uuid_v4() -> String {
|
|
uuid::Uuid::new_v4().to_string()
|
|
}
|
|
|
|
/// Media and message identifiers are time-ordered so that inserting them keeps
|
|
/// the primary-key index append-only, matching what Drift generated before.
|
|
pub(crate) fn new_uuid_v7() -> String {
|
|
uuid::Uuid::now_v7().to_string()
|
|
}
|
|
|
|
#[derive(Default, Clone)]
|
|
pub(crate) struct Shared<T>(Arc<RwLock<T>>);
|
|
impl<T> Shared<T> {
|
|
pub(crate) fn new(value: T) -> Self {
|
|
Self(Arc::new(RwLock::new(value)))
|
|
}
|
|
pub(crate) async fn get(&self) -> RwLockReadGuard<'_, T> {
|
|
self.0.read().await
|
|
}
|
|
// pub(crate) async fn set(&self, value: T) {
|
|
// *self.0.write().await = value;
|
|
// }
|
|
}
|
|
|
|
#[cfg(test)]
|
|
mod tests {
|
|
use super::{current_time, is_today, milliseconds_to_seconds};
|
|
|
|
#[test]
|
|
fn converts_milliseconds_to_seconds() {
|
|
assert_eq!(milliseconds_to_seconds(1_999), 1);
|
|
assert_eq!(milliseconds_to_seconds(1_000), 1);
|
|
assert_eq!(milliseconds_to_seconds(999), 0);
|
|
}
|
|
|
|
#[test]
|
|
fn recognizes_current_day() {
|
|
assert!(is_today(current_time().timestamp()));
|
|
assert!(!is_today(i64::MAX));
|
|
}
|
|
}
|