Skip to content

Commit ebd921f

Browse files
authored
Added Support for displaying the timestamp messages (#990)
1 parent 6b6340a commit ebd921f

2 files changed

Lines changed: 123 additions & 0 deletions

File tree

packages/markups/src/elements/InlineElements.js

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ import ChannelMention from '../mentions/ChannelMention';
1010
import ColorElement from './ColorElement';
1111
import LinkSpan from './LinkSpan';
1212
import UserMention from '../mentions/UserMention';
13+
import TimestampElement from './TimestampElement';
1314

1415
const InlineElements = ({ contents }) =>
1516
contents.map((content, index) => {
@@ -53,6 +54,10 @@ const InlineElements = ({ contents }) =>
5354
}
5455
/>
5556
);
57+
58+
case 'TIMESTAMP':
59+
return <TimestampElement key={index} contents={content.value} />;
60+
5661
default:
5762
return null;
5863
}
Lines changed: 118 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,118 @@
1+
import React from 'react';
2+
import PropTypes from 'prop-types';
3+
import CodeElement from './CodeElement';
4+
5+
function timeAgo(dateParam, locale) {
6+
const int = new Intl.RelativeTimeFormat(locale, { style: 'long' });
7+
8+
const date = new Date(dateParam).getTime();
9+
const today = new Date().getTime();
10+
const seconds = Math.round((date - today) / 1000);
11+
const minutes = Math.round(seconds / 60);
12+
const hours = Math.round(minutes / 60);
13+
const days = Math.round(hours / 24);
14+
const weeks = Math.round(days / 7);
15+
const months = new Date(date).getMonth() - new Date().getMonth();
16+
const years = new Date(date).getFullYear() - new Date().getFullYear();
17+
18+
if (Math.abs(seconds) < 60) {
19+
return int.format(seconds, 'seconds');
20+
}
21+
if (Math.abs(minutes) < 60) {
22+
return int.format(minutes, 'minutes');
23+
}
24+
if (Math.abs(hours) < 24) {
25+
return int.format(hours, 'hours');
26+
}
27+
if (Math.abs(days) < 7) {
28+
return int.format(days, 'days');
29+
}
30+
if (Math.abs(weeks) < 4) {
31+
return int.format(weeks, 'weeks');
32+
}
33+
if (Math.abs(months) < 12) {
34+
return int.format(months, 'months');
35+
}
36+
return int.format(years, 'years');
37+
}
38+
39+
const formatTimestamp = (timestamp, format) => {
40+
const date = new Date(timestamp * 1000);
41+
42+
const getOrdinalDate = (day) => {
43+
const suffix = ['th', 'st', 'nd', 'rd'];
44+
const val = day % 100;
45+
return day + (suffix[(val - 20) % 10] || suffix[val] || suffix[0]);
46+
};
47+
48+
const timeZoneOffset = date.getTimezoneOffset();
49+
const sign = timeZoneOffset > 0 ? '-' : '+';
50+
const hours = Math.floor(Math.abs(timeZoneOffset) / 60);
51+
const minutes = Math.abs(timeZoneOffset) % 60;
52+
const timeZone = `GMT${sign}${String(hours).padStart(2, '0')}:${String(
53+
minutes
54+
).padStart(2, '0')}`;
55+
56+
const month = date.toLocaleString('en-US', { month: 'long' });
57+
const day = getOrdinalDate(date.getDate());
58+
const year = date.getFullYear();
59+
const time = date.toLocaleString([], {
60+
hour: '2-digit',
61+
minute: '2-digit',
62+
second: '2-digit',
63+
});
64+
65+
const shortDate = date.toLocaleDateString('en-US');
66+
const shortTime = date.toLocaleTimeString([], {
67+
hour: '2-digit',
68+
minute: '2-digit',
69+
});
70+
71+
switch (format) {
72+
case 't': {
73+
return shortTime;
74+
}
75+
case 'T': {
76+
return time;
77+
}
78+
case 'd': {
79+
return shortDate;
80+
}
81+
case 'D': {
82+
return `${shortDate}, ${shortTime}`;
83+
}
84+
case 'f': {
85+
return `${month} ${day}, ${year} at ${time} ${timeZone}`;
86+
}
87+
case 'F': {
88+
const weekday = date.toLocaleString('en-US', { weekday: 'long' });
89+
return `${weekday}, ${month} ${day} ${year} at ${time} ${timeZone}`;
90+
}
91+
case 'R': {
92+
return timeAgo(timestamp * 1000, 'en');
93+
}
94+
default: {
95+
return date.toLocaleString();
96+
}
97+
}
98+
};
99+
100+
const TimestampElement = ({ contents }) => {
101+
if (typeof contents === 'object' && contents.timestamp && contents.format) {
102+
const { timestamp, format } = contents;
103+
104+
const formattedTimestamp = formatTimestamp(parseInt(timestamp, 10), format);
105+
return <CodeElement contents={{ value: formattedTimestamp }} />;
106+
}
107+
108+
return null;
109+
};
110+
111+
export default TimestampElement;
112+
113+
TimestampElement.propTypes = {
114+
contents: PropTypes.shape({
115+
timestamp: PropTypes.string.isRequired,
116+
format: PropTypes.string.isRequired,
117+
}).isRequired,
118+
};

0 commit comments

Comments
 (0)