🚀 Socket Launch Week Day 5:Introducing Repository Access Permissions and Custom Roles.Learn more
Sign In

temporal-react-hook

Package Overview
Dependencies
Maintainers
1
Versions
39
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

temporal-react-hook - npm Package Compare versions

Comparing version
1.7.0
to
1.7.1
+119
demo/components/DemoUseTimeZoneOffset.tsx
import { useState } from 'react';
import './DemoCard.css';
import useTimeZoneOffset from '../../src/useTimeZoneOffset';
const COMMON_ZONES = [
'UTC',
'America/New_York',
'America/Los_Angeles',
'Europe/London',
'Europe/Berlin',
'Europe/Paris',
'Asia/Tokyo',
'Asia/Singapore',
'Australia/Sydney',
];
export default function DemoUseTimeZoneOffset() {
const [zone, setZone] = useState<string>('UTC');
const [customZone, setCustomZone] = useState<string>('');
const [asMinutes, setAsMinutes] = useState<boolean>(false);
const offset = useTimeZoneOffset(zone, { asMinutes });
const applyCustomZone = () => {
const trimmed = customZone.trim();
if (trimmed) {
setZone(trimmed);
setCustomZone('');
}
};
return (
<section className="demo-card">
<h3>useTimeZoneOffset</h3>
<div className="demo-config-panel">
<div className="demo-config-row">
<label style={{ marginRight: 8 }}>Time Zone:</label>
<select
className="demo-select"
value={COMMON_ZONES.includes(zone) ? zone : 'custom'}
onChange={(e) => {
const val = e.target.value;
if (val !== 'custom') setZone(val);
}}
>
{COMMON_ZONES.map((z) => (
<option key={z} value={z}>{z}</option>
))}
<option value="custom">Custom…</option>
</select>
</div>
{(!COMMON_ZONES.includes(zone) || customZone) && (
<div className="demo-config-row">
<input
type="text"
value={customZone}
onChange={(e) => setCustomZone(e.target.value)}
placeholder="Enter IANA time-zone"
className="demo-input"
style={{ flex: 1, marginRight: 8 }}
/>
<button className="demo-button" onClick={applyCustomZone}>Apply</button>
</div>
)}
<div className="demo-config-row">
<label>
<input
type="checkbox"
checked={asMinutes}
onChange={(e) => setAsMinutes(e.target.checked)}
/>{' '}
Return as minutes
</label>
</div>
</div>
<div className="demo-output-panel">
<div className="demo-config-row">
<b>Current Offset:</b>&nbsp;
<span>{offset.toString()}</span>
</div>
</div>
<div className="demo-info-card">
<div className="demo-description">
<strong>Description:</strong>
<span>
Returns the current UTC offset for a given IANA time-zone and updates automatically on DST transitions.
</span>
</div>
<div className="demo-usage">
<span>
<strong>Syntax:</strong> useTimeZoneOffset(zone?, options?)<br/>
<strong>Parameters:</strong><br/>
– zone: string | Temporal.TimeZoneLike — IANA zone, default system<br/>
– options: {'{'} asMinutes?: boolean; updateOnTick?: number {'}'}<br/>
<strong>Returns:</strong> string | number — formatted offset (e.g. "UTC+02:00") or minutes east of UTC<br/>
<strong>Example:</strong>
<code className="example-code">
<pre style={{margin: 0}}>{`import { useTimeZoneOffset } from 'temporal-react-hook';
// London offset as formatted string
const offsetStr = useTimeZoneOffset('Europe/London');
// New York offset as minutes (negative west of UTC)
const nyMinutes = useTimeZoneOffset('America/New_York', { asMinutes: true });
console.log(offsetStr); // "UTC+01:00"
console.log(nyMinutes); // -300
`}</pre>
</code>
</span>
</div>
</div>
</section>
);
}
import { useState, useEffect, useCallback } from 'react';
import { Temporal } from '@js-temporal/polyfill';
export interface TimeZoneOffsetOptions {
/**
* If true, the hook returns the offset as a signed number of minutes.
* If false (default), it returns a formatted string such as "UTC+04:00".
*/
asMinutes?: boolean;
/**
* Interval, in milliseconds, at which to re-evaluate the offset.
* Defaults to 60 000 ms (one minute) which is ample to capture DST jumps.
*/
updateOnTick?: number;
}
/**
* React hook that returns the current UTC offset for a given IANA time-zone and
* keeps it up-to-date as Daylight Saving Time transitions occur.
*
* @param zone IANA time-zone identifier. Defaults to the system zone.
* @param opts Behavioural options – see {@link TimeZoneOffsetOptions}.
* @returns Either a formatted offset string (e.g. "UTC+02:00") or a signed
* number of minutes east of UTC, depending on `opts.asMinutes`.
*/
export default function useTimeZoneOffset(
zone: string | Temporal.TimeZoneLike | undefined = Temporal.Now.timeZoneId(),
opts: TimeZoneOffsetOptions = {}
): string | number {
const { asMinutes = false, updateOnTick = 60_000 } = opts;
const calcOffset = useCallback(() => {
const zdt = Temporal.Now.zonedDateTimeISO(zone as any);
const minutes = zdt.offsetNanoseconds / 60_000_000_000;
return asMinutes ? minutes : formatOffset(minutes);
}, [zone, asMinutes]);
const [offset, setOffset] = useState<string | number>(() => calcOffset());
useEffect(() => {
setOffset(calcOffset()); // sync immediately when deps change
const id = window.setInterval(() => setOffset(calcOffset()), updateOnTick);
return () => window.clearInterval(id);
}, [calcOffset, updateOnTick]);
return offset;
}
function formatOffset(totalMinutes: number): string {
const sign = totalMinutes >= 0 ? '+' : '−'; // U+2212 minus sign for aesthetics
const abs = Math.abs(totalMinutes);
const hours = Math.floor(abs / 60)
.toString()
.padStart(2, '0');
const minutes = (abs % 60).toString().padStart(2, '0');
return `UTC${sign}${hours}:${minutes}`;
}
+19
-0

