У меня есть этот кипарисовый тест, где я проверяю правильную дату выставления счета. Наш сайт имеет ежемесячную подписку и работает следующим образом: Если вы начнете подписку 31 января, ваша следующая дата выставления счетов автоматически будет 1 марта, поскольку в феврале всего 28 дней. То же самое, если вы начнете подписку 31 марта, тогда ваша следующая дата выставления счетов будет 1 мая, поскольку в апреле нет 31 числа, и оно автоматически изменяется на первое число следующего месяца. Начиная с других обычных дат, таких как 15-е, всегда будет одна и та же дата (15-е) следующего месяца и т. д.
Моя проблема заключается в том, что при тестировании этого с кипарисом я всегда получаю последний день следующего месяца. Например, если я проверю, что я начну свою подписку 31 марта, мой тест будет иметь ожидаемый результат 30 апреля, что неверно, поскольку я хочу, чтобы ожидаемый результат моего теста был 1 мая.
Я использую эту функцию, но я не могу заставить ее работать должным образом, так как в месяцах много различий.
export const getBillingDate = (todayDate: string, months: number) => {
const date1 = new Date(todayDate)
const date2 = new Date(todayDate)
date1.setDate(1)
const daysInNextMonth = getDaysInMonth(addMonths(date1, months))
date2.setDate(Math.min(date2.getDate(), daysInNextMonth))
return format(addMonths(date2, months), 'MMMM do, yyyy')
}
Я был бы очень признателен за помощь в этом, так как я новичок в Cypress и тестировании в целом. (Извините, английский не мой родной язык)
@AlapanDas На самом деле на нашей платформе дата отображается так: «Ваш следующий счет на 13,99 евро 1 мая 2022 года». Но я использую другую функцию в своем тесте на кипарис: «const billingDate = getBillingDate(new Date().toString(), 1)», чтобы преобразовать дату в строку, чтобы я мог проверить правильность текста.



![Безумие обратных вызовов в javascript [JS]](https://i.imgur.com/WsjO6zJb.png)


Day.js уже существует для вычисления дат.
Вы можете использовать их .add(), чтобы добавить 30 дней к дате dayjs().add(30, 'day').
Вы также можете форматировать даты с помощью .format(), чтобы форматировать так, как вы хотите dayjs('2019-01-25').format('DD/MM/YYYY') // '25/01/2019'
Благодарю вас! Но как это будет выглядеть, если сегодня 31 января и я собираюсь добавить 30 дней? Так как февраля может быть только 28 или 29?
Я предполагаю, что day.js учитывает дни високосного года. Если ваши даты выставления счетов составляют 30 дней или месяц, вы можете добавить этот пограничный случай для FEb.
@jjhelguero - вряд ли это крайний случай, это случается часто.
И dayjs, и javascript new Date() не могут добавить все даты именно так, как вы хотите.
Но вы можете использовать dayjs().daysInMonth(), чтобы получить результаты точно в соответствии с вашим описанием,
const getBilling = (startDate) => {
const [year, month, day] = startDate.split('/')
const sd = dayjs(startDate)
const firstOfNextMonth = sd.month(sd.month() + 1).date(1)
const daysInNextMonth = dayjs(firstOfNextMonth).daysInMonth()
let end;
if (daysInNextMonth < day) {
end = `${year}/${+month+2}/${1}` // always bump to 1st day of month + 2
} else {
end = `${year}/${+month+1}/${day}`
}
return dayjs(end, 'YYYY/MM/DD').format('YYYY/MM/DD')
}
it('gets billing date, accounting for short months', () => {
//Jan
expect(getBilling('2022/01/15')).to.eq('2022/02/15')
expect(getBilling('2022/01/31')).to.eq('2022/03/01')
//Feb
expect(getBilling('2022/02/15')).to.eq('2022/03/15')
expect(getBilling('2022/02/28')).to.eq('2022/03/28')
//Mar
expect(getBilling('2022/03/15')).to.eq('2022/04/15')
expect(getBilling('2022/03/31')).to.eq('2022/05/01')
})
Большое спасибо! Это сработало именно так, как я хотел. Я ценю вашу помощь.
Ваши требования немного необычны. Обычно при добавлении месяца и его переполнении требуется вернуть последний день месяца, а не первый день следующего месяца. Но это несложно, просто получите начальную дату (день в месяце), добавьте месяц и, если полученная дата не совпадает, установите ее на 1-ю, например:
function addBillingMonth(date = new Date()) {
let d = new Date(+date);
let dayNum = d.getDate();
d.setMonth(d.getMonth() + 1);
if (dayNum !== d.getDate()) {
d.setDate(1);
}
return d;
}
// Examples
[ new Date(2021,11,31), // 31 Dec
new Date(2022, 0,15), // 15 Jan
new Date(2022, 0,31), // 31 Jan
new Date(2022, 2,31), // 31 Mar
].forEach(d => console.info(d.toDateString() +
' next bill: ' + addBillingMonth(d).toDateString())
);
У вас есть параметр months, если вы хотите увеличить более чем на один месяц, вы должны рассчитывать каждый месяц отдельно.
'dayjs' определенно дает вам больше возможностей для игры.
const expect = chai.expect
const addBillingMonth = (start) => {
let next = start.add(1, 'month')
if (start.date() !== next.date()) {
next = next.add(1, 'month').startOf('month')
}
return next
}
const getBilling = (startDate, months = 1) => {
let result = dayjs(startDate)
for (let i = 0; i < months; i++) {
result = addBillingMonth(result) // repeat for each month
}
return result.format('YYYY/MM/DD')
}
expect(getBilling('2022/01/15')).to.eq('2022/02/15')
expect(getBilling('2022/01/31')).to.eq('2022/03/01')
expect(getBilling('2022/02/15')).to.eq('2022/03/15')
expect(getBilling('2022/02/28')).to.eq('2022/03/28')
expect(getBilling('2022/03/15')).to.eq('2022/04/15')
expect(getBilling('2022/03/31')).to.eq('2022/05/01')<script src = "https://cdnjs.cloudflare.com/ajax/libs/chai/4.3.6/chai.min.js"></script>
<script src = "https://unpkg.com/[email protected]/dayjs.min.js"></script>
Каков точный формат даты начала выставления счета и даты следующего выставления счета.