Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature/implement generic add #1581

Merged
merged 19 commits into from
Jan 4, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
9 changes: 7 additions & 2 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,13 +10,18 @@ This change log follows the format documented in [Keep a CHANGELOG].

## Unreleased

Thanks to [@mborgbrant](https://github.com/mborgbrant), [@saintplay](https://github.com/saintplay), [@mrenty](https://github.com/mrenty).
Thanks to [@mborgbrant](https://github.com/mborgbrant), [@saintplay](https://github.com/saintplay), [@mrenty](https://github.com/mrenty), [@kibertoad](https://github.com/kibertoad), [@levibuzolic](https://github.com/levibuzolic).

### Added

- [Added `eachMonthOfInterval` and `eachYearOfInterval`](https://github.com/date-fns/date-fns/pull/618).
- [Added `inclusive` option to `areIntervalsOverlapping](https://github.com/date-fns/date-fns/pull/643).
- [Added `isExists` function that checks if the given date is exists]().
- [Added `isExists` function that checks if the given date is exists](https://github.com/date-fns/date-fns/pull/682).
- [Added `add` function to add seconds, minutes, hours, weeks, years in single call](https://github.com/date-fns/date-fns/pull/1504).

### Changed

- [Reduced the total minified build size by 1Kb/4%](https://github.com/date-fns/date-fns/pull/1563).

## [2.8.1] - 2019-11-22

Expand Down
25 changes: 25 additions & 0 deletions src/add/benchmark.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
// @flow
/* eslint-env mocha */
/* global suite, benchmark */

import add from '.'
import moment from 'moment'

suite(
'add',
function() {
benchmark('date-fns', function() {
return add(this.date, { hours: 5, minutes: 10 })
})

benchmark('Moment.js', function() {
return this.moment.add({ hours: 5, minutes: 10 }, 'seconds')
})
},
{
setup: function() {
this.date = new Date()
this.moment = moment()
}
}
)
4 changes: 4 additions & 0 deletions src/add/index.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
// This file is generated automatically by `scripts/build/typings.js`. Please, don't change it.

import { add } from 'date-fns'
export default add
66 changes: 66 additions & 0 deletions src/add/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
import addMonths from '../addMonths/index.js'
import toDate from '../toDate/index.js'
import requiredArgs from '../_lib/requiredArgs/index.js'
import toInteger from '../_lib/toInteger/index.js'

/**
* @name add
* @category Common Helpers
* @summary Add the specified years, months, days, hours, minutes and seconds to the given date.
*
* @description
* Add the specified years, months, days, hours, minutes and seconds to the given date.
*
* @param {Date|Number} date - the date to be changed
* @param {Object} duration - the object with years, months, days, hours, minutes and seconds to be added
*
* | Key | Description |
* |----------------|------------------------------------|
* | years | Amount of years to be added |
* | months | Amount of months to be added |
* | days | Amount of days to be added |
* | hours | Amount of hours to be added |
* | minutes | Amount of minutes to be added |
* | seconds | Amount of seconds to be added |
*
* All values default to 0
*
* @returns {Date} the new date with the seconds added
* @throws {TypeError} 2 arguments required
*
* @example
* // Add the following duration to 1 September 2014, 10:19:50
* var result = add(new Date(2014, 8, 1, 10, 19, 50), {
* years: 2,
* months: 24,
* days: 7,
* hours: 5,
* minutes: 9,
* seconds: 30,
* })
* //=> Sat Sep 8 2018 15:29:20
*/
export default function add(dirtyDate, duration) {
requiredArgs(2, arguments)

if (!duration || typeof duration !== 'object') return new Date(NaN)

const years = 'years' in duration ? toInteger(duration.years) : 0
const months = 'months' in duration ? toInteger(duration.months) : 0
const days = 'days' in duration ? toInteger(duration.days) : 0
const hours = 'hours' in duration ? toInteger(duration.hours) : 0
const minutes = 'minutes' in duration ? toInteger(duration.minutes) : 0
const seconds = 'seconds' in duration ? toInteger(duration.seconds) : 0

// Add years and months
const dateWithMonths = addMonths(toDate(dirtyDate), months + years * 12)

// Add days, hours, minutes and seconds
const hoursToAdd = hours + days * 24
const minutesToAdd = minutes + hoursToAdd * 60
const secondsToAdd = seconds + minutesToAdd * 60
const msToAdd = secondsToAdd * 1000
const finalDate = new Date(dateWithMonths.getTime() + msToAdd)

return finalDate
}
38 changes: 38 additions & 0 deletions src/add/index.js.flow
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
// @flow
// This file is generated automatically by `scripts/build/typings.js`. Please, don't change it.

export type Interval = {
start: Date | number,
end: Date | number
}

export type Locale = {
formatDistance: (...args: Array<any>) => any,
formatRelative: (...args: Array<any>) => any,
localize: {
ordinalNumber: (...args: Array<any>) => any,
era: (...args: Array<any>) => any,
quarter: (...args: Array<any>) => any,
month: (...args: Array<any>) => any,
day: (...args: Array<any>) => any,
dayPeriod: (...args: Array<any>) => any
},
formatLong: Object,
date: (...args: Array<any>) => any,
time: (...args: Array<any>) => any,
dateTime: (...args: Array<any>) => any,
match: {
ordinalNumber: (...args: Array<any>) => any,
era: (...args: Array<any>) => any,
quarter: (...args: Array<any>) => any,
month: (...args: Array<any>) => any,
day: (...args: Array<any>) => any,
dayPeriod: (...args: Array<any>) => any
},
options?: {
weekStartsOn?: 0 | 1 | 2 | 3 | 4 | 5 | 6,
firstWeekContainsDate?: 1 | 2 | 3 | 4 | 5 | 6 | 7
}
}

declare module.exports: (date: Date | number, duration: Object) => Date
78 changes: 78 additions & 0 deletions src/add/test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
// @flow
/* eslint-env mocha */

import assert from 'power-assert'
import add from '.'

describe('add', function() {
it('adds the values from the given object', function() {
var result = add(new Date(2014, 8 /* Sep */, 1, 10, 19, 50), {
seconds: 30,
minutes: 9,
hours: 5,
days: 7,
months: 9,
years: 2
})
assert.deepEqual(result, new Date(2017, 5 /* June */, 8, 15, 29, 20))
})

it('returns same date object when passed empty duration values', function() {
var result = add(new Date(2014, 8 /* Sep */, 1, 10).getTime(), {})
assert.deepEqual(result, new Date(2014, 8 /* Sep */, 1, 10))
})

it('accepts a timestamp', function() {
var result = add(new Date(2014, 8 /* Sep */, 1, 10).getTime(), { hours: 4 })
assert.deepEqual(result, new Date(2014, 8 /* Sep */, 1, 14))
})

it('converts a fractional number to an integer', function() {
var result = add(new Date(2014, 8 /* Sep */, 1, 10), { hours: 4.2 })
assert.deepEqual(result, new Date(2014, 8 /* Sep */, 1, 14))
})

it('implicitly converts number arguments', function() {
var result = add(new Date(2014, 8 /* Sep */, 1, 10), { hours: '4.2' })
assert.deepEqual(result, new Date(2014, 8 /* Sep */, 1, 14))
})

it('does not mutate the original date', function() {
var date = new Date(2014, 8 /* Sep */, 1, 10)
add(date, { hours: 4 })
assert.deepEqual(date, new Date(2014, 8 /* Sep */, 1, 10))
})

it('works well if the desired month has fewer days and the provided date is in the last day of a month', function() {
var date = new Date(2014, 11 /* Dec */, 31)
var result = add(date, { months: 9 })
assert.deepEqual(result, new Date(2015, 8 /* Sep */, 30))
})

it('handles dates before 100 AD', function() {
var initialDate = new Date(0)
initialDate.setFullYear(-1, 10 /* Nov */, 30)
initialDate.setHours(0, 0, 0, 0)
var expectedResult = new Date(0)
expectedResult.setFullYear(0, 1 /* Feb */, 29)
expectedResult.setHours(0, 0, 0, 0)
var result = add(initialDate, { months: 3 })
assert.deepEqual(result, expectedResult)
})

it('returns `Invalid Date` if the given date is invalid', function() {
var result = add(new Date(NaN), { hours: 5 })
assert(result instanceof Date && isNaN(result))
})

it('throws RangeError exception if passed Number as duration', function() {
// $ExpectedMistake
const result = add(new Date(2014, 8, 1), 'wut')
assert(result instanceof Date && isNaN(result))
})

it('throws TypeError exception if passed less than 2 arguments', function() {
assert.throws(add.bind(null), TypeError)
assert.throws(add.bind(null, 1), TypeError)
})
})
4 changes: 4 additions & 0 deletions src/fp/add/index.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
// This file is generated automatically by `scripts/build/typings.js`. Please, don't change it.

import { add } from 'date-fns/fp'
export default add
8 changes: 8 additions & 0 deletions src/fp/add/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
// This file is generated automatically by `scripts/build/fp.js`. Please, don't change it.

import fn from '../../add/index.js'
import convertToFP from '../_lib/convertToFP/index.js'

var add = convertToFP(fn, 2)

export default add
44 changes: 44 additions & 0 deletions src/fp/add/index.js.flow
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
// @flow
// This file is generated automatically by `scripts/build/typings.js`. Please, don't change it.

export type Interval = {
start: Date | number,
end: Date | number
}

export type Locale = {
formatDistance: (...args: Array<any>) => any,
formatRelative: (...args: Array<any>) => any,
localize: {
ordinalNumber: (...args: Array<any>) => any,
era: (...args: Array<any>) => any,
quarter: (...args: Array<any>) => any,
month: (...args: Array<any>) => any,
day: (...args: Array<any>) => any,
dayPeriod: (...args: Array<any>) => any
},
formatLong: Object,
date: (...args: Array<any>) => any,
time: (...args: Array<any>) => any,
dateTime: (...args: Array<any>) => any,
match: {
ordinalNumber: (...args: Array<any>) => any,
era: (...args: Array<any>) => any,
quarter: (...args: Array<any>) => any,
month: (...args: Array<any>) => any,
day: (...args: Array<any>) => any,
dayPeriod: (...args: Array<any>) => any
},
options?: {
weekStartsOn?: 0 | 1 | 2 | 3 | 4 | 5 | 6,
firstWeekContainsDate?: 1 | 2 | 3 | 4 | 5 | 6 | 7
}
}

type CurriedFn1<A, R> = <A>(a: A) => R

type CurriedFn2<A, B, R> = <A>(
a: A
) => CurriedFn1<B, R> | (<A, B>(a: A, b: B) => R)

declare module.exports: CurriedFn2<Object, Date | number, Date>
1 change: 1 addition & 0 deletions src/fp/index.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
// This file is generated automatically by `scripts/build/indices.js`. Please, don't change it.

export { default as add } from './add/index.js'
export { default as addBusinessDays } from './addBusinessDays/index.js'
export { default as addDays } from './addDays/index.js'
export { default as addHours } from './addHours/index.js'
Expand Down
1 change: 1 addition & 0 deletions src/fp/index.js.flow
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,7 @@ type CurriedFn4<A, B, C, D, R> = <A>(
) => CurriedFn1<D, R> | (<A, B, C, D>(a: A, b: B, c: C, d: D) => R)))

declare module.exports: {
add: CurriedFn2<Object, Date | number, Date>,
addBusinessDays: CurriedFn2<number, Date | number, Date>,
addDays: CurriedFn2<number, Date | number, Date>,
addHours: CurriedFn2<number, Date | number, Date>,
Expand Down
1 change: 1 addition & 0 deletions src/index.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
// This file is generated automatically by `scripts/build/indices.js`. Please, don't change it.

export { default as add } from './add/index.js'
export { default as addBusinessDays } from './addBusinessDays/index.js'
export { default as addDays } from './addDays/index.js'
export { default as addHours } from './addHours/index.js'
Expand Down
2 changes: 2 additions & 0 deletions src/index.js.flow
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,8 @@ export type Locale = {
}

declare module.exports: {
add: (date: Date | number, duration: Object) => Date,

addBusinessDays: (date: Date | number, amount: number) => Date,

addDays: (date: Date | number, amount: number) => Date,
Expand Down