161 lines
3.6 KiB
TypeScript
161 lines
3.6 KiB
TypeScript
import { Injectable } from '@nestjs/common'
|
|
import * as _ from 'lodash'
|
|
import {
|
|
DateTime,
|
|
Settings,
|
|
HourNumbers,
|
|
MinuteNumbers,
|
|
SecondNumbers,
|
|
DayNumbers,
|
|
WeekdayNumbers,
|
|
} from 'luxon'
|
|
|
|
Settings.defaultLocale = 'en-US'
|
|
Settings.defaultZone = 'utc'
|
|
Settings.defaultWeekSettings = {
|
|
firstDay: 2,
|
|
minimalDays: 1,
|
|
weekend: [6, 7],
|
|
}
|
|
|
|
export type TimeType = {
|
|
hour: HourNumbers
|
|
minute: MinuteNumbers
|
|
second: SecondNumbers
|
|
}
|
|
|
|
@Injectable()
|
|
export class DateTimeUtils {
|
|
static nowAsJSDate(): Date {
|
|
return DateTime.now().toJSDate()
|
|
}
|
|
|
|
static now(): DateTime {
|
|
return DateTime.now()
|
|
}
|
|
|
|
static getOverlapRange(
|
|
startA: DateTime,
|
|
endA: DateTime,
|
|
startB: DateTime,
|
|
endB: DateTime,
|
|
): { start: DateTime; end: DateTime } {
|
|
const overlapStart = DateTime.max(startA, startB)
|
|
const overlapEnd = DateTime.min(endA, endB)
|
|
return {
|
|
start: overlapStart,
|
|
end: overlapEnd,
|
|
}
|
|
}
|
|
|
|
static isExpired(expires: string): boolean {
|
|
return DateTime.fromISO(expires) < DateTime.now()
|
|
}
|
|
|
|
static isOverlap(
|
|
startA: DateTime,
|
|
endA: DateTime,
|
|
startB: DateTime,
|
|
endB: DateTime,
|
|
): boolean {
|
|
return (
|
|
this.getOverlapRange(startA, endA, startB, endB).start <
|
|
this.getOverlapRange(startA, endA, startB, endB).end
|
|
)
|
|
}
|
|
|
|
static isOverlaps(
|
|
listA: { start: DateTime; end: DateTime }[],
|
|
listB: { start: DateTime; end: DateTime }[],
|
|
): boolean {
|
|
for (const a of listA) {
|
|
for (const b of listB) {
|
|
if (this.isOverlap(a.start, a.end, b.start, b.end)) {
|
|
return true
|
|
}
|
|
}
|
|
}
|
|
return false
|
|
}
|
|
|
|
static fromIsoString(isoString: string): DateTime {
|
|
const dateTime = DateTime.fromISO(isoString)
|
|
if (!dateTime.isValid) {
|
|
throw new Error('Invalid date time')
|
|
}
|
|
return dateTime
|
|
}
|
|
|
|
static fromDate(date: Date): DateTime {
|
|
const dateTime = DateTime.fromJSDate(date)
|
|
if (!dateTime.isValid) {
|
|
throw new Error('Invalid date time')
|
|
}
|
|
return dateTime
|
|
}
|
|
|
|
static toIsoString(dateTime: DateTime): string {
|
|
const isoString = dateTime.toISO()
|
|
if (!isoString) {
|
|
throw new Error('Invalid date time')
|
|
}
|
|
return isoString
|
|
}
|
|
|
|
static getTodayWithTime(date: DateTime) {
|
|
const today = DateTime.now().set({
|
|
hour: date.hour,
|
|
minute: date.minute,
|
|
second: date.second,
|
|
})
|
|
return today
|
|
}
|
|
|
|
static getSpecificDateWithNowTime(date: DateTime) {
|
|
return date.set({
|
|
hour: DateTime.now().hour,
|
|
minute: DateTime.now().minute,
|
|
second: DateTime.now().second,
|
|
})
|
|
}
|
|
static getATimeWithDateB(a: DateTime, b: DateTime) {
|
|
return a.set({
|
|
year: b.year,
|
|
month: b.month,
|
|
day: b.day,
|
|
hour: a.hour,
|
|
minute: a.minute,
|
|
second: a.second,
|
|
})
|
|
}
|
|
|
|
// example: 12:00:00
|
|
static toTime(time: string): TimeType {
|
|
const [hour, minute, second] = time.split(':').map(Number)
|
|
return {
|
|
hour: hour as HourNumbers,
|
|
minute: minute as MinuteNumbers,
|
|
second: second as SecondNumbers,
|
|
}
|
|
}
|
|
|
|
static getTimeFromDateTime(dateTime: DateTime): TimeType {
|
|
return this.toTime(`${dateTime.hour}:${dateTime.minute}:${dateTime.second}`)
|
|
}
|
|
|
|
static subtractDaysFromTimeframe(timeframe: string): DateTime {
|
|
// convert timeframe to number of days: 'day' -> 1, 'week' -> 7, 'month' -> 30, 'year' -> 365
|
|
const daysMap: Record<string, number> = {
|
|
day: 1,
|
|
week: 7,
|
|
month: 30,
|
|
year: 365,
|
|
}
|
|
const days = daysMap[timeframe.toLowerCase()]
|
|
if (days === undefined) {
|
|
throw new Error(`Invalid timeframe: ${timeframe}`)
|
|
}
|
|
return DateTime.now().minus({ days })
|
|
}
|
|
}
|