Files
epess-web-backend/src/common/utils/datetime.utils.ts
2024-12-16 20:00:11 +07:00

150 lines
3.8 KiB
TypeScript

import { Injectable } from '@nestjs/common'
import _ from 'lodash'
import { DateTime, DayNumbers, HourNumbers, MinuteNumbers, SecondNumbers, Settings, 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 format(dateTime: DateTime, format: string): string {
return dateTime.toFormat(format)
}
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 })
}
static withoutTime(dateTime: DateTime): DateTime {
return dateTime.set({ hour: 0, minute: 0, second: 0, millisecond: 0 })
}
}