-
-
Notifications
You must be signed in to change notification settings - Fork 1.8k
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
Add parseISODuration #1947
Add parseISODuration #1947
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
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 { parseISODuration } from 'date-fns/fp' | ||
export default parseISODuration |
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 '../../parseISODuration/index.js' | ||
import convertToFP from '../_lib/convertToFP/index.js' | ||
|
||
var parseISODuration = convertToFP(fn, 1) | ||
|
||
export default parseISODuration |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,52 @@ | ||
// @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 = { | ||
code?: string, | ||
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?: { | ||
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 | ||
} | ||
} | ||
|
||
export type Duration = { | ||
years?: number, | ||
months?: number, | ||
weeks?: number, | ||
days?: number, | ||
hours?: number, | ||
minutes?: number, | ||
seconds?: number | ||
} | ||
|
||
type CurriedFn1<A, R> = <A>(a: A) => R | ||
|
||
declare module.exports: CurriedFn1<string, Duration | null> |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
// @flow | ||
/* eslint-env mocha */ | ||
/* global suite, benchmark */ | ||
|
||
import parseISODuration from '.' | ||
import moment from 'moment' | ||
|
||
suite('parseISODuration', function() { | ||
benchmark('date-fns', function() { | ||
return parseISODuration('P2.2Y3.3M4.4DT5.5H6.6M7.7S') | ||
}) | ||
|
||
benchmark('Moment.js', function() { | ||
return moment.duration('P2.2Y3.3M4.4DT5.5H6.6M7.7S') | ||
}) | ||
}) |
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 { parseISODuration } from 'date-fns' | ||
export default parseISODuration |
Original file line number | Diff line number | Diff line change | ||||
---|---|---|---|---|---|---|
@@ -0,0 +1,68 @@ | ||||||
import requiredArgs from '../_lib/requiredArgs/index' | ||||||
|
||||||
var nr = '\\d+(?:[\\.,]\\d+)?' | ||||||
var dateRegex = '(' + nr + 'Y)?(' + nr + 'M)?(' + nr + 'D)?' | ||||||
var timeRegex = 'T(' + nr + 'H)?(' + nr + 'M)?(' + nr + 'S)?' | ||||||
var durationRegex = new RegExp('P' + dateRegex + '(?:' + timeRegex + ')?') | ||||||
|
||||||
/** | ||||||
* @name parseISODuration | ||||||
* @category Common Helpers | ||||||
* @summary Parse ISO duration string | ||||||
* | ||||||
* @description | ||||||
* Parse the given string in ISO 8601 duration format and return an instance of Duration. | ||||||
* | ||||||
* Function accepts complete ISO 8601 formats. | ||||||
* ISO 8601: http://en.wikipedia.org/wiki/ISO_8601 | ||||||
* | ||||||
* If the argument isn't a string, the function cannot parse the string or | ||||||
* the values are invalid, it returns null. | ||||||
* | ||||||
* @param {String} argument - the value to convert | ||||||
* @returns {Duration | null} the parsed duration or null | ||||||
* @throws {TypeError} 1 argument required | ||||||
* | ||||||
* @example | ||||||
* // Convert string 'P1DT5M30S' to duration: | ||||||
* var result = parseISO('P1HT5M30S') | ||||||
* //=> { days: 1, minutes: 5, seconds: 30 } | ||||||
*/ | ||||||
export default function parseISODuration(argument) { | ||||||
requiredArgs(1, arguments) | ||||||
|
||||||
if ( | ||||||
!( | ||||||
typeof argument === 'string' || | ||||||
Object.prototype.toString.call(argument) === '[object String]' | ||||||
) | ||||||
) { | ||||||
return null | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Here and everywhere below, I suggest returning an empty object instead of There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||
} | ||||||
|
||||||
var match = argument.match(durationRegex) | ||||||
if (!match) { | ||||||
return null | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||
} | ||||||
|
||||||
// at least one part must be specified | ||||||
if ( | ||||||
!match[1] && | ||||||
!match[2] && | ||||||
!match[3] && | ||||||
!match[4] && | ||||||
!match[5] && | ||||||
!match[6] | ||||||
) { | ||||||
return null | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||
} | ||||||
|
||||||
var duration = {} | ||||||
if (match[1]) duration.years = parseFloat(match[1]) | ||||||
if (match[2]) duration.months = parseFloat(match[2]) | ||||||
if (match[3]) duration.days = parseFloat(match[3]) | ||||||
if (match[4]) duration.hours = parseFloat(match[4]) | ||||||
if (match[5]) duration.minutes = parseFloat(match[5]) | ||||||
if (match[6]) duration.seconds = parseFloat(match[6]) | ||||||
return duration | ||||||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,50 @@ | ||
// @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 = { | ||
code?: string, | ||
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?: { | ||
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 | ||
} | ||
} | ||
|
||
export type Duration = { | ||
years?: number, | ||
months?: number, | ||
weeks?: number, | ||
days?: number, | ||
hours?: number, | ||
minutes?: number, | ||
seconds?: number | ||
} | ||
|
||
declare module.exports: (argument: string) => Duration | null |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,80 @@ | ||
// @flow | ||
/* eslint-env mocha */ | ||
|
||
import assert from 'power-assert' | ||
import parseISODuration from '.' | ||
|
||
describe('parseISODuration', () => { | ||
describe('parsing', () => { | ||
it('parses with all members', () => { | ||
const result = parseISODuration('P2.2Y3.3M4.4DT5.5H6.6M7.7S') | ||
assert.deepEqual(result, { | ||
years: 2.2, | ||
months: 3.3, | ||
days: 4.4, | ||
hours: 5.5, | ||
minutes: 6.6, | ||
seconds: 7.7 | ||
}) | ||
}) | ||
|
||
it('parses without time', () => { | ||
const result = parseISODuration('P2Y3M5D') | ||
assert.deepEqual(result, { years: 2, months: 3, days: 5 }) | ||
}) | ||
|
||
it('parses missing years without time', () => { | ||
const result = parseISODuration('P3M5D') | ||
assert.deepEqual(result, { months: 3, days: 5 }) | ||
}) | ||
|
||
it('parses missing months without time', () => { | ||
const result = parseISODuration('P2Y5D') | ||
assert.deepEqual(result, { years: 2, days: 5 }) | ||
}) | ||
|
||
it('parses missing days without time', () => { | ||
const result = parseISODuration('P2Y3M') | ||
assert.deepEqual(result, { years: 2, months: 3 }) | ||
}) | ||
|
||
it('parses without days', () => { | ||
const result = parseISODuration('PT65H40M22S') | ||
assert.deepEqual(result, { hours: 65, minutes: 40, seconds: 22 }) | ||
}) | ||
|
||
it('parses missing hours without date', () => { | ||
const result = parseISODuration('PT3M4S') | ||
assert.deepEqual(result, { minutes: 3, seconds: 4 }) | ||
}) | ||
|
||
it('parses missing minutes without date', () => { | ||
const result = parseISODuration('PT2H4S') | ||
assert.deepEqual(result, { hours: 2, seconds: 4 }) | ||
}) | ||
|
||
it('parses missing seconds without date', () => { | ||
const result = parseISODuration('PT2H3M') | ||
assert.deepEqual(result, { hours: 2, minutes: 3 }) | ||
}) | ||
}) | ||
|
||
describe('validation', () => { | ||
it('returns `null` for invalid string', () => { | ||
const result = parseISODuration('abcdef') | ||
assert(result === null) | ||
}) | ||
it('returns null when all parts are missing', () => { | ||
const result = parseISODuration('P') | ||
assert.deepEqual(result, null) | ||
}) | ||
it('returns null for non-string', () => { | ||
// $ExpectedMistake | ||
const result = parseISODuration(150) | ||
assert(result === null) | ||
}) | ||
it('throws TypeError exception if passed less than 1 argument', () => { | ||
assert.throws(parseISODuration.bind(null), TypeError) | ||
}) | ||
}) | ||
}) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.