temporal-react-hook
Advanced tools
| import { Temporal } from '@js-temporal/polyfill'; | ||
| import React, { useState } from 'react'; | ||
| import useDifference from '../../src/useDifference'; | ||
| import useTemporalDateTime from '../../src/useTemporalDateTime'; | ||
| import './DemoCard.css'; | ||
| const DemoUseDifference: React.FC = () => { | ||
| const currentDateTime = useTemporalDateTime(); | ||
| const [dateLeft, setDateLeft] = useState(currentDateTime); | ||
| const [dateRight, setDateRight] = useState(() => currentDateTime.subtract({ days: 10 })); | ||
| const [unit, setUnit] = useState<"year" | "month" | "week" | "day" | "hour" | "minute" | "second">('day'); | ||
| const difference = useDifference({ | ||
| dateLeft: dateLeft.toZonedDateTime(Temporal.Now.timeZoneId()), | ||
| dateRight: dateRight.toZonedDateTime(Temporal.Now.timeZoneId()), | ||
| unit, | ||
| }); | ||
| const units: ("year" | "month" | "week" | "day" | "hour" | "minute" | "second")[] = ['year', 'month', 'week', 'day', 'hour', 'minute', 'second']; | ||
| return ( | ||
| <section className="demo-card"> | ||
| <h3>useDifference</h3> | ||
| {/* Configuration panel */} | ||
| <div className="demo-config-panel"> | ||
| <div className="demo-config-row"> | ||
| <span>Date Left:</span> | ||
| <input | ||
| type="datetime-local" | ||
| value={dateLeft.toString().slice(0, 16)} | ||
| onChange={e => setDateLeft(useTemporalDateTime(e.target.value))} | ||
| className="demo-input-compact demo-input-margin" | ||
| /> | ||
| </div> | ||
| <div className="demo-config-row"> | ||
| <span>Date Right:</span> | ||
| <input | ||
| type="datetime-local" | ||
| value={dateRight.toString().slice(0, 16)} | ||
| onChange={e => setDateRight(useTemporalDateTime(e.target.value))} | ||
| className="demo-input-compact demo-input-margin" | ||
| /> | ||
| </div> | ||
| <div className="demo-config-row"> | ||
| <span>Unit:</span> | ||
| <select value={unit} onChange={e => setUnit(e.target.value as typeof unit)} className="demo-input-compact demo-input-margin"> | ||
| {units.map(u => ( | ||
| <option key={u} value={u}>{u}</option> | ||
| ))} | ||
| </select> | ||
| </div> | ||
| </div> | ||
| {/* Results display */} | ||
| <div className="demo-config-panel"> | ||
| <div className="demo-config-row"> | ||
| <span>Difference:</span> | ||
| <span className="demo-value">{difference} {unit}(s)</span> | ||
| </div> | ||
| </div> | ||
| {/* Documentation */} | ||
| <div className="demo-info-card"> | ||
| <div className="demo-description"> | ||
| <strong>Description:</strong> | ||
| <span>Calculates the numerical difference between two dates in a specified unit.</span> | ||
| </div> | ||
| <div className="demo-usage"> | ||
| <span> | ||
| <strong>Syntax:</strong> useDifference({ dateLeft, dateRight, unit })<br/> | ||
| <strong>Parameters:</strong><br/> | ||
| - dateLeft: The first date (string or Temporal object)<br/> | ||
| - dateRight: The second date (string or Temporal object)<br/> | ||
| - unit: The unit for the difference ('year', 'month', 'week', 'day', 'hour', 'minute', 'second')<br/> | ||
| <strong>Returns:</strong> A number representing the difference in the specified unit.<br/> | ||
| <strong>Example:</strong> | ||
| <code className="example-code"> | ||
| <pre style={{ margin: 0 }}>{`const differenceInDays = useDifference({ | ||
| dateLeft: '2024-01-01', | ||
| dateRight: '2024-01-11', | ||
| unit: 'day', | ||
| }); // returns: -10`}</pre> | ||
| </code> | ||
| </span> | ||
| </div> | ||
| </div> | ||
| </section> | ||
| ); | ||
| }; | ||
| export default DemoUseDifference; |
| import { Temporal } from '@js-temporal/polyfill'; | ||
| import { useMemo } from 'react'; | ||
| type DateInput = Temporal.ZonedDateTime | string; | ||
| /** | ||
| * The unit to calculate the difference in. | ||
| */ | ||
| type DifferenceUnit = 'year' | 'month' | 'week' | 'day' | 'hour' | 'minute' | 'second' | 'millisecond' | 'microsecond' | 'nanosecond'; | ||
| interface UseDifferenceOptions { | ||
| /** The first date. */ | ||
| dateLeft: DateInput; | ||
| /** The second date, which will be subtracted from the first. */ | ||
| dateRight: DateInput; | ||
| /** The unit to return the difference in. */ | ||
| unit: DifferenceUnit; | ||
| } | ||
| const normalizeDate = (date: DateInput): Temporal.ZonedDateTime => { | ||
| if (date instanceof Temporal.ZonedDateTime) { | ||
| return date; | ||
| } | ||
| try { | ||
| return Temporal.ZonedDateTime.from(date); | ||
| } catch (error) { | ||
| throw new Error(`Invalid date input: ${date}. Please provide a valid ISO 8601 string or a Temporal.ZonedDateTime object.`); | ||
| } | ||
| }; | ||
| /** | ||
| * Calculates the numerical difference between two dates in a specified unit. | ||
| * | ||
| * @param {UseDifferenceOptions} options - The options for the hook. | ||
| * @returns {number} The total difference between the two dates in the specified unit. | ||
| */ | ||
| const useDifference = ({ dateLeft, dateRight, unit }: UseDifferenceOptions): number => { | ||
| const difference = useMemo(() => { | ||
| const zonedDateLeft = normalizeDate(dateLeft); | ||
| const zonedDateRight = normalizeDate(dateRight); | ||
| // Calculate the duration between the two dates. | ||
| // `dateLeft.since(dateRight)` is equivalent to `dateLeft - dateRight`. | ||
| const duration = zonedDateLeft.since(zonedDateRight); | ||
| // Return the total duration in the specified unit. | ||
| return duration.total({ unit }); | ||
| }, [dateLeft, dateRight, unit]); | ||
| return difference; | ||
| }; | ||
| export default useDifference; |
+13
-0
@@ -8,2 +8,15 @@ # Changelog | ||
| ## [2.0.0] - 2025-07-14 | ||
| ### Added | ||
| - `useDifference` hook to calculate the numerical difference between two dates in a specified unit. | ||
| - `DemoUseDifference` component to showcase the new hook. | ||
| ## [1.8.0] - 2025-07-11 | ||
| ### Added | ||
| - `useIsBetween` hook to check if a date falls within a specified date range. | ||
| - `DemoUseIsBetween` component to demonstrate the new hook's functionality with configurable options. | ||
| ## [1.7.1] - 2025-06-17 | ||
@@ -10,0 +23,0 @@ |
| import { Temporal } from '@js-temporal/polyfill'; | ||
| import React, { useState } from 'react'; | ||
| import { useState } from 'react'; | ||
| import useIsBetween from '../../src/useIsBetween'; | ||
@@ -4,0 +4,0 @@ |
@@ -1,2 +0,2 @@ | ||
| import React, { useState, FC, useRef, useEffect } from "react"; | ||
| import { useState, FC, useRef, useEffect } from "react"; | ||
| import DemoUseCurrentDateTime from "./components/DemoUseCurrentDateTime"; | ||
@@ -22,2 +22,3 @@ import DemoUseTimeZone from "./components/DemoUseTimeZone"; | ||
| import DemoUseTemporalDateTime from "./components/DemoUseTemporalDateTime"; | ||
| import DemoUseDifference from "./components/DemoUseDifference"; | ||
@@ -45,2 +46,3 @@ const demoSections = [ | ||
| { key: "calendartime", label: "useCalendarTime", component: <DemoUseCalendarTime /> }, | ||
| { key: "difference", label: "useDifference", component: <DemoUseDifference /> }, | ||
| ]; | ||
@@ -47,0 +49,0 @@ |
+1
-1
| { | ||
| "name": "temporal-react-hook", | ||
| "version": "1.8.0", | ||
| "version": "2.0.0", | ||
| "description": "A React library that provides hooks for handling date and time operations using the Temporal API", | ||
@@ -5,0 +5,0 @@ "main": "index.js", |
+1
-0
@@ -31,2 +31,3 @@ # temporal-react-hook | ||
| | `useIsBetween` | Check if a date falls within a specified date range (e.g., `useIsBetween({ date, startDate, endDate })`) | | ||
| | `useDifference` | Calculate the numerical difference between two dates in a specified unit | | ||
| | `useIsToday` | Check if a date is today | | ||
@@ -33,0 +34,0 @@ | `useIsThisWeek` | Check if a date is in the current week | |
+1
-0
@@ -20,1 +20,2 @@ export { default as useCurrentDateTime } from './useCurrentDateTime'; | ||
| export { default as useTimeZoneOffset } from './useTimeZoneOffset'; | ||
| export { default as useDifference } from './useDifference'; |
398849
1.54%69
2.99%9281
1.43%75
1.35%