commit 642c1def6e899f383293045423009ddb471a4e20
parent 3370defc76916b0c86ce0bea2a38a5f97e5d367c
Author: triesap <137732411+triesap@users.noreply.github.com>
Date: Wed, 13 Nov 2024 08:19:32 +0000
utils: add/edit utils
Diffstat:
8 files changed, 157 insertions(+), 36 deletions(-)
diff --git a/utils/src/currency.ts b/utils/src/currency.ts
@@ -1,28 +1,17 @@
+import { regex } from "./regex";
+
export type FiatCurrency = `usd` | `eur`;
export const fiat_currencies: FiatCurrency[] = [`usd`, `eur`] as const;
export type FiatCurrencyGlyphs = `dollar` | `eur`;
-export type CurrencyPrice = {
- symbol: string;
- currency: FiatCurrency;
- /**
- * integer value
- */
- val_i: number;
- /**
- * fractional value
- */
- val_f: number;
-};
-
export type CurrencyPriceFmt = [string, FiatCurrency, number, number]
export function parse_currency(val?: string): FiatCurrency {
const _val = val?.trim().toLowerCase()
switch (_val) {
- case "usd":
- case "eur":
+ case `usd`:
+ case `eur`:
return _val;
default:
return `usd`;
@@ -40,23 +29,111 @@ export function parse_currency_glyph_key(val?: string): | `currency-${FiatCurren
};
};
-export const parse_currency_price = (locale: string, _currency: string, amount: number): CurrencyPrice => {
- const currency = parse_currency(_currency);
+export type CurrencyDecimalSeparator = `,` | `.`;
+
+export type CurrencyMetadata = {
+ cur: FiatCurrency;
+ /**
+ * currency symbol
+ */
+ cur_s: string;
+ /**
+ * currency marker
+ */
+ cur_m: string;
+ /**
+ * true if symbol is at the start
+ */
+ cur_pos: boolean;
+ dec_s: CurrencyDecimalSeparator;
+}
+
+
+export type CurrencyPrice = CurrencyMetadata & {
+ /**
+ * integer num
+ */
+ num_i: number;
+ /**
+ * fractional num
+ */
+ num_f: number;
+ /**
+ * integer value
+ */
+ val_i: string;
+ /**
+ * fractional value
+ */
+ val_f: string;
+};
+
+export const locale_fractional_decimal = (locale: string): CurrencyDecimalSeparator => {
+ const formatter = new Intl.NumberFormat(locale);
+ const formatted = formatter.format(1.1);
+ return formatted.includes(',') ? `,` : `.`;
+};
+
+export const parse_currency_marker = (locale: string, currency: string): string => {
+ const cur = parse_currency(currency);
+ const fmt = new Intl.NumberFormat(`en-US`, {
+ style: 'currency',
+ currency: cur.toUpperCase(),
+ minimumFractionDigits: 2,
+ });
+ const fmt_basis = fmt.format(1);
+ let fmt_res: string | undefined = undefined;
+ fmt_res = fmt_basis.match(regex.currency_marker)?.[0];
+ if (fmt_res) return fmt_res;
+ fmt_res = fmt_basis.match(regex.currency_symbol)?.[0];
+ if (fmt_res) return fmt_res;
+ fmt_res = fmt_basis.match(new RegExp(cur, `i`))?.[0];
+ if (fmt_res) return fmt_res;
+ return cur.toUpperCase();
+}
+
+export const parse_currency_price = (locale: string, currency: string, price: number | string): CurrencyPrice | undefined => {
+ const num_amt = Math.max(typeof price === `number` ? price : Number(price.replace(/[^0-9.]/g, ``)), 0);
+ const cur = parse_currency(currency);
const fmt = new Intl.NumberFormat(locale, {
style: 'currency',
- currency: currency.toUpperCase(),
+ currency: cur.toUpperCase(),
minimumFractionDigits: 2,
});
- const fmt_amt = fmt.format(amount);
- const [symbol_val_i, val_f] = fmt_amt.split('.');
+ const fmt_amt = fmt.format(num_amt);
+ const fmt_num = fmt_amt.replace(/[^0-9.,\s\u200F\u00A0]+/g, ``).trim()
+ const cur_s = fmt_amt.match(regex.currency_symbol)?.[0] || fmt_amt.match(new RegExp(cur, `i`))?.[0];
+ if (!cur_s) return undefined;
+ const cur_m = fmt_amt.match(regex.currency_marker)?.[0] || cur_s;
+ const cur_pos = fmt_amt.startsWith(cur_m);
+ const dec_s = locale_fractional_decimal(locale);
+ const [_val_i, _val_f] = fmt_num.split(dec_s);
+ const val_i = _val_i.replace(regex.nbsp_rp, ``).replace(regex.rtlm_rp, ``);
+ const val_f = _val_f.replace(regex.nbsp_rp, ``).replace(regex.rtlm_rp, ``)
+ const num_i = parseInt(val_i.replace(dec_s === `,` ? regex.periods : regex.commas, ``));
+ const num_f = parseInt(val_f);
return {
- symbol: symbol_val_i.charAt(0),
- currency,
- val_i: Number(symbol_val_i.replaceAll(`,`, ``).slice(1)),
- val_f: Number(val_f),
+ cur,
+ cur_s,
+ cur_m,
+ cur_pos,
+ dec_s,
+ num_i,
+ num_f,
+ val_i,
+ val_f,
};
};
+export const fmt_currency_price = (currency_price: CurrencyPrice, hide_currency_marker?: boolean): string => {
+ const cur_val = hide_currency_marker ? currency_price.cur_s : currency_price.cur_m;
+ return `${currency_price.cur_pos ? `${cur_val} ` : ``}${currency_price.val_i}${currency_price.dec_s}${currency_price.val_f}${currency_price.cur_pos ? `` : ` ${cur_val}`}`
+};
+
+export const sum_currency_price = (currency_price: CurrencyPrice): number => {
+ return currency_price.num_i + (currency_price.num_f / 100);
+};
+
export const parse_currency_price_fmt = (locale: string, _currency: string, amount: number): CurrencyPriceFmt => {
const currency = parse_currency(_currency);
const fmt = new Intl.NumberFormat(locale, {
diff --git a/utils/src/file.ts b/utils/src/file.ts
@@ -1,4 +1,4 @@
-import type { FileBytesFormat } from "./types";
+import type { FileBytesFormat, FilePath } from "./types";
export const parse_file_name = (file_path: string): string => {
const file_path_dirs = file_path.split(`/`);
@@ -23,3 +23,14 @@ export const format_file_bytes = (num_bytes: number, format: FileBytesFormat): s
const result = num_bytes / factor;
return `${result.toFixed(2)} ${format.toUpperCase()}`;
};
+
+export const parse_file_path = (file_path: string): FilePath | undefined => {
+ const file_path_spl = file_path.split(`/`);
+ const file_path_file = file_path_spl[file_path_spl.length - 1];
+ const [file_name, mime_type] = file_path_file.split(`.`);
+ if (!file_name || !mime_type) return undefined;
+ return {
+ file_name,
+ mime_type
+ };
+};
+\ No newline at end of file
diff --git a/utils/src/list.ts b/utils/src/list.ts
@@ -14,3 +14,9 @@ export const list_move_index = <T>(array: T[], index_start: number, index_end: n
...newArray.slice(adjustedIndexEnd)
];
};
+
+export const list_assign = (list_curr: string[], list_new: string[]): string[] => {
+ return Array.from(
+ new Set([...list_curr, ...list_new]),
+ ).filter((i) => !!i);
+};
diff --git a/utils/src/math.ts b/utils/src/math.ts
@@ -1,3 +1,5 @@
export const round_to_5 = (num: number): number => {
return Math.round(num / 5) * 5;
};
+
+export const num_str = (num: number): string => num.toString();
+\ No newline at end of file
diff --git a/utils/src/regex.ts b/utils/src/regex.ts
@@ -1,4 +1,10 @@
-export const regex: Record<string, RegExp> = {
+export const regex = {
+ nbsp: /[\u00A0]/g,
+ nbsp_rp: /[\u00A0]+/g,
+ rtlm: /[\u200F]/g,
+ rtlm_rp: /[\u200F]+/g,
+ commas: /[,]+/g,
+ periods: /[.]+/g,
word_only: /^[a-zA-Z]+$/,
alpha: /[a-zA-Z ]$/,
alpha_ch: /[a-zA-Z ]$/,
@@ -9,5 +15,8 @@ export const regex: Record<string, RegExp> = {
price_ch: /[0-9.]$/,
profile_name: /^[a-zA-Z0-9._]{3,30}$/,
profile_name_ch: /[a-zA-Z0-9._]/,
- trade_product_key: /^(?:[a-zA-Z0-9]+(?:\s+[a-zA-Z0-9]+){0,2})$/
+ trade_product_key: /^(?:[a-zA-Z0-9]+(?:\s+[a-zA-Z0-9]+){0,2})$/,
+ currency_symbol: /(?:[A-Za-z]{3,5}\$|\p{Sc})/u,
+ currency_marker: /(?:[A-Za-z]{2,4}[^\d\s]+|[^\d\s]{1,3}[A-Za-z]{2,4})/
+ ///(?:[A-Za-z]{2,4}\$|\$(?=[A-Za-z]{2,4}$))/
};
diff --git a/utils/src/time.ts b/utils/src/time.ts
@@ -1,7 +1,5 @@
-export function time_now_ms(): number {
- return Math.floor(new Date().getTime() / 1000);
-};
+export const time_now_ms = (): number => Math.floor(new Date().getTime() / 1000);
-export function time_created_on(): string {
- return new Date().toISOString();
-};
-\ No newline at end of file
+export const time_created_on = (): string => new Date().toISOString();
+
+export const year_curr = (): string => new Date().getFullYear().toString();
+\ No newline at end of file
diff --git a/utils/src/types.ts b/utils/src/types.ts
@@ -17,4 +17,7 @@ export type LocationPoint = GeolocationCoordinatesPoint & {
}
export type NumberTuple = [number, number];
-export type FileBytesFormat = `kb` | `mb` | `gb`;
-\ No newline at end of file
+
+export type FileBytesFormat = `kb` | `mb` | `gb`;
+export type FileMimeType = string;
+export type FilePath = { file_name: string; mime_type: FileMimeType; }
+\ No newline at end of file
diff --git a/utils/src/units.ts b/utils/src/units.ts
@@ -39,4 +39,17 @@ export const mass_g = (units: MassUnit, amt: number): number => {
export const mass_tf = (units_from: MassUnit, units_to: MassUnit, amt: number): number => {
return convert(amt, units_from).to(units_to);
+};
+
+export const mass_tf_u = (units_from: MassUnit, units_to: string, amt: number): number => {
+ const _units_to = parse_mass_unit_u(units_to);
+ if (!_units_to) throw new Error(`Malformed units.`)
+ return convert(amt, units_from).to(_units_to);
+};
+
+export const mass_tf_str = (units_from: string, units_to: string, amt: number): number => {
+ const _units_from = parse_mass_unit_u(units_from);
+ const _units_to = parse_mass_unit_u(units_to);
+ if (!_units_from || !_units_to) throw new Error(`Malformed units.`)
+ return convert(amt, _units_from).to(_units_to);
};
\ No newline at end of file