Skip to content

Instantly share code, notes, and snippets.

@NathBabs
Created February 15, 2024 00:49
Show Gist options
  • Save NathBabs/4a1041ff58af94444f6abb6c7021859f to your computer and use it in GitHub Desktop.
Save NathBabs/4a1041ff58af94444f6abb6c7021859f to your computer and use it in GitHub Desktop.
General Utilities
import fs from "fs";
import path from "path";
import crypto from "crypto";
import GoogleLibPhone from "google-libphonenumber";
import moment from "moment";
/**
* get date instance by timezone
* @param date
* @param timeZone
* @returns {Date}
*/
export const dateInstanceByTimeZone = ({ date, timeZone = "Africa/Lagos" }) =>
new Date(
(typeof date === "string"
? new Date(date)
: date || new Date()
).toLocaleString("en-US", {
timeZone,
})
);
export const convertToBase64 = (value: string) => {
const buffer = Buffer.from(value);
return buffer.toString("base64");
};
export const formatMorningDate = (date: string): string =>
`${date}T00:00:00.000Z`;
export const formatNightDate = (date: string): string =>
`${date}T23:59:00.000Z`;
export const genPassword = (length) =>
Math.round(36 ** length + 1 - Math.random() * 36 ** length)
.toString(36)
.slice(1);
export const getMainWallet = (stores) => {
// eslint-disable-next-line no-restricted-syntax
for (const store of stores) {
const wallets = store.wallet;
const main = wallets.find((wallet) => wallet.type === "MAIN");
if (main) {
return main;
}
}
return null;
};
export const hash512 = (data: string) => {
const hash = crypto.createHash("sha512");
const updatedHash = hash.update(data, "utf-8");
return updatedHash.digest("hex");
};
export const transformValueToArrayLowercase = (object) =>
Object.values(object).map((data) => data.toLocaleLowerCase());
// sample format :Sun Dec 01 00:00:00 GMT+01:00 2017
export const formatDate = (dateInString) => {
const dateInstance = new Date(dateInString);
const dateByZone = dateInstanceByTimeZone({ date: dateInstance });
const date = `${dateByZone}`
.replace("(West Africa Standard Time)", "")
.trim();
const dateArr = date.split(" ");
return `${dateArr[0]} ${dateArr[1]} ${dateArr[2]} 00:00:00 GMT+01:00 ${dateArr[3]}`;
};
const phoneUtil = GoogleLibPhone.PhoneNumberUtil.getInstance();
const PNF = GoogleLibPhone.PhoneNumberFormat;
export const validatePhone = ({ phone, countryCode = "NG" }) => {
const formatPhoneNumber = phoneUtil.parse(phone, countryCode);
const isValid = phoneUtil.isValidNumber(formatPhoneNumber);
if (!isValid) {
throw new Error(`Phone number ${phone} is not valid`);
}
return phoneUtil.format(formatPhoneNumber, PNF.INTERNATIONAL);
};
export const numberOfDaysDiff = ({ startDate, endDate }) => {
const date1 = new Date(startDate).getTime();
const date2 = new Date(endDate).getTime();
const dateDiff = date2 - date1;
return dateDiff / (1000 * 3600 * 24);
};
export const checkIfMonthIsWithinRange = (
startDate,
endDate,
limit
): Boolean => {
const diff = numberOfDaysDiff({ startDate, endDate });
return Math.floor(diff / 30) <= limit;
};
export const capitalize = (s) => {
if (typeof s !== "string") return "";
return s.charAt(0).toUpperCase() + s.slice(1);
};
export const getPastTimeInMilli = (minutesToAdd: number) => {
const currentDate = Date.now();
return currentDate - minutesToAdd * 60000;
};
export const encodeBase64 = (data) => Buffer.from(data).toString("base64");
export const DecodeBase64 = (data) =>
Buffer.from(data, "base64").toString("ascii");
export const friendlyDate = (date) => {
const almostNow = moment(date, "YYYYMMDD");
return almostNow.fromNow();
};
export const morning = () => {
const fromDate = new Date();
fromDate.setHours(0, 0, 0, 0);
return fromDate;
};
export const formatDateByFormat = ({ date, format }) =>
moment(date).format(format || "YYYY-MM-DD");
export const getCurrentDate = (format) => {
const date = morning();
return moment(date).format(format || "YYYY-MM-DD");
};
export const twoDaysAgo = () => {
const formattedDate = moment().tz("Africa/Lagos");
return formattedDate.subtract(2, "day").valueOf();
};
export const generateKey = () => {
const primeLength = 200;
const diffHell = crypto.createDiffieHellman(primeLength);
diffHell.generateKeys("base64");
const secretKey = diffHell.getPrivateKey("hex");
return `GRUPPSECK_${secretKey}`;
};
export const getFileContent = (fileName: string) =>
fs.readFileSync(path.join(__dirname, fileName), "utf8");
/**
* Function to get the past 12 months, starting from the current month
*
*/
export const getPast12Months = () => {
const today = new Date();
const months = [];
for (let i = 0; i < 12; i += 1) {
const firstDay = new Date(today.getFullYear(), today.getMonth() - i, 1);
const tmp = firstDay.toISOString().split("T")[0];
const lastDay = new Date(today.getFullYear(), today.getMonth() - i + 1, 0)
.toISOString()
.split("T")[0];
const month = firstDay.toLocaleString("default", { month: "long" });
months.push({ firstDay: tmp, lastDay, month });
}
return months;
};
// get past 7 days starting from today and label them with the day of the week with the date
export const getPast7Days = () => {
const today = new Date();
const days = [];
for (let i = 0; i < 7; i += 1) {
const day = new Date(
today.getFullYear(),
today.getMonth(),
today.getDate() - i
);
const dayOfWeek = day.toLocaleString("default", { weekday: "short" });
const date = moment(day).format("YYYY-MM-DD");
days.push({ dayOfWeek, date });
}
return days;
};
// get days within range of startDate and endDate labeled with the day of the week with the date
/**
*
* @param {{startDate: Date, endDate: Date}} param0
* @returns
*/
export const getDaysWithinRange = ({ startTime, endTime }) => {
const days = [];
const start = new Date(startTime);
const end = new Date(endTime);
const diff = end.getTime() - start.getTime();
const daysDiff = Math.floor(diff / (1000 * 3600 * 24));
for (let i = 0; i < daysDiff; i += 1) {
const day = new Date(
start.getFullYear(),
start.getMonth(),
start.getDate() + i
);
const dayOfWeek = day.toLocaleString("default", { weekday: "short" });
const date = moment(day).format("YYYY-MM-DD");
days.push({ dayOfWeek, date });
}
return days;
};
// get begining and end of each month within a time range even across years including the current month
// get begining and end of each month within a time range even across years including the current month
export const getMonthsWithinRange = (startDate, endDate) => {
const months = [];
const start = moment(startDate);
const end = moment(endDate).add(1, "month");
const current = moment(start);
while (current <= end) {
const firstDay = current.startOf("month");
const lastDay = current.endOf("month");
const month = firstDay.format("MMMM"); // toLocaleString("default", { month: "long" });
months.push({
firstDay: firstDay.format("YYYY-MM-01"),
lastDay: lastDay.format("YYYY-MM-DD"),
month,
});
current.add(1, "month");
}
return months;
};
/**
* A Function that formats the data for the monthly summary and returns
* an array of objects, containing the date, value, and volume property
* @param data
* @returns {{date: String, value: Number, volume: Number}[]}
*
*/
export const formatTimeTransaction = (data) => {
const formattedData = [];
data.forEach((time) => {
formattedData.push({
date: time.date,
value: time.data.totalValue.value,
volume: time.data.aggs.value,
});
});
return formattedData;
};
// calculate percentage change in volume
/**
* Function that calculates the percentage change in volume.
* The array must be reversed, because the current month is at the first
* index, which will mean you'll be calculating percentage change backward.
* @param {*} data
* @returns {{date: String, value: Number, volume: Number, percentageChange: String}[]}
*/
export const calculatePercentageChange = (data) => {
const formattedData = [];
data.forEach((month) => {
const previousMonth = data[data.indexOf(month) - 1];
let percentageChange = "0.00%";
if (previousMonth) {
if (previousMonth.volume === 0) {
if (month.volume > 0) {
percentageChange = "100.00%";
formattedData.push({
date: month.date,
volume: month.volume,
value: month.value,
percentageChange,
dayOfWeek: month?.dayOfWeek,
});
return;
}
percentageChange = "0.00%";
formattedData.push({
date: month.date,
volume: month.volume,
value: month.value,
percentageChange,
dayOfWeek: month?.dayOfWeek,
});
return;
}
const currentChangeInPercentage = (
((month.value - previousMonth.value) / previousMonth.value) *
100
).toFixed(2);
percentageChange = `${Math.abs(currentChangeInPercentage)}%`;
} else {
percentageChange = "0.00%";
}
formattedData.push({
date: month.date,
volume: month.volume,
value: month.value,
percentageChange,
dayOfWeek: month?.dayOfWeek,
});
});
return formattedData;
};
/**
* recursive function to flatten an object to dot notation
* e.g {bio: { name: "James", age: 12, gender: "male" }} becomes
* { bio.name: "James", bio.age: 12, bio.gender: "male" }
* {@link https://stackoverflow.com/questions/44134212}
* @param {*} ob
* @param {*} prefix
* @param {*} result
* @returns
*/
export function dotify(ob, prefix = false, result = null) {
const finalResult = result || {};
// Preserve empty objects and arrays, they are lost otherwise
if (
prefix &&
typeof ob === "object" &&
ob !== null &&
Object.keys(ob).length === 0
) {
finalResult[prefix] = Array.isArray(ob) ? [] : {};
return finalResult;
}
const prefixChar = prefix ? `${prefix}.` : "";
const keys = Object.keys(ob);
const values = Object.values(ob);
for (let i = 0; i < keys.length; i += 1) {
if (Object.prototype.hasOwnProperty.call(values, i)) {
if (typeof values[i] === "object" && values[i] !== null) {
// Recursion on deeper objects
dotify(values[i], prefixChar + keys[i], finalResult);
} else {
finalResult[prefixChar + keys[i]] = values[i];
}
}
}
return finalResult;
}
export const getLastThreeMonth = () => {
const date = new Date();
date.setMonth(date.getMonth() - 3);
date.setDate(1);
return formatDateByFormat({ date });
};
export const getLastSeventhDate = () => {
const date = new Date();
date.setDate(date.getDate() - 7);
return formatDateByFormat({ date });
};
// duration is assumed to be of this format yyyy-mm-dd
export const getFirstAndLastDateOfTheMonth = ({ duration }) => {
const tonight = formatMorningDate(duration);
const date = new Date(tonight);
const startDate = new Date(date.getTime());
const endDate = new Date(date.getTime());
endDate.setMonth(endDate.getMonth() + 1);
return { startDate, endDate };
};
export const isDateValid = ({ date }) => {
const dateInstance = new Date(date);
return dateInstance instanceof Date && !Number.isNaN(dateInstance);
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment