1 |
|
2 | function showtimeago(dateParam) {
|
3 | try {
|
4 | const MONTH_NAMES = [
|
5 | 'January', 'February', 'March', 'April', 'May', 'June',
|
6 | 'July', 'August', 'September', 'October', 'November', 'December'
|
7 | ];
|
8 |
|
9 |
|
10 | function getOrdinalNum(n) {
|
11 | return n + (n > 0 ? ['th', 'st', 'nd', 'rd'][(n > 3 && n < 21) || n % 10 > 3 ? 0 : n % 10] : '');
|
12 | }
|
13 |
|
14 |
|
15 | function getFormattedDate(date, preformattedDate, hideYear) {
|
16 | const day = date.getDate();
|
17 | const month = MONTH_NAMES[date.getMonth()];
|
18 | const year = date.getFullYear();
|
19 | let hours = date.getHours();
|
20 | let minutes = date.getMinutes();
|
21 | const ampm = hours >= 12 ? 'PM' : 'AM';
|
22 |
|
23 | hours = hours % 12 || 12;
|
24 | minutes = minutes < 10 ? `0${minutes}` : minutes;
|
25 |
|
26 | if (preformattedDate) {
|
27 | return `${preformattedDate} at ${hours}:${minutes} ${ampm}`;
|
28 | }
|
29 |
|
30 | if (hideYear) {
|
31 | return `${month} ${getOrdinalNum(day)}, at ${hours}:${minutes} ${ampm}`;
|
32 | }
|
33 |
|
34 | return `${month} ${getOrdinalNum(day)}, ${year} at ${hours}:${minutes} ${ampm}`;
|
35 | }
|
36 |
|
37 |
|
38 | function validateDateParam(dateParam) {
|
39 | if (dateParam === undefined || dateParam === null) {
|
40 | throw new Error("Invalid date parameter: dateParam cannot be empty. It must be a valid ISO date string or a Date object.");
|
41 | }
|
42 | if (typeof dateParam === 'string') {
|
43 | const date = new Date(dateParam);
|
44 | if (isNaN(date.getTime())) {
|
45 | throw new Error("Invalid date parameter: dateParam is not a valid ISO date string.");
|
46 | }
|
47 | return date;
|
48 | }
|
49 | if (typeof dateParam === 'object' && dateParam instanceof Date) {
|
50 | return dateParam;
|
51 | }
|
52 | throw new Error("Invalid date parameter: dateParam must be a valid ISO date string or a Date object.");
|
53 | }
|
54 |
|
55 |
|
56 | function timeAgo(dateParam) {
|
57 | const date = validateDateParam(dateParam);
|
58 | const now = new Date();
|
59 |
|
60 |
|
61 | if (date > now) {
|
62 | throw new Error("Invalid date: The provided date is in the future.");
|
63 | }
|
64 |
|
65 | const DAY_IN_MS = 86400000;
|
66 | const YEAR_IN_MS = 365.25 * DAY_IN_MS;
|
67 | const yesterday = new Date(now.getTime() - DAY_IN_MS);
|
68 |
|
69 | const seconds = Math.round((now.getTime() - date.getTime()) / 1000);
|
70 | const minutes = Math.round(seconds / 60);
|
71 | const hours = Math.round(minutes / 60);
|
72 | const days = Math.round(hours / 24);
|
73 | const months = Math.round(days / 30.44);
|
74 | const years = Math.floor(days / 365.25);
|
75 |
|
76 | const isToday = now.toDateString() === date.toDateString();
|
77 | const isYesterday = yesterday.toDateString() === date.toDateString();
|
78 |
|
79 |
|
80 | const oneYearAgo = new Date(now.getFullYear() - 1, now.getMonth(), now.getDate(), now.getHours(), now.getMinutes(), now.getSeconds(), now.getMilliseconds());
|
81 | if (date.toDateString() === oneYearAgo.toDateString()) {
|
82 | return '1 year ago';
|
83 | }
|
84 |
|
85 |
|
86 |
|
87 |
|
88 |
|
89 |
|
90 |
|
91 |
|
92 |
|
93 |
|
94 |
|
95 |
|
96 |
|
97 |
|
98 |
|
99 | switch (true) {
|
100 | case (seconds < 2):
|
101 | return 'now';
|
102 | case (seconds < 60):
|
103 | return `${seconds} seconds ago`;
|
104 | case (seconds < 90):
|
105 | return 'about a minute ago';
|
106 | case (minutes < 60):
|
107 | return `${minutes} minutes ago`;
|
108 | case (hours === 1):
|
109 | return '1 hour ago';
|
110 | case (hours < 24):
|
111 | return `${hours} hours ago`;
|
112 | case (isToday):
|
113 | return getFormattedDate(date, 'Today');
|
114 | case (isYesterday):
|
115 | return getFormattedDate(date, 'Yesterday');
|
116 | case (days < 30):
|
117 | return `${days} days ago`;
|
118 | case (months === 1):
|
119 | return '1 month ago';
|
120 | case (months < 12):
|
121 | return `${months} months ago`;
|
122 | case (years === 1):
|
123 | return '1 year ago';
|
124 | case (years > 1):
|
125 | return `${years} years ago`;
|
126 | default:
|
127 | return getFormattedDate(date);
|
128 | }
|
129 | }
|
130 |
|
131 | return timeAgo(dateParam);
|
132 |
|
133 | } catch (error) {
|
134 | console.error("Error in showtimeago function:", error);
|
135 | throw new Error(error.message);
|
136 | }
|
137 | }
|
138 |
|
139 |
|
140 |
|
141 |
|
142 |
|
143 |
|
144 |
|
145 |
|
146 |
|
147 |
|
148 |
|
149 |
|
150 |
|
151 |
|
152 |
|
153 |
|
154 |
|
155 | module.exports = showtimeago; |
\ | No newline at end of file |