mirror of
https://git.mirrors.martin98.com/https://github.com/SigNoz/signoz
synced 2025-10-12 10:41:31 +08:00

* feat: time picker hint and timezone picker UI with basic functionality + helper to get timezones * feat: add support for esc keypress to close the timezone picker * chore: add the selected timezone as url param and close timezone picker on select * fix: overall improvement + add searchIndex to timezone * feat: timezone preferences UI * chore: improve timezone utils * chore: change timezone item from div to button * feat: display timezone in timepicker input * chore: fix the typo * fix: don't focus on time picker when timezone is clicked * fix: fix the issue of timezone breaking for browser and utc timezones * fix: display the timezone in timepicker hint 'You are at' * feat: timezone basic functionality (#6492) * chore: change div to fragment + change type to any as the ESLint complains otherwise * chore: manage etc timezone filtering with an arg * chore: update timezone wrapper class name * fix: add timezone support to downloaded logs * feat: add current timezone to dashboard list and configure metadata modal * fix: add pencil icon next to timezone hint + change the copy to Current timezone * fix: properly handle the escape button behavior for timezone picker * chore: replace @vvo/tzdb with native Intl API for timezones * feat: lightmode for timezone picker and timezone adaptation components * fix: use normald tz in browser timezone * fix: timezone picker lightmode fixes * feat: display selected time range in 12 hour format * chore: remove unnecessary optional chaining * fix: fix the typo in css variable * chore: add em dash and change icon for timezone hint in date/time picker * chore: move pen line icon to the right of timezone offset * fix: fix the failing tests * feat: handle switching off the timezone adaptation
104 lines
2.8 KiB
TypeScript
104 lines
2.8 KiB
TypeScript
import { Timezone } from 'components/CustomTimePicker/timezoneUtils';
|
|
import dayjs from 'dayjs';
|
|
import timezone from 'dayjs/plugin/timezone';
|
|
import utc from 'dayjs/plugin/utc';
|
|
import { useCallback, useEffect, useMemo } from 'react';
|
|
|
|
// Initialize dayjs plugins
|
|
dayjs.extend(utc);
|
|
dayjs.extend(timezone);
|
|
|
|
// Types
|
|
export type TimestampInput = string | number | Date;
|
|
interface CacheEntry {
|
|
value: string;
|
|
timestamp: number;
|
|
}
|
|
|
|
//
|
|
|
|
// Constants
|
|
const CACHE_SIZE_LIMIT = 1000;
|
|
const CACHE_CLEANUP_PERCENTAGE = 0.5; // Remove 50% when limit is reached
|
|
|
|
function useTimezoneFormatter({
|
|
userTimezone,
|
|
}: {
|
|
userTimezone: Timezone;
|
|
}): {
|
|
formatTimezoneAdjustedTimestamp: (
|
|
input: TimestampInput,
|
|
format?: string,
|
|
) => string;
|
|
} {
|
|
// Initialize cache using useMemo to persist between renders
|
|
const cache = useMemo(() => new Map<string, CacheEntry>(), []);
|
|
|
|
// Clear cache when timezone changes
|
|
useEffect(() => {
|
|
cache.clear();
|
|
}, [cache, userTimezone]);
|
|
|
|
const clearCacheEntries = useCallback(() => {
|
|
if (cache.size <= CACHE_SIZE_LIMIT) return;
|
|
|
|
// Sort entries by timestamp (oldest first)
|
|
const sortedEntries = Array.from(cache.entries()).sort(
|
|
(a, b) => a[1].timestamp - b[1].timestamp,
|
|
);
|
|
|
|
// Calculate how many entries to remove (50% or overflow, whichever is larger)
|
|
const entriesToRemove = Math.max(
|
|
Math.floor(cache.size * CACHE_CLEANUP_PERCENTAGE),
|
|
cache.size - CACHE_SIZE_LIMIT,
|
|
);
|
|
|
|
// Remove oldest entries
|
|
sortedEntries.slice(0, entriesToRemove).forEach(([key]) => cache.delete(key));
|
|
}, [cache]);
|
|
|
|
/**
|
|
* Formats a timestamp with the user's timezone and caches the result
|
|
* @param {TimestampInput} input - The timestamp to format (string, number, or Date)
|
|
* @param {string} [format='YYYY-MM-DD HH:mm:ss'] - The desired output format
|
|
* @returns {string} The formatted timestamp string in the user's timezone
|
|
* @example
|
|
* // Input: UTC timestamp
|
|
* // User timezone: 'UTC - 4'
|
|
* // Returns: "2024-03-14 15:30:00"
|
|
* formatTimezoneAdjustedTimestamp('2024-03-14T19:30:00Z')
|
|
*/
|
|
const formatTimezoneAdjustedTimestamp = useCallback(
|
|
(input: TimestampInput, format = 'YYYY-MM-DD HH:mm:ss'): string => {
|
|
const timestamp = dayjs(input).valueOf();
|
|
const cacheKey = `${timestamp}_${userTimezone.value}`;
|
|
|
|
// Check cache first
|
|
const cachedValue = cache.get(cacheKey);
|
|
if (cachedValue) {
|
|
return cachedValue.value;
|
|
}
|
|
// Format timestamp
|
|
const formattedValue = dayjs(input).tz(userTimezone.value).format(format);
|
|
|
|
// Update cache
|
|
cache.set(cacheKey, {
|
|
value: formattedValue,
|
|
timestamp: Date.now(),
|
|
});
|
|
|
|
// Clear expired entries and enforce size limit
|
|
if (cache.size > CACHE_SIZE_LIMIT) {
|
|
clearCacheEntries();
|
|
}
|
|
|
|
return formattedValue;
|
|
},
|
|
[cache, clearCacheEntries, userTimezone.value],
|
|
);
|
|
|
|
return { formatTimezoneAdjustedTimestamp };
|
|
}
|
|
|
|
export default useTimezoneFormatter;
|