@@ -76,6 +76,15 @@ const next = (value) => {
7676 return generator . next ( )
7777}
7878
79+ function getTimezoneOffsetString ( date ) {
80+ const offset = - date . getTimezoneOffset ( )
81+ const sign = offset >= 0 ? "+" : "-"
82+ const absOffset = Math . abs ( offset )
83+ const hours = String ( Math . floor ( absOffset / 60 ) ) . padStart ( 2 , "0" )
84+ const minutes = String ( absOffset % 60 ) . padStart ( 2 , "0" )
85+ return `${ sign } ${ hours } :${ minutes } `
86+ }
87+
7988export const builtInFilters = {
8089 cycle,
8190 next,
@@ -103,54 +112,102 @@ export const builtInFilters = {
103112 return `${ number . toFixed ( 2 ) } ${ symbol } `
104113 } ,
105114
106- dateFormat : ( value , format = "YYYY-MM-DD" , useUTC = true ) => {
107- // Safely handle null or undefined values
108- if ( value === null || value === undefined ) {
109- return ""
110- }
115+ dateFormat : ( value , format = "YYYY-MM-DD" , useUTC = true , locale = { } ) => {
116+ if ( value === null || value === undefined ) return ""
111117
112- // Create a date object from the input value
113118 const date = new Date ( value )
119+ if ( isNaN ( date . getTime ( ) ) ) return `Invalid date: ${ value } `
114120
115- // Check if the date is valid
116- if ( isNaN ( date . getTime ( ) ) ) {
117- return `Invalid date: ${ value } `
118- }
119-
120- // Define getter functions based on useUTC parameter
121+ // Getters
121122 const getYear = useUTC ? ( ) => date . getUTCFullYear ( ) : ( ) => date . getFullYear ( )
122123 const getMonth = useUTC ? ( ) => date . getUTCMonth ( ) : ( ) => date . getMonth ( )
123124 const getDay = useUTC ? ( ) => date . getUTCDate ( ) : ( ) => date . getDate ( )
124125 const getHours = useUTC ? ( ) => date . getUTCHours ( ) : ( ) => date . getHours ( )
125126 const getMinutes = useUTC ? ( ) => date . getUTCMinutes ( ) : ( ) => date . getMinutes ( )
126127 const getSeconds = useUTC ? ( ) => date . getUTCSeconds ( ) : ( ) => date . getSeconds ( )
128+ const getDayOfWeek = useUTC ? ( ) => date . getUTCDay ( ) : ( ) => date . getDay ( )
127129
128- // Get all values at once
129130 const year = getYear ( )
130- const month = getMonth ( ) + 1 // Months are 0-based in JavaScript
131+ const month = getMonth ( ) + 1
131132 const day = getDay ( )
132133 const hours = getHours ( )
133134 const minutes = getMinutes ( )
134135 const seconds = getSeconds ( )
135-
136- // Create a dictionary of replacements
136+ const dayOfWeek = getDayOfWeek ( )
137+ const ampm = hours >= 12 ? "PM" : "AM"
138+ const timezoneOffset = useUTC ? "+00:00" : getTimezoneOffsetString ( date )
139+
140+ // Fallback to default English if no locale is provided
141+ const defaultLocale = {
142+ monthNames : [
143+ "January" ,
144+ "February" ,
145+ "March" ,
146+ "April" ,
147+ "May" ,
148+ "June" ,
149+ "July" ,
150+ "August" ,
151+ "September" ,
152+ "October" ,
153+ "November" ,
154+ "December" ,
155+ ] ,
156+ monthNamesShort : [ "Jan" , "Feb" , "Mar" , "Apr" , "May" , "Jun" , "Jul" , "Aug" , "Sep" , "Oct" , "Nov" , "Dec" ] ,
157+ weekdayNames : [ "Sunday" , "Monday" , "Tuesday" , "Wednesday" , "Thursday" , "Friday" , "Saturday" ] ,
158+ weekdayNamesShort : [ "Sun" , "Mon" , "Tue" , "Wed" , "Thu" , "Fri" , "Sat" ] ,
159+ }
160+
161+ const loc = {
162+ ...defaultLocale ,
163+ ...locale ,
164+ }
165+
166+ // Replacements map
137167 const replacements = {
138168 YYYY : String ( year ) ,
169+ yyyy : String ( year ) ,
139170 YY : String ( year ) . slice ( - 2 ) ,
171+ yy : String ( year ) . slice ( - 2 ) ,
172+
173+ MMMM : loc . monthNames [ getMonth ( ) ] ,
174+ MMM : loc . monthNamesShort [ getMonth ( ) ] ,
175+ mmmm : loc . monthNames [ getMonth ( ) ] ,
176+ mmm : loc . monthNamesShort [ getMonth ( ) ] ,
177+
140178 MM : String ( month ) . padStart ( 2 , "0" ) ,
141179 M : String ( month ) ,
180+
142181 DD : String ( day ) . padStart ( 2 , "0" ) ,
143182 D : String ( day ) ,
183+ dd : String ( day ) . padStart ( 2 , "0" ) ,
184+ d : String ( day ) ,
185+
186+ dddd : loc . weekdayNames [ dayOfWeek ] ,
187+ ddd : loc . weekdayNamesShort [ dayOfWeek ] ,
188+
144189 HH : String ( hours ) . padStart ( 2 , "0" ) ,
145190 H : String ( hours ) ,
191+ hh : String ( hours ) . padStart ( 2 , "0" ) ,
192+ h : String ( hours ) ,
193+
146194 mm : String ( minutes ) . padStart ( 2 , "0" ) ,
147195 m : String ( minutes ) ,
196+
148197 ss : String ( seconds ) . padStart ( 2 , "0" ) ,
149198 s : String ( seconds ) ,
199+
200+ A : ampm ,
201+ a : ampm . toLowerCase ( ) ,
202+
203+ Z : timezoneOffset ,
150204 }
151205
152- // Replace tokens in the format string
153- return format . replace ( / Y Y Y Y | Y Y | M M | M | D D | D | H H | H | m m | m | s s | s / g, ( match ) => replacements [ match ] )
206+ // Use regex to match all supported tokens
207+ return format . replace (
208+ / Y Y Y Y | y y y y | Y Y | y y | M M M M | m m m m | m m m | M M | M | D D | D | d d | d | d d d d | d d d | H H | H | h h | h | m m | m | s s | s | A | a | Z / g,
209+ ( match ) => replacements [ match ] ?? match
210+ )
154211 } ,
155212
156213 defaults : ( value , ...fallbacks ) => {
0 commit comments