Відніміть дні, місяці, роки від дати в JavaScript


83

Хтось знає про простий спосіб взяти дату (наприклад, сьогодні) і повернутися назад X днів, X місяців і X років?

Я пробував це:

var date = new Date();
$("#searchDateFrom").val((date.getMonth() -1 ) + '/' + (date.getDate() - 6) + '/' + (date.getFullYear() - 1));

Але я отримав негативну дату, наприклад, сьогодні результат:

3 / -3 / 2015

Будь-яка порада?

Дякую.


4
date.get....поверне a, Numberі якщо ви віднімаєте число з іншого number, значення може бути від’ємним (якщо ліве значення менше) .. Я б запропонував вам скористатися DateObj.set...методами, а потім отримати відповідні значення ...
— район

Відповіді:


108

Ви просто зменшуєте значення з числа. Тож віднімання 6 з 3 (дата) поверне лише -3.

Вам потрібно індивідуально додати / видалити одиницю часу в об’єкті дати

var date = new Date();
date.setDate( date.getDate() - 6 );
date.setFullYear( date.getFullYear() - 1 );
$("#searchDateFrom").val((date.getMonth() ) + '/' + (date.getDate()) + '/' + (date.getFullYear()));

14
getMonth () дорівнює нулю. Це означає, що він покаже неправильний місяць. Приклад: 10 листопада.
— Тоні,

1
скажемо просто: getMonth () базується на індексі.
— GottZ

22

Як сказали інші, ви віднімаєте з числових значень, повернутих із методів типу date.getDate(), вам потрібно скинути ці значення у вашій змінній дати. Я створив метод нижче, який зробить це за вас. Він створює дату, new Date()яка ініціює поточну дату, а потім встановлює дату, місяць та рік відповідно до переданих значень. Наприклад, якщо ви хочете повернутися на 6 днів, тоді передайте -6 приблизно так var newdate = createDate(-6,0,0). Якщо ви не хочете встановлювати значення нуля (або ви можете встановити значення за замовчуванням). Метод поверне для вас нову дату (перевірено в Chrome та Firefox).

function createDate(days, months, years) {
        var date = new Date(); 
        date.setDate(date.getDate() + days);
        date.setMonth(date.getMonth() + months);
        date.setFullYear(date.getFullYear() + years);
        return date;    
    }

17

Я рекомендую використовувати бібліотеки MomentJS. Вони роблять всі взаємодії з Датами набагато простішими.

Якщо ви використовуєте Moment, ваш код буде таким простим:

var today = moment();
var nextMonth = today.add('month', 1);
// note that both variables `today` and `nextMonth` refer to 
// the next month at this point, because `add` mutates in-place

Ви можете знайти MomentJS тут: http://momentjs.com/

ОНОВЛЕННЯ:

У JavaScript функція Date.getDate () повертає поточний день місяця з 1-31. Ви віднімаєте з цього числа 6, і зараз це 3 числа місяця. Це призводить до значення -3.


@Fvb Дякую, я прочитав керівництво, і це відмінна бібліотека, дякую за ідею використовувати його.
— user3378165

Майте на увазі, що moment.js додає до вашого додатку близько 16 тис. Зазвичай не велика справа. Але якщо продуктивність критична, дотримуватися звичайного старого js дешевше для таких невеликих обчислень.
— shanemgrey

3
поточна версія моменту (2.18.2 на момент написання статті) дає попередження щодо цієї функції. add / subtract ('period', number) застаріло і пропонує замість цього використовувати add / subtract (число, 'period').
— Jamie M

13

Це чиста функція, яка бере передану дату початку, спираючись на відповідь Філа:

function deltaDate(input, days, months, years) {
    return new Date(
      input.getFullYear() + years, 
      input.getMonth() + months, 
      Math.min(
        input.getDate() + days,
        new Date(input.getFullYear() + years, input.getMonth() + months + 1, 0).getDate()
      )
    );
}

наприклад, записує дату місяць тому в журнал консолі:

console.log(deltaDate(new Date(), 0, -1, 0));

наприклад, віднімає місяць з 30 березня 2020 року:

console.log(deltaDate(new Date(2020, 2, 30), 0, -1, 0)); // Feb 29, 2020

Зверніть увагу, що це працює, навіть якщо ви перейшли кінець місяця чи року.

Оновлення: Як показує приклад вище, це оновлення оновлено для обробки відмінностей у кількості днів у місяці.


2
Але це матиме дивну поведінку наприкінці місяців. 29 березня - 1 місяць = 29 лютого, результат якого - 1 березня. 31 березня + 1 місяць = 31 квітня, результат - 1 травня. Залежно від вашого випадку використання, це може бути не тим, що ви очікували.
— Йоханнеке

