КИПАРИС: Как добавить один месяц к моей текущей дате, учитывая такие месяцы, как февраль (28 дней) и месяцы, в которых 30 дней?

У меня есть этот кипарисовый тест, где я проверяю правильную дату выставления счета. Наш сайт имеет ежемесячную подписку и работает следующим образом: Если вы начнете подписку 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 и тестировании в целом. (Извините, английский не мой родной язык)

Каков точный формат даты начала выставления счета и даты следующего выставления счета.

Alapan Das 31.03.2022 17:43

@AlapanDas На самом деле на нашей платформе дата отображается так: «Ваш следующий счет на 13,99 евро 1 мая 2022 года». Но я использую другую функцию в своем тесте на кипарис: «const billingDate = getBillingDate(new Date().toString(), 1)», чтобы преобразовать дату в строку, чтобы я мог проверить правильность текста.

Mimz 31.03.2022 17:55

Вероятно дубликат Функция JavaScript для добавления X месяцев к дате

RobG 01.04.2022 00:37
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
В настоящее время производительность загрузки веб-сайта имеет решающее значение не только для удобства пользователей, но и для ранжирования в...
Безумие обратных вызовов в javascript [JS]
Безумие обратных вызовов в javascript [JS]
Здравствуйте! Юный падаван 🚀. Присоединяйся ко мне, чтобы разобраться в одной из самых запутанных концепций, когда вы начинаете изучать мир...
Система управления парковками с использованием HTML, CSS и JavaScript
Система управления парковками с использованием HTML, CSS и JavaScript
Веб-сайт по управлению парковками был создан с использованием HTML, CSS и JavaScript. Это простой сайт, ничего вычурного. Основная цель -...
JavaScript Вопросы с множественным выбором и ответы
JavaScript Вопросы с множественным выбором и ответы
Если вы ищете платформу, которая предоставляет вам бесплатный тест JavaScript MCQ (Multiple Choice Questions With Answers) для оценки ваших знаний,...
1
3
65
4
Перейти к ответу Данный вопрос помечен как решенный

Ответы 4

Day.js уже существует для вычисления дат.

Вы можете использовать их .add(), чтобы добавить 30 дней к дате dayjs().add(30, 'day').

Вы также можете форматировать даты с помощью .format(), чтобы форматировать так, как вы хотите dayjs('2019-01-25').format('DD/MM/YYYY') // '25/01/2019'

Благодарю вас! Но как это будет выглядеть, если сегодня 31 января и я собираюсь добавить 30 дней? Так как февраля может быть только 28 или 29?

Mimz 31.03.2022 18:05

Я предполагаю, что day.js учитывает дни високосного года. Если ваши даты выставления счетов составляют 30 дней или месяц, вы можете добавить этот пограничный случай для FEb.

jjhelguero 31.03.2022 18:30

@jjhelguero - вряд ли это крайний случай, это случается часто.

RobG 01.04.2022 00:39
Ответ принят как подходящий

И 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')

})

Большое спасибо! Это сработало именно так, как я хотел. Я ценю вашу помощь.

Mimz 01.04.2022 14:17

Ваши требования немного необычны. Обычно при добавлении месяца и его переполнении требуется вернуть последний день месяца, а не первый день следующего месяца. Но это несложно, просто получите начальную дату (день в месяце), добавьте месяц и, если полученная дата не совпадает, установите ее на 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>

Другие вопросы по теме