minimal working
This commit is contained in:
1 parent
2093433b96
commit
13ea8c80da
11 files changed
+727
-337
No files matched your search
@@ -0,0 +1,337 @@
|
||||
import Vue from 'vue'
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
Vue.filter('format', (v: any) => {
|
||||
if (typeof v === 'number') {
|
||||
return v || v === 0 ? v.toLocaleString() : ''
|
||||
} else if (v instanceof Date) {
|
||||
return v.toLocaleDateString([], {
|
||||
year: 'numeric',
|
||||
month: 'long',
|
||||
day: 'numeric',
|
||||
weekday: 'short',
|
||||
})
|
||||
} else if (v && typeof v === 'object') {
|
||||
return JSON.stringify(v)
|
||||
}
|
||||
return v
|
||||
})
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
Vue.filter('formatDate', (v: any) => {
|
||||
return v
|
||||
? new Date(v).toLocaleDateString([], {
|
||||
year: 'numeric',
|
||||
month: 'long',
|
||||
day: 'numeric',
|
||||
weekday: 'short',
|
||||
})
|
||||
: ''
|
||||
})
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
Vue.filter('duration', (v: any) => {
|
||||
return v
|
||||
? new Duration(new Date(v), new Date()).toString({
|
||||
sign: false,
|
||||
granularity: 2,
|
||||
})
|
||||
: ''
|
||||
})
|
||||
|
||||
/**
|
||||
* Possible duration units in this parser
|
||||
*/
|
||||
export type DurationUnit = 'ms' | 's' | 'min' | 'h' | 'd' | 'w' | 'mo' | 'y'
|
||||
|
||||
export interface IDurationOptions {
|
||||
/**
|
||||
* @default true
|
||||
*/
|
||||
sign?: boolean
|
||||
/**
|
||||
* Number of units plus subunits
|
||||
*/
|
||||
granularity?: number
|
||||
/**
|
||||
* Number of max units shown
|
||||
*/
|
||||
maxUnit?: number
|
||||
/**
|
||||
* Smallest unit shown
|
||||
*
|
||||
* @default 's'
|
||||
*/
|
||||
smallest?: DurationUnit
|
||||
/**
|
||||
* Custom naming for units
|
||||
*/
|
||||
unit?: Partial<Record<DurationUnit, string>>
|
||||
}
|
||||
|
||||
export class Duration {
|
||||
/**
|
||||
* Sign in front of the output toString()
|
||||
*/
|
||||
sign: '+' | '-' | '' = '+'
|
||||
|
||||
/**
|
||||
* Milliseconds
|
||||
*/
|
||||
ms: number
|
||||
/**
|
||||
* Seconds
|
||||
*/
|
||||
s: number
|
||||
/**
|
||||
* Minutes
|
||||
*/
|
||||
min: number
|
||||
/**
|
||||
* Hours
|
||||
*/
|
||||
h: number
|
||||
/**
|
||||
* Days
|
||||
*/
|
||||
d: number
|
||||
/**
|
||||
* Weeks
|
||||
*/
|
||||
w: number
|
||||
/**
|
||||
* Months
|
||||
*/
|
||||
mo: number
|
||||
/**
|
||||
* Years
|
||||
*/
|
||||
y: number
|
||||
|
||||
private _dates: [Date, Date] = [new Date(this.from), new Date(this.to)]
|
||||
|
||||
/**
|
||||
* Parse milliseconds (i.e. epoch) to Duration, based on before present time
|
||||
*/
|
||||
static of(msec: number) {
|
||||
const to = new Date()
|
||||
const output = new this(new Date(+to - msec), to)
|
||||
output.sign = ''
|
||||
|
||||
return output
|
||||
}
|
||||
|
||||
constructor(
|
||||
/**
|
||||
* Starting Date
|
||||
*/
|
||||
public from: Date,
|
||||
/**
|
||||
* Ending date
|
||||
*/
|
||||
public to: Date
|
||||
) {
|
||||
if (from > to) {
|
||||
this.sign = '-'
|
||||
this._dates = this._dates.reverse() as [Date, Date]
|
||||
}
|
||||
|
||||
this.ms = this._parse((d) => d.getMilliseconds(), {
|
||||
get: (d) => d.getSeconds(),
|
||||
set: (d, v) => d.setSeconds(v),
|
||||
inc: () => 1000,
|
||||
})
|
||||
|
||||
this.s = this._parse((d) => d.getSeconds(), {
|
||||
get: (d) => d.getMinutes(),
|
||||
set: (d, v) => d.setMinutes(v),
|
||||
inc: () => 60,
|
||||
})
|
||||
|
||||
this.min = this._parse((d) => d.getMinutes(), {
|
||||
get: (d) => d.getHours(),
|
||||
set: (d, v) => d.setHours(v),
|
||||
inc: () => 60,
|
||||
})
|
||||
|
||||
this.h = this._parse((d) => d.getHours(), {
|
||||
get: (d) => d.getDate(),
|
||||
set: (d, v) => d.setDate(v),
|
||||
inc: () => 24,
|
||||
})
|
||||
|
||||
this.d = this._parse((d) => d.getDate(), {
|
||||
get: (d) => d.getMonth(),
|
||||
set: (d, v) => d.setMonth(v),
|
||||
inc: (d) => {
|
||||
const y = d.getFullYear()
|
||||
let isLeapYear = true
|
||||
if (y % 4) {
|
||||
isLeapYear = false
|
||||
} else if (y % 100) {
|
||||
isLeapYear = true
|
||||
} else if (y % 400) {
|
||||
isLeapYear = false
|
||||
}
|
||||
|
||||
return [
|
||||
31, // Jan
|
||||
isLeapYear ? 29 : 28, // Feb
|
||||
31, // Mar
|
||||
30, // Apr
|
||||
31, // May
|
||||
30, // Jun
|
||||
31, // Jul
|
||||
31, // Aug
|
||||
30, // Sep
|
||||
31, // Oct
|
||||
30, // Nov
|
||||
31, // Dec
|
||||
][d.getMonth()]!
|
||||
},
|
||||
})
|
||||
|
||||
this.w = Math.floor(this.d / 7)
|
||||
this.d = this.d % 7
|
||||
|
||||
this.mo = this._parse((d) => d.getMonth(), {
|
||||
get: (d) => d.getFullYear(),
|
||||
set: (d, v) => d.setFullYear(v),
|
||||
inc: () => 12,
|
||||
})
|
||||
|
||||
this.y = this._parse((d) => d.getFullYear())
|
||||
}
|
||||
|
||||
/**
|
||||
* To JSON-serializable OrderedDict
|
||||
*/
|
||||
toOrderedDict(): [DurationUnit, number][] {
|
||||
return [
|
||||
['ms', this.ms],
|
||||
['s', this.s],
|
||||
['min', this.min],
|
||||
['h', this.h],
|
||||
['d', this.d],
|
||||
['w', this.w],
|
||||
['mo', this.mo],
|
||||
['y', this.y],
|
||||
]
|
||||
}
|
||||
|
||||
/**
|
||||
* To String
|
||||
*
|
||||
* Works with `${duration}` also
|
||||
*/
|
||||
toString({
|
||||
sign = true,
|
||||
granularity,
|
||||
maxUnit,
|
||||
smallest = 's',
|
||||
unit = {},
|
||||
}: IDurationOptions = {}) {
|
||||
const odict = this.toOrderedDict()
|
||||
const smallestIndex = odict.map(([k]) => k).indexOf(smallest)
|
||||
const filteredDict = odict.filter(([, v], i) => v && i >= smallestIndex)
|
||||
|
||||
const str = filteredDict
|
||||
.slice(granularity ? filteredDict.length - granularity : 0)
|
||||
.reverse()
|
||||
.slice(0, maxUnit)
|
||||
.map(([k, v]) => `${v.toLocaleString()}${unit[k] || k}`)
|
||||
.join(' ')
|
||||
|
||||
if (sign) {
|
||||
return this.sign + str
|
||||
}
|
||||
|
||||
return str
|
||||
}
|
||||
|
||||
private _parse(
|
||||
current: (d: Date) => number,
|
||||
upper?: {
|
||||
get: (d: Date) => number
|
||||
set: (d: Date, v: number) => void
|
||||
inc: (d: Date) => number
|
||||
}
|
||||
) {
|
||||
let a = current(this._dates[1]) - current(this._dates[0])
|
||||
|
||||
if (upper) {
|
||||
while (a < 0) {
|
||||
upper.set(this._dates[1], upper.get(this._dates[1]) - 1)
|
||||
this._dates[1] = new Date(this._dates[1])
|
||||
|
||||
a += upper.inc(this._dates[1])
|
||||
}
|
||||
}
|
||||
|
||||
return a
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Date adding functions
|
||||
*/
|
||||
export function addDate(d: Date): Record<DurationUnit, (n: number) => Date> {
|
||||
return {
|
||||
/**
|
||||
* Milliseconds
|
||||
*/
|
||||
ms: (n) => {
|
||||
d.setMilliseconds(d.getMilliseconds() + n)
|
||||
return new Date(d)
|
||||
},
|
||||
/**
|
||||
* Seconds
|
||||
*/
|
||||
s: (n) => {
|
||||
d.setSeconds(d.getSeconds() + n)
|
||||
return new Date(d)
|
||||
},
|
||||
/**
|
||||
* Minutes
|
||||
*/
|
||||
min: (n) => {
|
||||
d.setMinutes(d.getMinutes() + n)
|
||||
return new Date(d)
|
||||
},
|
||||
/**
|
||||
* Hours
|
||||
*/
|
||||
h: (n) => {
|
||||
d.setHours(d.getHours() + n)
|
||||
return new Date(d)
|
||||
},
|
||||
/**
|
||||
* Date
|
||||
*/
|
||||
d: (n) => {
|
||||
d.setDate(d.getDate() + n)
|
||||
return new Date(d)
|
||||
},
|
||||
/**
|
||||
* Weeks
|
||||
*/
|
||||
w: (n) => {
|
||||
d.setDate(d.getDate() + n * 7)
|
||||
return new Date(d)
|
||||
},
|
||||
/**
|
||||
* Months
|
||||
*/
|
||||
mo: (n) => {
|
||||
d.setMonth(d.getMonth() + n)
|
||||
return new Date(d)
|
||||
},
|
||||
/**
|
||||
* Years
|
||||
*/
|
||||
y: (n) => {
|
||||
d.setFullYear(d.getFullYear() + n)
|
||||
return new Date(d)
|
||||
},
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user