slack_morphism/models/blocks/
datetime.rs1use crate::SlackTextFormat;
2
3pub enum SlackDateTimeFormats {
4 DateNum,
5 Date,
6 DateShort,
7 DateLong,
8 DatePretty,
9 DateShortPretty,
10 DateLongPretty,
11 Time,
12 TimeSecs,
13}
14
15#[allow(clippy::to_string_trait_impl)]
16impl ToString for SlackDateTimeFormats {
17 fn to_string(&self) -> String {
18 match self {
19 SlackDateTimeFormats::DateNum => "{date_num}".into(),
20 SlackDateTimeFormats::Date => "{date}".into(),
21 SlackDateTimeFormats::DateShort => "{date_short}".into(),
22 SlackDateTimeFormats::DateLong => "{date_long}".into(),
23 SlackDateTimeFormats::DatePretty => "{date_pretty}".into(),
24 SlackDateTimeFormats::DateShortPretty => "{date_short_pretty}".into(),
25 SlackDateTimeFormats::DateLongPretty => "{date_long_pretty}".into(),
26 SlackDateTimeFormats::Time => "{time}".into(),
27 SlackDateTimeFormats::TimeSecs => "{time_secs}".into(),
28 }
29 }
30}
31
32fn fmt_slack_date_parts(
33 timestamp: i64,
34 fallback: &str,
35 token_string: &str,
36 link: Option<&String>,
37) -> String {
38 let link_part = link
39 .map(|value| format!("^{value}"))
40 .unwrap_or_else(|| "".into());
41 format!(
42 "<!date^{timestamp}^{token_string}{link_part}|{fallback}>",
43 timestamp = timestamp,
44 token_string = token_string,
45 link_part = link_part,
46 fallback = fallback
47 )
48}
49
50#[cfg(not(feature = "obsolete-chrono"))]
51pub fn fmt_slack_date(
52 date: &crate::SlackUtcDateTime,
53 token_string: &str,
54 link: Option<&String>,
55) -> String {
56 use crate::models::common::datetime::{to_rfc2822, unix_seconds};
57
58 fmt_slack_date_parts(
59 unix_seconds(date),
60 to_rfc2822(date).as_str(),
61 token_string,
62 link,
63 )
64}
65
66#[cfg(feature = "obsolete-chrono")]
67pub fn fmt_slack_date<TZ: chrono::TimeZone>(
68 date: &chrono::DateTime<TZ>,
69 token_string: &str,
70 link: Option<&String>,
71) -> String
72where
73 <TZ as chrono::offset::TimeZone>::Offset: std::fmt::Display,
74{
75 fmt_slack_date_parts(
76 date.timestamp(),
77 date.to_rfc2822().as_str(),
78 token_string,
79 link,
80 )
81}
82
83#[cfg(feature = "obsolete-chrono")]
84impl<TZ: chrono::TimeZone> SlackTextFormat for chrono::DateTime<TZ>
85where
86 <TZ as chrono::offset::TimeZone>::Offset: std::fmt::Display,
87{
88 fn to_slack_format(&self) -> String {
89 fmt_slack_date(
90 self,
91 SlackDateTimeFormats::DatePretty.to_string().as_str(),
92 None,
93 )
94 }
95}
96
97#[cfg(not(feature = "obsolete-chrono"))]
98impl SlackTextFormat for jiff::Timestamp {
99 fn to_slack_format(&self) -> String {
100 fmt_slack_date(
101 self,
102 SlackDateTimeFormats::DatePretty.to_string().as_str(),
103 None,
104 )
105 }
106}
107
108#[cfg(not(feature = "obsolete-chrono"))]
109impl SlackTextFormat for jiff::Zoned {
110 fn to_slack_format(&self) -> String {
111 let fallback = jiff::fmt::rfc2822::to_string(self).unwrap_or_else(|_| self.to_string());
112 fmt_slack_date_parts(
113 self.timestamp().as_second(),
114 fallback.as_str(),
115 SlackDateTimeFormats::DatePretty.to_string().as_str(),
116 None,
117 )
118 }
119}
120
121#[cfg(test)]
122mod test {
123 use super::*;
124 use crate::prelude::SlackUtcDateTime;
125
126 const EXPECTED_FALLBACK: &str = "Wed, 1 Jan 2020 00:42:42 +0000";
129
130 #[test]
131 fn test_fmt_slack_date() {
132 let dt = "2020-01-01T00:42:42Z".parse::<SlackUtcDateTime>().unwrap();
133
134 assert_eq!(
135 fmt_slack_date(
136 &dt,
137 SlackDateTimeFormats::DatePretty.to_string().as_str(),
138 None
139 ),
140 format!("<!date^1577839362^{{date_pretty}}|{EXPECTED_FALLBACK}>")
141 );
142 }
143
144 #[test]
145 fn test_fmt_slack_date_with_link() {
146 let dt = "2020-01-01T00:42:42Z".parse::<SlackUtcDateTime>().unwrap();
147
148 assert_eq!(
149 fmt_slack_date(
150 &dt,
151 SlackDateTimeFormats::DateNum.to_string().as_str(),
152 Some(&"https://example.net/".to_string())
153 ),
154 format!("<!date^1577839362^{{date_num}}^https://example.net/|{EXPECTED_FALLBACK}>")
155 );
156 }
157}