@@ -23,32 +23,55 @@ export function formatDate(date: Date, pattern: string, localeCode?: string): st
2323 const dayNameShort = locale . dayNamesShort [ dayOfWeek ] ?? 'Unknown'
2424 const monthName = locale . monthNames [ month - 1 ] ?? 'Unknown'
2525 const monthNameShort = locale . monthNamesShort [ month - 1 ] ?? 'Unknown'
26+ const offsetMinutes = Helpers . getTimezoneOffset ( date )
27+ const offsetHours = Math . floor ( Math . abs ( offsetMinutes ) / 60 )
28+ const offsetMins = Math . abs ( offsetMinutes ) % 60
29+ const offsetSign = offsetMinutes >= 0 ? '+' : '-'
30+ const offsetString = `${ offsetSign } ${ Helpers . padNumber ( offsetHours , 2 ) } ${
31+ Helpers . padNumber (
32+ offsetMins ,
33+ 2
34+ )
35+ } `
36+ const offsetStringColon = `${ offsetSign } ${ Helpers . padNumber ( offsetHours , 2 ) } :${
37+ Helpers . padNumber (
38+ offsetMins ,
39+ 2
40+ )
41+ } `
42+ const unixSeconds = Math . floor ( date . getTime ( ) / 1000 )
43+ const unixMilliseconds = date . getTime ( )
2644 const tokens : Record < string , string > = {
27- YYYY : year . toString ( ) ,
28- YY : ( year % 100 ) . toString ( ) . padStart ( 2 , '0' ) ,
29- MM : Helpers . padNumber ( month , 2 ) ,
30- M : month . toString ( ) ,
31- DD : Helpers . padNumber ( day , 2 ) ,
45+ A : hour >= 12 ? 'PM' : 'AM' ,
3246 D : day . toString ( ) ,
33- HH : Helpers . padNumber ( hour , 2 ) ,
47+ DD : Helpers . padNumber ( day , 2 ) ,
48+ Do : Helpers . toOrdinal ( day ) ,
3449 H : hour . toString ( ) ,
35- hh : Helpers . padNumber ( hour % 12 || 12 , 2 ) ,
50+ HH : Helpers . padNumber ( hour , 2 ) ,
51+ M : month . toString ( ) ,
52+ MM : Helpers . padNumber ( month , 2 ) ,
53+ MMM : monthNameShort ,
54+ MMMM : monthName ,
55+ S : Math . floor ( millisecond / 100 ) . toString ( ) ,
56+ SS : Helpers . padNumber ( Math . floor ( millisecond / 10 ) , 2 ) ,
57+ SSS : Helpers . padNumber ( millisecond , 3 ) ,
58+ X : unixSeconds . toString ( ) ,
59+ YY : ( year % 100 ) . toString ( ) . padStart ( 2 , '0' ) ,
60+ YYYY : year . toString ( ) ,
61+ Z : offsetStringColon ,
62+ ZZ : offsetString ,
63+ a : hour >= 12 ? 'pm' : 'am' ,
64+ d : dayOfWeek . toString ( ) ,
65+ dd : Helpers . padNumber ( dayOfWeek , 2 ) ,
66+ ddd : dayNameShort ,
67+ dddd : dayName ,
3668 h : ( hour % 12 || 12 ) . toString ( ) ,
37- mm : Helpers . padNumber ( minute , 2 ) ,
69+ hh : Helpers . padNumber ( hour % 12 || 12 , 2 ) ,
3870 m : minute . toString ( ) ,
39- ss : Helpers . padNumber ( second , 2 ) ,
71+ mm : Helpers . padNumber ( minute , 2 ) ,
4072 s : second . toString ( ) ,
41- SSS : Helpers . padNumber ( millisecond , 3 ) ,
42- SS : Helpers . padNumber ( Math . floor ( millisecond / 10 ) , 2 ) ,
43- S : Math . floor ( millisecond / 100 ) . toString ( ) ,
44- dddd : dayName ,
45- ddd : dayNameShort ,
46- dd : Helpers . padNumber ( dayOfWeek , 2 ) ,
47- d : dayOfWeek . toString ( ) ,
48- MMMM : monthName ,
49- MMM : monthNameShort ,
50- A : hour >= 12 ? 'PM' : 'AM' ,
51- a : hour >= 12 ? 'pm' : 'am'
73+ ss : Helpers . padNumber ( second , 2 ) ,
74+ x : unixMilliseconds . toString ( )
5275 }
5376 const placeholderStart = '\uE000'
5477 let result = pattern
@@ -60,10 +83,39 @@ export function formatDate(date: Date, pattern: string, localeCode?: string): st
6083 continue
6184 }
6285 const value = tokens [ key ]
63- if ( value !== undefined && result . includes ( key ) ) {
64- const placeholder = `${ placeholderStart } ${ String . fromCharCode ( 0xe000 + i ) } `
65- replacements . push ( { placeholder, value } )
66- result = result . replaceAll ( key , placeholder )
86+ if ( value === undefined ) {
87+ continue
88+ }
89+ if ( key . length === 1 ) {
90+ const char = key [ 0 ]
91+ if ( char === undefined ) {
92+ continue
93+ }
94+ let searchStart = 0
95+ while ( true ) {
96+ const index = result . indexOf ( char , searchStart )
97+ if ( index === - 1 ) {
98+ break
99+ }
100+ const prevChar = index > 0 ? result [ index - 1 ] : ''
101+ const nextChar = index < result . length - 1 ? result [ index + 1 ] : ''
102+ const isPrevAlpha = / [ a - z A - Z ] / . test ( prevChar ?? '' )
103+ const isNextAlpha = / [ a - z A - Z ] / . test ( nextChar ?? '' )
104+ if ( ! isPrevAlpha && ! isNextAlpha ) {
105+ const placeholder = `${ placeholderStart } ${ String . fromCharCode ( 0xe000 + i ) } `
106+ replacements . push ( { placeholder, value } )
107+ result = result . substring ( 0 , index ) + placeholder + result . substring ( index + 1 )
108+ searchStart = index + placeholder . length
109+ } else {
110+ searchStart = index + 1
111+ }
112+ }
113+ } else {
114+ if ( result . includes ( key ) ) {
115+ const placeholder = `${ placeholderStart } ${ String . fromCharCode ( 0xe000 + i ) } `
116+ replacements . push ( { placeholder, value } )
117+ result = result . replaceAll ( key , placeholder )
118+ }
67119 }
68120 }
69121 for ( const { placeholder, value } of replacements ) {
0 commit comments