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

Fix - add and subtract when duration has undefined params #2515

Merged
merged 3 commits into from Jul 23, 2021
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
16 changes: 8 additions & 8 deletions src/add/index.ts
Expand Up @@ -20,7 +20,7 @@ import { Duration } from '../types'
* |----------------|------------------------------------|
* | years | Amount of years to be added |
* | months | Amount of months to be added |
* | weeks | Amount of weeks to be added |
* | weeks | Amount of weeks to be added |
* | days | Amount of days to be added |
* | hours | Amount of hours to be added |
* | minutes | Amount of minutes to be added |
Expand Down Expand Up @@ -52,13 +52,13 @@ export default function add(

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 weeks = 'weeks' in duration ? toInteger(duration.weeks) : 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
const years = duration.years ? toInteger(duration.years) : 0
const months = duration.months ? toInteger(duration.months) : 0
const weeks = duration.weeks ? toInteger(duration.weeks) : 0
const days = duration.days ? toInteger(duration.days) : 0
const hours = duration.hours ? toInteger(duration.hours) : 0
const minutes = duration.minutes ? toInteger(duration.minutes) : 0
const seconds = duration.seconds ? toInteger(duration.seconds) : 0

// Add years and months
const date = toDate(dirtyDate)
Expand Down
56 changes: 41 additions & 15 deletions src/add/test.ts
Expand Up @@ -5,50 +5,76 @@ import assert from 'assert'
import add from '.'
import { getDstTransitions } from '../../test/dst/tzOffsetTransitions'

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

it('returns same date object when passed empty duration values', function() {
it('supports an undefined value in the duration object', function () {
const result = add(new Date(2014, 8 /* Sep */, 1, 10, 19, 50), {
years: undefined,
months: 9,
weeks: 1,
days: 7,
hours: 5,
minutes: 9,
seconds: 30,
})
assert.deepStrictEqual(result, new Date(2015, 5 /* June */, 15, 15, 29, 20))
})

it('returns same date object when passed empty duration values', function () {
const result = add(new Date(2014, 8 /* Sep */, 1, 10).getTime(), {
years: undefined,
months: undefined,
weeks: undefined,
days: undefined,
hours: undefined,
minutes: undefined,
seconds: undefined,
})
assert.deepStrictEqual(result, new Date(2014, 8 /* Sep */, 1, 10))
})

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

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

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

it('implicitly converts number arguments', function() {
it('implicitly converts number arguments', function () {
// @ts-expect-error
const result = add(new Date(2014, 8 /* Sep */, 1, 10), { hours: '4.2' })
assert.deepStrictEqual(result, new Date(2014, 8 /* Sep */, 1, 14))
})

it('does not mutate the original date', function() {
it('does not mutate the original date', function () {
const date = new Date(2014, 8 /* Sep */, 1, 10)
add(date, { hours: 4 })
assert.deepStrictEqual(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() {
it('works well if the desired month has fewer days and the provided date is in the last day of a month', function () {
const date = new Date(2014, 11 /* Dec */, 31)
const result = add(date, { months: 9 })
assert.deepStrictEqual(result, new Date(2015, 8 /* Sep */, 30))
Expand All @@ -61,14 +87,14 @@ describe('add', function() {

dstOnly(
`works at DST-end boundary in local timezone: ${tz || '(unknown)'}`,
function() {
function () {
const date = dstTransitions.end
const result = add(date!, { hours: 1 })
assert.deepStrictEqual(result, new Date(date!.getTime() + HOUR))
}
)

it('handles dates before 100 AD', function() {
it('handles dates before 100 AD', function () {
const initialDate = new Date(0)
initialDate.setFullYear(-1, 10 /* Nov */, 30)
initialDate.setHours(0, 0, 0, 0)
Expand All @@ -79,18 +105,18 @@ describe('add', function() {
assert.deepStrictEqual(result, expectedResult)
})

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

it('throws RangeError exception if passed Number as duration', function() {
it('throws RangeError exception if passed Number as duration', function () {
// @ts-expect-error
const result = add(new Date(2014, 8, 1), 'wut')
assert(result instanceof Date && isNaN(result.getTime()))
})

it('throws TypeError exception if passed less than 2 arguments', function() {
it('throws TypeError exception if passed less than 2 arguments', function () {
// @ts-expect-error
assert.throws(add.bind(null), TypeError)
// @ts-expect-error
Expand Down
14 changes: 7 additions & 7 deletions src/sub/index.js
Expand Up @@ -48,13 +48,13 @@ export default function sub(dirtyDate, duration) {

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 weeks = 'weeks' in duration ? toInteger(duration.weeks) : 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
const years = duration.years ? toInteger(duration.years) : 0
const months = duration.months ? toInteger(duration.months) : 0
const weeks = duration.weeks ? toInteger(duration.weeks) : 0
const days = duration.days ? toInteger(duration.days) : 0
const hours = duration.hours ? toInteger(duration.hours) : 0
const minutes = duration.minutes ? toInteger(duration.minutes) : 0
const seconds = duration.seconds ? toInteger(duration.seconds) : 0

// Subtract years and months
const dateWithoutMonths = subMonths(toDate(dirtyDate), months + years * 12)
Expand Down
30 changes: 28 additions & 2 deletions src/sub/test.js
Expand Up @@ -13,19 +13,45 @@ describe('sub', () => {
days: 7,
hours: 5,
minutes: 9,
seconds: 30
seconds: 30,
})
assert.deepEqual(result, new Date(2014, 8 /* Sep */, 1, 10, 19, 50))
})

it('supports an undefined value in the duration object', function () {
const result = sub(new Date(2017, 5 /* June */, 15, 15, 29, 20), {
years: undefined,
months: 9,
weeks: 1,
days: 7,
hours: 5,
minutes: 9,
seconds: 30,
})
assert.deepEqual(result, new Date(2016, 8 /* Sep */, 1, 10, 19, 50))
})

it('returns same date object when passed empty duration values', function () {
const result = sub(new Date(2014, 8 /* Sep */, 1, 10).getTime(), {
years: undefined,
months: undefined,
weeks: undefined,
days: undefined,
hours: undefined,
minutes: undefined,
seconds: undefined,
})
assert.deepStrictEqual(result, new Date(2014, 8 /* Sep */, 1, 10))
})

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

it('accepts a timestamp', () => {
const result = sub(new Date(2014, 8 /* Sep */, 1, 14).getTime(), {
hours: 4
hours: 4,
})
assert.deepEqual(result, new Date(2014, 8 /* Sep */, 1, 10))
})
Expand Down