Search code examples
javascriptsapui5ui5-webcomponents

UI5 - DateTimePicker - minDate can be undershot and overwritten at the same time


I am currently using a sap.m.DateTimePicker in one of my projects. Since I want to limit the input time range, I use the properties minDate and maxDate.

My UI5 version is 1.71 (yes I know, not very up-to-date).

Now to my error: If the sap.m.DateTimePicker is opened for the first time and I change the preselected time but NOT the preselected date, it is possible to go below the minDate after confirming the selection. I have also noticed that this also overwrites the minDate, i.e. the invalid value also becomes the new minDate.

Here is an example:

minDate: 2024/09/11 16:00:00 / maxDate: 2024/09/12 16:00:00

  1. I open the calendar of the sap.m.DateTimePicker to select a date
  2. The 2024/09/11 16:00:00 is preselected
  3. I select a time (14:00:00), but keep the date
  4. I confirm my selection, which closes the calendar
  5. The 2024/09/11 14:00:00 is displayed in the input field

However, the 2024/09/11 16:00:00 should be displayed.

This is probably caused by the following standard method in sap.m.DateTimePicker:

 DateTimePicker.prototype._fillDateRange = function() {
  var oDate = this.getDateValue();

  if (oDate) {
    oDate = new Date(oDate.getTime());
  } else {
    oDate = this._getInitialFocusedDateValue();
    var iMaxTimeMillis = this._oMaxDate.getTime();

    if (oDate.getTime() < this._oMinDate.getTime() || oDate.getTime() > iMaxTimeMillis) {
      oDate = this._oMinDate; // this line :)
    }
  }

  this._oCalendar.focusDate(oDate);
  if (!this._oDateRange.getStartDate() || this._oDateRange.getStartDate().getTime() != oDate.getTime()) {
    this._oDateRange.setStartDate(oDate);
  }

  this._oSliders._setTimeValues(oDate);

};

Here the date gets initialised with the minDate, but in JS this means that it is not a copy, but both refer to the same object. The effect of this is that when the date gets confirmed, the minDate will also be changed. I was able to solve the whole thing as follows:

DateTimePicker.prototype._fillDateRange = function() {
  var oDate = this.getDateValue();

  if (oDate) {
    oDate = new Date(oDate.getTime());
  } else {
    oDate = this._getInitialFocusedDateValue();

    // copy the min or max date, but do not refer to the same object
    if (oDate.getTime() < this._oMinDate.getTime()) {
      oDate = new Date(this._oMinDate.getTime());
    } else if (oDate.getTime() > this._oMaxDate.getTime()) {
      oDate = new Date(this._oMaxDate.getTime());
    }
  }

  this._oCalendar.focusDate(oDate);
  if (!this._oDateRange.getStartDate() || this._oDateRange.getStartDate().getTime() != oDate.getTime()) {
    this._oDateRange.setStartDate(oDate);
  }

  this._oSliders._setTimeValues(oDate);

};

Are you aware of this error? Or am I using the sap.m.DateTimePicker incorrectly?

In the current SAPUI5 version, the error still exists ( in my understanding):

DateTimePicker.prototype._fillDateRange = function() {

  var oDate = this.getDateValue(),
    bDateFound = true,
    sFormattedDate;

  if (oDate) {
    oDate = UI5Date.getInstance(oDate.getTime());
    this._oOKButton.setEnabled(true);
  } else {
    bDateFound = false;
    oDate = this.getInitialFocusedDateValue();
    if (!oDate) {
      oDate = UI5Date.getInstance();
      this._oCalendar.removeAllSelectedDates();
    }
    this._oOKButton.setEnabled(false);
  }

  if (oDate.getTime() < this._oMinDate.getTime()) {
    oDate = this._oMinDate;
  } else if (oDate.getTime() > this._oMaxDate.getTime()) {
    oDate = this._oMaxDate;
  }

  // convert the date to local date for the calendar and the clocks if binding is used
  if (this._isTimezoneBinding()) {
    sFormattedDate = this._getPickerParser().format(oDate, this._getTimezone(true));
    oDate = this._getPickerParser().parse(sFormattedDate)[0];
  }
  this._oCalendar.focusDate(oDate);

  if (bDateFound) {
    if (!this._oDateRange.getStartDate() || this._oDateRange.getStartDate().getTime() != oDate.getTime()) {
      this._oDateRange.setStartDate(oDate);
    }
  }

  this._oClocks._setTimeValues(oDate);
};

Solution

  • I can reproduce the issue only in 1.71 where it's still possible to confirm the time change without even selecting date initially. Since change Ic3c736537e4efaeab3019659aaf6dca092fb8b2d (1.80), the OK button of the DT picker is simply disabled until the date is selected, preventing the issue to occur.

    You can request a downport of the above change to 1.71 in github.com/SAP/openui5/issues/new.