UNPKG

0xweb

Version:

Contract package manager and other web3 tools

698 lines (627 loc) 18.9 kB
import { l } from './$logger'; export class DateTool { protected constructor(public date: Date = new Date()) { } /** * - DD-MM-YYYYY (HH:mm)? * - DD.MM.YYYYY (HH:mm)? * - ISODate * - Ticks */ static with(mix: string | number | Date) { let date: Date; if (typeof mix === 'string' || typeof mix === 'number') { date = $date.parse(mix); } else { date = mix; } return new DateTool(date); } static withNow() { return new DateTool(); } clone() { return new DateTool(new Date(this.date)); } add(x: string | number) { this.date = $date.additive(this.date, x) return this; } dayStart() { this.date = $date.dayStart(this.date); return this; } dayEnd() { this.date = $date.dayEnd(this.date); return this; } weekStart() { this.date = $date.weekStart(this.date); return this; } weekEnd() { this.date = $date.weekEnd(this.date); return this; } monthStart() { this.date = $date.monthStart(this.date); return this; } monthEnd() { this.date = $date.monthEnd(this.date); return this; } daysBetween(b: Date) { return $date.daysBetween(this.date, b); } /** e.g. yyyy-MM-dd HH:mm */ format(format: string) { return $date.format(this.date, format); } setMilliseconds(v: number) { this.date.setMilliseconds(v); return this; } setSeconds(v: number) { this.date.setSeconds(v); return this; } setMinutes(v: number) { this.date.setMinutes(v); return this; } setHours(h: number, min?: number, sec?: number, ms?: number) { this.date.setHours(h); if (min != null) this.date.setMinutes(min); if (sec != null) this.date.setSeconds(sec); if (ms != null) this.date.setMilliseconds(ms); return this; } /** Sets the numeric day-of-the-month value of the Date object using local time. */ setDate(v: number) { this.date.setDate(v); return this; } setMonth(v: number) { this.date.setMonth(v); return this; } setFullYear(v: number) { this.date.setFullYear(v); return this; } nextDay(h?: number, min?: number, s?: number, ms?: number) { this.date = $date.additive(this.date, '1d'); if (h != null) { this.date.setHours(h); } if (min != null) { this.date.setMinutes(min); } if (s != null) { this.date.setSeconds(s); } if (ms != null) { this.date.setMilliseconds(ms); } return this; } toUnixTimestamp(): number { return $date.toUnixTimestamp(this.date); } } class Timer { private paused = false; private from = Date.now(); private pausedAt: number; constructor (private name?: string) { } log (msg?: string): this { let str = this.name ? `"${this.name}"` : ''; if (msg) { str += ` - ${msg}`; } let ms = $date.formatTimespan(Date.now() - this.from); l`Timer ${str}: ${ms}`; return this; } pause (): this { if (this.pausedAt == null) { this.pausedAt = Date.now(); } return this; } resume (): this { if (this.pausedAt != null) { let pauseTime = Date.now() - this.pausedAt; this.pausedAt = null; this.from += pauseTime; } return this; } restart (name?: string) { this.pausedAt = null; this.from = Date.now(); this.name = name ?? this.name; return this; } } export namespace $date { export function tool(dateStr: string): DateTool export function tool(date: Date): DateTool export function tool(): DateTool export function tool(date: string | Date = new Date()): DateTool { if (typeof date === 'string') { date = parse(date); } return DateTool.with(date); } export function timer (name?: string) { let timer = new Timer(name); return timer; } /** e.g. yyyy-MM-dd HH:mm */ export function format(date: number | string | Date, format: string) { if (typeof date === 'string' || typeof date === 'number') { date = parse(date); } return Formatter.format(date, format); } export function formatTimespan(ms: number) { ms = Math.round(ms); let str = ''; const SECOND = 1000; const MINUTE = 60 * SECOND; const HOUR = 60 * MINUTE; const DAY = 24 * HOUR; if (DAY < ms) { let days = Math.floor(ms / DAY); str += `${days}d`; ms -= days * DAY; } if (HOUR < ms) { let hours = Math.floor(ms / HOUR); str += ` ${hours}h`; ms -= hours * HOUR; } if (MINUTE < ms) { let minutes = Math.floor(ms / MINUTE); str += ` ${minutes}min`; ms -= minutes * MINUTE; } if (SECOND < ms) { let seconds = Math.floor(ms / SECOND); str += ` ${seconds}s`; ms -= seconds * SECOND; } if (0 < ms) { str += ` ${ms}ms`; } return str.trim(); } export function dayStart(date = new Date()) { let result = new Date(date); result.setHours(0, 0, 0, 0); return result; } export function hourStart(date = new Date()) { let result = new Date(date); result.setMinutes(0, 0, 0); return result; } export function dayEnd(date = new Date()) { let result = new Date(date); result.setHours(23, 59, 59, 999); return result; } export function weekStart(date = new Date()) { let result = new Date(date); let day = result.getDay() - 1; if (day === -1) { day = 6; } result.setDate(result.getDate() - day); result.setHours(0, 0, 0, 0); return result; } export function weekEnd(date = new Date()) { let result = new Date(date); let day = result.getDay() - 1; if (day === -1) { day = 6; } result.setDate(result.getDate() + (6 - day)); result.setHours(23, 59, 59, 999); return result; } export function monthStart(date = new Date()) { let result = new Date(date); result.setDate(1); result.setHours(0, 0, 0, 0); return result; } export function monthEnd(date = new Date()) { let result = new Date(date); result.setMonth(result.getMonth() + 1); result.setDate(1); result.setHours(0, 0, 0, -1); return result; } /** date1 + X === date2 */ export function daysBetween(a: Date, b: Date, abs: boolean = true) { let aStart = dayStart(a); let bStart = dayStart(b); let diff = bStart.valueOf() - aStart.valueOf(); if (abs) diff = Math.abs(diff); return Math.floor(diff / (24 * 60 * 60 * 1000)); } /** hour1 + X === hour2 */ export function hoursBetween(a: Date, b: Date, abs: boolean = true) { let aStart = hourStart(a); let bStart = hourStart(b); let diff = bStart.valueOf() - aStart.valueOf(); if (abs) diff = Math.abs(diff); return Math.floor(diff / (60 * 60 * 1000)); } export function minsBetween(a: Date | string, b: Date | string, abs: boolean = true) { if (typeof a === 'string') { a = parse(a); } if (typeof b === 'string') { b = parse(b); } let ms = b.valueOf() - a.valueOf() if (abs) ms = Math.abs(ms); return Math.floor(ms / (60 * 1000)); } /** * - DD-MM-YYYYY (HH:mm)? * - DD.MM.YYYYY (HH:mm)? * - ISODate * - Ticks */ export function parse(mix: Date | number | string, default_?: Date) { if (mix instanceof Date) { return mix; } if (typeof mix === 'number') { return new Date(mix); } if (mix == null || mix === '') { return default_; } if (mix.includes('T') || mix.includes('Z')) { return new Date(mix); } let format = mix; let H = 0; let Min = 0; let hours = /(\d{2}):(\d{2})/.exec(format); if (hours) { H = Number(hours[1]); Min = Number(hours[2]); } let Y = 0; let M = 1; let D = 1; let dateMatch = /(\d{2})[\.\-](\d{2})[\.\-](\d{4})/.exec(format); if (dateMatch) { D = Number(dateMatch[1]); M = Number(dateMatch[2]); Y = Number(dateMatch[3]); } else { dateMatch = /(\d{4})[\.\-](\d{2})[\.\-](\d{2})/.exec(format); if (dateMatch) { Y = Number(dateMatch[1]); M = Number(dateMatch[2]); D = Number(dateMatch[3]); } } if (Y === 0) { if (arguments.length > 1) { return default_; } throw new Error(`Invalid format ${format}`); } return new Date(Y, M - 1, D, H, Min); } /** * s|sec|seconds|m|mins?|h|hours?|d|days?|w|weeks?|months?|y|years? * e.g: 2h * @param str * @param opts Default: ms */ export function parseTimespan(str: string, opts?: { get?: 'ms' | 's', anchor?: Date }): number { let direction = str[0] === '-' ? -1 : +1; if (direction === -1) { str = str.substring(1); } if (/\s+/.test(str)) { let value = str.split(/\s+/).reduce((agr, x ) => { return agr + parseTimespan(x, opts); }, 0); return value * direction; } let rgx = /^(?<value>[\d\.]+)?(ms|s|sec|seconds|m|mins?|h|hours?|d|days?|w|weeks?|months?|y|years?)$/ let match = rgx.exec(str); if (match == null) { throw new Error(`Invalid Humanize seconds. Pattern: ${rgx.toString()}. Got: ${str}`); } let val = match.groups.value ? parseFloat(match[1]) : 1; let unit = match[2]; let MS = 1000; if (opts?.get === 's') { MS = 1; } MS *= direction; switch (unit) { case 'ms': return val; case 's': case 'sec': return val * MS; case 'm': case 'min': case 'mins': return val * 60 * MS; case 'h': case 'hour': case 'hours': return val * 60 * 60 * MS; case 'd': case 'day': case 'days': return val * 60 * 60 * 24 * MS; case 'w': case 'week': case 'weeks': return val * 60 * 60 * 24 * 7 * MS; case 'month': case 'months': if (opts?.anchor) { let date = new Date(opts.anchor); date.setMonth(date.getMonth() + val * direction); let result = date.valueOf() - opts.anchor.valueOf(); if (opts?.get === 's') { result = Math.round(result / 1000); } return result; } return val * 60 * 60 * 24 * 31 * MS; case 'y': case 'year': case 'years': if (opts?.anchor) { let date = new Date(opts.anchor); date.setFullYear(date.getFullYear() + val * direction); let result = date.valueOf() - opts.anchor.valueOf(); if (opts?.get === 's') { result = Math.round(result / 1000); } return result; } return val * 60 * 60 * 24 * 365 * MS; } throw new Error(`Invalid units ${str}`); } export function additive(date: Date | number | string, x: string | number) { let d = parse(date); let timestamp = d.getTime(); if (typeof x === 'number') { return new Date(timestamp + x); } let ms = parseTimespan(x, { anchor: d }); let target = new Date(timestamp + ms); let offset = d.getTimezoneOffset(); var diff = offset - target.getTimezoneOffset(); if (diff !== 0) { const h = diff / 60 | 0; target.setHours(target.getHours() - h); } return target; } export function equal(a: Date, b: Date, precision: 'year' | 'month' | 'date' | 'hour' | 'minute' | 'second' | 'ms' = 'ms') { let aYear = a.getFullYear(); let bYear = b.getFullYear(); if (aYear !== bYear) { return false; } if (precision === 'year') { return true; } let aMonth = a.getMonth(); let bMonth = b.getMonth(); if (aMonth !== bMonth) { return false; } if (precision === 'month') { return true; } let aDate = a.getDate(); let bDate = b.getDate(); if (aDate !== bDate) { return false; } if (precision === 'date') { return true; } let aHours = a.getHours(); let bHours = b.getHours(); if (aHours !== bHours) { return false; } if (precision === 'hour') { return true; } let aMins = a.getMinutes(); let bMins = b.getMinutes(); if (aMins !== bMins) { return false; } if (precision === 'minute') { return true; } let aSec = a.getSeconds(); let bSec = b.getSeconds(); if (aSec !== bSec) { return false; } if (precision === 'second') { return true; } let aMs = a.getMilliseconds(); let bMs = b.getMilliseconds(); if (aMs !== bMs) { return false; } return true; } export function isSameDay(a: Date, b: Date) { if (a.getFullYear() !== b.getFullYear()) { return false; } if (a.getMonth() !== b.getMonth()) { return false; } if (a.getDate() !== b.getDate()) { return false; } return true; } export function toUnixTimestamp(date: Date = new Date()): number { return Math.floor(date.getTime() / 1000); } export function fromUnixTimestamp(seconds: number | bigint): Date { return new Date(Number(seconds) * 1000); } namespace Formatter { const _cultureInfo: { MONTH, MONTH_SHORT, DAY, DAY_SHORT } = { MONTH: [ 'January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December', ], MONTH_SHORT: [ 'Jan', 'Feb', 'Mar', 'Apr', 'May', 'June', 'July', 'Aug', 'Sept', 'Oct', 'Nov', 'Dec', ], DAY: [ 'Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday', ], DAY_SHORT: [ 'Mon', 'Tues', 'Weds', 'Thurs', 'Fri', 'Sat', 'Sun', ], }; let _date: Date; export function format(date: Date, format: string) { _date = date; return format .replace('Mm', Mm) .replace('MMM', MMM) .replace('MM', MM) .replace('#M', $M) .replace('yyyy', yyyy) .replace('yy', yy) .replace('dd', dd) .replace('#d', $d) .replace('Dd', Dd) .replace('DDD', DDD) .replace('HH', HH) .replace('hh', hh) .replace('#h', $h) .replace('mm', mm) .replace('#m', $m) .replace('ss', ss) .replace('#s', $s) .replace('ms', ms) ; }; const yyyy = function () { return String(_date.getFullYear()); }; const yy = function () { return String(_date.getFullYear() % 100); }; const $M = function () { return String(_date.getMonth() + 1); }; const MM = function () { return pad(_date.getMonth() + 1); }; const Mm = function () { return _cultureInfo.MONTH_SHORT[_date.getMonth()]; }; const MMM = function () { return _cultureInfo.MONTH[_date.getMonth()]; }; const $d = function () { return String(_date.getDate()); }; const dd = function () { return pad(_date.getDate()); }; const Dd = function () { return _cultureInfo.DAY_SHORT[_date.getMonth()]; }; const DDD = function () { return _cultureInfo.DAY_SHORT[_date.getMonth()]; }; const $H = function () { return String(_date.getHours()); }; const HH = function () { return pad(_date.getHours()); }; const hh = HH; const $h = $H; const $m = function () { return String(_date.getMinutes()); }; const mm = function () { return pad(_date.getMinutes()); }; const $s = function () { return String(_date.getSeconds()); }; const ss = function () { return pad(_date.getSeconds()); }; const ms = function () { return pad(_date.getMilliseconds()); }; function pad(value) { return value > 9 ? value : '0' + value; } } }