t1m0n / air-datepicker

Lightweight, dependency-free JavaScript datepicker.
https://air-datepicker.com
MIT License
2.58k stars 1.36k forks source link

internal function `createDate(date)` incompatible with rest of library #592

Closed cloudymeatball closed 4 months ago

cloudymeatball commented 4 months ago
// src/utils.js
export function createDate(date) {
    ...
    if (!(date instanceof Date)) {
        resultDate = new Date(date);
    }
    ...
}

Basically, Date(year, month ... ) is interpreted in local time but Date(string) uses the timezone in the string and date strings without time resolves to UTC

This means if the programmer provides a date string without time, such as '2024-02-29', this function will use the UTC midnight, which will lead to problems in various internal date comparisons against other local timestamps, as well populating the datepicker grid itself, especially in min/max mode which uses

_createMinMaxDates() {
      let {minDate, maxDate} = this.opts;

      this.minDate = minDate ? createDate(minDate) : false;
      this.maxDate = maxDate ? createDate(maxDate) : false;
  }

This may be one of the underlying issues in https://github.com/t1m0n/air-datepicker/issues/589, https://github.com/t1m0n/air-datepicker/issues/544, https://github.com/t1m0n/air-datepicker/issues/504, https://github.com/t1m0n/air-datepicker/issues/462, and possibly others. In particular https://github.com/t1m0n/air-datepicker/issues/589 illustrates a divergence between ill- and well-formatted date/time strings as they use different Date() constructors mentioned above.

The best solution probably is to extract year, month ... from date so all internal calls uses new Date(year, month ...) syntax. This enables _createMinMaxDates above to use 00:00:00 for min, and 23:59:59 for max. The other solution is to get the programmer to supply a well-formatted timestamp in the user's timezone. But as a lazy programmer who just want to use a third-party datepicker, I like the first one better.

cloudymeatball commented 4 months ago

In the meantime let date = new Date('2024-02-29'); date.setTime(date.getTime() + date.getTimezoneOffset() * 60 * 1000) will set a Date to midnight local time.

t1m0n commented 4 months ago

fixed in 3.5.0