dayjs icon indicating copy to clipboard operation
dayjs copied to clipboard

DayJS parses wrong year value for the date "0001-01-01"

Open matheusot opened this issue 4 years ago • 16 comments

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

matheusot avatar Nov 23 '20 13:11 matheusot

will this is a new concept to me. What's the year '0000' stand for, pls?

iamkun avatar Nov 23 '20 13:11 iamkun

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.

matheusot avatar Nov 23 '20 15:11 matheusot

Oh, I see, because Day.js use new Date(1, 0, 0) to init the date and it results in 1901-1-1

iamkun avatar Nov 24 '20 06:11 iamkun

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)

naulacambra avatar Nov 24 '20 10:11 naulacambra

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 ?

clementoriol avatar Dec 17 '20 22:12 clementoriol

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.

jods4 avatar Jul 12 '21 14:07 jods4

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

jods4 avatar Jul 12 '21 15:07 jods4

Absolutely same thing as described by @clementoriol and @jods4

What about some fixes?

stanf0rd avatar Oct 21 '21 14:10 stanf0rd

Looks like lib is abounded. Author don't want understand that people lived before 1970 as well.

VerVera avatar Oct 21 '21 15:10 VerVera

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.

AHBruns avatar Dec 12 '21 19:12 AHBruns

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.

sylvaindubus avatar Apr 19 '22 17:04 sylvaindubus

@iamkun yo man the solution suggested by @sylvaindubus is the right way to go I think! it does the trick: image

shye0000 avatar Apr 19 '22 17:04 shye0000

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.

shye0000 avatar Apr 19 '22 20:04 shye0000

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.

BePo65 avatar Jun 01 '22 04:06 BePo65

Encountered this issue too. @BePo65 is this PR going to be merged soon?

pazreshef-clear avatar Sep 07 '22 11:09 pazreshef-clear

Good question - depends on the review capacity of @iamkun

BePo65 avatar Sep 07 '22 11:09 BePo65

Seems the author still hasn't fixed this. Any updates?

timmd909 avatar Apr 24 '23 21:04 timmd909

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)

jhsenjaliya avatar Aug 03 '23 02:08 jhsenjaliya