Last active
October 10, 2023 06:09
-
-
Save andreschoultz/8142eba11bf7850c541767062498386f to your computer and use it in GitHub Desktop.
A TypeScript format extension for dates. Quick & easy C# like date formattingđź“…
This file contains 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
interface Date { | |
/** | |
* Extends the Date object with a `format` method to format dates as strings. | |
* | |
* @param {string} format - The format string specifying the desired date/time format. | |
* @returns {string} The formatted date string. | |
* | |
* @example | |
* ```typescript | |
* const myDate: Date = new Date(); | |
* console.log(myDate.format("yyyy/MM/dd HH:mm:ss.fff")); // Output: "2023/10/09 15:30:45.123" | |
* ``` | |
* | |
* @remarks | |
* This method supports various format options, such as: | |
* - `d`, `dd`: Day of the month (1 through 31). | |
* - `ddd`, `dddd`: Abbreviated and full names of the day (Mon, Monday, etc). | |
* - `H`, `HH`, `h`, `hh`: 24-hour and 12-hour clock hours. | |
* - `m`, `mm`: Minutes. | |
* - `M`, `MM`, `MMM`, `MMMM`: Month in various formats. | |
* - `s`, `ss`: Seconds. | |
* - `t`, `tt`: AM/PM. | |
* - `y`, `yy`, `yyy`, `yyyy`: Year in various formats. | |
* - `K`: Time zone offset. | |
* - `z`, `zz`, `zzz`: Time zone offset in various formats. | |
* - `f`, `ff`, `fff`: Milliseconds and fractions of a second. | |
* | |
* | |
* Date formatting extension inspired by and adapted from the work of OpenAI"s ChatGPT, created by OpenAI. | |
* | |
* @see {@link https://www.openai.com/} | |
* @see {@link https://platform.openai.com/docs/api-reference/introduction} | |
* | |
* Original implementation: OpenAI"s ChatGPT | |
* Curated and adapted for TypeScript: Andre Schoultz | |
*/ | |
format(format: string): string; | |
} | |
Date.prototype.format = function (format: string): string { | |
const daysOfWeek: string[] = ["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"]; | |
const months: string[] = ["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"]; | |
return format.replace(/(d{1,4}|M{1,4}|y{1,4}|HH|H|hh|h|mm|ss|t{1,2}|K|z{1,3}|f{1,3})/g, (match: string): string => { | |
switch (match) { | |
case "d": | |
return this.getDate().toString(); | |
case "dd": | |
return ("0" + this.getDate()).slice(-2); | |
case "ddd": | |
return daysOfWeek[this.getDay()].slice(0, 3); | |
case "dddd": | |
return daysOfWeek[this.getDay()]; | |
case "H": | |
return this.getHours().toString(); | |
case "HH": | |
return ("0" + this.getHours()).slice(-2); | |
case "h": | |
return (this.getHours() % 12 || 12).toString(); | |
case "hh": | |
return ("0" + (this.getHours() % 12 || 12)).slice(-2); | |
case "m": | |
return this.getMinutes().toString(); | |
case "mm": | |
return ("0" + this.getMinutes()).slice(-2); | |
case "M": | |
return (this.getMonth() + 1).toString(); | |
case "MM": | |
return ("0" + (this.getMonth() + 1)).slice(-2); | |
case "MMM": | |
return months[this.getMonth()].slice(0, 3); | |
case "MMMM": | |
return months[this.getMonth()]; | |
case "s": | |
return this.getSeconds().toString(); | |
case "ss": | |
return ("0" + this.getSeconds()).slice(-2); | |
case "t": | |
return this.getHours() < 12 ? "A" : "P"; | |
case "tt": | |
return this.getHours() < 12 ? "AM" : "PM"; | |
case "y": | |
return (this.getFullYear() % 100).toString(); | |
case "yy": | |
return ("0" + (this.getFullYear() % 100)).slice(-2); | |
case "yyy": | |
return this.getFullYear().toString().padStart(3, "0"); | |
case "yyyy": | |
return this.getFullYear().toString().padStart(4, "0"); | |
case "K": | |
const offsetMinutes: number = this.getTimezoneOffset(); | |
const offsetHours: number = Math.abs(offsetMinutes / 60); | |
const offsetSign: string = offsetMinutes > 0 ? "-" : "+"; | |
return offsetSign + ("0" + offsetHours).slice(-2) + ":" + ("0" + Math.abs(offsetMinutes % 60)).slice(-2); | |
case "z": | |
return (this.getTimezoneOffset() / 60).toString(); | |
case "zz": | |
const timezoneOffset: number = this.getTimezoneOffset() / 60; | |
return (timezoneOffset > 0 ? "+" : "-") + ("0" + Math.abs(timezoneOffset)).slice(-2); | |
case "zzz": | |
const tzOffset: number = this.getTimezoneOffset(); | |
const tzHours: number = Math.abs(tzOffset / 60); | |
const tzSign: string = tzOffset > 0 ? "-" : "+"; | |
return tzSign + ("0" + tzHours).slice(-2) + ":" + ("0" + Math.abs(tzOffset % 60)).slice(-2); | |
case "f": | |
return Math.floor(this.getMilliseconds() / 100).toString(); | |
case "ff": | |
return ("0" + Math.floor(this.getMilliseconds() / 10)).slice(-2); | |
case "fff": | |
return this.getMilliseconds().toString().padEnd(3, "0"); | |
default: | |
return match; | |
} | |
}); | |
}; |
This file contains 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
const runFromatTest = () => { | |
const testDate = new Date("2015-05-29T05:50:06.7199222"); | |
const expectedResults: any = { | |
"MM/dd/yyyy": "05/29/2015", | |
"dddd, dd MMMM yyyy": "Friday, 29 May 2015", | |
"dddd, dd MMMM yyyy HH:mm": "Friday, 29 May 2015 05:50", | |
"dddd, dd MMMM yyyy hh:mm tt": "Friday, 29 May 2015 05:50 AM", | |
"dddd, dd MMMM yyyy H:mm": "Friday, 29 May 2015 5:50", | |
"dddd, dd MMMM yyyy h:mm tt": "Friday, 29 May 2015 5:50 AM", | |
"dddd, dd MMMM yyyy HH:mm:ss": "Friday, 29 May 2015 05:50:06", | |
"MM/dd/yyyy HH:mm": "05/29/2015 05:50", | |
"MM/dd/yyyy hh:mm tt": "05/29/2015 05:50 AM", | |
"MM/dd/yyyy H:mm": "05/29/2015 5:50", | |
"MM/dd/yyyy h:mm tt": "05/29/2015 5:50 AM", | |
"MM/dd/yyyy HH:mm:ss": "05/29/2015 05:50:06", | |
"MMMM dd": "May 29", | |
"yyyy-MM-ddTHH:mm:ss.fffK": "2015-05-29T05:50:06.719+02:00", // Adapt to own timezone when testing | |
"ddd, dd MMM yyy HH:mm:ss": "Fri, 29 May 2015 05:50:06", | |
"yyyy-MM-ddTHH:mm:ss": "2015-05-29T05:50:06", | |
"HH:mm": "05:50", | |
"hh:mm tt": "05:50 AM", | |
"H:mm": "5:50", | |
"h:mm tt": "5:50 AM", | |
"HH:mm:ss": "05:50:06", | |
"yyyy MMMM": "2015 May", | |
}; | |
Object.keys(expectedResults).forEach((format) => { | |
const result = testDate.format(format); | |
const expected = expectedResults[format]; | |
console.log(`${format}:`, result); | |
if (result === expected) { | |
console.log(" Test Passed"); | |
} else { | |
console.error(` Test Failed! Expected: ${expected}, Actual: ${result}`); | |
} | |
}); | |
}; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment