UNPKG

inventoresed

Version:

Z-Wave driver written entirely in JavaScript/TypeScript

120 lines (107 loc) 3.32 kB
import dayjs from "dayjs"; export interface DSTInfo { startDate: Date; endDate: Date; standardOffset: number; dstOffset: number; } /** * Returns a fallback DSTInfo in case we cannot determine the correct one. * This fallback has no additional DST shift. * The dummy DST starts on March 31st and ends on October 31st, both times at 01:00 UTC. * @param defaultOffset - The offset to use for both standardOffset and dstOffset */ export function getDefaultDSTInfo(defaultOffset?: number): DSTInfo { const thisYear = new Date().getUTCFullYear(); if (defaultOffset == undefined) defaultOffset = -new Date().getTimezoneOffset(); return { startDate: new Date(Date.UTC(thisYear, 2, 31, 1)), endDate: new Date(Date.UTC(thisYear, 9, 31, 1)), standardOffset: defaultOffset, dstOffset: defaultOffset, }; } /** * Finds the first date on which the given timezone offset is in effect. * date1 must be the smaller one of the two dates */ function findSwitchDate( date1: Date, date2: Date, offset: number, ): Date | undefined { const stepSize = 60000; // 1 minute function middleDate(date1: Date, date2: Date): Date { const middleTime = Math.floor((date1.getTime() + date2.getTime()) / 2 / stepSize) * stepSize; return new Date(middleTime); } while (date1 < date2) { const mid = middleDate(date1, date2); if (mid.getTimezoneOffset() === offset) { date2 = mid; } else { date1 = new Date(mid.getTime() + stepSize); } } if (date1.getTimezoneOffset() !== offset) return undefined; return date1; } /** Returns the current system's daylight savings time information if possible */ export function getDSTInfo(now: Date = new Date()): DSTInfo { const halfAYearAgo = dayjs(now).subtract(6, "months").toDate(); const inAHalfYear = dayjs(now).add(6, "months").toDate(); if ( now.getTimezoneOffset() === halfAYearAgo.getTimezoneOffset() || now.getTimezoneOffset() === inAHalfYear.getTimezoneOffset() ) { // There is no DST in this timezone return getDefaultDSTInfo(); } // Javascript has the offsets inverted, we use the normal interpretation const offsets = [ -now.getTimezoneOffset(), -inAHalfYear.getTimezoneOffset(), ]; const dates = [ findSwitchDate(halfAYearAgo, now, -offsets[0]), findSwitchDate(now, inAHalfYear, -offsets[1]), ]; if (dates[0] == undefined || dates[1] == undefined) { // This shouldn't happen, but better be sure return getDefaultDSTInfo(); } if (offsets[0] > offsets[1]) { // DST is always the higher offset return { startDate: dates[0], endDate: dates[1], dstOffset: offsets[0], standardOffset: offsets[1], }; } else { return { // We don't have DST now, this is the next start date startDate: dates[1], endDate: dates[0], dstOffset: offsets[1], standardOffset: offsets[0], }; } } /** Returns a timestamp with nano-second precision */ export function highResTimestamp(): number { const [s, ns] = process.hrtime(); return s * 1e9 + ns; } export const timespan = Object.freeze({ seconds: (num: number) => num * 1000, minutes: (num: number) => timespan.seconds(num * 60), hours: (num: number) => timespan.minutes(num * 60), days: (num: number) => timespan.hours(num * 24), }); export function formatDate(date: Date, format: string): string { return dayjs(date).format(format); }