deseretdigital / dayzed

Primitives to build simple, flexible, WAI-ARIA compliant React date-picker components.
https://dayzed.netlify.app
MIT License
660 stars 27 forks source link

Incorrect handling of years 0000-0099 #51

Open RandScullard opened 2 years ago

RandScullard commented 2 years ago

There are a number of places in utils.js where you call new Date(year, month, day). There is a documented issue with the JavaScript Date constructor where year values from 0-99 are interpreted as a relative offset from the year 1900. See this MDN article:

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date#interpretation_of_two-digit_years

The result is that if we pass a year in this range to useDayzed, the calendar shows (for example) 1999 instead of 0099.

Admittedly, it's pretty unlikely that real users will be working with years in this range - we only ran across the problem because we were testing extreme values. But I thought you should be aware that this issue exists.

ricovitch commented 1 year ago

We are facing this issue and searching for a workaround. A simple workaround with the Date constructor is to do something like this

const date = new Date(year, month, day);
date.setFullYear(year);

Display of years on four digits can also be fixed with leading zero with help of the String.padStart method for example.

ricovitch commented 1 year ago

For anyone facing this issue, it seems the following patch works in my case. Could also be a starting point to propose a PR to dayzed library.

diff --git a/node_modules/dayzed/dist/dayzed.cjs.js b/node_modules/dayzed/dist/dayzed.cjs.js
index 3a4f7cd..e0f5999 100644
--- a/node_modules/dayzed/dist/dayzed.cjs.js
+++ b/node_modules/dayzed/dist/dayzed.cjs.js
@@ -584,6 +584,7 @@ function getMonths(_ref6) {

   for (var day = 1; day <= daysInMonth; day++) {
     var date = new Date(year, month, day);
+    date.setFullYear(year);
     var dateObj = {
       date: date,
       selected: isSelected(selectedDates, date),
@@ -596,7 +597,9 @@ function getMonths(_ref6) {
   }

   var firstDayOfMonth = new Date(year, month, 1);
+  firstDayOfMonth.setFullYear(year);
   var lastDayOfMonth = new Date(year, month, daysInMonth);
+  lastDayOfMonth.setFullYear(year);
   var frontWeekBuffer = fillFrontWeek({
     firstDayOfMonth: firstDayOfMonth,
     minDate: minDate,
@@ -662,6 +665,7 @@ function fillFrontWeek(_ref7) {

     while (counter < firstDay) {
       var date = new Date(prevDateYear, prevDateMonth, prevDate - counter);
+      date.setFullYear(prevDateYear);
       var dateObj = {
         date: date,
         selected: isSelected(selectedDates, date),
@@ -718,6 +722,7 @@ function fillBackWeek(_ref8) {

     while (counter < 6 - lastDay) {
       var date = new Date(nextDateYear, nextDateMonth, 1 + counter);
+      date.setFullYear(nextDateYear);
       var dateObj = {
         date: date,
         selected: isSelected(selectedDates, date),
@@ -757,6 +762,7 @@ function getNumDaysMonthYear(month, year) {
   // Let Date handle the overflow of the month,
   // which should return the normalized month and year.
   var normalizedMonthYear = new Date(year, month, 1);
+  normalizedMonthYear.setFullYear(year);
   month = normalizedMonthYear.getMonth();
   year = normalizedMonthYear.getFullYear(); // Overflow the date to the next month, then subtract the difference
   // to get the number of days in the previous month.
diff --git a/node_modules/dayzed/dist/dayzed.esm.js b/node_modules/dayzed/dist/dayzed.esm.js
index 9e8d156..9aa1ffb 100644
--- a/node_modules/dayzed/dist/dayzed.esm.js
+++ b/node_modules/dayzed/dist/dayzed.esm.js
@@ -565,9 +565,9 @@ function getMonths(_ref6) {
   year = daysMonthYear.year; // Fill out the dates for the month.

   var dates = [];
-
   for (var day = 1; day <= daysInMonth; day++) {
     var date = new Date(year, month, day);
+    date.setFullYear(year);
     var dateObj = {
       date: date,
       selected: isSelected(selectedDates, date),
@@ -580,7 +580,9 @@ function getMonths(_ref6) {
   }

   var firstDayOfMonth = new Date(year, month, 1);
+  firstDayOfMonth.setFullYear(year);
   var lastDayOfMonth = new Date(year, month, daysInMonth);
+  lastDayOfMonth.setFullYear(year);
   var frontWeekBuffer = fillFrontWeek({
     firstDayOfMonth: firstDayOfMonth,
     minDate: minDate,
@@ -646,6 +648,7 @@ function fillFrontWeek(_ref7) {

     while (counter < firstDay) {
       var date = new Date(prevDateYear, prevDateMonth, prevDate - counter);
+      date.setFullYear(prevDateYear);
       var dateObj = {
         date: date,
         selected: isSelected(selectedDates, date),
@@ -702,6 +705,7 @@ function fillBackWeek(_ref8) {

     while (counter < 6 - lastDay) {
       var date = new Date(nextDateYear, nextDateMonth, 1 + counter);
+      date.setFullYear(nextDateYear);
       var dateObj = {
         date: date,
         selected: isSelected(selectedDates, date),
@@ -741,6 +745,7 @@ function getNumDaysMonthYear(month, year) {
   // Let Date handle the overflow of the month,
   // which should return the normalized month and year.
   var normalizedMonthYear = new Date(year, month, 1);
+  normalizedMonthYear.setFullYear(year);
   month = normalizedMonthYear.getMonth();
   year = normalizedMonthYear.getFullYear(); // Overflow the date to the next month, then subtract the difference
   // to get the number of days in the previous month.
AndyOGo commented 1 week ago

Ping @mkartchner994 @arthurdenner

AndyOGo commented 1 week ago

@JustinCarmony