dayjs
dayjs copied to clipboard
Default year should be the current year instead of 2001
Describe the bug
If we parse the date "12/30" (e.g. dayjs("12/30")), dayjs uses 2001 as the default year:
dayjs("12/30").format() //Yields "2001-12-30T00:00:00-07:00"
Expected behavior The most logical and useful behavior is for dayjs to use the current year as the default year.
-
It's natural and human-like. When humans write dates, if they omit the year, it's implied that the date applies to the current year. No human would think, "I'm writing a date in 2001, so I can omit the year". The notion that year-less dates should default to the "first" year (2001, strangely) is a computer-centric approach.
-
It's awkward to implement otherwise. If datejs defaults the year to 2001 (instead of the current year), we may be inclined to do something like the following to change all dates from 2001 to the current year:
let s = "12/30";
let d = dayjs(s);
if(d.year() === 2001) {
d = d.year(dayjs().year());
}
d.format(); //Yields "2020-12-30T00:00:00-07:00"
The huge flaw in this approach is that we've now lost the ability to parse legitimate dates from 2001. They will be automatically "converted" to their 2020 equivalent.
Another approach is to process the original string, detecting if a year is present, and appending the current year if one isn't present yet. However, with so many different formats, that's a tough bit of code to implement with lots of edge cases. This wouldn't be a show-stopper except for the fact that the whole point of using a library like dayjs is to simplify this kind of date parsing.
- It looks like Moment.js may already have this feature.
Information
- Day.js Version 1.9.6
- OS: macOS
- Browser: Node 14.1.0
- Time zone: GMT-7
Hi, there's nothing right or wrong of returning 2001 or 2020. All dayjs could do is to guess. And new Date('12/03') also returns 2001
So consistent results parsing anything other than ISO 8601 strings, you should use String + Format.
https://day.js.org/docs/en/parse/string-format
import dayjs from 'dayjs'
import customParseFormat from 'dayjs/plugin/customParseFormat'
dayjs.extend(customParseFormat)
console.log(dayjs('12/30', 'MM/DD').format());
Hi, @iamkun! Thank you for your response! Clearly, you are much more credentialed and qualified to comment on this issue than I am. However, I'm not sure I entirely agree that all dayjs can do is to guess. In my Issue submission, I tried to provide clear examples why using the current year (2020) is better than another, fixed year (2001).
In my particular use case, I can be confident that all 2001 dates should be transformed into their 2020 equivalents. So, I'm not concerned for my own application. However, I do believe it's in the best interest of the dayjs library and its users to use the "current year" as the default.
Do you have specific pushback on the three points I mentioned above?
Ultimately, my opinion might be changed if someone could provide an alternative to the code provided in point 2 above that doesn't prevent legitimate dates from 2001 from being used.
Thank you!
It might be better to keep the same behavior with JS Date object, and resulting in the same result as new Date('12/03')
@iamkun I came looking for an answer to the same issue as @rinogo
date-fns allows you to specify a reference date param: https://date-fns.org/v2.21.3/docs/parse
chrono-node defaults to current year

luxon defaults to current year
The reference date is prob the best path as explicit.
That would be a good solution! The "reference date" could default to 2001 if @iamkun still feels that that is the best year, but it could be overridden in instances in which a different "reference date" was desired.
I have the same issue. Posting my dummy workaround here:
function fixDayjs(input: string): Dayjs | undefined {
const date = dayjs(input)
if (date.isValid()) {
// https://github.com/iamkun/dayjs/issues/1902
// https://github.com/iamkun/dayjs/issues/1251
if (date.year() === 2001 && !input.split(' ').includes('2001')) {
return date.set('year', dayjs().year())
}
return date
}
return undefined
}
i have got this example too for my cypress test const mydate = Cypress.dayjs('07 / 12') cy.get('.dateOptions').contains('July 2017').click() cy.get('.display').should('contain', mydate.format('DD/MM/YYYY')) Instead of displaying the date 12/07/2017 it is showing 12/07/2001 in the runner.
You guys might find this explanation interesting. Day.js behaves in the same way as this explanation.
Let me leave this link: https://stackoverflow.com/a/65658435/4771623