dayjs
dayjs copied to clipboard
DayJS parses wrong year value for the date "0001-01-01"
Describe the bug When trying to parse the dates "0000-01-01" and "0001-01-01" DayJS returns the years 1900 and 1901 respectively:
const dayjs = require('dayjs')
console.log(dayjs("0001-01-01", "YYYY-MM-DD"))
Output:
d {
'$L': 'en',
'$d': 1901-01-01T03:06:28.000Z,
'$x': {},
'$y': 1901,
'$M': 0,
'$D': 1,
'$W': 2,
'$H': 0,
'$m': 0,
'$s': 0,
'$ms': 0
}
Expected behavior The expected behavior is that the returned object has the correct year. Setting the year manually we can see the correct behavior working:
const dayjs = require('dayjs')
console.log(dayjs("2020-01-01", "YYYY-MM-DD").year(1))
Output:
d {
'$L': 'en',
'$d': 0001-01-01T03:06:28.000Z,
'$x': {},
'$y': 1,
'$M': 0,
'$D': 1,
'$W': 1,
'$H': 0,
'$m': 0,
'$s': 0,
'$ms': 0
}
Information
- Day.js Version v1.9.6
- OS: Windows
- Browser: N/A (Node.js v12.18.3)
- Time zone: GMT-03:00
will this is a new concept to me. What's the year '0000' stand for, pls?
Considering that year 1 is the year that Jesus was born, talking about year 0 does not make any sense as we count years from one and beyond. I tought it wrongly, sorry for that. I corrected the issue and removed anything related to year 0, thanks for pointing it out.
Oh, I see, because Day.js use new Date(1, 0, 0) to init the date and it results in 1901-1-1
This might be useful
Date - Two digit years map to 1900 – 1999
let date = new Date(98, 1) // Sun Feb 01 1998 00:00:00 GMT+0000 (GMT)
// Deprecated method; 98 maps to 1998 here as well
date.setYear(98) // Sun Feb 01 1998 00:00:00 GMT+0000 (GMT)
date.setFullYear(98) // Sat Feb 01 0098 00:00:00 GMT+0000 (BST)
Just had the same issue, it's related to https://github.com/iamkun/dayjs/pull/548.
I actually got a use case for this 😀 . I'm using a native date input and I'm parsing the user input as a Date, for form validation (checking if the date is after year X). When the user starts typing the year, like "01-10-2***", the input value is "0002-01-01". Which dayjs parses to the year 1901. For now I have to manually account for this and monkey-patch it.
Do you thing fixing this could cause issues ? Could someone rely on this behavior ?
I came here for exactly the same reason as @clementoriol .
As you type in a standard <input type="date">
, you'll get through intermediate dates such as 0002-01-01
then 0020-01-01
etc.
Because those dates don't round-trip with Dayjs, it breaks my date input component.
I noticed a related bug that breaks the round-tripping scenario with input
: format('YYYY')
doesn't include 4 digits for dates < 1000 as suggested by the documentation. For example 01/01/0001 is formatted as 1-01-01
Absolutely same thing as described by @clementoriol and @jods4
What about some fixes?
Looks like lib is abounded. Author don't want understand that people lived before 1970 as well.
So, we just can't use this with a regular date input without writing a custom guard?
const date = countLeadingZeroes(dateString.split("-")[2] ?? "0000")) === 0 ? dayjs(dateString) : null
Seems pretty annoying considering the whole point of a date lib is to prevent having to parse and manipulate dates manually. Even more so when this is a problem for anyone who parses a date input's value.
I have the same issue, this lib seems to use the following syntax new Date(1, 0, 0)
instead of new Date('0001-01-01')
which lead to have 1901 instead of 0001. It's annoying when we try to convert a date which the user is currently typing.
@iamkun yo man the solution suggested by @sylvaindubus is the right way to go I think! it does the trick:
This might be useful
Date - Two digit years map to 1900 – 1999
let date = new Date(98, 1) // Sun Feb 01 1998 00:00:00 GMT+0000 (GMT) // Deprecated method; 98 maps to 1998 here as well date.setYear(98) // Sun Feb 01 1998 00:00:00 GMT+0000 (GMT) date.setFullYear(98) // Sat Feb 01 0098 00:00:00 GMT+0000 (BST)
@iamkun yo, just created a PR to fix this issue in which I refactored a bit the parseDate method using the method setFullYear
inspired by @naulacambra
all tests has passed, could you plz review this PR? we really need this fix for our project, thx in advance.
Just to support the arguments given so far:
- for this use case (4 digit year below 100) the behavior of dayjs is different from what moment does (parses year '0001' to '0001')
- using this perhaps not so common years '0001' e.a. for converting user input while user is typing, gives a better need (what you asked for in PR 548)
So IMHO this issue solves not only a deviation from moment, but also a pretty common use case (formatting user input while entering data). 👍
PR #1862 would fix this issue.
Encountered this issue too. @BePo65 is this PR going to be merged soon?
Good question - depends on the review capacity of @iamkun
Seems the author still hasn't fixed this. Any updates?
without the fix, this can get you 0001-01-01T00:00:00.000Z
time
if you dont use utc()
then it will be 0001-01-01T<localTime>.000Z
dayjs().utc().year(1).month(0).date(1).hour(0)
.minute(0)
.second(0).millisecond(0)