Skip to content

Commit 9163fc0

Browse files
Merge branch 'develop' into feat/openapi-oauth-apps-create
2 parents 6012729 + 85f227a commit 9163fc0

File tree

3 files changed

+76
-4
lines changed

3 files changed

+76
-4
lines changed

packages/message-parser/src/grammar.pegjs

Lines changed: 20 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@
3333
tasks,
3434
unorderedList,
3535
timestamp,
36+
timestampFromHours,
3637
} = require('./utils');
3738

3839
let skipBold = false;
@@ -74,12 +75,28 @@ Blockquote = b:BlockquoteLine+ { return quote(b); }
7475
BlockquoteLine = ">" [ \t]* @Paragraph
7576

7677
// <t:1630360800:?{format}>
78+
// <t:2025-07-22T10:00:00.000Z?:?{format}>
79+
// <t:2025-07-22T10:00:00:?{format}>
80+
// <t:00:00:?{format}>
7781

7882
TimestampType = "t" / "T" / "d" / "D" / "f" / "F" / "R"
7983

8084
Unixtime = d:Digit |10| { return d.join(''); }
8185

82-
Timestamp = "<t:" date:Unixtime ":" format:TimestampType ">" { return timestamp(date, format); } / "<t:" date:Unixtime ">" { return timestamp(date); }
86+
TimestampHoursMinutesSeconds = hours:Digit |2| ":" minutes:Digit|2| ":" seconds:Digit |2| "Z"? { return timestampFromHours(hours.join(''), minutes.join(''), seconds.join('')); }
87+
88+
TimestampHoursMinutes = hours:Digit |2| ":" minutes:Digit|2| "Z"? { return timestampFromHours(hours.join(''), minutes.join('')); }
89+
90+
91+
Timestamp = TimestampHoursMinutesSeconds / TimestampHoursMinutes
92+
93+
94+
ISO8601Date = year:Digit |4| "-" month:Digit |2| "-" day:Digit |2| "T" hours:Digit |2| ":" minutes:Digit|2| ":" seconds:Digit |2| "." milliseconds:Digit |3| "Z"? { return new Date(year.join('') + '-' + month.join('') + '-' + day.join('') + 'T' + hours.join('') + ':' + minutes.join('') + ':' + seconds.join('') + '.' + milliseconds.join('') + 'Z').getTime().toString(); }
95+
96+
ISO8601DateWithoutMilliseconds = year:Digit |4| "-" month:Digit |2| "-" day:Digit |2| "T" hours:Digit |2| ":" minutes:Digit|2| ":" seconds:Digit |2| "Z"? { return new Date(year.join('') + '-' + month.join('') + '-' + day.join('') + 'T' + hours.join('') + ':' + minutes.join('') + ':' + seconds.join('') + 'Z').getTime().toString(); }
97+
98+
99+
TimestampRules = "<t:" date:(Unixtime / ISO8601Date / ISO8601DateWithoutMilliseconds / Timestamp) ":" format:TimestampType ">" { return timestamp(date, format); } / "<t:" date:(Unixtime / ISO8601Date / ISO8601DateWithoutMilliseconds / Timestamp) ">" { return timestamp(date); }
83100

84101
/**
85102
*
@@ -230,7 +247,7 @@ InlineEmoji = & { return !skipInlineEmoji; } emo:Emoji { return emo; }
230247
InlineEmoticon = & { return !skipInlineEmoji; } emo:Emoticon & (EmoticonNeighbor / InlineItemPattern) { skipInlineEmoji = false; return emo; }
231248

232249
InlineItemPattern = Whitespace
233-
/ Timestamp
250+
/ TimestampRules
234251
/ MaybeReferences
235252
/ AutolinkedPhone
236253
/ AutolinkedEmail
@@ -494,7 +511,7 @@ BoldEmoticon = & { return !skipBoldEmoji; } emo:Emoticon & (EmoticonNeighbor / B
494511
/* Strike */
495512
Strikethrough = [\x7E] [\x7E] @StrikethroughContent [\x7E] [\x7E] / [\x7E] @StrikethroughContent [\x7E]
496513

497-
StrikethroughContent = text:(Timestamp / Whitespace / InlineCode / MaybeReferences / UserMention / ChannelMention / MaybeItalic / MaybeBold / Emoji / Emoticon / AnyStrike / Line)+ {
514+
StrikethroughContent = text:(TimestampRules / Whitespace / InlineCode / MaybeReferences / UserMention / ChannelMention / MaybeItalic / MaybeBold / Emoji / Emoticon / AnyStrike / Line)+ {
498515
return strike(reducePlainTexts(text));
499516
}
500517

packages/message-parser/src/utils.ts

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -251,6 +251,20 @@ export const timestamp = (
251251
};
252252
};
253253

254+
export const timestampFromHours = (
255+
hours: string,
256+
minutes = '00',
257+
seconds = '00',
258+
) => {
259+
const date = new Date();
260+
261+
const yearMonthDay = date.toISOString().split('T')[0];
262+
263+
return new Date(`${yearMonthDay}T${hours}:${minutes}:${seconds}Z`)
264+
.getTime()
265+
.toString();
266+
};
267+
254268
export const extractFirstResult = (
255269
value: Types[keyof Types]['value'],
256270
): Types[keyof Types]['value'] => {

packages/message-parser/tests/timestamp.test.ts

Lines changed: 42 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,12 @@
11
import { parse } from '../src';
2-
import { bold, paragraph, plain, strike, timestamp } from '../src/utils';
2+
import {
3+
bold,
4+
paragraph,
5+
plain,
6+
strike,
7+
timestamp,
8+
timestampFromHours,
9+
} from '../src/utils';
310

411
test.each([
512
[`<t:1708551317>`, [paragraph([timestamp('1708551317')])]],
@@ -25,3 +32,37 @@ test.each([
2532
])('parses %p', (input, output) => {
2633
expect(parse(input)).toMatchObject(output);
2734
});
35+
36+
test.each([
37+
[
38+
'<t:2025-07-22T10:00:00.000Z:R>',
39+
[paragraph([timestamp('1753178400000', 'R')])],
40+
],
41+
[
42+
'<t:2025-07-22T10:00:00.000Z:R>',
43+
[paragraph([timestamp('1753178400000', 'R')])],
44+
],
45+
[
46+
'<t:2025-07-22T10:00:00.000:R>',
47+
[paragraph([timestamp('1753178400000', 'R')])],
48+
],
49+
['<t:2025-07-22T10:00:00:R>', [paragraph([timestamp('1753178400000', 'R')])]],
50+
[
51+
'<t:10:00:00:R>',
52+
[paragraph([timestamp(timestampFromHours('10', '00', '00'), 'R')])],
53+
],
54+
[
55+
'<t:10:00:R>',
56+
[paragraph([timestamp(timestampFromHours('10', '00', '00'), 'R')])],
57+
],
58+
[
59+
'<t:10:00:00>',
60+
[paragraph([timestamp(timestampFromHours('10', '00', '00'), 't')])],
61+
],
62+
[
63+
'<t:10:00>',
64+
[paragraph([timestamp(timestampFromHours('10', '00', '00'), 't')])],
65+
],
66+
])('parses %p', (input, output) => {
67+
expect(parse(input)).toMatchObject(output);
68+
});

0 commit comments

Comments
 (0)