Last active
September 30, 2023 09:23
-
-
Save ahmedazhar05/227e75aa9f252d5c50cd584ca1136120 to your computer and use it in GitHub Desktop.
Date format function similar to date command(https://man7.org/linux/man-pages/man1/date.1.html) in unix, Note: this code haven't been tested even once yet, may contain tons of bugs
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
export default function format(formatString: string): string { | |
const day = this.getDate(); | |
const month = this.getMonth(); | |
const year = this.getFullYear(); | |
const isLeapYear = (year % 4 == 0 && year % 100 != 0) || year % 400 == 0; | |
const data = { | |
weekdays: ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday'], | |
months: ["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"], | |
dayCount: [31, Number(isLeapYear) + 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31], | |
get cumulativeDayCount() { | |
// return this.dayCount.map(function p(c, i, a): number { return i ? a[i - 1] + p(c, i - 1, a): 0 }); | |
const cumulated: number[] = []; | |
let sum = 0; | |
for(const count of this.dayCount){ | |
cumulated.push(sum); | |
sum += count; | |
} | |
return cumulated; | |
} | |
} as const; | |
const dayOfYear = data.cumulativeDayCount[month] + day; | |
const abbreviate = (value: string) => value.slice(0, 3); | |
const removeFraction = (value: number): number => Number(value.toString().split('.')[0]); | |
const padWith = (filler?: string) => (value: number | string, digits: number = 2) => value.toString().padStart(digits, filler); | |
const padZero = padWith("0"); | |
const padSpace = padWith(" "); | |
// const removePadding = (value: string, filler: string = "[0 ]") => value.replace(new RegExp('^' + filler + '+'), ''); | |
const dayOfWeek = this.getDay(); | |
const hour = this.getHours(); | |
const minutes = this.getMinutes(); | |
const seconds = this.getSeconds(); | |
const twelveHour = ((hour + 11) % 12) + 1; | |
const weekDay = data.weekdays[dayOfWeek]; | |
const monthName = data.months[month]; | |
const abbrMonth = abbreviate(monthName); | |
const weekNumber = removeFraction((data.cumulativeDayCount[month] + day) / 7); | |
const timezoneDiff = this.getTimezoneOffset() * -1; | |
const timezone = { | |
sign: timezoneDiff >= 0 ? '+' : '-', | |
hour: removeFraction(timezoneDiff / 60), | |
minute: timezoneDiff % 60, | |
name: this.toTimeString().replace(/^.+\(|\).*$/g, ''), | |
get abbr() { return this.name.replace(/[a-z áéä'-]/g, ''); } | |
} as const; | |
const specifiers: { readonly [_: string]: string | number } = { | |
"a": abbreviate(weekDay), | |
"A": weekDay, | |
"b": abbrMonth, | |
"B": monthName, | |
"c": this.format("%a %b %-d %R:%S %Y"), | |
"C": removeFraction(year / 100), | |
"-d": day, | |
"d": padZero(day), | |
"D": this.format("%m/%d/%y"), | |
"-e": day, | |
"e": padSpace(day), | |
"F": this.format("%4Y-%m-%d"), | |
"h": abbrMonth, // same as "b" | |
"-H": hour, | |
"H": padZero(hour), | |
"-I": twelveHour, | |
"I": padZero(twelveHour), | |
"-j": dayOfYear, | |
"j": padZero(dayOfYear, 3), | |
"-k": hour, | |
"k": padSpace(hour), | |
"-l": twelveHour, | |
"l": padSpace(twelveHour), | |
"-m": month + 1, | |
"m": padZero(month + 1), | |
"-M": minutes, | |
"M": padZero(minutes), | |
"n": `\n`, | |
"N": this.getMilliseconds() * 1000000, | |
"#o": timezone.name.toLowerCase(), // not in unix date command | |
"^o": timezone.name, // not in unix date command | |
"o": timezone.name, // not in unix date command | |
"^p": hour < 12 ? 'AM' : 'PM', | |
"#p": hour < 12 ? 'AM' : 'PM', | |
"p": hour < 12 ? 'am' : 'pm', | |
"^P": hour < 12 ? 'AM' : 'PM', | |
"#P": hour < 12 ? 'am' : 'pm', | |
"P": hour < 12 ? 'AM' : 'PM', | |
"q": removeFraction((month / 3) + 1), | |
"r": this.format("%I:%M:%S %P"), | |
"R": this.format("%H:%M"), | |
"s": removeFraction(Date.parse(this.toJSON()) / 1000), | |
"-S": seconds, | |
"S": padZero(seconds), | |
"t": `\t`, | |
"T": this.format("%H:%M:%S"), | |
"u": ((dayOfWeek + 6) % 7) + 1, | |
"-U": weekNumber, | |
"U": padZero(weekNumber), | |
"w": dayOfWeek, | |
"-W": weekNumber - Number(dayOfWeek == 0), | |
"W": padZero(weekNumber - Number(dayOfWeek == 0)), | |
"x": this.format("%m/%d/%y"), // same as D | |
"X": this.format("%H:%M:%S"), | |
"-y": year % 100, | |
"y": padZero(year % 100), | |
"Y": year, | |
"-z": timezone.hour + padZero(timezone.minute), | |
"z": padZero(timezone.hour) + padZero(timezone.minute), | |
"-:z": `${timezone.hour}:${padZero(timezone.minute)}`, | |
":z": `${padZero(timezone.hour)}:${padZero(timezone.minute)}`, | |
"-::z": `${timezone.hour}:${padZero(timezone.minute)}:00`, | |
"::z": `${padZero(timezone.hour)}:${padZero(timezone.minute)}:00`, | |
"-:::z": timezone.hour + (timezone.minute ? `:${padZero(timezone.minute)}`: ""), | |
":::z": padZero(timezone.hour) + (timezone.minute ? `:${padZero(timezone.minute)}`: ""), | |
"#Z": timezone.abbr.toLowerCase(), | |
"^Z": timezone.abbr, | |
"Z": timezone.abbr | |
} as const; | |
return formatString.replace(/%([-_0^#]?)(\d*)(:*z|[A-DFHIMNPR-UW-Za-ehj-uwxy])/g, (match: string, flag: string, width: string, identifier: string) => { | |
if(flag == '-') width = ''; | |
else if(['_', '0'].includes(flag)) { | |
identifier = `-${identifier}`; | |
if(!width){ | |
switch(identifier) { | |
case 'N': width = '9'; break; | |
case 'j': width = '3'; break; | |
case 'z': width = '4'; break; | |
case ':z': width = '5'; break; | |
case '::z': width = '8'; break; | |
case ':::z': width = timezone.minute == 0 ? '2' : '5'; break; | |
default: width = [..."deHIklmMSUWy"].includes(identifier.slice(-1)) ? '2' : ''; | |
} | |
} | |
} | |
let output: string = match; | |
if(width) { | |
if(flag == '_') { | |
if(identifier.slice(-1) == 'z') | |
output = padSpace(timezone.sign + specifiers[identifier], Number(width)); | |
} else if(flag == '0') output = padZero(specifiers[identifier], Number(width)); | |
else if([...'aAbBcDFhopPrRTxXZ'].includes(identifier.slice(-1))) output = padSpace(specifiers[identifier], Number(width)); | |
else output = padZero(specifiers[identifier], Number(width)); | |
} else output = specifiers[identifier].toString(); | |
return (identifier.slice(-1) == 'z' && flag != '_' ? timezone.sign : "") + output; | |
}); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Download
Download a copy of this into your project as:
Usage