Add support for sending stats to Matrix, split out some code into more generic classes. #1
13
callStats.js
Normal file
13
callStats.js
Normal file
|
@ -0,0 +1,13 @@
|
||||||
|
export class CallStats {
|
||||||
|
/**
|
||||||
|
* @param {CallStats} stats
|
||||||
|
*/
|
||||||
|
constructor(stats) {
|
||||||
|
}
|
||||||
|
|
||||||
|
totalCallsThisMonth;
|
||||||
|
totalCallsEverPlaced;
|
||||||
|
totalCallsMade;
|
||||||
|
allTimeRecord;
|
||||||
|
isNewRecord = false;
|
||||||
|
}
|
69
dateBuilder.js
Normal file
69
dateBuilder.js
Normal file
|
@ -0,0 +1,69 @@
|
||||||
|
export class DateBuilder {
|
||||||
|
// constructors
|
||||||
|
constructor(date = new Date()) {
|
||||||
|
if (!(date instanceof Date)) {
|
||||||
|
throw new Error("Invalid date object.");
|
||||||
|
}
|
||||||
|
this.date = new Date(date.getTime()); // Create a copy to avoid mutating the original date
|
||||||
|
}
|
||||||
|
|
||||||
|
// methods
|
||||||
|
addYears(years) {
|
||||||
|
this.date.setFullYear(this.date.getFullYear() + years);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
addMonths(months) {
|
||||||
|
this.date.setMonth(this.date.getMonth() + months);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
addDays(days) {
|
||||||
|
this.date.setDate(this.date.getDate() + days);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
addHours(hours) {
|
||||||
|
this.date.setHours(this.date.getHours() + hours);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
addMinutes(minutes) {
|
||||||
|
this.date.setMinutes(this.date.getMinutes() + minutes);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
addSeconds(seconds) {
|
||||||
|
this.date.setSeconds(this.date.getSeconds() + seconds);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
addMillis(millis) {
|
||||||
|
this.date.setTime(this.date.getTime() + millis);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
withDate(year, month, day) {
|
||||||
|
this.date.setFullYear(year, month - 1, day); // month is 0-based
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
withTime(hour, minute = 0, second = 0, millisecond = 0) {
|
||||||
|
this.date.setHours(hour, minute, second, millisecond);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
atStartOfDay() {
|
||||||
|
this.date.setHours(0, 0, 0, 0);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
atEndOfDay() {
|
||||||
|
this.date.setHours(23, 59, 59, 999);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
build() {
|
||||||
|
return new Date(this.date.getTime()); // Return a copy to avoid external mutation
|
||||||
|
}
|
||||||
|
}
|
0
dateBuilder.test.js
Normal file
0
dateBuilder.test.js
Normal file
248
index.js
248
index.js
|
@ -2,152 +2,156 @@ require("dotenv").config();
|
||||||
const cron = require("node-cron");
|
const cron = require("node-cron");
|
||||||
const os = require("os");
|
const os = require("os");
|
||||||
const Discord = require('discord.js');
|
const Discord = require('discord.js');
|
||||||
const { connect } = require("http2");
|
|
||||||
const mysql = require('mysql');
|
const mysql = require('mysql');
|
||||||
|
const { TimeSpan } = require("./timeSpan");
|
||||||
|
const { DateBuilder } = require("./dateBuilder");
|
||||||
|
const { CallStats } = require("./callStats");
|
||||||
|
const { CallRecord, Records } = require("./records");
|
||||||
const fs = require('fs').promises;
|
const fs = require('fs').promises;
|
||||||
|
|
||||||
const hook = new Discord.WebhookClient({ url: process.env.DISCORD_WEBHOOK_URL });
|
const hook = !!process.env.DISCORD_WEBHOOK_URL ? new Discord.WebhookClient({ url: process.env.DISCORD_WEBHOOK_URL }) : null;
|
||||||
|
|
||||||
const JSON_FILE = process.env.JSON_FILE || "records.json";
|
const JSON_FILE = process.env.JSON_FILE || "records.json";
|
||||||
|
const records = Records.fromJSONFile(JSON_FILE);
|
||||||
|
|
||||||
|
function getYesterday() {
|
||||||
|
return new TimeSpan(
|
||||||
|
new DateBuilder().addDays(-1).atStartOfDay().build().getTime(),
|
||||||
|
new DateBuilder().addDays(-1).atEndOfDay().build().getTime()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
function getStartOfYesterdayTimestamp() {
|
function getStartOfYesterdayTimestamp() {
|
||||||
const today = new Date();
|
const today = new Date();
|
||||||
// Set the date to yesterday
|
// Set the date to yesterday
|
||||||
today.setDate(today.getDate() - 1);
|
today.setDate(today.getDate() - 1);
|
||||||
// Create a new Date object for the start of yesterday
|
// Create a new Date object for the start of yesterday
|
||||||
const startOfYesterday = new Date(today.getFullYear(), today.getMonth(), today.getDate());
|
const startOfYesterday = new Date(today.getFullYear(), today.getMonth(), today.getDate());
|
||||||
return startOfYesterday.getTime(); // Returns the timestamp in milliseconds
|
return startOfYesterday.getTime(); // Returns the timestamp in milliseconds
|
||||||
}
|
|
||||||
|
|
||||||
async function loadRecords() {
|
|
||||||
try {
|
|
||||||
const data = await fs.readFile(JSON_FILE, 'utf-8');
|
|
||||||
return JSON.parse(data);
|
|
||||||
} catch (error) {
|
|
||||||
if (error.code === 'ENOENT') {
|
|
||||||
return { records: {} }; // Return empty records if file doesn't exist
|
|
||||||
}
|
|
||||||
throw error;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
async function saveRecords(root) {
|
|
||||||
const json = JSON.stringify(root, null, 2);
|
|
||||||
await fs.writeFile(JSON_FILE, json);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Fetch call statistics
|
||||||
|
* @returns {Promise<CallStats>}
|
||||||
|
*/
|
||||||
async function getPreviousDayData() {
|
async function getPreviousDayData() {
|
||||||
return new Promise(async (resolve, reject) => {
|
return new Promise(async (resolve, reject) => {
|
||||||
const previousDay = new Date(getStartOfYesterdayTimestamp()) // 24 hours ago
|
const yesterday = getYesterday();
|
||||||
const startTime = new Date(previousDay.setHours(0, 0, 0, 0));
|
const connection = await mysql.createConnection({
|
||||||
const endTime = new Date(previousDay.setHours(23, 59, 59, 999));
|
host: process.env.DATABASE_HOST,
|
||||||
const connection = await mysql.createConnection({
|
user: process.env.DATABASE_USER,
|
||||||
host: process.env.DATABASE_HOST,
|
password: process.env.DATABASE_PASSWORD,
|
||||||
user: process.env.DATABASE_USER,
|
database: process.env.DATABASE_NAME,
|
||||||
password: process.env.DATABASE_PASSWORD,
|
multipleStatements: true
|
||||||
database: process.env.DATABASE_NAME,
|
});
|
||||||
multipleStatements: true
|
await connection.connect();
|
||||||
});
|
await connection.query(`
|
||||||
await connection.connect();
|
SELECT COUNT(DISTINCT uniqueid) AS call_count
|
||||||
let callsMade;
|
FROM cdr
|
||||||
let recordForToday;
|
WHERE calldate BETWEEN ? AND ?;
|
||||||
let monthlyTotal;
|
SELECT COUNT(DISTINCT uniqueid) AS call_count
|
||||||
let totalCalls;
|
FROM cdr
|
||||||
await connection.query(`
|
WHERE MONTH (calldate) = MONTH (?) AND YEAR (calldate) = YEAR (?);
|
||||||
SELECT COUNT(DISTINCT uniqueid) AS call_count
|
SELECT COUNT(DISTINCT uniqueid) AS call_count
|
||||||
FROM cdr
|
FROM cdr;
|
||||||
WHERE calldate BETWEEN ? AND ?;
|
`, [ yesterday.start, yesterday.end, yesterday.start, yesterday.start ], (err, res) => {
|
||||||
SELECT COUNT(DISTINCT uniqueid) AS call_count
|
if (err) {
|
||||||
FROM cdr
|
reject(err);
|
||||||
WHERE MONTH (calldate) = MONTH (?) AND YEAR (calldate) = YEAR (?);
|
}
|
||||||
SELECT COUNT(DISTINCT uniqueid) AS call_count
|
connection.end();
|
||||||
FROM cdr;
|
// let output = {
|
||||||
`, [ startTime, endTime, previousDay, previousDay ], (err, res) => {
|
// "Calls Made": res[0][0].call_count,
|
||||||
if (err) {
|
// "Monthly Total": res[1][0].call_count,
|
||||||
reject(err);
|
// "Total Calls Ever Placed": res[2][0].call_count,
|
||||||
}
|
// "System Uptime": getSystemUptime().toString(false, false),
|
||||||
connection.end();
|
// "All Time Record": null, // Placeholder
|
||||||
let output = {
|
// }
|
||||||
"Calls Made": res[0][0].call_count,
|
|
||||||
"Monthly Total": res[1][0].call_count,
|
const stats = new CallStats({
|
||||||
"Total Calls Ever Placed": res[2][0].call_count,
|
callsMadeToday: res[0][0].call_count,
|
||||||
"System Uptime": getSystemUptime(),
|
totalCallsThisMonth: res[1][0].call_count,
|
||||||
"All Time Record": null, // Placeholder
|
totalCallsEverPlaced: res[2][0].call_count,
|
||||||
}
|
allTimeRecord: null // Placeholder
|
||||||
console.log(output);
|
});
|
||||||
resolve(output);
|
|
||||||
});
|
console.log(stats);
|
||||||
});
|
resolve(stats);
|
||||||
|
});
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
function getSystemUptime() {
|
function getSystemUptime() {
|
||||||
const uptime = os.uptime();
|
const uptime = os.uptime();
|
||||||
const days = Math.floor(uptime / 86400);
|
const now = new Date();
|
||||||
const hours = Math.floor((uptime % 86400) / 3600);
|
return new TimeSpan(now - (uptime * 1000), now.getTime());
|
||||||
const minutes = Math.floor((uptime % 3600) / 60);
|
|
||||||
const seconds = Math.floor(uptime % 60);
|
|
||||||
return `${days} days, ${hours} hours, ${minutes} minutes, ${seconds} seconds`;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function updateRecords(data, root) {
|
/**
|
||||||
const currentDate = new Date(getStartOfYesterdayTimestamp()).toISOString().split('T')[0];
|
* Update records with new data
|
||||||
const month = currentDate.slice(0, 7);
|
* @param {CallStats} callStats
|
||||||
let isNewRecord = false;
|
* @param {Records} records
|
||||||
|
* @returns {CallStats}
|
||||||
|
*/
|
||||||
|
function updateRecords(callStats, records) {
|
||||||
|
const yesterday = getYesterday().startDate;
|
||||||
|
let isNewRecord = false;
|
||||||
|
|
||||||
// Update all-time record
|
// Update all-time record
|
||||||
const allTimeRecord = root.records.record_calls || { date: currentDate, count: 0 };
|
const allTimeRecord = records.callRecord || new CallRecord({ date: yesterday, count: 0 });
|
||||||
if (!root.records.record_calls) {
|
if (!records.callRecord) {
|
||||||
root.records.record_calls = { date: currentDate, count: data["Calls Made"] };
|
records.callRecord = { date: currentDate, count: callStats.totalCallsMade };
|
||||||
isNewRecord = true;
|
isNewRecord = true;
|
||||||
} else if (parseInt(allTimeRecord.count) < data["Calls Made"]) {
|
} else if (parseInt(allTimeRecord.count) < callStats.totalCallsThisMonth) {
|
||||||
allTimeRecord.count = data["Calls Made"];
|
allTimeRecord.count = callStats.totalCallsThisMonth;
|
||||||
isNewRecord = true;
|
isNewRecord = true;
|
||||||
}
|
}
|
||||||
data["All Time Record"] = `${allTimeRecord.count} calls on ${allTimeRecord.date}`;
|
callStats.allTimeRecord = `${allTimeRecord.count} calls on ${allTimeRecord.date}`;
|
||||||
|
|
||||||
// Update total calls ever placed
|
// Update total calls ever placed
|
||||||
root.records.total_calls_ever_placed = data["Total Calls Ever Placed"];
|
records.totalCallsEverPlaced = callStats.totalCallsEverPlaced;
|
||||||
|
|
||||||
// Update monthly total
|
// Update monthly totals
|
||||||
root.records[`monthly_total_${month}`] = data["Monthly Total"];
|
records.monthlyTotals[yesterday.getFullYear().toString()][yesterday.getMonth().toString()] = callStats.totalCallsThisMonth;
|
||||||
|
|
||||||
if (isNewRecord) {
|
if (isNewRecord) {
|
||||||
data["NEW RECORD"] = true;
|
callStats.isNewRecord = true;
|
||||||
}
|
}
|
||||||
return data;
|
return callStats;
|
||||||
}
|
}
|
||||||
|
|
||||||
async function sendSummary() {
|
async function sendSummary() {
|
||||||
console.log("Preparing summary.");
|
console.log("Preparing summary.");
|
||||||
const data = await getPreviousDayData();
|
const data = await getPreviousDayData();
|
||||||
console.log("Loading records.");
|
console.log("Updating records...");
|
||||||
const root = await loadRecords();
|
const updatedData = await updateRecords(data, records);
|
||||||
console.log("Updating records...");
|
console.log("Saving.");
|
||||||
const updatedData = await updateRecords(data, root);
|
await records.toJSONFile(JSON_FILE);
|
||||||
console.log("Saving.");
|
|
||||||
await saveRecords(root);
|
|
||||||
|
|
||||||
const previousDayStart = new Date(getStartOfYesterdayTimestamp());
|
const yesterday = getYesterday();
|
||||||
const previousDayEnd = new Date(previousDayStart);
|
|
||||||
previousDayEnd.setHours(23, 59, 59, 999);
|
|
||||||
|
|
||||||
let embed = {
|
let embed = {
|
||||||
title: `Summary from <t:${Math.floor(previousDayStart / 1000)}:f> to <t:${Math.floor(previousDayEnd / 1000)}:f>`,
|
title: `Summary from <t:${Math.floor(yesterday.start / 1000)}:f> to <t:${Math.floor(yesterday.end / 1000)}:f>`,
|
||||||
color: 0x1E90FF,
|
color: 0x1E90FF,
|
||||||
fields: [],
|
fields: [],
|
||||||
timestamp: new Date(),
|
timestamp: new Date(),
|
||||||
footer: {}
|
footer: {}
|
||||||
}
|
}
|
||||||
for (const [ key, value ] of Object.entries(updatedData)) {
|
for (const [ key, value ] of Object.entries(updatedData)) {
|
||||||
if (key === "NEW RECORD") {
|
if (key === "NEW RECORD") {
|
||||||
embed.fields.push({ name: "NEW RECORD!", value: "A new record has been set!", inline: false });
|
embed.fields.push({ name: "NEW RECORD!", value: "A new record has been set!", inline: false });
|
||||||
} else {
|
} else {
|
||||||
embed.fields.push({ name: key, value: value, inline: false });
|
embed.fields.push({ name: key, value: value, inline: false });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
console.log("Sending message.");
|
const payload = { embeds: [ embed ] };
|
||||||
await hook.send({ embeds: [ embed ] });
|
console.log("Sending Discord message:", payload);
|
||||||
|
if (hook)
|
||||||
|
await hook.send(payload);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (process.env.NOOP) {
|
||||||
|
sendSummary();
|
||||||
|
return;
|
||||||
|
}
|
||||||
console.log("Scheduling...");
|
console.log("Scheduling...");
|
||||||
const schedule = cron.schedule("0 1 * * *", sendSummary);
|
const schedule = cron.schedule("0 1 * * *", sendSummary);
|
||||||
|
|
72
records.js
Normal file
72
records.js
Normal file
|
@ -0,0 +1,72 @@
|
||||||
|
import fs from "fs";
|
||||||
|
|
||||||
|
export class Records {
|
||||||
|
constructor(records = {}) {
|
||||||
|
if (typeof records.records === "object")
|
||||||
|
for (const [ key, value ] of Object.entries(records.records)) {
|
||||||
|
const oldTableMatches = key.match(/^monthly_total_(\d{4})-(\d{2})$/);
|
||||||
|
if (oldTableMatches) {
|
||||||
|
const year = oldTableMatches[1];
|
||||||
|
const month = oldTableMatches[2];
|
||||||
|
if (!this.monthlyTotals) this.monthlyTotals = {};
|
||||||
|
if (!this.monthlyTotals[year]) this.monthlyTotals[year] = {};
|
||||||
|
this.monthlyTotals[year][month] = value;
|
||||||
|
} else if (key === "record_calls" && typeof value === "object" && value !== null)
|
||||||
|
this.callRecord = new CallRecord(value.date, value.count);
|
||||||
|
else if (key === "total_calls_ever_placed" && typeof value === "number")
|
||||||
|
this.totalCallsEverPlaced = value;
|
||||||
|
else throw new Error(`Unknown legacy record key: ${key}`);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
for (const [ key, value ] of Object.entries(records))
|
||||||
|
this[key] = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
static fromJSONFile(path) {
|
||||||
|
const data = fs.readFileSync(path, "utf-8");
|
||||||
|
const obj = JSON.parse(data);
|
||||||
|
|
||||||
|
return new Records(obj);
|
||||||
|
}
|
||||||
|
|
||||||
|
toJSONFile(path) {
|
||||||
|
const data = JSON.stringify(this, null, 2);
|
||||||
|
fs.writeFileSync(path, data, "utf-8");
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @type {CallRecord}
|
||||||
|
*/
|
||||||
|
callRecord;
|
||||||
|
/**
|
||||||
|
* @type {number}
|
||||||
|
*/
|
||||||
|
totalCallsEverPlaced;
|
||||||
|
/**
|
||||||
|
* @type {{[year: string]: {[month: string]: number}}}
|
||||||
|
*/
|
||||||
|
monthlyTotals;
|
||||||
|
}
|
||||||
|
|
||||||
|
export class CallRecord {
|
||||||
|
constructor(date, count) {
|
||||||
|
this.date = date;
|
||||||
|
this.count = count;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @type {string} YYYY-MM-DD
|
||||||
|
*/
|
||||||
|
date;
|
||||||
|
/**
|
||||||
|
* @type {number}
|
||||||
|
*/
|
||||||
|
count;
|
||||||
|
}
|
||||||
|
|
||||||
|
// test (mjs)
|
||||||
|
if (import.meta.url === `file://${process.argv[1]}`) {
|
||||||
|
const records = Records.fromJSONFile("records.json");
|
||||||
|
console.log(records);
|
||||||
|
console.log(JSON.stringify(records, null, 2));
|
||||||
|
}
|
|
@ -1,7 +1,7 @@
|
||||||
/**
|
/**
|
||||||
* Represents a timespan with a start and end time.
|
* Represents a timespan with a start and end time.
|
||||||
*/
|
*/
|
||||||
export class Timespan {
|
export class TimeSpan {
|
||||||
// constructors
|
// constructors
|
||||||
constructor(start = Date.now(), end = Date.now()) {
|
constructor(start = Date.now(), end = Date.now()) {
|
||||||
if (start > end) {
|
if (start > end) {
|
||||||
|
@ -12,15 +12,15 @@ export class Timespan {
|
||||||
}
|
}
|
||||||
|
|
||||||
static fromDates(startDate, endDate) {
|
static fromDates(startDate, endDate) {
|
||||||
return new Timespan(startDate, endDate);
|
return new TimeSpan(startDate, endDate);
|
||||||
}
|
}
|
||||||
|
|
||||||
static fromMillis(millis) {
|
static fromMillis(millis) {
|
||||||
return new Timespan(0, millis);
|
return new TimeSpan(0, millis);
|
||||||
}
|
}
|
||||||
|
|
||||||
static fromSeconds(seconds) {
|
static fromSeconds(seconds) {
|
||||||
return Timespan.fromMillis(seconds * 1000);
|
return TimeSpan.fromMillis(seconds * 1000);
|
||||||
}
|
}
|
||||||
|
|
||||||
// methods
|
// methods
|
||||||
|
@ -118,11 +118,11 @@ export class Timespan {
|
||||||
return parts.join(withSpaces ? " " : "");
|
return parts.join(withSpaces ? " " : "");
|
||||||
}
|
}
|
||||||
|
|
||||||
get startTime() {
|
get startDate() {
|
||||||
return new Date(this.start);
|
return new Date(this.start);
|
||||||
}
|
}
|
||||||
|
|
||||||
get endTime() {
|
get endDate() {
|
||||||
return new Date(this.end);
|
return new Date(this.end);
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,21 +2,21 @@
|
||||||
|
|
||||||
const { it } = require("node:test");
|
const { it } = require("node:test");
|
||||||
const assert = require("node:assert/strict");
|
const assert = require("node:assert/strict");
|
||||||
const { Timespan } = require("./timespan");
|
const { TimeSpan } = require("./timeSpan");
|
||||||
|
|
||||||
it("should be able to return zero", () => {
|
it("should be able to return zero", () => {
|
||||||
const ts = new Timespan();
|
const ts = new TimeSpan();
|
||||||
assert.equal(ts.totalMillis, 0);
|
assert.equal(ts.totalMillis, 0);
|
||||||
});
|
});
|
||||||
|
|
||||||
it("should be able to return timespan from milliseconds", () => {
|
it("should be able to return timespan from milliseconds", () => {
|
||||||
const ts = Timespan.fromMillis(1000);
|
const ts = TimeSpan.fromMillis(1000);
|
||||||
assert.equal(ts.totalMillis, 1000);
|
assert.equal(ts.totalMillis, 1000);
|
||||||
assert.equal(ts.totalSeconds, 1);
|
assert.equal(ts.totalSeconds, 1);
|
||||||
});
|
});
|
||||||
|
|
||||||
it("should be able to return timespan from seconds", () => {
|
it("should be able to return timespan from seconds", () => {
|
||||||
const ts = Timespan.fromSeconds(60);
|
const ts = TimeSpan.fromSeconds(60);
|
||||||
assert.equal(ts.totalMillis, 60000);
|
assert.equal(ts.totalMillis, 60000);
|
||||||
assert.equal(ts.totalSeconds, 60);
|
assert.equal(ts.totalSeconds, 60);
|
||||||
assert.equal(ts.totalMinutes, 1);
|
assert.equal(ts.totalMinutes, 1);
|
||||||
|
@ -29,7 +29,7 @@ it("should be pure", () => {
|
||||||
const count = 1000;
|
const count = 1000;
|
||||||
const timestamps = [];
|
const timestamps = [];
|
||||||
for (let i = 0; i < count; i++) {
|
for (let i = 0; i < count; i++) {
|
||||||
timestamps.push(Timespan.fromMillis(8972347984));
|
timestamps.push(TimeSpan.fromMillis(8972347984));
|
||||||
for (const ts2 of timestamps) {
|
for (const ts2 of timestamps) {
|
||||||
assert.equal(ts2.totalMillis, 8972347984);
|
assert.equal(ts2.totalMillis, 8972347984);
|
||||||
assert.equal(ts2.totalSeconds, 8972347);
|
assert.equal(ts2.totalSeconds, 8972347);
|
||||||
|
@ -54,7 +54,7 @@ it("should be pure", () => {
|
||||||
});
|
});
|
||||||
|
|
||||||
it("should be able to stringify", () => {
|
it("should be able to stringify", () => {
|
||||||
const ts = Timespan.fromMillis(8972347984);
|
const ts = TimeSpan.fromMillis(8972347984);
|
||||||
assert.equal(ts.toString(), "3 months, 1 weeks, 5 days, 20 hours, 19 minutes, 7 seconds, 984 milliseconds");
|
assert.equal(ts.toString(), "3 months, 1 weeks, 5 days, 20 hours, 19 minutes, 7 seconds, 984 milliseconds");
|
||||||
assert.equal(ts.toString(true), "3 months, 1 weeks, 5 days, 20 hours, 19 minutes, 7 seconds, 984 milliseconds");
|
assert.equal(ts.toString(true), "3 months, 1 weeks, 5 days, 20 hours, 19 minutes, 7 seconds, 984 milliseconds");
|
||||||
assert.equal(ts.toString(true, false), "3 months, 1 weeks, 5 days, 20 hours, 19 minutes, 7 seconds");
|
assert.equal(ts.toString(true, false), "3 months, 1 weeks, 5 days, 20 hours, 19 minutes, 7 seconds");
|
||||||
|
@ -63,7 +63,7 @@ it("should be able to stringify", () => {
|
||||||
});
|
});
|
||||||
|
|
||||||
it("should be able to shortStringify", () => {
|
it("should be able to shortStringify", () => {
|
||||||
const ts = Timespan.fromMillis(8972347984);
|
const ts = TimeSpan.fromMillis(8972347984);
|
||||||
assert.equal(ts.toShortString(), "3mo1w5d20h19m7s984ms");
|
assert.equal(ts.toShortString(), "3mo1w5d20h19m7s984ms");
|
||||||
assert.equal(ts.toShortString(true), "3mo1w5d20h19m7s984ms");
|
assert.equal(ts.toShortString(true), "3mo1w5d20h19m7s984ms");
|
||||||
assert.equal(ts.toShortString(true, false), "3mo1w5d20h19m7s");
|
assert.equal(ts.toShortString(true, false), "3mo1w5d20h19m7s");
|
||||||
|
@ -72,7 +72,7 @@ it("should be able to shortStringify", () => {
|
||||||
});
|
});
|
||||||
|
|
||||||
it("should be able to shortStringify with spaces", () => {
|
it("should be able to shortStringify with spaces", () => {
|
||||||
const ts = Timespan.fromMillis(8972347984);
|
const ts = TimeSpan.fromMillis(8972347984);
|
||||||
assert.equal(ts.toShortString(undefined, undefined, true), "3mo 1w 5d 20h 19m 7s 984ms");
|
assert.equal(ts.toShortString(undefined, undefined, true), "3mo 1w 5d 20h 19m 7s 984ms");
|
||||||
assert.equal(ts.toShortString(true, undefined, true), "3mo 1w 5d 20h 19m 7s 984ms");
|
assert.equal(ts.toShortString(true, undefined, true), "3mo 1w 5d 20h 19m 7s 984ms");
|
||||||
assert.equal(ts.toShortString(true, false, true), "3mo 1w 5d 20h 19m 7s");
|
assert.equal(ts.toShortString(true, false, true), "3mo 1w 5d 20h 19m 7s");
|
||||||
|
|
Loading…
Reference in a new issue