Відніміть дні, місяці, роки від дати в 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.