1
Дякую @Johanneke, я оновив код для вирішення цієї проблеми.
— N8allan

1
Денна корекція робить цю відповідь дуже корисною, дякую!
— kol

4

Я реалізував функцію, подібну до методу momentjs віднімання .

- Якщо ви використовуєте Javascript

function addDate(dt, amount, dateType) {
  switch (dateType) {
    case 'days':
      return dt.setDate(dt.getDate() + amount) && dt;
    case 'weeks':
      return dt.setDate(dt.getDate() + (7 * amount)) && dt;
    case 'months':
      return dt.setMonth(dt.getMonth() + amount) && dt;
    case 'years':
      return dt.setFullYear( dt.getFullYear() + amount) && dt;
  }
}

приклад:

let dt = new Date();
dt = addDate(dt, -1, 'months');// use -1 to subtract 

- Якщо ви використовуєте Typescript:

export enum dateAmountType {
  DAYS,
  WEEKS,
  MONTHS,
  YEARS,
}

export function addDate(dt: Date, amount: number, dateType: dateAmountType): Date {
  switch (dateType) {
    case dateAmountType.DAYS:
      return dt.setDate(dt.getDate() + amount) && dt;
    case dateAmountType.WEEKS:
      return dt.setDate(dt.getDate() + (7 * amount)) && dt;
    case dateAmountType.MONTHS:
      return dt.setMonth(dt.getMonth() + amount) && dt;
    case dateAmountType.YEARS:
      return dt.setFullYear( dt.getFullYear() + amount) && dt;
  }
}

приклад:

let dt = new Date();
dt = addDate(dt, -1, 'months'); // use -1 to subtract

Необов’язково (модульні тести)

Я також зробив кілька модульних тестів для цієї функції, використовуючи Жасмин :

  it('addDate() should works properly', () => {
    for (const test of [
      { amount: 1,  dateType: dateAmountType.DAYS,   expect: '2020-04-13'},
      { amount: -1, dateType: dateAmountType.DAYS,   expect: '2020-04-11'},
      { amount: 1,  dateType: dateAmountType.WEEKS,  expect: '2020-04-19'},
      { amount: -1, dateType: dateAmountType.WEEKS,  expect: '2020-04-05'},
      { amount: 1,  dateType: dateAmountType.MONTHS, expect: '2020-05-12'},
      { amount: -1, dateType: dateAmountType.MONTHS, expect: '2020-03-12'},
      { amount: 1,  dateType: dateAmountType.YEARS,  expect: '2021-04-12'},
      { amount: -1, dateType: dateAmountType.YEARS,  expect: '2019-04-12'},
    ]) {
      expect(formatDate(addDate(new Date('2020-04-12'), test.amount, test.dateType))).toBe(test.expect);
    }

  });

Для використання цього тесту вам потрібна така функція:

// get format date as 'YYYY-MM-DD'
export function formatDate(date: Date): string {
  const d     = new Date(date);
  let month   = '' + (d.getMonth() + 1);
  let day     = '' + d.getDate();
  const year  = d.getFullYear();

  if (month.length < 2)  {
    month = '0' + month;
  }
  if (day.length < 2) {
    day = '0' + day;
  }

  return [year, month, day].join('-');
}

3

Використовуйте бібліотеку moment.js для керування часом та датами.

import moment = require('moment');

const now = moment();

now.subtract(7, 'seconds'); // 7 seconds ago
now.subtract(7, 'days');    // 7 days and 7 seconds ago
now.subtract(7, 'months');  // 7 months, 7 days and 7 seconds ago
now.subtract(7, 'years');   // 7 years, 7 months, 7 days and 7 seconds ago
// because `now` has been mutated, it no longer represents the current time

1
Дякую за вашу корисну відповідь. Якщо бути точнішим: "До версії 2.8.0 subtract(String, Number)також підтримувався синтаксис. Він був припинений на користь subtract(Number, String)".
— plkpiotr

1

Це не дає повного відповіді на запитання, але для кожного, хто зможе розрахувати кількість днів, на які вони хотіли б компенсувати початкову дату, працюватиме наступний метод:

myDate.setUTCDate(myDate.getUTCDate() + offsetDays);

offsetDays може бути позитивним або негативним, і результат буде правильним для будь-якої заданої початкової дати з будь-яким заданим зміщенням.


0

У мене є більш проста відповідь, яка чудово працює днями; протягом місяців це + -2 дні:

let today=new Date();
const days_to_subtract=30;
let new_date= new Date(today.valueOf()-(days_to_subtract*24*60*60*1000));

Ви розумієте - місяці помножте на 30; але це буде + -2 дні.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.