Use timezones wherever possible.
Replace uses of NaiveDateTime with DateTime<Utc>. Use timezones in postman to update days correctly. Use chrono::Months to update months rather than using MySQL query.
This commit is contained in:
parent
08e4c6cb57
commit
aa74a7f9a3
34
Cargo.lock
generated
34
Cargo.lock
generated
@ -56,9 +56,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "aho-corasick"
|
||||
version = "0.7.19"
|
||||
version = "0.7.20"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b4f55bd91a0978cbfd91c457a164bab8b4001c833b7f323132c0a4e1922dd44e"
|
||||
checksum = "cc936419f96fa211c1b9166887b38e5e40b19958e5b895be7c1f93adec7071ac"
|
||||
dependencies = [
|
||||
"memchr",
|
||||
]
|
||||
@ -225,15 +225,15 @@ checksum = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610"
|
||||
|
||||
[[package]]
|
||||
name = "bytes"
|
||||
version = "1.2.1"
|
||||
version = "1.3.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ec8a7b6a70fde80372154c65702f00a0f56f3e1c36abbc6c440484be248856db"
|
||||
checksum = "dfb24e866b15a1af2a1b663f10c6b6b8f397a84aadb828f12e5b289ec23a3a3c"
|
||||
|
||||
[[package]]
|
||||
name = "cc"
|
||||
version = "1.0.76"
|
||||
version = "1.0.77"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "76a284da2e6fe2092f2353e51713435363112dfd60030e22add80be333fb928f"
|
||||
checksum = "e9f73505338f7d905b19d18738976aae232eb46b8efc15554ffc56deb5d9ebe4"
|
||||
|
||||
[[package]]
|
||||
name = "cfg-if"
|
||||
@ -417,9 +417,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "crossbeam-queue"
|
||||
version = "0.3.7"
|
||||
version = "0.3.8"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ebb3d1683412e9be6a15533314f00ec223c0762c522a3f77f048b265aab4470c"
|
||||
checksum = "d1cfb3ea8a53f37c40dea2c7bedcbd88bdfae54f5e2175d6ecaff1c988353add"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"crossbeam-utils",
|
||||
@ -427,9 +427,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "crossbeam-utils"
|
||||
version = "0.8.13"
|
||||
version = "0.8.14"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "422f23e724af1240ec469ea1e834d87a4b59ce2efe2c6a96256b0c47e2fd86aa"
|
||||
checksum = "4fb766fa798726286dbbb842f174001dab8abc7b627a1dd86e0b7222a95d929f"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
]
|
||||
@ -1911,9 +1911,9 @@ checksum = "6ac9a59f73473f1b8d852421e59e64809f025994837ef743615c6d0c5b305160"
|
||||
|
||||
[[package]]
|
||||
name = "poise"
|
||||
version = "0.3.0"
|
||||
version = "0.4.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f6c01d22dcda434b0dfe956c60f6ac9b0352c4c2f4af852afb3155a971cd306d"
|
||||
checksum = "aee439543df35482730552e7c9ed0c45a5f1d521548e6c0249967c4ba8828f60"
|
||||
dependencies = [
|
||||
"async-trait",
|
||||
"derivative",
|
||||
@ -1930,9 +1930,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "poise_macros"
|
||||
version = "0.3.0"
|
||||
version = "0.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "52ff861b6a52ec47bc54eb17424c025feeb040e82836036276c25dda045a8a0c"
|
||||
checksum = "53d21213ff7aeef5ab69729a5cddfb351a84a9bf3dadf9f470032440d43746c2"
|
||||
dependencies = [
|
||||
"darling",
|
||||
"proc-macro2",
|
||||
@ -2133,7 +2133,7 @@ checksum = "456c603be3e8d448b072f410900c09faf164fbce2d480456f50eea6e25f9c848"
|
||||
|
||||
[[package]]
|
||||
name = "reminder_rs"
|
||||
version = "1.6.7"
|
||||
version = "1.6.8"
|
||||
dependencies = [
|
||||
"base64",
|
||||
"chrono",
|
||||
@ -2518,9 +2518,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "serde_json"
|
||||
version = "1.0.88"
|
||||
version = "1.0.89"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8e8b3801309262e8184d9687fb697586833e939767aea0dda89f5a8e650e8bd7"
|
||||
checksum = "020ff22c755c2ed3f8cf162dbb41a7268d934702f3ed3631656ea597e08fc3db"
|
||||
dependencies = [
|
||||
"itoa 1.0.4",
|
||||
"ryu",
|
||||
|
@ -1,11 +1,11 @@
|
||||
[package]
|
||||
name = "reminder_rs"
|
||||
version = "1.6.8"
|
||||
version = "1.6.9"
|
||||
authors = ["jellywx <judesouthworth@pm.me>"]
|
||||
edition = "2018"
|
||||
|
||||
[dependencies]
|
||||
poise = "0.3"
|
||||
poise = "0.4"
|
||||
dotenv = "0.15"
|
||||
tokio = { version = "1", features = ["process", "full"] }
|
||||
reqwest = "0.11"
|
||||
|
@ -1,4 +1,4 @@
|
||||
use chrono::{DateTime, Days, Duration};
|
||||
use chrono::{DateTime, Days, Duration, Months, TimeZone};
|
||||
use chrono_tz::Tz;
|
||||
use lazy_static::lazy_static;
|
||||
use log::{error, info, warn};
|
||||
@ -62,18 +62,23 @@ pub fn substitute(string: &str) -> String {
|
||||
let format = caps.name("format").map(|m| m.as_str());
|
||||
|
||||
if let (Some(final_time), Some(format)) = (final_time, format) {
|
||||
let dt = NaiveDateTime::from_timestamp(final_time, 0);
|
||||
let now = Utc::now().naive_utc();
|
||||
match NaiveDateTime::from_timestamp_opt(final_time, 0) {
|
||||
Some(dt) => {
|
||||
let now = Utc::now().naive_utc();
|
||||
|
||||
let difference = {
|
||||
if now < dt {
|
||||
dt - Utc::now().naive_utc()
|
||||
} else {
|
||||
Utc::now().naive_utc() - dt
|
||||
let difference = {
|
||||
if now < dt {
|
||||
dt - Utc::now().naive_utc()
|
||||
} else {
|
||||
Utc::now().naive_utc() - dt
|
||||
}
|
||||
};
|
||||
|
||||
fmt_displacement(format, difference.num_seconds() as u64)
|
||||
}
|
||||
};
|
||||
|
||||
fmt_displacement(format, difference.num_seconds() as u64)
|
||||
None => String::new(),
|
||||
}
|
||||
} else {
|
||||
String::new()
|
||||
}
|
||||
@ -243,10 +248,10 @@ pub struct Reminder {
|
||||
attachment: Option<Vec<u8>>,
|
||||
attachment_name: Option<String>,
|
||||
|
||||
utc_time: NaiveDateTime,
|
||||
utc_time: DateTime<Utc>,
|
||||
timezone: String,
|
||||
restartable: bool,
|
||||
expires: Option<NaiveDateTime>,
|
||||
expires: Option<DateTime<Utc>>,
|
||||
interval_seconds: Option<u32>,
|
||||
interval_months: Option<u32>,
|
||||
|
||||
@ -330,9 +335,7 @@ WHERE
|
||||
|
||||
async fn reset_webhook(&self, pool: impl Executor<'_, Database = Database> + Copy) {
|
||||
let _ = sqlx::query!(
|
||||
"
|
||||
UPDATE channels SET webhook_id = NULL, webhook_token = NULL WHERE channel = ?
|
||||
",
|
||||
"UPDATE channels SET webhook_id = NULL, webhook_token = NULL WHERE channel = ?",
|
||||
self.channel_id
|
||||
)
|
||||
.execute(pool)
|
||||
@ -341,44 +344,25 @@ UPDATE channels SET webhook_id = NULL, webhook_token = NULL WHERE channel = ?
|
||||
|
||||
async fn refresh(&self, pool: impl Executor<'_, Database = Database> + Copy) {
|
||||
if self.interval_seconds.is_some() || self.interval_months.is_some() {
|
||||
let now = Utc::now().naive_local();
|
||||
let mut updated_reminder_time = self.utc_time;
|
||||
let now = Utc::now();
|
||||
let mut updated_reminder_time =
|
||||
self.utc_time.with_timezone(&self.timezone.parse().unwrap_or(Tz::UTC));
|
||||
|
||||
if let Some(interval) = self.interval_months {
|
||||
match sqlx::query!(
|
||||
// use the second date_add to force return value to datetime
|
||||
"SELECT DATE_ADD(DATE_ADD(?, INTERVAL ? MONTH), INTERVAL 0 SECOND) AS new_time",
|
||||
updated_reminder_time,
|
||||
interval
|
||||
)
|
||||
.fetch_one(pool)
|
||||
.await
|
||||
{
|
||||
Ok(row) => match row.new_time {
|
||||
Some(datetime) => {
|
||||
updated_reminder_time = datetime;
|
||||
}
|
||||
None => {
|
||||
warn!("Could not update interval by months: got NULL");
|
||||
updated_reminder_time = updated_reminder_time
|
||||
.checked_add_months(Months::new(interval))
|
||||
.unwrap_or_else(|| {
|
||||
warn!("Could not add months to a reminder");
|
||||
|
||||
updated_reminder_time += Duration::days(30);
|
||||
}
|
||||
},
|
||||
|
||||
Err(e) => {
|
||||
warn!("Could not update interval by months: {:?}", e);
|
||||
|
||||
// naively fallback to adding 30 days
|
||||
updated_reminder_time += Duration::days(30);
|
||||
}
|
||||
}
|
||||
updated_reminder_time
|
||||
});
|
||||
}
|
||||
|
||||
fn increment_days(
|
||||
now: NaiveDateTime,
|
||||
mut new_time: NaiveDateTime,
|
||||
fn increment_days<T: TimeZone>(
|
||||
now: DateTime<Utc>,
|
||||
mut new_time: DateTime<T>,
|
||||
interval: u32,
|
||||
) -> Option<NaiveDateTime> {
|
||||
) -> Option<DateTime<T>> {
|
||||
while new_time < now {
|
||||
new_time = new_time.checked_add_days(Days::new((interval / 86400).into()))?;
|
||||
}
|
||||
@ -403,16 +387,12 @@ UPDATE channels SET webhook_id = NULL, webhook_token = NULL WHERE channel = ?
|
||||
}
|
||||
}
|
||||
|
||||
if self.expires.map_or(false, |expires| {
|
||||
NaiveDateTime::from_timestamp(updated_reminder_time.timestamp(), 0) > expires
|
||||
}) {
|
||||
if self.expires.map_or(false, |expires| updated_reminder_time > expires) {
|
||||
self.force_delete(pool).await;
|
||||
} else {
|
||||
sqlx::query!(
|
||||
"
|
||||
UPDATE reminders SET `utc_time` = ? WHERE `id` = ?
|
||||
",
|
||||
updated_reminder_time,
|
||||
"UPDATE reminders SET `utc_time` = ? WHERE `id` = ?",
|
||||
updated_reminder_time.with_timezone(&Utc),
|
||||
self.id
|
||||
)
|
||||
.execute(pool)
|
||||
@ -425,15 +405,10 @@ UPDATE reminders SET `utc_time` = ? WHERE `id` = ?
|
||||
}
|
||||
|
||||
async fn force_delete(&self, pool: impl Executor<'_, Database = Database> + Copy) {
|
||||
sqlx::query!(
|
||||
"
|
||||
DELETE FROM reminders WHERE `id` = ?
|
||||
",
|
||||
self.id
|
||||
)
|
||||
.execute(pool)
|
||||
.await
|
||||
.expect(&format!("Could not delete Reminder {}", self.id));
|
||||
sqlx::query!("DELETE FROM reminders WHERE `id` = ?", self.id)
|
||||
.execute(pool)
|
||||
.await
|
||||
.expect(&format!("Could not delete Reminder {}", self.id));
|
||||
}
|
||||
|
||||
async fn pin_message<M: Into<u64>>(&self, message_id: M, http: impl AsRef<Http>) {
|
||||
@ -571,9 +546,7 @@ DELETE FROM reminders WHERE `id` = ?
|
||||
.map_or(true, |inner| inner >= Utc::now().naive_local()))
|
||||
{
|
||||
let _ = sqlx::query!(
|
||||
"
|
||||
UPDATE `channels` SET paused = 0, paused_until = NULL WHERE `channel` = ?
|
||||
",
|
||||
"UPDATE `channels` SET paused = 0, paused_until = NULL WHERE `channel` = ?",
|
||||
self.channel_id
|
||||
)
|
||||
.execute(pool)
|
||||
|
@ -1,10 +1,6 @@
|
||||
use std::{
|
||||
collections::HashSet,
|
||||
string::ToString,
|
||||
time::{SystemTime, UNIX_EPOCH},
|
||||
};
|
||||
use std::{collections::HashSet, string::ToString};
|
||||
|
||||
use chrono::NaiveDateTime;
|
||||
use chrono::{DateTime, NaiveDateTime, Utc};
|
||||
use chrono_tz::Tz;
|
||||
use num_integer::Integer;
|
||||
use poise::{
|
||||
@ -60,18 +56,27 @@ pub async fn pause(
|
||||
let parsed = natural_parser(&until, &timezone.to_string()).await;
|
||||
|
||||
if let Some(timestamp) = parsed {
|
||||
let dt = NaiveDateTime::from_timestamp(timestamp, 0);
|
||||
match NaiveDateTime::from_timestamp_opt(timestamp, 0) {
|
||||
Some(dt) => {
|
||||
channel.paused = true;
|
||||
channel.paused_until = Some(dt);
|
||||
|
||||
channel.paused = true;
|
||||
channel.paused_until = Some(dt);
|
||||
channel.commit_changes(&ctx.data().database).await;
|
||||
|
||||
channel.commit_changes(&ctx.data().database).await;
|
||||
ctx.say(format!(
|
||||
"Reminders in this channel have been silenced until **<t:{}:D>**",
|
||||
timestamp
|
||||
))
|
||||
.await?;
|
||||
}
|
||||
|
||||
ctx.say(format!(
|
||||
"Reminders in this channel have been silenced until **<t:{}:D>**",
|
||||
timestamp
|
||||
))
|
||||
.await?;
|
||||
None => {
|
||||
ctx.say(format!(
|
||||
"Time processed could not be interpreted as `DateTime`. Please write the time as clearly as possible",
|
||||
))
|
||||
.await?;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
ctx.say(
|
||||
"Time could not be processed. Please write the time as clearly as possible",
|
||||
@ -432,11 +437,8 @@ pub fn show_delete_page(reminders: &[Reminder], page: usize, timezone: Tz) -> Cr
|
||||
reply
|
||||
}
|
||||
|
||||
fn time_difference(start_time: NaiveDateTime) -> String {
|
||||
let unix_time = SystemTime::now().duration_since(UNIX_EPOCH).unwrap().as_secs() as i64;
|
||||
let now = NaiveDateTime::from_timestamp(unix_time, 0);
|
||||
|
||||
let delta = (now - start_time).num_seconds();
|
||||
fn time_difference(start_time: DateTime<Utc>) -> String {
|
||||
let delta = (Utc::now() - start_time).num_seconds();
|
||||
|
||||
let (minutes, seconds) = delta.div_rem(&60);
|
||||
let (hours, minutes) = minutes.div_rem(&60);
|
||||
|
@ -175,17 +175,15 @@ impl<'a> MultiReminderBuilder<'a> {
|
||||
}
|
||||
|
||||
pub fn time<T: Into<i64>>(mut self, time: T) -> Self {
|
||||
self.utc_time = NaiveDateTime::from_timestamp(time.into(), 0);
|
||||
if let Some(utc_time) = NaiveDateTime::from_timestamp_opt(time.into(), 0) {
|
||||
self.utc_time = utc_time;
|
||||
}
|
||||
|
||||
self
|
||||
}
|
||||
|
||||
pub fn expires<T: Into<i64>>(mut self, time: Option<T>) -> Self {
|
||||
if let Some(t) = time {
|
||||
self.expires = Some(NaiveDateTime::from_timestamp(t.into(), 0));
|
||||
} else {
|
||||
self.expires = None;
|
||||
}
|
||||
self.expires = time.map(|t| NaiveDateTime::from_timestamp_opt(t.into(), 0)).flatten();
|
||||
|
||||
self
|
||||
}
|
||||
|
@ -6,7 +6,7 @@ pub mod look_flags;
|
||||
|
||||
use std::hash::{Hash, Hasher};
|
||||
|
||||
use chrono::{NaiveDateTime, TimeZone};
|
||||
use chrono::{DateTime, NaiveDateTime, Utc};
|
||||
use chrono_tz::Tz;
|
||||
use poise::serenity_prelude::{
|
||||
model::id::{ChannelId, GuildId, UserId},
|
||||
@ -24,7 +24,7 @@ pub struct Reminder {
|
||||
pub id: u32,
|
||||
pub uid: String,
|
||||
pub channel: u64,
|
||||
pub utc_time: NaiveDateTime,
|
||||
pub utc_time: DateTime<Utc>,
|
||||
pub interval_seconds: Option<u32>,
|
||||
pub interval_months: Option<u32>,
|
||||
pub expires: Option<NaiveDateTime>,
|
||||
@ -310,16 +310,15 @@ WHERE
|
||||
count + 1,
|
||||
self.display_content(),
|
||||
self.channel,
|
||||
timezone.timestamp(self.utc_time.timestamp(), 0).format("%Y-%m-%d %H:%M:%S")
|
||||
self.utc_time.with_timezone(timezone).format("%Y-%m-%d %H:%M:%S")
|
||||
)
|
||||
}
|
||||
|
||||
pub fn display(&self, flags: &LookFlags, timezone: &Tz) -> String {
|
||||
let time_display = match flags.time_display {
|
||||
TimeDisplayType::Absolute => timezone
|
||||
.timestamp(self.utc_time.timestamp(), 0)
|
||||
.format("%Y-%m-%d %H:%M:%S")
|
||||
.to_string(),
|
||||
TimeDisplayType::Absolute => {
|
||||
self.utc_time.with_timezone(timezone).format("%Y-%m-%d %H:%M:%S").to_string()
|
||||
}
|
||||
|
||||
TimeDisplayType::Relative => format!("<t:{}:R>", self.utc_time.timestamp()),
|
||||
};
|
||||
|
@ -1,9 +1,9 @@
|
||||
use chrono::NaiveDateTime;
|
||||
use chrono::{DateTime, Utc};
|
||||
use sqlx::MySqlPool;
|
||||
|
||||
pub struct Timer {
|
||||
pub name: String,
|
||||
pub start_time: NaiveDateTime,
|
||||
pub start_time: DateTime<Utc>,
|
||||
pub owner: u64,
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user