Repository: Hacker0x01/react-datepicker
Pull request #4683 (2024-04-12 15:52:09)

Add support second-level granularity to injectTimes 
## Description
**Linked issue**: None 

**Problem**
seconds from Datetime objects passed into injectTime setting is currently ignored by the date picker

**Changes**
added support for seconds, changed doc-site example to reflect it, and added 1 test as well.

also corrected `timeIntervals` to `intervals` on existing tests found in `inject_times_test.test.js` to account for the fact that `timeIntervals` does not exist as a parameter, and the correct one  should be `intervals` instead

## Contribution checklist
- [x] I have followed the [contributing guidelines](https://github.com/Hacker0x01/react-datepicker/blob/main/CONTRIBUTING.md).
- [x] I have added sufficient test coverage for my changes.
- [x] I have formatted my code with Prettier and checked for linting issues with ESLint for code readability.



Patch:
diff --git a/docs-site/src/examples/.eslintrc b/docs-site/src/examples/.eslintrc
index ccd81185..ec2c3dcb 100644
--- a/docs-site/src/examples/.eslintrc
+++ b/docs-site/src/examples/.eslintrc
@@ -15,6 +15,7 @@
         "DatePicker": false,
         "getHours": false,
         "setHours": false,
+        "setSeconds": false,
         "setMinutes": false,
         "getDate": false,
         "addDays": false,
diff --git a/docs-site/src/examples/injectTimes.js b/docs-site/src/examples/injectTimes.js
index a5ce1e31..eb83aff1 100644
--- a/docs-site/src/examples/injectTimes.js
+++ b/docs-site/src/examples/injectTimes.js
@@ -7,9 +7,9 @@
       selected={startDate}
       onChange={(date) => setStartDate(date)}
       showTimeSelect
-      timeFormat="HH:mm"
+      timeFormat="HH:mm:ss"
       injectTimes={[
-        setHours(setMinutes(new Date(), 1), 0),
+        setHours(setMinutes(setSeconds(new Date(), 10), 1), 0),
         setHours(setMinutes(new Date(), 5), 12),
         setHours(setMinutes(new Date(), 59), 23),
       ]}
diff --git a/src/date_utils.js b/src/date_utils.js
index 8f6adce4..5f094009 100644
--- a/src/date_utils.js
+++ b/src/date_utils.js
@@ -55,6 +55,7 @@ import { isWithinInterval } from "date-fns/isWithinInterval";
 import { toDate } from "date-fns/toDate";
 import { parse } from "date-fns/parse";
 import { parseISO } from "date-fns/parseISO";
+import { addSeconds } from "date-fns";
 
 export const DEFAULT_YEAR_ITEM_NUMBER = 12;
 
@@ -295,7 +296,15 @@ export function getEndOfMonth(date) {
 
 // *** Addition ***
 
-export { addMinutes, addDays, addWeeks, addMonths, addQuarters, addYears };
+export {
+  addSeconds,
+  addMinutes,
+  addDays,
+  addWeeks,
+  addMonths,
+  addQuarters,
+  addYears,
+};
 
 // *** Subtraction ***
 
@@ -850,10 +859,11 @@ export function timesToInjectAfter(
   const l = injectedTimes.length;
   const times = [];
   for (let i = 0; i < l; i++) {
-    const injectedTime = addMinutes(
-      addHours(startOfDay, getHours(injectedTimes[i])),
-      getMinutes(injectedTimes[i]),
-    );
+    let injectedTime = startOfDay;
+    injectedTime = addHours(injectedTime, getHours(injectedTimes[i]));
+    injectedTime = addMinutes(injectedTime, getMinutes(injectedTimes[i]));
+    injectedTime = addSeconds(injectedTime, getSeconds(injectedTimes[i]));
+
     const nextTime = addMinutes(
       startOfDay,
       (currentMultiplier + 1) * intervals,
diff --git a/src/time.jsx b/src/time.jsx
index 4295abaa..62c2e716 100644
--- a/src/time.jsx
+++ b/src/time.jsx
@@ -13,6 +13,7 @@ import {
   getHoursInDay,
   isSameMinute,
 } from "./date_utils";
+import { getSeconds } from "date-fns";
 
 export default class Time extends React.Component {
   static get defaultProps() {
@@ -121,9 +122,13 @@ export default class Time extends React.Component {
     if (this.isDisabledTime(time)) {
       classes.push("react-datepicker__time-list-item--disabled");
     }
+
+    //convert this.props.intervals and the relevant time to seconds and check if it it's a clean multiple of the interval
     if (
       this.props.injectTimes &&
-      (getHours(time) * 60 + getMinutes(time)) % this.props.intervals !== 0
+      (getHours(time) * 3600 + getMinutes(time) * 60 + getSeconds(time)) %
+        (this.props.intervals * 60) !==
+        0
     ) {
       classes.push("react-datepicker__time-list-item--injected");
     }


Test patch:
diff --git a/test/inject_times_test.test.js b/test/inject_times_test.test.js
index 13af9352..59a2dd7d 100644
--- a/test/inject_times_test.test.js
+++ b/test/inject_times_test.test.js
@@ -26,7 +26,7 @@ describe("TimeComponent", () => {
     const today = utils.getStartOfDay(utils.newDate());
     const { container } = render(
       <TimeComponent
-        timeIntervals={60}
+        intervals={60}
         injectTimes={[
           utils.addMinutes(today, 0),
           utils.addMinutes(today, 60),
@@ -45,7 +45,7 @@ describe("TimeComponent", () => {
     const today = utils.getStartOfDay(utils.newDate());
     const { container } = render(
       <TimeComponent
-        timeIntervals={60}
+        intervals={60}
         injectTimes={[
           utils.addMinutes(today, 1),
           utils.addMinutes(today, 2),
@@ -62,9 +62,10 @@ describe("TimeComponent", () => {
 
   it("should sort injected times automatically", () => {
     const today = utils.getStartOfDay(utils.newDate());
+
     const { container } = render(
       <TimeComponent
-        timeIntervals={60}
+        intervals={60}
         injectTimes={[
           utils.addMinutes(today, 3),
           utils.addMinutes(today, 1),
@@ -82,4 +83,30 @@ describe("TimeComponent", () => {
       "12:03 AM",
     ]);
   });
+
+  it("should support hours, minutes, and seconds", () => {
+    const today = utils.getStartOfDay(utils.newDate());
+
+    const { container } = render(
+      <TimeComponent
+        format="HH:mm:ss"
+        intervals={60}
+        injectTimes={[
+          utils.addSeconds(today, 1),
+          utils.addMinutes(utils.addSeconds(today, 1), 30),
+          utils.addHours(utils.addMinutes(utils.addSeconds(today, 1), 30), 1),
+        ]}
+      />,
+    );
+
+    const injectedItems = container.querySelectorAll(
+      ".react-datepicker__time-list-item--injected",
+    );
+
+    expect(Array.from(injectedItems).map((node) => node.textContent)).toEqual([
+      "00:00:01",
+      "00:30:01",
+      "01:30:01",
+    ]);
+  });
 });