@foxglove/xmlrpc
Version:
TypeScript library implementing an XMLRPC client and server with pluggable server backend
121 lines (108 loc) • 3.79 kB
text/typescript
export type DateFormatterOptions = {
colons?: boolean;
hyphens?: boolean;
ms?: boolean;
};
export class DateFormatter {
private _colons = true;
private _hyphens = true;
private _ms = true;
// Regular Expression that dissects an ISO 8601 formatted string into an array of parts
static ISO8601 =
/([0-9]{4})([-]?([0-9]{2}))([-]?([0-9]{2}))(T-?([0-9]{2})(((:?([0-9]{2}))?((:?([0-9]{2}))?(\.([0-9]+))?))?)(Z|([+-]([0-9]{2}(:?([0-9]{2}))?)))?)?/;
constructor(options?: DateFormatterOptions) {
if (options != undefined) {
this._colons = options.colons ?? this._colons;
this._hyphens = options.hyphens ?? this._hyphens;
this._ms = options.ms ?? this._ms;
}
}
/**
* Converts a date time stamp following the ISO8601 format to a JavaScript Date
* object.
*
* @param {string} time - String representation of timestamp.
* @return {Date} - Date object from timestamp.
*/
decodeIso8601(time: string): Date {
const dateParts = DateFormatter.ISO8601.exec(time.toString());
if (dateParts == null) {
throw new Error(`Expected a ISO8601 datetime but got "${time}"`);
}
let date = [
[dateParts[1], dateParts[3] ?? "01", dateParts[5] ?? "01"].join("-"),
"T",
[dateParts[7] ?? "00", dateParts[11] ?? "00", dateParts[14] ?? "00"].join(":"),
".",
dateParts[16] ?? "000",
].join("");
date +=
dateParts[17] != undefined
? dateParts[17] + (dateParts[19] != undefined && dateParts[20] == undefined ? "00" : "")
: "Z";
return new Date(date);
}
/**
* Converts a JavaScript Date object to an ISO8601 timestamp.
*
* @param {Date} date - Date object.
* @return {string} - String representation of timestamp.
*/
encodeIso8601(date: Date): string {
const parts = DateFormatter.getUTCDateParts(date);
return [
[parts[0], parts[1], parts[2]].join(this._hyphens ? "-" : ""),
"T",
[parts[3], parts[4], parts[5]].join(this._colons ? ":" : ""),
this._ms ? "." + parts[6] : "",
"Z",
].join("");
}
/**
* Helper function to get the current timezone to default decoding to
* rather than UTC. (for backward compatibility)
*
* @return {string} - in the format /Z|[+-]\d{2}:\d{2}/
*/
static formatCurrentOffset(d?: Date): string {
const offset = (d ?? new Date()).getTimezoneOffset();
return offset === 0
? "Z"
: [
offset < 0 ? "+" : "-",
DateFormatter.zeroPad(Math.abs(Math.floor(offset / 60)), 2),
":",
DateFormatter.zeroPad(Math.abs(offset % 60), 2),
].join("");
}
/**
* Helper function to pad the digits with 0s to meet date formatting
* requirements.
*
* @param {number} digit - The number to pad.
* @param {number} length - Length of digit string, prefix with 0s if not
* already length.
* @return {string} - String with the padded digit
*/
static zeroPad(digit: number, length: number): string {
return digit.toString().padStart(length, "0");
}
/**
* Helper function to get an array of zero-padded date parts,
* in UTC
*
* @param {Date} date - Date Object
* @return {[string, string, string, string, string, string, string]}
*/
static getUTCDateParts(date: Date): [string, string, string, string, string, string, string] {
return [
date.getUTCFullYear().toString(),
DateFormatter.zeroPad(date.getUTCMonth() + 1, 2),
DateFormatter.zeroPad(date.getUTCDate(), 2),
DateFormatter.zeroPad(date.getUTCHours(), 2),
DateFormatter.zeroPad(date.getUTCMinutes(), 2),
DateFormatter.zeroPad(date.getUTCSeconds(), 2),
DateFormatter.zeroPad(date.getUTCMilliseconds(), 3),
];
}
}