DatePicker still parses short dates incorrectly in 24.3.6 if reference date is set

Was excited to see that this bug was fixed, so upgraded and tested it out.
Unfortunately, when I enter “1”, I get “01.03.1984” !

Don’t get me wrong: 1984 was a great year, but it was not what I was expecting…

Looks like it is because I have

DatePickerI18n.setReferenceDate(LocalDate.now().minusYears(40))

(We skew the reference date because we want date of births to be expandable, and we rarely have dates more than 10 years into the future)
Whatever the reference date is, it should only affect the century, not the decade. It is not the default year.

https://github.com/vaadin/platform/issues/5135

1 is not a format that DatePicker supports, though. Supported formats are listed here: https://vaadin.com/docs/latest/components/date-picker#using-custom-date-formats-java-only

The way referenceDate is implemented, is does affect the entire omitted part of the date, so if you leave out the year entirely, it will be exactly the year of the reference date, which in your case is 1984.

The component doesn’t officially support anything not included in that list though, so it might not work as expected even with that logic.

I just picked the shortest example.
1 → 01.03.1984
01 → 01.03.1984
0101 → 01.01.1984

Javadoc:

The reference date is used to determine the century when parsing two-digit years

Aside from that: It has no value otherwise

If you use the reference date as default date, I assume you will get weird edge cases when field is created on one day, and used the next…
So, field is created 31.12.2023 23:00, and used an hour later in 01.01.2024.
1 and 01 → 01.12.2023
0101 → 01.01.2023

The whole point of referenceDate is, as your javadoc says, to be able to decide when xx becomes 19xx and when it becomes 20xx

none of those are supported formats

please read the documentation

How would you expect this to work? Can you give concrete examples of various inputs, formats and refdates?

(Hmm, just realized we’re not nearly clear enough about the fact that date formats without all 3 parts: day month year, are not supported. We should make that more clear in the docs.)

Here is what I’m running with:

datePicker.setI18n
( new DatePickerI18n()

.setDateFormats(“dd.MM.yyyy”, “dd”, “ddMM”, “ddMMyy”, “ddMMyyyy”, “yyyy-MM-dd”, “MM/dd/yyyy”)
.setReferenceDate(LocalDate.now().minusYears(40))
);

There are two parts here:

  • For current dates it is very annoying to force users to write the year every time. Of course they mean the current year, so of course they should be able to refer to today as “0603”
  • For dates outside this year, it is very annoying to force the users to write the century. Of course “010120” means “01.01.2020”, and of course “010190” means 01.01.1990

Out of the box, both of these work.
However, when entering date of birth, it makes sense that “010168” is 01.01.1968 not 01.01.2068, while for other use-cases 2068 might be the desired expansion.
This is why you have reference date. Before 24.3.0 I believe all of his worked, so that I could get “010168” to expand to 01.01.1968

We discussed first part back in 2021, when we wanted access to “invalid dates” on the server-side, so that we could do this ourselves.
You suggested that Vaadin should expand the DatePicker to do it on the client-side instead:

Ok so those general parsing and formatting needs would indeed be solved by the feature we’re currently planning:
The idea is to use date-fns for parsing and formatting, and you would be able to provide multiple parsing formats,
so configuring the datepicker with setParsers(“d”, “dd”, “ddMM”, “ddMMyy”, “ddMMyyyy”); and setFormat(“dd.MM.yyyy”); would give you exactly that.

Can’t remember if we also discussed reference date, but imho, it doesn’t make sense any other way than I describe.

User input:
image.png

Without reference date:
image.png

With reference date LocalDate.now().minusYears(40):
image.png

But, that screws up the places where I want to enter ddMM:
image.png

becomes
image.png

https://github.com/vaadin/flow-components/issues/2466 here is a issue to upvote - it has to be customizable on the server. It’s impossible to let the Framework do all that logic, which differs from requirement to requirement.

So, are you using the same refDate both in datepickers where you want the -40y logic, and the ones where you don’t want that? Because you can set different refDates on those fields. (I’m assuming you don’t need both in the same field)

Well, as I see it, the referenceDate is only to decide the century when you have provided a 2-digit year, as the javadoc states:

The reference date is used to determine the century when parsing two-digit years.
The century that makes the date closest to the reference date is applied.
The default value is the current date. Example: for a reference date of 1970-10-30; years {10, 40, 80} become {2010, 1940, 1980}.

When you don’t provide a year (or month) at all, it should be defaulted from todays date. Reference date should never be used for this.

I can think of no case where it makes sense for “0603” to be expanded to “06.03.1984”, and as far as I know, it didn’t either, before 24.3.0
If there are any cases where you’d want to define where to take default month/year from, it should be separate from referenceDate.

I could conceivably set referenceDate only for date of birth fields, where I expect the users to write ddMMyy, and set nothing for fields where I expect the user to write ddMM.
That would work for me, but it would still not be logical.

Say I expect the user to write both ddMM and ddMMyy.
For ddMM we want this year.
For ddMMyy we want it to always be this century. Ie 90 should be 2090
How do I achieve that?

For the first part to work, I can not set referenceDate.
For the second part to work, I must set referenceDate.

( Btw: Not directly related, but with DateTimePicker it is useful to have a “default date” other than today. Can’t remember if it has anything like that, but we wrote our own. There, when the user enters only a time, we can fill the date from a predefined value )