Created
July 16, 2026 21:54
-
-
Save paceaux/2e8b45a45daf4cd2d6cfbf6b15418215 to your computer and use it in GitHub Desktop.
Date Converter
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| /* for converting date strings formatted as YYYY-MM-DD into ... other formats. | |
| e.g.: | |
| const dc = new DateConverter('1984-08-09'); | |
| const pretty = dc.format('Started %MMMM %ddd, %yyyy'); | |
| m - lowercase month name | |
| M - variable width month | |
| MM - fixed width month | |
| D - variable width day | |
| DD -fixed width day | |
| DDD - ordinal day (1st, 2nd, etc) | |
| YY - year of century | |
| YYYY - full century | |
| */ | |
| const months = [ | |
| 'January', | |
| 'February', | |
| 'March', | |
| 'April', | |
| 'May', | |
| 'June', | |
| 'July', | |
| 'August', | |
| 'September', | |
| 'October', | |
| 'November', | |
| 'December', | |
| ]; | |
| const days = [ | |
| 'Sunday', | |
| 'Monday', | |
| 'Tuesday', | |
| 'Wednesday', | |
| 'Thursday', | |
| 'Friday', | |
| 'Saturday', | |
| 'Sunday', | |
| ]; | |
| class DateConverter { | |
| static months = months; | |
| static days = days; | |
| /** | |
| * @param {string} string - a string with a date | |
| */ | |
| constructor(string) { | |
| if (string) { | |
| this.rawString = string; | |
| } | |
| } | |
| set date(val) { | |
| this.rawString = val; | |
| } | |
| get date() { | |
| return this.rawString; | |
| } | |
| get dateParts() { | |
| let [year, month, day] = this.rawString.split('-'); | |
| month = month || ''; | |
| day = day || ''; | |
| return { year, month, day }; | |
| } | |
| static getDayFormatFromSize(size = 1) { | |
| let formatType = ''; | |
| switch (size) { | |
| case 1: | |
| formatType = 'variableWidth'; | |
| break; | |
| case 2: | |
| formatType = 'fixedWidth'; | |
| break; | |
| case 3: | |
| formatType = 'ordinal'; | |
| break; | |
| } | |
| return formatType; | |
| } | |
| static getMonthFormatFromSize(size = 1) { | |
| let formatType = ''; | |
| switch (size) { | |
| case 1: | |
| formatType = 'variableWidth'; | |
| break; | |
| case 2: | |
| formatType = 'fixedWidth'; | |
| break; | |
| case 3: | |
| formatType = 'shortName'; | |
| break; | |
| case 4: | |
| formatType = 'longName'; | |
| break; | |
| } | |
| return formatType; | |
| } | |
| static getYearFormatFromSize(size = 2) { | |
| let formatType = ''; | |
| if (size > 0 && size <= 2) { | |
| formatType = 'yearOfCentury'; | |
| } else if (size > 2) { | |
| formatType = 'fullYear'; | |
| } | |
| return formatType; | |
| } | |
| /** | |
| * @param {string} day - the day | |
| * @param {'variableWidth'|'fixedWidth'|'dayOfYear'} - formatStyle | |
| * | |
| * @returns string | |
| */ | |
| static formatDay(day, formatStyle) { | |
| let formattedDay = day; | |
| if (day && formatStyle === 'fixedWidth') { | |
| formattedDay = day.padStart(2, '0'); | |
| } | |
| if (day && formatStyle === 'ordinal') { | |
| const dayInt = parseInt(day, 10); | |
| let suffix = 'th'; | |
| switch (dayInt) { | |
| case 1: | |
| suffix = 'st'; | |
| break; | |
| case 2: | |
| suffix = 'nd'; | |
| break; | |
| case 3: | |
| suffix = 'rd'; | |
| break; | |
| } | |
| formattedDay = `${dayInt}${suffix}`; | |
| } | |
| return formattedDay; | |
| } | |
| /** | |
| * @param {string} month - the string of the month | |
| * @param {'variableWidth'|'fixedWidth'|'shortName'|'longName'} formatStyle - the way the month should be formatted | |
| * | |
| * @returns {string} a string that contains a formatted month | |
| */ | |
| static formatMonth(month, formatStyle) { | |
| let formattedMonth = month; | |
| if (month) { | |
| if (formatStyle.includes('Name')) { | |
| const monthInt = parseInt(month, 10) - 1; | |
| const monthName = DateConverter.months[monthInt]; | |
| formattedMonth = | |
| formatStyle === 'shortName' ? monthName.slice(0, 3) : monthName; | |
| } else if (formatStyle === 'fixedWidth') { | |
| formattedMonth = month.padStart(2, '0'); | |
| } | |
| } | |
| return formattedMonth; | |
| } | |
| /** | |
| * @param {string} year - the year | |
| * @param {'yearOfCentury'|'fullYear'} | |
| */ | |
| static formatYear(year, formatStyle) { | |
| let formattedYear = year; | |
| if (year && formatStyle === 'yearOfCentury') { | |
| formattedYear = year.slice(-2); | |
| } | |
| return formattedYear; | |
| } | |
| /** | |
| * @param {string} formatString - a string that contains formatting instructions based on the date | |
| * | |
| * @returns {string} | |
| */ | |
| format(formatString = '%YYYY') { | |
| const yearMatch = formatString.match(/Y/gi) || []; | |
| const monthMatch = formatString.match(/M/gi) || []; | |
| const dayMatch = formatString.match(/D/gi) || []; | |
| const isMonthLowercased = monthMatch[0].toLowerCase() === monthMatch[0]; | |
| const yearSize = yearMatch.length; | |
| const monthSize = monthMatch.length; | |
| const daySize = dayMatch.length; | |
| const yearFormatType = DateConverter.getYearFormatFromSize(yearSize); | |
| const monthFormatType = DateConverter.getMonthFormatFromSize(monthSize); | |
| const dayFormatType = DateConverter.getDayFormatFromSize(daySize); | |
| const { year, month, day } = this.dateParts; | |
| const formattedYear = DateConverter.formatYear(year, yearFormatType); | |
| let formattedMonth = ''; | |
| let formattedDay = ''; | |
| if (month) { | |
| formattedMonth = DateConverter.formatMonth(month, monthFormatType); | |
| if (isMonthLowercased) { | |
| formattedMonth = formattedMonth.toLocaleLowerCase(); | |
| } | |
| } | |
| if (day) { | |
| formattedDay = DateConverter.formatDay(day, dayFormatType); | |
| } | |
| return formatString | |
| .replace(/%y+/i, formattedYear) | |
| .replace(/%M+/i, formattedMonth) | |
| .replace(/%D+/gi, formattedDay); | |
| } | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment