mail_builder/headers/
date.rs1use std::{
13 io::{self, Write},
14 time::SystemTime,
15};
16
17pub static DOW: &[&str] = &["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"];
18pub static MONTH: &[&str] = &[
19 "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec",
20];
21
22use super::Header;
23
24#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord)]
26pub struct Date {
27 pub date: i64,
28}
29
30impl Date {
31 pub fn new(date: i64) -> Self {
33 Self {
34 date,
35 }
36 }
37
38 pub fn now() -> Self {
40 Self {
41 date: SystemTime::now()
42 .duration_since(SystemTime::UNIX_EPOCH)
43 .map(|d| d.as_secs())
44 .unwrap_or(0) as i64,
45 }
46 }
47
48 pub fn to_rfc822(&self) -> String {
50 let (z, seconds) = ((self.date / 86400) + 719468, self.date % 86400);
52 let era: i64 = (if z >= 0 { z } else { z - 146096 }) / 146097;
53 let doe: u64 = (z - era * 146097) as u64; let yoe: u64 = (doe - doe / 1460 + doe / 36524 - doe / 146096) / 365; let y: i64 = (yoe as i64) + era * 400;
56 let doy: u64 = doe - (365 * yoe + yoe / 4 - yoe / 100); let mp = (5 * doy + 2) / 153; let d: u64 = doy - (153 * mp + 2) / 5 + 1; let m: u64 = if mp < 10 { mp + 3 } else { mp - 9 }; let (h, mn, s) = (seconds / 3600, (seconds / 60) % 60, seconds % 60);
61
62 format!(
63 "{}, {} {} {:04} {:02}:{:02}:{:02} +0000", DOW[(((self.date as f64 / 86400.0).floor() as i64 + 4).rem_euclid(7)) as usize],
65 d,
66 MONTH.get(m.saturating_sub(1) as usize).unwrap_or(&""),
67 (y + i64::from(m <= 2)),
68 h,
69 mn,
70 s,
71 )
79 }
80}
81
82impl From<i64> for Date {
83 fn from(datetime: i64) -> Self {
84 Date::new(datetime)
85 }
86}
87
88impl From<u64> for Date {
89 fn from(datetime: u64) -> Self {
90 Date::new(datetime as i64)
91 }
92}
93
94impl Header for Date {
95 fn write_header(&self, mut output: impl Write, _bytes_written: usize) -> io::Result<usize> {
96 output.write_all(self.to_rfc822().as_bytes())?;
97 output.write_all(b"\r\n")?;
98 Ok(0)
99 }
100}