@@ -8,2 +8,21 @@ # Changelog

## [1.7.1] - 2025-06-17
### Added
- `useTimeZoneOffset` hook for retrieving the current UTC offset of any IANA time-zone with automatic updates on DST transitions.
- `DemoUseTimeZoneOffset` component demonstrating the hook with common and custom zones, string/minutes output, and info card documentation.
## [1.7.0] - 2025-06-16
### Added
- `useDateTimeRange` hook and `DemoUseDateTimeRange` component::
- Manages a range of `Temporal.PlainDateTime` values with guaranteed `start <= end` ordering.
- Options to clamp the end date to the current time (`clampToNow`).
- Option to specify `smallestUnit` ('day', 'hour', 'minute', 'second') for `length` calculation and `toArray` enumeration.
- Provides `setStart`, `setEnd` setters.
- Includes `shiftBy(duration)` method to move the entire range.
- Exposes `length` (number of `smallestUnit`s in range, inclusive).
- Exposes `contains(dateTime)` method to check if a `Temporal.PlainDateTime` is within the range.
- Exposes `toArray()` method to enumerate all `Temporal.PlainDateTime` instances in the range by the `smallestUnit`.
## [1.6.15] - 2025-06-11

@@ -10,0 +29,0 @@

+2
-0
import { useState, FC, useRef, useEffect } from "react";
import DemoUseCurrentDateTime from "./components/DemoUseCurrentDateTime";
import DemoUseTimeZone from "./components/DemoUseTimeZone";
import DemoUseTimeZoneOffset from "./components/DemoUseTimeZoneOffset";
import DemoUseDuration from "./components/DemoUseDuration";

@@ -25,2 +26,3 @@ import DemoUseRelativeTime from "./components/DemoUseRelativeTime";

{ key: "timezone", label: "useTimeZone", component: <DemoUseTimeZone /> },
{ key: "timezoneoffset", label: "useTimeZoneOffset", component: <DemoUseTimeZoneOffset /> },
{ key: "duration", label: "useDuration", component: <DemoUseDuration /> },

@@ -27,0 +29,0 @@ { key: "relativetime", label: "useRelativeTime", component: <DemoUseRelativeTime /> },

+1
-1
{
"name": "temporal-react-hook",
"version": "1.7.0",
"version": "1.7.1",
"description": "A React library that provides hooks for handling date and time operations using the Temporal API",

@@ -5,0 +5,0 @@ "main": "index.js",

@@ -5,3 +5,3 @@ # temporal-react-hook

## 🖥️ [Live Demo](https://vlad-grigoryan.github.io/temporal-react-hook/)
## [Live Demo](https://vlad-grigoryan.github.io/temporal-react-hook/)

@@ -40,2 +40,4 @@ ## Installation

| `useTemporalEndOf` | Get the end of a time unit (day, week, month, etc.) |
| `useTimeZoneOffset` | Get the current UTC offset for a time zone, auto-updates on DST |
| `useDateTimeRange` | Manage a date-time range with ordering, clamping, and helper functions |

@@ -42,0 +44,0 @@ ## Running the Demo Locally

@@ -18,1 +18,2 @@ export { default as useCurrentDateTime } from './useCurrentDateTime';

export { default as useDateTimeRange } from './useDateTimeRange';
export { default as useTimeZoneOffset } from './useTimeZoneOffset';