@atomic-utils/time
Version:
559 lines • 23.7 kB
JavaScript
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.getCsoLength = exports.isHalfMonth = exports.findNumCyclesInPastMaturityExists = exports.findCycleMaturityMonthsInPast = exports.extractCsoEventIdDateFromStr = exports.getEventIdType = exports.getCsoEventIdType = exports.getParamsFromManualEventId = exports.getParamsFromCsoTradeUnsplitEventId = exports.getParamsFromCsoTradeSplitEventId = exports.getParamsFromCsoEventId = exports.getManualEventId = exports.getCsoTradeUnsplitEventId = exports.getCsoTradeSplitEventId = exports.getCsoEventId = exports.getPreviousFriday = exports.getUpcomingFriday = exports.getCsoStartAndEndDate = exports.getCsoEvent = exports.getCsoEventDates = exports.getPreviousCycleMaturityDate = exports.getNextCycleMaturityDate = exports.getCurrentCycleMaturityDate = exports.getLastFridayInMonth = exports.STR_DATE_REGEX = exports.TRADING_OPEN_HALF_MONTH_LEN = exports.HALF_MONTH_ENTRY_CLOSED_LEN = exports.NEW_ENTRY_CLOSED_LEN = exports.NEW_ENTRY_OPEN_LEN = exports.ROLLOVER_OPEN_LEN = exports.DLC_ATTESTATION_LEN = exports.DLC_EXPIRY_LEN = void 0;
exports.DLC_EXPIRY_LEN = 7;
exports.DLC_ATTESTATION_LEN = 1;
exports.ROLLOVER_OPEN_LEN = 24;
exports.NEW_ENTRY_OPEN_LEN = 36;
exports.NEW_ENTRY_CLOSED_LEN = 8;
exports.HALF_MONTH_ENTRY_CLOSED_LEN = 6;
exports.TRADING_OPEN_HALF_MONTH_LEN = 334;
const deribit_1 = require("@atomic-utils/deribit");
const assert_1 = __importDefault(require("assert"));
exports.STR_DATE_REGEX = /(\d{1,2})([A-Z]+)(\d{1,2})/;
/**
* getLastFridayInMonth
*
* Pass in year and month and return Date object with
* last friday of the month
*
* @param {number} y Year in full format (i.e. 2022)
* @param {number} m Month NOT 0-indexed (i.e. 1 => January)
* @returns {Date} last friday of month
*/
const getLastFridayInMonth = (y, m) => {
const lastDay = new Date(Date.UTC(y, m, 0, 8, 0, 0));
if (lastDay.getUTCDay() < 5) {
lastDay.setDate(lastDay.getDate() - 7);
}
lastDay.setDate(lastDay.getDate() - (lastDay.getUTCDay() - 5));
return lastDay;
};
exports.getLastFridayInMonth = getLastFridayInMonth;
/**
* getCurrentCycleMaturityDate
*
* @param {Date} t_ current time
* @returns {Date} last friday in current cycle
*/
const getCurrentCycleMaturityDate = (t_) => {
const t = new Date(t_.getTime()); // clone to avoid mutation
let y = t.getUTCFullYear();
(0, assert_1.default)(y >= 2009, // since cycle maturity cannot be before Bitcoin was created
`Invalid date provided ${t} with timestamp ${t.getTime()}, you may have used seconds instead of milliseconds`);
(0, assert_1.default)(y <= 2100, // reasonable upper bound
`Invalid date provided ${t} with timestamp ${t.getTime()}, you may have used microseconds instead of milliseconds`);
let m = t.getUTCMonth() + 1;
let lastFriday = (0, exports.getLastFridayInMonth)(y, m);
if (t >= lastFriday) {
t.setUTCDate(1);
t.setUTCMonth(t.getUTCMonth() + 1);
y = t.getUTCFullYear();
m = t.getUTCMonth() + 1;
lastFriday = (0, exports.getLastFridayInMonth)(y, m);
}
return lastFriday;
};
exports.getCurrentCycleMaturityDate = getCurrentCycleMaturityDate;
/**
* getNextCycleMaturityDate
*
* @param {Date} t_ current time
* @returns {Date} last friday in next cycle
*/
const getNextCycleMaturityDate = (t_) => {
const t = new Date(t_.getTime()); // clone to avoid mutation
const currentLastFriday = (0, exports.getCurrentCycleMaturityDate)(t);
currentLastFriday.setUTCSeconds(currentLastFriday.getUTCSeconds() + 1);
const nextLastFriday = (0, exports.getCurrentCycleMaturityDate)(currentLastFriday);
return nextLastFriday;
};
exports.getNextCycleMaturityDate = getNextCycleMaturityDate;
/**
* getPreviousCycleMaturityDate
*
* @param {Date} t_ current time
* @returns {Date} last friday in previous cycle
*/
const getPreviousCycleMaturityDate = (t_) => {
const t = new Date(t_.getTime()); // clone to avoid mutation
const currentLastFriday = (0, exports.getCurrentCycleMaturityDate)(t);
currentLastFriday.setUTCMonth(currentLastFriday.getUTCMonth() - 1);
currentLastFriday.setUTCDate(currentLastFriday.getDate() - 14);
const previousLastFriday = (0, exports.getCurrentCycleMaturityDate)(currentLastFriday);
return previousLastFriday;
};
exports.getPreviousCycleMaturityDate = getPreviousCycleMaturityDate;
const getCsoEventDates = (t_) => {
const t = new Date(t_.getTime());
const upcomingDlcExpiry = (0, exports.getCurrentCycleMaturityDate)(t);
const previousDlcExpiry = (0, exports.getPreviousCycleMaturityDate)(t);
const dlcAttestation = new Date(previousDlcExpiry.getTime());
dlcAttestation.setUTCHours(dlcAttestation.getUTCHours() + exports.DLC_EXPIRY_LEN);
const rolloverOpen = new Date(dlcAttestation.getTime());
rolloverOpen.setUTCHours(rolloverOpen.getUTCHours() + exports.DLC_ATTESTATION_LEN);
const newEntryOpen = new Date(rolloverOpen.getTime());
newEntryOpen.setUTCHours(newEntryOpen.getUTCHours() + exports.ROLLOVER_OPEN_LEN);
const newEntryClosed = new Date(newEntryOpen.getTime());
newEntryClosed.setUTCHours(newEntryClosed.getUTCHours() + exports.NEW_ENTRY_OPEN_LEN);
const tradingOpen = new Date(newEntryClosed.getTime());
tradingOpen.setUTCHours(tradingOpen.getUTCHours() + exports.NEW_ENTRY_CLOSED_LEN);
const tradingOpenHalfMonth = new Date(upcomingDlcExpiry.getTime());
tradingOpenHalfMonth.setUTCHours(tradingOpenHalfMonth.getUTCHours() - exports.TRADING_OPEN_HALF_MONTH_LEN);
const halfMonthEntryClosed = new Date(tradingOpenHalfMonth.getTime());
halfMonthEntryClosed.setUTCHours(halfMonthEntryClosed.getUTCHours() - exports.HALF_MONTH_ENTRY_CLOSED_LEN);
return {
previousDlcExpiry,
dlcAttestation,
rolloverOpen,
newEntryOpen,
newEntryClosed,
tradingOpen,
halfMonthEntryClosed,
tradingOpenHalfMonth,
upcomingDlcExpiry,
};
};
exports.getCsoEventDates = getCsoEventDates;
/**
* getCsoEvent
*
* @param {Date} t_ current time
* @returns {CsoEvent} which cso event the date provided is within
*/
const getCsoEvent = (t_) => {
const t = new Date(t_.getTime());
const { previousDlcExpiry, dlcAttestation, rolloverOpen, newEntryOpen, newEntryClosed, tradingOpen, halfMonthEntryClosed, tradingOpenHalfMonth, upcomingDlcExpiry, } = (0, exports.getCsoEventDates)(t);
switch (true) {
case t >= previousDlcExpiry && t < dlcAttestation:
return 'dlcExpiry';
case t >= dlcAttestation && t < rolloverOpen:
return 'dlcAttestation';
case t >= rolloverOpen && t < newEntryOpen:
return 'rolloverOpen';
case t >= newEntryOpen && t < newEntryClosed:
return 'newEntryOpen';
case t >= newEntryClosed && t < tradingOpen:
return 'newEntryClosed';
case t >= tradingOpen && t < halfMonthEntryClosed:
return 'tradingOpen';
case t >= halfMonthEntryClosed && t < tradingOpenHalfMonth:
return 'halfMonthEntryClosed';
case t >= tradingOpenHalfMonth && t < upcomingDlcExpiry:
return 'tradingOpenHalfMonth';
case t.getTime() === upcomingDlcExpiry.getTime():
return 'dlcExpiry';
}
};
exports.getCsoEvent = getCsoEvent;
/**
* getCsoStartAndEndDate
*
* Pass in current time and get start and end date of event that user can enter into
* immediately
*
* @param t_ current time
* @returns {StartEndDates} start and end dates of the CSO event
*/
const getCsoStartAndEndDate = (t_, forceExtendedPeriod = false) => {
const t = new Date(t_.getTime());
const csoEvent = (0, exports.getCsoEvent)(t);
const { newEntryClosed, halfMonthEntryClosed, upcomingDlcExpiry } = (0, exports.getCsoEventDates)(t);
const { upcomingDlcExpiry: followingDlcExpiry } = (0, exports.getCsoEventDates)(new Date(upcomingDlcExpiry.getTime() + 1));
if (csoEvent === 'halfMonthEntryClosed' ||
csoEvent === 'tradingOpenHalfMonth') {
// Create full month for next month
const nextT = new Date(upcomingDlcExpiry.getTime() + 1);
const { newEntryClosed: nextNewEntryClosed, upcomingDlcExpiry: nextDlcExpiry, } = (0, exports.getCsoEventDates)(nextT);
const { upcomingDlcExpiry: followingDlcExpiry } = (0, exports.getCsoEventDates)(new Date(nextDlcExpiry.getTime() + 1));
return {
startDate: nextNewEntryClosed,
endDate: forceExtendedPeriod ? followingDlcExpiry : nextDlcExpiry,
};
}
else if (csoEvent === 'newEntryClosed' || csoEvent === 'tradingOpen') {
// Create half month event ID
return {
startDate: halfMonthEntryClosed,
endDate: forceExtendedPeriod ? followingDlcExpiry : upcomingDlcExpiry,
};
}
else {
// Create full month for current month
return {
startDate: newEntryClosed,
endDate: forceExtendedPeriod ? followingDlcExpiry : upcomingDlcExpiry,
};
}
};
exports.getCsoStartAndEndDate = getCsoStartAndEndDate;
/**
* getUpcomingFriday
*
* From the current time, get the upcoming Friday.
* If the current time is Friday and is after 8am UTC, then return the next week's Friday
*
* @param {Date} t_ current time
* @returns
*/
const getUpcomingFriday = (t_) => {
const t = new Date(t_.getTime());
let dayDelta = (5 - t.getUTCDay()) % 7;
if (dayDelta === 0 && t.getUTCHours() >= 8) {
dayDelta = 7;
}
t.setUTCDate(t.getUTCDate() + dayDelta);
return new Date(t.setUTCHours(8, 0, 0, 0));
};
exports.getUpcomingFriday = getUpcomingFriday;
/**
* getPreviousFriday
*
* From the current time, get the previous Friday.
* If the current time is Friday and is before 8am UTC, then return the previous week's Friday
*
* @param {Date} t_ current time
* @returns
*/
const getPreviousFriday = (t_) => {
const t = new Date(t_.getTime());
let dayDelta = (5 - t.getUTCDay() + 7) % 7;
if (dayDelta === 0 &&
(t.getUTCHours() > 8 ||
(t.getUTCHours() === 8 &&
t.getUTCMinutes() === 0 &&
t.getUTCSeconds() > 0) ||
(t.getUTCHours() === 8 && t.getUTCMinutes() > 0))) {
dayDelta = 7;
}
t.setUTCDate(t.getUTCDate() - (7 - dayDelta));
return new Date(t.setUTCHours(8, 0, 0, 0));
};
exports.getPreviousFriday = getPreviousFriday;
/**
* getCsoEventId
*
* Pass in Date and return event ID of announcement that user can enter into immediately
*
* @param {Date} t_ current time
* @param {string} provider company or trader providing strategy
* @param {string} strategyId unique identifier for strategy
* @param {CsoPeriod} period i.e. monthly
* @returns {string} event ID string i.e. atomic-call_spread_v1-monthly-27JUN22-29JUL22
*/
const getCsoEventId = (t_, provider, strategyId, period, forceExtendedPeriod = false) => {
const t = new Date(t_.getTime());
const { startDate, endDate } = (0, exports.getCsoStartAndEndDate)(t, forceExtendedPeriod);
return [
provider,
strategyId,
period,
(0, deribit_1.getStrDate)(startDate),
(0, deribit_1.getStrDate)(endDate),
].join('-');
};
exports.getCsoEventId = getCsoEventId;
/**
* getCsoTradeSplitEventId
*
* This function generates an event ID for a split trade.
*
* @param {string} provider - The company or trader providing the strategy.
* @param {string} strategyId - The unique identifier for the strategy.
* @param {number} tradeIndex - The index of the trade.
* @returns {string} - The event ID string in the format [provider]-[strategyId]-trade-[tradeIndex].
* i.e. atomic-oyster-trade-84
*/
const getCsoTradeSplitEventId = (provider, strategyId, tradeIndex) => {
return [provider, strategyId, 'trade', tradeIndex].join('-');
};
exports.getCsoTradeSplitEventId = getCsoTradeSplitEventId;
/**
* getCsoTradeUnsplitEventId
*
* This function generates an event ID for an unsplit trade.
*
* @param {Date} t_ - The current time.
* @param {string} provider - The company or trader providing the strategy.
* @param {string} strategyId - The unique identifier for the strategy.
* @param {number} numTrades - The number of trades.
* @returns {string} - The event ID string in the format [provider]-[strategyId]-[numTrades]-trades-[startDate].
* i.e. atomic-oyster-5-trades-1JAN24
*/
const getCsoTradeUnsplitEventId = (t_, provider, strategyId, numTrades) => {
const t = new Date(t_.getTime());
return [provider, strategyId, numTrades, 'trades', (0, deribit_1.getStrDate)(t)].join('-');
};
exports.getCsoTradeUnsplitEventId = getCsoTradeUnsplitEventId;
const getManualEventId = (provider, source, maturity, symbol = 'BTC') => {
const month = maturity
.toLocaleString('default', { month: 'short' })
.toUpperCase()
.split('.')[0];
const year = maturity.getFullYear().toString().slice(-2);
const day = maturity.getDate().toString();
return `${provider}-${source}-${symbol}-${day}${month}${year}`;
};
exports.getManualEventId = getManualEventId;
/**
* getStartAndEndDateFromCsoEventId
*
* Pass in eventId and return start and end date by checking if date is
* equal to tradingOpen, tradingOpenHalfMonth or dlcExpiry, else just
* output date inside cso params for eventId
*
* @param {string} eventId format [provider]-[strategyId]-[period]-[startDate]-[endDate]
* @returns {CsoParams} provider, strategyId, period, and start and end dates
*/
const getParamsFromCsoEventId = (eventId) => {
const eventParams = eventId.split('-');
if (eventParams.length !== 5)
throw Error(`Invalid eventId provided: ${eventId}. Expected format [provider]-[strategyId]-[period]-[startDate]-[endDate]`);
const [provider, strategyId, period, startDateStr, endDateStr] = eventParams;
if (!exports.STR_DATE_REGEX.test(startDateStr) || !exports.STR_DATE_REGEX.test(endDateStr))
throw new Error(`Invalid start or end date provided. Start Date: ${startDateStr}. End Date: ${endDateStr}`);
const startDate = (0, exports.extractCsoEventIdDateFromStr)(startDateStr);
const endDate = (0, exports.extractCsoEventIdDateFromStr)(endDateStr);
return {
provider,
strategyId,
period,
startDate,
endDate,
};
};
exports.getParamsFromCsoEventId = getParamsFromCsoEventId;
const getParamsFromCsoTradeSplitEventId = (eventId) => {
const eventParams = eventId.split('-');
if (eventParams.length !== 4)
throw Error(`Invalid eventId provided: ${eventId}. Expected format [provider]-[strategyId]-[trade]-[tradeIndex]`);
const [provider, strategyId, , tradeIndexStr] = eventParams;
const tradeIndex = parseInt(tradeIndexStr);
if (isNaN(tradeIndex))
throw Error(`Invalid tradeIndex provided: ${tradeIndexStr}. Expected integer`);
return {
provider,
strategyId,
tradeIndex,
};
};
exports.getParamsFromCsoTradeSplitEventId = getParamsFromCsoTradeSplitEventId;
const getParamsFromCsoTradeUnsplitEventId = (eventId) => {
const eventParams = eventId.split('-');
if (eventParams.length !== 5)
throw Error(`Invalid eventId provided: ${eventId}. Expected format [provider]-[strategyId]-[numTrades]-[trades]-[startDate]`);
const [provider, strategyId, numTradesStr, , startDateStr] = eventParams;
const numTrades = parseInt(numTradesStr);
if (isNaN(numTrades))
throw Error(`Invalid numTrades provided: ${numTradesStr}. Expected integer`);
if (!exports.STR_DATE_REGEX.test(startDateStr))
throw new Error(`Invalid start date provided: ${startDateStr}`);
const startDate = (0, exports.extractCsoEventIdDateFromStr)(startDateStr);
return {
provider,
strategyId,
numTrades,
startDate,
};
};
exports.getParamsFromCsoTradeUnsplitEventId = getParamsFromCsoTradeUnsplitEventId;
/**
* getParamsFromManualEventId
*
* Pass in eventId and return provider, source, maturity, and symbol
*
* @param {string} eventId format [provider]-[source]-[symbol]-[maturity]
* @returns {ManualEventParams} provider, source, maturity, and symbol
*/
const getParamsFromManualEventId = (eventId) => {
const eventParams = eventId.split('-');
if (eventParams.length !== 4)
throw Error(`Invalid eventId provided: ${eventId}. Expected format [provider]-[source]-[symbol]-[maturity]`);
const [provider, source, symbol, maturityStr] = eventParams;
if (!exports.STR_DATE_REGEX.test(maturityStr))
throw new Error(`Invalid maturity date provided: ${maturityStr}`);
const maturity = (0, exports.extractCsoEventIdDateFromStr)(maturityStr);
return {
provider,
source,
symbol,
maturity,
};
};
exports.getParamsFromManualEventId = getParamsFromManualEventId;
const getCsoEventIdType = (eventId) => {
const eventParams = eventId.split('-');
// Check the length and specific parts of the split eventId to determine its type
switch (eventParams.length) {
case 5:
// If the eventId splits into 5 parts, it could be 'period' or 'unsplit'
// Check the fourth part to differentiate
return eventParams[3] === 'trades' ? 'unsplit' : 'period';
case 4:
// If the eventId splits into 4 parts, it's a 'split'
return 'split';
default:
// If the eventId doesn't match the above cases, throw an error
throw new Error(`Invalid eventId provided: ${eventId}`);
}
};
exports.getCsoEventIdType = getCsoEventIdType;
const getEventIdType = (eventId) => {
const eventParams = eventId.split('-');
// Check if the eventId is of type 'manual'
if (eventParams.length === 4 && eventParams[2] !== 'trade') {
return 'manual';
}
// If not 'manual', use the existing function to determine the type
return (0, exports.getCsoEventIdType)(eventId);
};
exports.getEventIdType = getEventIdType;
/**
* extractCsoEventIdDateFromStr
*
* Get Date from string date while checking if date matches tradingOpen,
* tradingOpenHalfMonth or dlcExpiry
*
* @param {string} dateStr string date in format [day][month][year] i.e. 21AUG22
* @returns {Date}
*/
const extractCsoEventIdDateFromStr = (dateStr) => {
const [, day, month, year] = dateStr.match(exports.STR_DATE_REGEX);
// Create a more reliable date parsing that works across all JS environments
// Map month abbreviations to month numbers (0-indexed)
const monthMap = {
JAN: 0,
FEB: 1,
MAR: 2,
APR: 3,
MAY: 4,
JUN: 5,
JUL: 6,
AUG: 7,
SEP: 8,
OCT: 9,
NOV: 10,
DEC: 11,
};
const monthNum = monthMap[month];
if (monthNum === undefined) {
throw new Error(`Invalid month abbreviation: ${month}`);
}
// Convert 2-digit year to 4-digit year (assuming 20xx for years 00-99)
const fullYear = parseInt(year) < 50 ? 2000 + parseInt(year) : 1900 + parseInt(year);
const dayNum = parseInt(day);
// Create date using UTC constructor for consistency
const date = new Date(Date.UTC(fullYear, monthNum, dayNum, 12, 0, 0, 0));
// Validate the date was created successfully
if (isNaN(date.getTime())) {
throw new Error(`Invalid date created from: ${dateStr}`);
}
const csoEvent = (0, exports.getCsoEvent)(date);
const { previousDlcExpiry, newEntryClosed, tradingOpen, tradingOpenHalfMonth, upcomingDlcExpiry, } = (0, exports.getCsoEventDates)(date);
if (csoEvent === 'tradingOpen') {
if (date.getUTCDate() === tradingOpen.getUTCDate())
return newEntryClosed;
}
else if (csoEvent === 'tradingOpenHalfMonth') {
if (date.getUTCDate() === tradingOpenHalfMonth.getUTCDate())
return tradingOpenHalfMonth;
}
else if (csoEvent === 'dlcExpiry') {
if (date.getUTCDate() === upcomingDlcExpiry.getUTCDate()) {
return upcomingDlcExpiry;
}
else if (date.getUTCDate() === previousDlcExpiry.getUTCDate()) {
return previousDlcExpiry;
}
}
else if (csoEvent === 'newEntryClosed') {
return newEntryClosed;
}
return date;
};
exports.extractCsoEventIdDateFromStr = extractCsoEventIdDateFromStr;
/**
* findCycleMaturityMonthsInPast
*
* Enter number of cycles to look in past and get cycle maturity
* i.e. passing in numMonths 3 will get the cycle maturity 3 months ago
*
* @param {Date} t_ current time
* @param {number} numMonths number of months to go back
* @returns {Date}
*/
const findCycleMaturityMonthsInPast = (t_, numMonths) => {
let t = new Date(t_.getTime());
if (numMonths === 0)
throw Error('numMonths must be at least 1');
for (let i = 0; i < numMonths; i++) {
t = (0, exports.getPreviousCycleMaturityDate)(new Date(t.getTime() - 1));
}
return t;
};
exports.findCycleMaturityMonthsInPast = findCycleMaturityMonthsInPast;
/**
* findNumCyclesInPastMaturityExists
*
* Enter previousExpiry and find out how many months ago this expiry was
*
* @param {Date} t_ current time
* @param {Date} previousExpiry previous cycle expiry
* @returns {number}
*/
const findNumCyclesInPastMaturityExists = (t_, previousExpiry_, maxTries = 1000) => {
let t = new Date(t_.getTime());
if (previousExpiry_.getTime() >= t.getTime())
throw Error('Previous Expiry should be less than current date');
if ((0, exports.getCsoEvent)(previousExpiry_) !== 'dlcExpiry')
throw Error('Previous Expiry should be in time period dlcExpiry');
const { previousDlcExpiry } = (0, exports.getCsoEventDates)(previousExpiry_);
const previousExpiry = previousDlcExpiry;
if (t.getTime() === previousExpiry.getTime())
return 0;
for (let i = 0; i < maxTries; i++) {
t = (0, exports.getPreviousCycleMaturityDate)(new Date(t.getTime() - 1));
if (t.getTime() === previousExpiry.getTime())
return i + 1;
}
throw Error(`Could not find cycle maturity in the past after checking ${maxTries} months`);
};
exports.findNumCyclesInPastMaturityExists = findNumCyclesInPastMaturityExists;
/**
* isHalfMonth
*
* Determine if the current cycle is a half month cycle
* @param {string} eventId current time
* @returns {boolean} whether the current cycle is a half month
*/
const isHalfMonth = (eventId) => {
const startDate = (0, exports.getParamsFromCsoEventId)(eventId).startDate;
return (startDate.getTime() ===
(0, exports.getCsoEventDates)(startDate).tradingOpenHalfMonth.getTime() ||
startDate.getTime() ===
(0, exports.getCsoEventDates)(startDate).halfMonthEntryClosed.getTime());
};
exports.isHalfMonth = isHalfMonth;
const getCsoLength = (eventId) => {
const { startDate, endDate } = (0, exports.getParamsFromCsoEventId)(eventId);
const containsHalfMonth = (0, exports.isHalfMonth)(eventId);
// Get the difference in days
const diffInDays = Math.floor((endDate.getTime() - startDate.getTime()) / (1000 * 60 * 60 * 24));
if (containsHalfMonth) {
if (diffInDays > 30)
return 'one-and-a-half-months';
else
return 'half-month';
}
else {
if (diffInDays > 45)
return 'two-months';
else
return 'full-month';
}
};
exports.getCsoLength = getCsoLength;
//# sourceMappingURL=cso.js.map
;