first commit
This commit is contained in:
32
calcom/packages/dayjs/index.ts
Normal file
32
calcom/packages/dayjs/index.ts
Normal file
@@ -0,0 +1,32 @@
|
||||
/* eslint-disable @calcom/eslint/deprecated-imports */
|
||||
import dayjs from "dayjs";
|
||||
import customParseFormat from "dayjs/plugin/customParseFormat";
|
||||
import duration from "dayjs/plugin/duration";
|
||||
import isBetween from "dayjs/plugin/isBetween";
|
||||
import isToday from "dayjs/plugin/isToday";
|
||||
import localizedFormat from "dayjs/plugin/localizedFormat";
|
||||
import minmax from "dayjs/plugin/minMax";
|
||||
import relativeTime from "dayjs/plugin/relativeTime";
|
||||
import timeZone from "dayjs/plugin/timezone";
|
||||
import toArray from "dayjs/plugin/toArray";
|
||||
import utc from "dayjs/plugin/utc";
|
||||
|
||||
import BusinessDaysPlugin from "./plugins/business-days-plugin";
|
||||
|
||||
dayjs.extend(customParseFormat);
|
||||
dayjs.extend(BusinessDaysPlugin);
|
||||
dayjs.extend(isBetween);
|
||||
dayjs.extend(isToday);
|
||||
dayjs.extend(localizedFormat);
|
||||
dayjs.extend(relativeTime);
|
||||
dayjs.extend(timeZone);
|
||||
dayjs.extend(toArray);
|
||||
dayjs.extend(utc);
|
||||
dayjs.extend(minmax);
|
||||
dayjs.extend(duration);
|
||||
|
||||
export type Dayjs = dayjs.Dayjs;
|
||||
|
||||
export type { ConfigType } from "dayjs";
|
||||
|
||||
export default dayjs;
|
||||
25
calcom/packages/dayjs/locales.ts
Normal file
25
calcom/packages/dayjs/locales.ts
Normal file
@@ -0,0 +1,25 @@
|
||||
import "dayjs/locale/ar";
|
||||
import "dayjs/locale/bg";
|
||||
import "dayjs/locale/cs";
|
||||
import "dayjs/locale/de";
|
||||
import "dayjs/locale/es";
|
||||
import "dayjs/locale/es-mx";
|
||||
import "dayjs/locale/fr";
|
||||
import "dayjs/locale/he";
|
||||
import "dayjs/locale/hu";
|
||||
import "dayjs/locale/it";
|
||||
import "dayjs/locale/ja";
|
||||
import "dayjs/locale/ko";
|
||||
import "dayjs/locale/nl";
|
||||
import "dayjs/locale/pl";
|
||||
import "dayjs/locale/pt";
|
||||
import "dayjs/locale/pt-br";
|
||||
import "dayjs/locale/ro";
|
||||
import "dayjs/locale/ru";
|
||||
import "dayjs/locale/sr";
|
||||
import "dayjs/locale/sv";
|
||||
import "dayjs/locale/tr";
|
||||
import "dayjs/locale/uk";
|
||||
import "dayjs/locale/vi";
|
||||
import "dayjs/locale/zh-cn";
|
||||
import "dayjs/locale/zh-tw";
|
||||
10
calcom/packages/dayjs/package.json
Normal file
10
calcom/packages/dayjs/package.json
Normal file
@@ -0,0 +1,10 @@
|
||||
{
|
||||
"name": "@calcom/dayjs",
|
||||
"description": "Cal.com's Day.js shared library",
|
||||
"private": true,
|
||||
"version": "1.0.0",
|
||||
"main": "./index.ts",
|
||||
"dependencies": {
|
||||
"dayjs": "1.11.2"
|
||||
}
|
||||
}
|
||||
242
calcom/packages/dayjs/plugins/business-days-plugin.ts
Normal file
242
calcom/packages/dayjs/plugins/business-days-plugin.ts
Normal file
@@ -0,0 +1,242 @@
|
||||
import type { Dayjs, PluginFunc } from "dayjs";
|
||||
|
||||
interface BusinessDaysPluginOptions {
|
||||
holidays?: string[];
|
||||
holidayFormat?: string;
|
||||
additionalWorkingDays?: string[];
|
||||
additionalWorkingDayFormat?: string;
|
||||
workingWeekdays?: number[];
|
||||
}
|
||||
|
||||
const BusinessDaysPlugin: PluginFunc<BusinessDaysPluginOptions> = (
|
||||
options = {},
|
||||
dayjsClass,
|
||||
dayjsFactory
|
||||
) => {
|
||||
const defaultWorkingWeekdays = [1, 2, 3, 4, 5];
|
||||
|
||||
dayjsFactory.getWorkingWeekdays = function (): number[] {
|
||||
return options.workingWeekdays || defaultWorkingWeekdays;
|
||||
};
|
||||
|
||||
dayjsFactory.setWorkingWeekdays = function (workingWeekdays: number[]): void {
|
||||
options.workingWeekdays = workingWeekdays;
|
||||
};
|
||||
|
||||
dayjsFactory.getHolidays = function (): string[] {
|
||||
return options.holidays || [];
|
||||
};
|
||||
|
||||
dayjsFactory.setHolidays = function (holidays: string[]): void {
|
||||
options.holidays = holidays;
|
||||
};
|
||||
|
||||
dayjsFactory.getHolidayFormat = function (): string | undefined {
|
||||
return options.holidayFormat;
|
||||
};
|
||||
|
||||
dayjsFactory.setHolidayFormat = function (holidayFormat: string): void {
|
||||
options.holidayFormat = holidayFormat;
|
||||
};
|
||||
|
||||
dayjsFactory.getAdditionalWorkingDays = function (): string[] {
|
||||
return options.additionalWorkingDays || [];
|
||||
};
|
||||
|
||||
dayjsFactory.setAdditionalWorkingDays = function (additionalWorkingDays: string[]): void {
|
||||
options.additionalWorkingDays = additionalWorkingDays;
|
||||
};
|
||||
|
||||
dayjsFactory.getAdditionalWorkingDayFormat = function (): string | undefined {
|
||||
return options.additionalWorkingDayFormat;
|
||||
};
|
||||
|
||||
dayjsFactory.setAdditionalWorkingDayFormat = function (additionalWorkingDayFormat: string): void {
|
||||
options.additionalWorkingDayFormat = additionalWorkingDayFormat;
|
||||
};
|
||||
|
||||
dayjsClass.prototype.isHoliday = function (this: Dayjs): boolean {
|
||||
if (!options.holidays) {
|
||||
return false;
|
||||
}
|
||||
if (options.holidays.includes(this.format(options.holidayFormat))) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
};
|
||||
|
||||
dayjsClass.prototype.isBusinessDay = function (this: Dayjs): boolean {
|
||||
const workingWeekdays = options.workingWeekdays || defaultWorkingWeekdays;
|
||||
|
||||
if (this.isHoliday()) {
|
||||
return false;
|
||||
}
|
||||
if (this.isAdditionalWorkingDay()) {
|
||||
return true;
|
||||
}
|
||||
if (workingWeekdays.includes(this.day())) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
};
|
||||
|
||||
dayjsClass.prototype.isAdditionalWorkingDay = function (this: Dayjs): boolean {
|
||||
if (!options.additionalWorkingDays) {
|
||||
return false;
|
||||
}
|
||||
if (options.additionalWorkingDays.includes(this.format(options.additionalWorkingDayFormat))) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
};
|
||||
|
||||
dayjsClass.prototype.businessDaysAdd = function (this: Dayjs, days: number): Dayjs {
|
||||
const numericDirection = days < 0 ? -1 : 1;
|
||||
let currentDay = this.clone();
|
||||
let daysRemaining = Math.abs(days);
|
||||
|
||||
while (daysRemaining > 0) {
|
||||
currentDay = currentDay.add(numericDirection, `d`);
|
||||
|
||||
if (currentDay.isBusinessDay()) {
|
||||
daysRemaining -= 1;
|
||||
}
|
||||
}
|
||||
|
||||
return currentDay;
|
||||
};
|
||||
|
||||
dayjsClass.prototype.businessDaysSubtract = function (this: Dayjs, days: number): Dayjs {
|
||||
let currentDay = this.clone();
|
||||
|
||||
currentDay = currentDay.businessDaysAdd(days * -1);
|
||||
|
||||
return currentDay;
|
||||
};
|
||||
|
||||
dayjsClass.prototype.businessDiff = function (this: Dayjs, date: Dayjs): number {
|
||||
const day1 = this.clone();
|
||||
const day2 = date.clone();
|
||||
|
||||
const isPositiveDiff = day1 >= day2;
|
||||
let start = isPositiveDiff ? day2 : day1;
|
||||
const end = isPositiveDiff ? day1 : day2;
|
||||
|
||||
let daysBetween = 0;
|
||||
|
||||
if (start.isSame(end)) {
|
||||
return daysBetween;
|
||||
}
|
||||
|
||||
while (start < end) {
|
||||
if (start.isBusinessDay()) {
|
||||
daysBetween += 1;
|
||||
}
|
||||
|
||||
start = start.add(1, `d`);
|
||||
}
|
||||
|
||||
return isPositiveDiff ? daysBetween : -daysBetween;
|
||||
};
|
||||
|
||||
dayjsClass.prototype.nextBusinessDay = function (this: Dayjs): Dayjs {
|
||||
const searchLimit = 7;
|
||||
let currentDay = this.clone();
|
||||
|
||||
let loopIndex = 1;
|
||||
while (loopIndex < searchLimit) {
|
||||
currentDay = currentDay.add(1, `day`);
|
||||
|
||||
if (currentDay.isBusinessDay()) {
|
||||
break;
|
||||
}
|
||||
loopIndex += 1;
|
||||
}
|
||||
|
||||
return currentDay;
|
||||
};
|
||||
|
||||
dayjsClass.prototype.prevBusinessDay = function (this: Dayjs): Dayjs {
|
||||
const searchLimit = 7;
|
||||
let currentDay = this.clone();
|
||||
|
||||
let loopIndex = 1;
|
||||
while (loopIndex < searchLimit) {
|
||||
currentDay = currentDay.subtract(1, `day`);
|
||||
|
||||
if (currentDay.isBusinessDay()) {
|
||||
break;
|
||||
}
|
||||
loopIndex += 1;
|
||||
}
|
||||
|
||||
return currentDay;
|
||||
};
|
||||
|
||||
dayjsClass.prototype.businessDaysInMonth = function (this: Dayjs): Dayjs[] {
|
||||
if (!this.isValid()) {
|
||||
return [];
|
||||
}
|
||||
|
||||
let currentDay = this.clone().startOf(`month`);
|
||||
const monthEnd = this.clone().endOf(`month`);
|
||||
const businessDays: Dayjs[] = [];
|
||||
let monthComplete = false;
|
||||
|
||||
while (!monthComplete) {
|
||||
if (currentDay.isBusinessDay()) {
|
||||
businessDays.push(currentDay.clone());
|
||||
}
|
||||
|
||||
currentDay = currentDay.add(1, `day`);
|
||||
|
||||
if (currentDay.isAfter(monthEnd)) {
|
||||
monthComplete = true;
|
||||
}
|
||||
}
|
||||
|
||||
return businessDays;
|
||||
};
|
||||
|
||||
dayjsClass.prototype.lastBusinessDayOfMonth = function (this: Dayjs): Dayjs {
|
||||
const businessDays = this.businessDaysInMonth();
|
||||
const lastBusinessDay = businessDays[businessDays.length - 1];
|
||||
return lastBusinessDay;
|
||||
};
|
||||
|
||||
dayjsClass.prototype.businessWeeksInMonth = function (this: Dayjs): Dayjs[][] {
|
||||
if (!this.isValid()) {
|
||||
return [];
|
||||
}
|
||||
|
||||
let currentDay = this.clone().startOf(`month`);
|
||||
const monthEnd = this.clone().endOf(`month`);
|
||||
const businessWeeks: Dayjs[][] = [];
|
||||
let businessDays: Dayjs[] = [];
|
||||
let monthComplete = false;
|
||||
|
||||
while (!monthComplete) {
|
||||
if (currentDay.isBusinessDay()) {
|
||||
businessDays.push(currentDay.clone());
|
||||
}
|
||||
|
||||
if (currentDay.day() === 5 || currentDay.isSame(monthEnd, `day`)) {
|
||||
businessWeeks.push(businessDays);
|
||||
businessDays = [];
|
||||
}
|
||||
|
||||
currentDay = currentDay.add(1, `day`);
|
||||
|
||||
if (currentDay.isAfter(monthEnd)) {
|
||||
monthComplete = true;
|
||||
}
|
||||
}
|
||||
|
||||
return businessWeeks;
|
||||
};
|
||||
};
|
||||
|
||||
export default BusinessDaysPlugin;
|
||||
4
calcom/packages/dayjs/tsconfig.json
Normal file
4
calcom/packages/dayjs/tsconfig.json
Normal file
@@ -0,0 +1,4 @@
|
||||
{
|
||||
"extends": "@calcom/tsconfig/base.json",
|
||||
"include": [".", "../types/business-days-plugin.d.ts"]
|
||||
}
|
||||
Reference in New Issue
Block a user