Skip to content

Instantly share code, notes, and snippets.

@ahmedazhar05
Last active September 30, 2023 09:23
Show Gist options
  • Save ahmedazhar05/227e75aa9f252d5c50cd584ca1136120 to your computer and use it in GitHub Desktop.
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
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;
});
}
@ahmedazhar05
Copy link
Author

Download

Download a copy of this into your project as:

project/
├── src/
│   ├── scripts/
│   │   ├── Date.prototype.format.js
│   │   └── ...
│   └── ...
└── ...

Usage

import format from '/src/scripts/Date.prototype.format.js'
Date.prototype.format = format;

...

const date = new Date();
console.log(date.format("%H:%M:%S"));   // "23:59:59"

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment