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

Rework toDate and extract parseISO #1023

Merged
merged 7 commits into from Jan 9, 2019
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
60 changes: 40 additions & 20 deletions CHANGELOG.md
Expand Up @@ -19,8 +19,9 @@ for the list of changes made since `v2.0.0-alpha.1`.
that support [currying](https://en.wikipedia.org/wiki/Currying), and, as a consequence,
functional-style [function composing](https://medium.com/making-internets/why-using-chain-is-a-mistake-9bc1f80d51ba).

Each non-FP function has two FP counterparts: one that has [Options](docs/Options) object as its first argument
and one that hasn't. The name of the former has `WithOptions` added to the end of its name.
Functions with options (`format`, `parse`, etc.) have two FP counterparts:
one that has the options object as its first argument and one that hasn't.
The name of the former has `WithOptions` added to the end of its name.

In FP functions, the order of arguments is reversed.

Expand Down Expand Up @@ -173,8 +174,33 @@ for the list of changes made since `v2.0.0-alpha.1`.

- Build-efficient `lightFormat` that only supports the popular subset of tokens. See [#1050](https://github.com/date-fns/date-fns/pull/1015).

- `parseISO` function that parses ISO 8601 strings. See [#1023](https://github.com/date-fns/date-fns/pull/1023).

### Changed
kossnocorp marked this conversation as resolved.
Show resolved Hide resolved

- **BREAKING**: now functions don't accept string arguments, but only
numbers or dates. When a string is passed, it will result in
an unexpected result (`Invalid Date`, `NaN`, etc).

From now on a string should be parsed using `parseISO` (ISO 8601)
or `parse`.

In v1 we've used `new Date()` to parse strings, but it resulted in many
hard-to-track bugs caused by inconsistencies in different browsers.
To address that we've implemented our ISO 8601 parser but that made
library to significantly grow in size. To prevent inevitable bugs
and keep the library tiny, we made this trade-off.

See [this post](https://blog.date-fns.org/post/TODO) for more details.

```javascript
// Before v2.0.0
addDays('2016-01-01', 1)

// v2.0.0 onward
addDays(parseISO('2016-01-01'), 1)
```

- **BREAKING**: new format string API for `format` function
which is based on [Unicode Technical Standard #35](https://www.unicode.org/reports/tr35/tr35-dates.html#Date_Field_Symbol_Table).
See [this post](https://blog.date-fns.org/post/unicode-tokens-in-date-fns-v2-sreatyki91jg) for more details.
Expand Down Expand Up @@ -590,28 +616,27 @@ for the list of changes made since `v2.0.0-alpha.1`.
)
```

- **BREAKING**: `parse` renamed to `toDate`,
created a new function `parse` which parses a string using a provided format.
- **BREAKING**: `parse` that previously used to convert strings and
numbers to dates now parse only strings in an arbitrary format
specified as an argument. Use `toDate` to coerce numbers and `parseISO`
to parse ISO 8601 strings.

```javascript
// Before v2.0.0
parse('2016-01-01')
parse(1547005581366)
parse(new Date()) // Clone the date

// v2.0.0 onward
toDate('2016-01-01')
parse('2016-01-01', 'yyyy-MM-dd', new Date())
parseISO('2016-01-01')
toDate(1547005581366)
toDate(new Date()) // Clone the date
```

- **BREAKING**: `toDate` now validates separate date and time values in ISO-8601 strings
and returns `Invalid Date` if the date is invalid.

```javascript
toDate('2018-13-32')
//=> Invalid Date
```

- **BREAKING**: `toDate` now doesn't fall back to `new Date` constructor
if it fails to parse a string argument. Instead, it returns `Invalid Date`.
- **BREAKING**: `toDate` (previously `parse`) now doesn't accept string
arguments but only numbers and dates. `toDate` called with an invalid
argument will return `Invalid Date`.

- **BREAKING**: new locale format.
See [docs/Locale](https://date-fns.org/docs/Locale).
Expand Down Expand Up @@ -657,7 +682,6 @@ for the list of changes made since `v2.0.0-alpha.1`.
- **BREAKING**: functions now throw `RangeError` if optional values passed to `options`
are not `undefined` or have expected values.
This change is introduced for consistency with ECMAScript standard library which does the same.
See [docs/Options.js](https://github.com/date-fns/date-fns/blob/master/docs/Options.js)

- **BREAKING**: all functions now implicitly convert arguments by following rules:

Expand Down Expand Up @@ -697,10 +721,6 @@ for the list of changes made since `v2.0.0-alpha.1`.
- **BREAKING**: all functions now check if the passed number of arguments is less
than the number of required arguments and throw `TypeError` exception if so.

- Every function now has `options` as the last argument which is passed to all its dependencies
for consistency and future features.
See [docs/Options.js](https://github.com/date-fns/date-fns/blob/master/docs/Options.js)

- **BREAKING**: The Bower & UMD/CDN package versions are no longer supported.

- **BREAKING**: `null` now is not a valid date. `isValid(null)` returns `false`;
Expand Down
4 changes: 2 additions & 2 deletions docs/Interval.js
Expand Up @@ -6,8 +6,8 @@
* An object that combines two dates to represent the time interval.
*
* @typedef {Object} Interval
* @property {Date|String|Number} start - the start of the interval
* @property {Date|String|Number} end - the end of the interval
* @property {Date|Number} start - the start of the interval
* @property {Date|Number} end - the end of the interval
* @throws {RangeError} The start of an interval cannot be after its end
* @throws {RangeError} Date in interval cannot be `Invalid Date`
*/
Expand Down
2 changes: 1 addition & 1 deletion docs/Locale.js
Expand Up @@ -43,7 +43,7 @@
* @property {Function} match.day - the function that parses a localized day of the week
* @property {Function} match.dayPeriod - the function that parses a localized time of the day
*
* @property {Object} [options] - the object with default `weekStartsOn`. See [Options]{@link https://date-fns.org/docs/Options}
* @property {Object} [options] - an object with locale options.
* @property {0|1|2|3|4|5|6} [options.weekStartsOn=0] - the index of the first day of the week (0 - Sunday).
* Used by `differenceInCalendarWeeks`, `endOfWeek`, `format`, `getWeek`, `getWeekOfMonth`,
* `getWeeksInMonth`, `isSameWeek`, `isSameWeek`, `lastDayOfWeek`, `parse`, `setDay`,
Expand Down
80 changes: 0 additions & 80 deletions docs/Options.js

This file was deleted.

7 changes: 4 additions & 3 deletions docs/fp.md
Expand Up @@ -14,8 +14,9 @@ that support [currying](https://en.wikipedia.org/wiki/Currying).

FP functions are provided via `'date-fns/fp'` submodule.

Each non-FP function has two FP counterparts: one that has [Options](https://date-fns.org/docs/Options) object as its first argument
and one that hasn't. The name of the former has `WithOptions` added to the end of its name.
Functions with options (`format`, `parse`, etc.) have two FP counterparts:
one that has the options object as its first argument and one that hasn't.
The name of the former has `WithOptions` added to the end of its name.

In **date-fns'** FP functions, the order of arguments is reversed.

Expand All @@ -28,7 +29,7 @@ import toUpper from 'lodash/fp/toUpper' // 'date-fns/fp' is compatible with 'lod
const addFiveYears = addYears(5)

// Several arguments can be curried at once
const dateToString = formatWithOptions({locale: eo}, 'd MMMM yyyy')
const dateToString = formatWithOptions({ locale: eo }, 'd MMMM yyyy')

const dates = [
new Date(2017, 0 /* Jan */, 1),
Expand Down
3 changes: 0 additions & 3 deletions docs/index.js
Expand Up @@ -125,9 +125,6 @@ module.exports = {
{
fullPath: path.join(__dirname, 'Interval.js')
},
{
fullPath: path.join(__dirname, 'Options.js')
},
{
fullPath: path.join(__dirname, 'Locale.js')
}
Expand Down
3 changes: 3 additions & 0 deletions docs/strings.md
@@ -0,0 +1,3 @@
# String Arguments

TODO
kossnocorp marked this conversation as resolved.
Show resolved Hide resolved
14 changes: 13 additions & 1 deletion docs/upgradeGuide.md
Expand Up @@ -12,10 +12,22 @@
import differenceInCalendarISOYears from 'date-fns/differenceInCalendarISOYears'
```

- Functions now don't accept strings as arguments. Strings should
be parsed using `parseISO` (ISO 8601) or `parse`.

See [this post](https://blog.date-fns.org/post/TODO) for more details.
kossnocorp marked this conversation as resolved.
Show resolved Hide resolved

```javascript
// Before v2.0.0
addDays('2016-01-01', 1)

// v2.0.0 onward
addDays(parseISO('2016-01-01'), 1)
```

- Functions now throw `RangeError` if optional values passed to `options`
are not `undefined` or have expected values.
This change is introduced for consistency with ECMAScript standard library which does the same.
See [docs/Options.js](https://github.com/date-fns/date-fns/blob/master/docs/Options.js)

- All functions now implicitly convert arguments by following rules:

Expand Down
4 changes: 2 additions & 2 deletions examples/babel/example.js
@@ -1,4 +1,4 @@
import {format} from 'date-fns'
import { format } from 'date-fns'

const result = format('2017-01-25T21:28:15.000Z', 'dd.MM.yyyy HH:mm:ss')
const result = format(new Date(2017, 0, 25, 21, 28, 15), 'dd.MM.yyyy HH:mm:ss')
console.log(result === '25.01.2017 21:28:15')
2 changes: 1 addition & 1 deletion examples/browserify/example.js
@@ -1,4 +1,4 @@
var format = require('date-fns/format')

var result = format('2017-01-25T21:28:15.000Z', 'dd.MM.yyyy HH:mm:ss')
var result = format(new Date(2017, 0, 25, 21, 28, 15), 'dd.MM.yyyy HH:mm:ss')
console.log(result === '25.01.2017 21:28:15')
6 changes: 5 additions & 1 deletion examples/browserify/misc.js
Expand Up @@ -2,5 +2,9 @@ var dateFns = require('date-fns')
var format = dateFns.format
var eo = require('date-fns/locale/eo')

var result = format('2017-01-25T21:28:15.000Z', 'eeee, dd MMMM HH:mm:ss', {locale: eo})
var result = format(
new Date(2017, 0, 25, 21, 28, 15),
'eeee, dd MMMM HH:mm:ss',
{ locale: eo }
)
console.log(result === 'merkredo, 25 januaro 21:28:15')
8 changes: 4 additions & 4 deletions examples/flow/example.js.flow
@@ -1,8 +1,8 @@
// @flow

var format = require('date-fns/format')
const format = require('date-fns/format')

var dateString : string = '2017-01-25T21:28:15.000Z'
var formatString : string = 'dd.MM.yyyy HH:mm:ss'
var result : string = format(dateString, formatString)
const dateString : Date = new Date(2017, 0, 25, 21, 28, 15)
const formatString : string = 'dd.MM.yyyy HH:mm:ss'
const result : string = format(dateString, formatString)
console.log(result === '25.01.2017 21:28:15')
16 changes: 8 additions & 8 deletions examples/flow/fp.js.flow
@@ -1,19 +1,19 @@
var addYears = require('date-fns/fp/addYears')
var dateFns = require('date-fns/fp')
var formatWithOptions = dateFns.formatWithOptions
var eo = require('date-fns/locale/eo')
const addYears = require('date-fns/fp/addYears')
const dateFns = require('date-fns/fp')
const formatWithOptions = dateFns.formatWithOptions
const eo = require('date-fns/locale/eo')

const addFiveYears = addYears(5)
const dateToString = formatWithOptions({locale: eo}, 'd MMMM yyyy')
const dateToString = formatWithOptions({ locale: eo }, 'd MMMM yyyy')

const dates : Date[] = [
const dates: Date[] = [
new Date(2017, 0 /* Jan */, 1),
new Date(2017, 1 /* Feb */, 11),
new Date(2017, 6 /* Jul */, 2)
]

const formattedDates : string = dates
.map((date) => dateToString(addFiveYears(date)))
const formattedDates: string = dates
.map(date => dateToString(addFiveYears(date)))
.join(', ')

console.log(formattedDates === '1 januaro 2022, 11 februaro 2022, 2 julio 2022')
10 changes: 5 additions & 5 deletions examples/flow/misc.js.flow
@@ -1,9 +1,9 @@
// @flow

var format = require('date-fns').format
var eo = require('date-fns/locale/eo')
const format = require('date-fns').format
const eo = require('date-fns/locale/eo')

var dateString : string = '2017-01-25T21:28:15.000Z'
var formatString : string = 'dd.MM.yyyy HH:mm:ss'
var result : string = format('2017-01-25T21:28:15.000Z', 'eeee, dd MMMM HH:mm:ss', {locale: eo})
const dateString : Date = new Date(2017, 0, 25, 21, 28, 15)
const formatString : string = 'dd.MM.yyyy HH:mm:ss'
const result : string = format(new Date(2017, 0, 25, 21, 28, 15), 'eeee, dd MMMM HH:mm:ss', {locale: eo})
console.log(result === 'merkredo, 25 januaro 21:28:15')
20 changes: 17 additions & 3 deletions examples/lodash-fp/example.js
@@ -1,16 +1,30 @@
import addYears from 'date-fns/fp/addYears'
import formatWithOptions from 'date-fns/fp/formatWithOptions'
import parseISO from 'date-fns/fp/parseISO'
import eo from 'date-fns/locale/eo'

import compose from 'lodash/fp/compose'
import toUpper from 'lodash/fp/toUpper'
import isEqual from 'lodash/isEqual'

const addFiveYears = addYears(5)
const dateToString = formatWithOptions({locale: eo}, 'd MMMM yyyy')
const dateToString = formatWithOptions({ locale: eo }, 'd MMMM yyyy')

const dates = ['2017-01-01', '2017-02-11', '2017-07-02']

const formattedDates = dates.map(compose(toUpper, dateToString, addFiveYears))
const formattedDates = dates.map(
compose(
toUpper,
dateToString,
addFiveYears,
parseISO
)
)

console.log(isEqual(formattedDates, ['1 JANUARO 2022', '11 FEBRUARO 2022', '2 JULIO 2022']))
console.log(
isEqual(formattedDates, [
'1 JANUARO 2022',
'11 FEBRUARO 2022',
'2 JULIO 2022'
])
)
2 changes: 1 addition & 1 deletion examples/rollup/example.js
@@ -1,4 +1,4 @@
import format from 'date-fns/esm/format'

const result = format('2017-01-25T21:28:15.000Z', 'dd.MM.yyyy HH:mm:ss')
const result = format(new Date(2017, 0, 25, 21, 28, 15), 'dd.MM.yyyy HH:mm:ss')
console.log(result === '25.01.2017 21:28:15')
10 changes: 7 additions & 3 deletions examples/rollup/misc.js
@@ -1,5 +1,9 @@
import {format} from 'date-fns/esm'
import {eo} from 'date-fns/esm/locale'
import { format } from 'date-fns/esm'
import { eo } from 'date-fns/esm/locale'

const result = format('2017-01-25T21:28:15.000Z', 'eeee, dd MMMM HH:mm:ss', {locale: eo})
const result = format(
new Date(2017, 0, 25, 21, 28, 15),
'eeee, dd MMMM HH:mm:ss',
{ locale: eo }
)
console.log(result === 'merkredo, 25 januaro 21:28:15')