@prefecthq/prefect-ui-library
Version:
This library is the Vue and Typescript component library for [Prefect 2](https://github.com/PrefectHQ/prefect) and [Prefect Cloud 2](https://www.prefect.io/cloud/). _The components and utilities in this project are not meant to be used independently_.
141 lines (107 loc) • 3.71 kB
text/typescript
import * as dateFns from 'date-fns'
import { formatInTimeZone, getTimezoneOffset, toZonedTime, fromZonedTime } from 'date-fns-tz'
import { ref, computed } from 'vue'
import { isDate } from '@/utilities/dates'
export const selectedTimezone = ref<string | null>(null)
export const utcTimezone = 'Etc/UTC'
export function timezoneIsUtc(timezone: string): timezone is typeof utcTimezone {
return timezone === utcTimezone
}
export const browserUtcOffset = -new Date().getTimezoneOffset()
export const utcOffsetMilliseconds = computed(() => selectedTimezone.value === null ? dateFns.minutesToMilliseconds(browserUtcOffset) : getTimezoneOffset(selectedTimezone.value))
export const utcOffsetMinutes = computed(() => dateFns.millisecondsToMinutes(utcOffsetMilliseconds.value))
export function assignTimezone(date: Date, timezone = selectedTimezone.value): Date {
if (date.timezone) {
date = unassignTimezone(date, date.timezone)
}
if (timezone) {
const value = toZonedTime(date, timezone)
value.timezone = timezone
return value
}
return date
}
export function unassignTimezone(date: Date, timezone = selectedTimezone.value): Date {
if (timezone) {
const value = fromZonedTime(date, timezone)
value.timezone = undefined
return value
}
return date
}
export function toDate(value: Date | string | null | undefined): Date {
if (!value) {
return new Date()
}
if (typeof value === 'string') {
return new Date(value)
}
if (value.timezone) {
return unassignTimezone(value)
}
return value
}
export function formatDateInTimezone(date: Date, format: string, timezone = selectedTimezone.value): string {
if (date.timezone || !timezone) {
return dateFns.format(date, format)
}
return formatInTimeZone(date, timezone, format)
}
function isRelativeDateFunction(args: unknown[]): boolean {
return args.length === 0
}
export function now(): Date {
return assignTimezone(new Date())
}
export function secondsFromEpoch(date?: Date | string): number {
const value = date ? new Date(date) : now()
return value.getTime()
}
export const dateFunctions = new Proxy({ ...dateFns }, {
get(target, prop, receiver) {
const property = Reflect.get(target, prop, receiver)
if (typeof property !== 'function') {
return property
}
return (...args: unknown[]) => {
const anyDateArgsUnapplied = args.map(arg => {
if (isDate(arg) && arg.timezone) {
return unassignTimezone(arg, arg.timezone)
}
return arg
})
const value = property.apply(this, anyDateArgsUnapplied)
if (!isDate(value)) {
return value
}
if (isRelativeDateFunction(args)) {
return unassignTimezone(value)
}
return assignTimezone(value)
}
},
})
/**
* Converts a date in local time into the same date/time in a different timezone
*
* @param {Date} date - The date to be converted.
* @param {string} timezone - The timezone the date should be offset to.
* @returns {Date}
*/
export function setTimezone(date: Date, timezone: string): Date {
const offset = date.getHours() - assignTimezone(date, timezone).getHours()
const offsetDate = dateFns.addHours(date, offset)
return offsetDate
}
/**
* Converts a date in a timezone into the same date/time in a local date
*
* @param {Date} date - The date to be converted.
* @param {string} timezone - The timezone the date should be offset from.
* @returns {Date}
*/
export function unsetTimezone(date: Date, timezone: string): Date {
const offset = date.getHours() - assignTimezone(date, timezone).getHours()
const offsetDate = dateFns.subHours(date, offset)
return offsetDate
}