mcaptcha/
date.rs

1// Copyright (C) 2022  Aravinth Manivannan <realaravinth@batsense.net>
2// SPDX-FileCopyrightText: 2023 Aravinth Manivannan <realaravinth@batsense.net>
3//
4// SPDX-License-Identifier: AGPL-3.0-or-later
5
6use std::fmt::Debug;
7
8use sqlx::types::time::OffsetDateTime;
9
10#[derive(Clone)]
11pub struct Date {
12    pub time: OffsetDateTime,
13}
14
15impl Debug for Date {
16    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
17        f.debug_struct("Date")
18            .field("time", &self.print_date())
19            .finish()
20    }
21}
22
23pub const MINUTE: i64 = 60;
24pub const HOUR: i64 = MINUTE * 60;
25pub const DAY: i64 = HOUR * 24;
26pub const WEEK: i64 = DAY * 7;
27
28impl Date {
29    pub fn format(date: &OffsetDateTime) -> String {
30        let timestamp = date.unix_timestamp();
31        let now = OffsetDateTime::now_utc().unix_timestamp();
32
33        let difference = now - timestamp;
34
35        if difference >= 3 * WEEK {
36            format!("{}{}{}", date.year(), date.month(), date.date())
37        } else if (DAY..(3 * WEEK)).contains(&difference) {
38            format!("{} days ago", date.hour())
39        } else if (HOUR..DAY).contains(&difference) {
40            format!("{} hours ago", date.hour())
41        } else if (MINUTE..HOUR).contains(&difference) {
42            format!("{} minutes ago", date.minute())
43        } else {
44            format!("{} seconds ago", date.second())
45        }
46    }
47
48    /// print relative time from date
49    pub fn print_date(&self) -> String {
50        Self::format(&self.time)
51    }
52
53    /// print date
54    pub fn date(&self) -> String {
55        format!(
56            "{}{}{}",
57            self.time.year(),
58            self.time.month(),
59            self.time.date()
60        )
61    }
62
63    pub fn new(unix: i64) -> Self {
64        Self {
65            time: OffsetDateTime::from_unix_timestamp(unix).unwrap(),
66        }
67    }
68}
69
70#[cfg(test)]
71mod tests {
72    use super::*;
73
74    #[test]
75    fn print_date_test() {
76        let mut n = Date {
77            time: OffsetDateTime::now_utc(),
78        };
79
80        let timestamp = n.time.unix_timestamp();
81        println!("timestamp: {}", timestamp);
82
83        // seconds test
84        assert!(n.print_date().contains("seconds ago"));
85        n.time = OffsetDateTime::from_unix_timestamp(timestamp - 5).unwrap();
86        assert!(n.print_date().contains("seconds ago"));
87
88        // minutes test
89        n.time = OffsetDateTime::from_unix_timestamp(timestamp - MINUTE * 2).unwrap();
90        assert!(n.print_date().contains("minutes ago"));
91        n.time = OffsetDateTime::from_unix_timestamp(timestamp - MINUTE * 56).unwrap();
92        assert!(n.print_date().contains("minutes ago"));
93
94        // hours test
95        n.time = OffsetDateTime::from_unix_timestamp(timestamp - HOUR).unwrap();
96        assert!(n.print_date().contains("hours ago"));
97        n.time = OffsetDateTime::from_unix_timestamp(timestamp - HOUR * 23).unwrap();
98        assert!(n.print_date().contains("hours ago"));
99
100        // days test
101        n.time = OffsetDateTime::from_unix_timestamp(timestamp - 2 * WEEK).unwrap();
102        assert!(n.print_date().contains("days ago"));
103
104        // date test
105        n.time = OffsetDateTime::from_unix_timestamp(timestamp - 6 * WEEK).unwrap();
106        let date = format!("{}{}{}", n.time.year(), n.time.month(), n.time.date());
107        assert!(n.print_date().contains(&date))
108    }
109}