Localization: New date formatting (#6780)

This commit is contained in:
zubiden 2026-03-31 11:28:55 +02:00 committed by Alexander Zinchuk
parent 88b6d3a6d7
commit cdebd3b479
109 changed files with 869 additions and 119 deletions

View File

@ -24,13 +24,13 @@ import usePrevious from '../hooks/usePrevious';
import { useSignalEffect } from '../hooks/useSignalEffect';
import { getIsInBackground } from '../hooks/window/useBackgroundMode';
// import Test from './test/TestCleanupOrder';
import Auth from './auth/Auth';
import Notifications from './common/Notifications';
import UiLoader from './common/UiLoader';
import AppInactive from './main/AppInactive';
import LockScreen from './main/LockScreen.async';
import Main from './main/Main.async';
// import Test from './test/TestDateFormat';
import Transition from './ui/Transition';
import styles from './App.module.scss';

View File

@ -18,7 +18,7 @@ import {
IS_REQUEST_FULLSCREEN_SUPPORTED,
} from '../../../util/browser/windowEnvironment';
import buildClassName from '../../../util/buildClassName';
import { formatMediaDuration } from '../../../util/dates/dateFormat';
import { formatMediaDuration } from '../../../util/dates/oldDateFormat';
import { getServerTime } from '../../../util/serverTime';
import { LOCAL_TGS_URLS } from '../../common/helpers/animatedAssets';
import renderText from '../../common/helpers/renderText';

View File

@ -29,7 +29,7 @@ import { selectMessageMediaDuration } from '../../global/selectors/media';
import { makeTrackId } from '../../util/audioPlayer';
import buildClassName from '../../util/buildClassName';
import { captureEvents } from '../../util/captureEvents';
import { formatMediaDateTime, formatMediaDuration, formatPastTimeShort } from '../../util/dates/dateFormat';
import { formatMediaDateTime, formatMediaDuration, formatPastTimeShort } from '../../util/dates/oldDateFormat';
import { decodeWaveform, interpolateArray } from '../../util/waveform';
import { LOCAL_TGS_URLS } from './helpers/animatedAssets';
import renderText from './helpers/renderText';

View File

@ -11,7 +11,7 @@ import type { RepeatedMessageMode } from '../../util/scheduledMessages';
import { MAX_INT_32 } from '../../config';
import { selectIsCurrentUserPremium } from '../../global/selectors';
import buildClassName from '../../util/buildClassName';
import { formatDateToString, formatTime, getDayStart } from '../../util/dates/dateFormat';
import { formatDateToString, formatTime, getDayStart } from '../../util/dates/oldDateFormat';
import { ALL_REPEAT_MODES, getScheduleRepeatModeText, TEST_SERVER_ONLY_MODES } from '../../util/scheduledMessages';
import useContextMenuHandlers from '../../hooks/useContextMenuHandlers';

View File

@ -115,7 +115,7 @@ import {
} from '../../global/selectors/threads';
import { IS_IOS, IS_VOICE_RECORDING_SUPPORTED } from '../../util/browser/windowEnvironment';
import buildClassName from '../../util/buildClassName';
import { formatMediaDuration, formatVoiceRecordDuration } from '../../util/dates/dateFormat';
import { formatMediaDuration, formatVoiceRecordDuration } from '../../util/dates/oldDateFormat';
import { processDeepLink } from '../../util/deeplink';
import { tryParseDeepLink } from '../../util/deepLinkParser';
import deleteLastCharacterOutsideSelection from '../../util/deleteLastCharacterOutsideSelection';

View File

@ -7,7 +7,7 @@ import type { IconName } from '../../types/icons';
import { IS_CANVAS_FILTER_SUPPORTED } from '../../util/browser/windowEnvironment';
import buildClassName from '../../util/buildClassName';
import { formatMediaDateTime, formatPastTimeShort } from '../../util/dates/dateFormat';
import { formatMediaDateTime, formatPastTimeShort } from '../../util/dates/oldDateFormat';
import { getColorFromExtension } from './helpers/documentInfo';
import { getDocumentThumbnailDimensions } from './helpers/mediaDimensions';
import renderText from './helpers/renderText';

View File

@ -3,7 +3,7 @@ import { memo } from '../../lib/teact/teact';
import type { ApiMessage, ApiMessageOutgoingStatus } from '../../api/types';
import buildClassName from '../../util/buildClassName';
import { formatPastTimeShort } from '../../util/dates/dateFormat';
import { formatPastTimeShort } from '../../util/dates/oldDateFormat';
import useOldLang from '../../hooks/useOldLang';

View File

@ -11,7 +11,7 @@ import {
} from '../../global/helpers';
import { IS_TOUCH_ENV } from '../../util/browser/windowEnvironment';
import buildClassName from '../../util/buildClassName';
import { formatMediaDuration } from '../../util/dates/dateFormat';
import { formatMediaDuration } from '../../util/dates/oldDateFormat';
import stopEvent from '../../util/stopEvent';
import useMessageMediaHash from '../../hooks/media/useMessageMediaHash';

View File

@ -5,7 +5,7 @@ import type { ApiBotPreviewMedia } from '../../api/types';
import type { ObserveFn } from '../../hooks/useIntersectionObserver';
import buildClassName from '../../util/buildClassName';
import { formatMediaDuration } from '../../util/dates/dateFormat';
import { formatMediaDuration } from '../../util/dates/oldDateFormat';
import stopEvent from '../../util/stopEvent';
import useMessageMediaHash from '../../hooks/media/useMessageMediaHash';

View File

@ -3,7 +3,7 @@ import { getActions, withGlobal } from '../../global';
import { selectChatMessage, selectTabState } from '../../global/selectors';
import buildClassName from '../../util/buildClassName';
import { formatDateAtTime } from '../../util/dates/dateFormat';
import { formatDateAtTime } from '../../util/dates/oldDateFormat';
import useCurrentOrPrev from '../../hooks/useCurrentOrPrev';
import useLastCallback from '../../hooks/useLastCallback';

View File

@ -11,7 +11,7 @@ import {
} from '../../global/helpers';
import { selectWebPageFromMessage } from '../../global/selectors';
import buildClassName from '../../util/buildClassName';
import { formatPastTimeShort } from '../../util/dates/dateFormat';
import { formatPastTimeShort } from '../../util/dates/oldDateFormat';
import trimText from '../../util/trimText';
import { renderMessageSummary } from './helpers/renderMessageText';
import renderText from './helpers/renderText';

View File

@ -20,7 +20,7 @@ import {
import { getMediaContentTypeDescription } from '../../../global/helpers/messageSummary';
import { getPeerTitle } from '../../../global/helpers/peers';
import buildClassName from '../../../util/buildClassName';
import { formatScheduledDateTime } from '../../../util/dates/dateFormat';
import { formatScheduledDateTime } from '../../../util/dates/oldDateFormat';
import { isUserId } from '../../../util/entities/ids';
import { formatStarsAsIcon, formatTonAsIcon } from '../../../util/localization/format';
import { getPictogramDimensions } from '../helpers/mediaDimensions';

View File

@ -8,7 +8,7 @@ import type {
import { DEFAULT_STATUS_ICON_ID, TME_LINK_PREFIX } from '../../../config';
import { STARS_CURRENCY_CODE } from '../../../config';
import { copyTextToClipboard } from '../../../util/clipboard';
import { formatDateAtTime } from '../../../util/dates/dateFormat';
import { formatDateAtTime } from '../../../util/dates/oldDateFormat';
import { getServerTime } from '../../../util/serverTime';
import useLang from '../../../hooks/useLang';

View File

@ -3,7 +3,7 @@ import type { TeactNode } from '../../../lib/teact/teact';
import type { ApiPeer, ApiStarGiftAttributeOriginalDetails } from '../../../api/types';
import { getPeerTitle } from '../../../global/helpers/peers';
import { formatDateTimeToString } from '../../../util/dates/dateFormat';
import { formatDateTimeToString } from '../../../util/dates/oldDateFormat';
import { type LangFn } from '../../../util/localization';
import { renderTextWithEntities } from './renderTextWithEntities';

View File

@ -12,7 +12,7 @@ import {
} from '../../../util/animations/viewTransitionTypes';
import { IS_TOUCH_ENV } from '../../../util/browser/windowEnvironment';
import buildClassName from '../../../util/buildClassName';
import { formatTime, formatWeekday } from '../../../util/dates/dateFormat';
import { formatTime, formatWeekday } from '../../../util/dates/oldDateFormat';
import {
getUtcOffset, getWeekStart, shiftTimeRanges, splitDays,
} from '../../../util/dates/workHours';

View File

@ -12,7 +12,7 @@ import { getStickerMediaHash } from '../../../global/helpers';
import { selectIsPremiumPurchaseBlocked } from '../../../global/selectors';
import { IS_OFFSET_PATH_SUPPORTED } from '../../../util/browser/windowEnvironment';
import buildClassName from '../../../util/buildClassName';
import { formatDateToString } from '../../../util/dates/dateFormat';
import { formatDateToString } from '../../../util/dates/oldDateFormat';
import { buildCollectionByKey } from '../../../util/iteratees';
import * as mediaLoader from '../../../util/mediaLoader';
import renderText from '../helpers/renderText';

View File

@ -21,7 +21,7 @@ import { IS_TAURI } from '../../../util/browser/globalEnvironment';
import { IS_APP, IS_MAC_OS } from '../../../util/browser/windowEnvironment';
import buildClassName from '../../../util/buildClassName';
import captureEscKeyListener from '../../../util/captureEscKeyListener';
import { formatDateToString } from '../../../util/dates/dateFormat';
import { formatDateToString } from '../../../util/dates/oldDateFormat';
import useAppLayout from '../../../hooks/useAppLayout';
import useConnectionStatus from '../../../hooks/useConnectionStatus';

View File

@ -9,7 +9,7 @@ import { AudioOrigin, LoadMoreDirection } from '../../../types';
import { SLIDE_TRANSITION_DURATION } from '../../../config';
import { getIsDownloading } from '../../../global/helpers';
import { selectMessageDownloadableMedia } from '../../../global/selectors/media';
import { formatMonthAndYear, toYearMonth } from '../../../util/dates/dateFormat';
import { formatMonthAndYear, toYearMonth } from '../../../util/dates/oldDateFormat';
import { parseSearchResultKey } from '../../../util/keys/searchResultKey';
import { MEMO_EMPTY_ARRAY } from '../../../util/memo';
import { throttle } from '../../../util/schedulers';

View File

@ -15,7 +15,7 @@ import {
import { isApiPeerUser } from '../../../global/helpers/peers';
import { selectPeer } from '../../../global/selectors';
import buildClassName from '../../../util/buildClassName';
import { formatPastTimeShort } from '../../../util/dates/dateFormat';
import { formatPastTimeShort } from '../../../util/dates/oldDateFormat';
import { type LangFn } from '../../../util/localization';
import { renderMessageSummary } from '../../common/helpers/renderMessageText';

View File

@ -1,7 +1,7 @@
import type { FC } from '../../../lib/teact/teact';
import { memo, useMemo } from '../../../lib/teact/teact';
import { formatDateToString } from '../../../util/dates/dateFormat';
import { formatDateToString } from '../../../util/dates/oldDateFormat';
import Icon from '../../common/icons/Icon';

View File

@ -10,7 +10,7 @@ import { LoadMoreDirection } from '../../../types';
import { SLIDE_TRANSITION_DURATION } from '../../../config';
import { getIsDownloading, getMessageDocument } from '../../../global/helpers';
import { formatMonthAndYear, toYearMonth } from '../../../util/dates/dateFormat';
import { formatMonthAndYear, toYearMonth } from '../../../util/dates/oldDateFormat';
import { parseSearchResultKey } from '../../../util/keys/searchResultKey';
import { MEMO_EMPTY_ARRAY } from '../../../util/memo';
import { throttle } from '../../../util/schedulers';

View File

@ -13,7 +13,7 @@ import { type AnimationLevel, GlobalSearchContent } from '../../../types';
import { selectTabState } from '../../../global/selectors';
import { selectSharedSettings } from '../../../global/selectors/sharedState';
import { parseDateString } from '../../../util/dates/dateFormat';
import { parseDateString } from '../../../util/dates/oldDateFormat';
import { resolveTransitionName } from '../../../util/resolveTransitionName';
import useHistoryBack from '../../../hooks/useHistoryBack';

View File

@ -9,7 +9,7 @@ import type { StateProps } from './helpers/createMapStateToProps';
import { LoadMoreDirection } from '../../../types';
import { SLIDE_TRANSITION_DURATION } from '../../../config';
import { formatMonthAndYear, toYearMonth } from '../../../util/dates/dateFormat';
import { formatMonthAndYear, toYearMonth } from '../../../util/dates/oldDateFormat';
import { parseSearchResultKey } from '../../../util/keys/searchResultKey';
import { MEMO_EMPTY_ARRAY } from '../../../util/memo';
import { throttle } from '../../../util/schedulers';

View File

@ -5,7 +5,7 @@ import { getActions, withGlobal } from '../../../global';
import type { ApiSession } from '../../../api/types';
import buildClassName from '../../../util/buildClassName';
import { formatDateTimeToString } from '../../../util/dates/dateFormat';
import { formatDateTimeToString } from '../../../util/dates/oldDateFormat';
import getSessionIcon from './helpers/getSessionIcon';
import useCurrentOrPrev from '../../../hooks/useCurrentOrPrev';

View File

@ -7,7 +7,7 @@ import { getActions, withGlobal } from '../../../global';
import type { ApiSession } from '../../../api/types';
import type { GlobalState } from '../../../global/types';
import { formatPastTimeShort } from '../../../util/dates/dateFormat';
import { formatPastTimeShort } from '../../../util/dates/oldDateFormat';
import getSessionIcon from './helpers/getSessionIcon';
import useFlag from '../../../hooks/useFlag';

View File

@ -7,7 +7,7 @@ import { getActions, getGlobal, withGlobal } from '../../../global';
import type { ApiWebSession } from '../../../api/types';
import buildClassName from '../../../util/buildClassName';
import { formatPastTimeShort } from '../../../util/dates/dateFormat';
import { formatPastTimeShort } from '../../../util/dates/oldDateFormat';
import useFlag from '../../../hooks/useFlag';
import useHistoryBack from '../../../hooks/useHistoryBack';

View File

@ -11,7 +11,7 @@ import { PURCHASE_USERNAME, TME_LINK_PREFIX, USERNAME_PURCHASE_ERROR } from '../
import { getChatAvatarHash } from '../../../global/helpers';
import { selectTabState, selectUser, selectUserFullInfo } from '../../../global/selectors';
import { selectCurrentLimit } from '../../../global/selectors/limits';
import { formatDateToString } from '../../../util/dates/dateFormat';
import { formatDateToString } from '../../../util/dates/oldDateFormat';
import { getNextArrowReplacement } from '../../../util/localization/format';
import { throttle } from '../../../util/schedulers';
import renderText from '../../common/helpers/renderText';

View File

@ -13,7 +13,6 @@ import { selectSharedSettings } from '../../../global/selectors/sharedState';
import {
IS_ANDROID, IS_IOS, IS_MAC_OS,
} from '../../../util/browser/windowEnvironment';
import { setTimeFormat } from '../../../util/oldLangProvider';
import { getSystemTheme } from '../../../util/systemTheme';
import useAppLayout from '../../../hooks/useAppLayout';
@ -105,8 +104,6 @@ const SettingsGeneral: FC<OwnProps & StateProps> = ({
const handleTimeFormatChange = useCallback((newTimeFormat: string) => {
setSharedSettingOption({ timeFormat: newTimeFormat as TimeFormat });
setSharedSettingOption({ wasTimeFormatSetManually: true });
setTimeFormat(newTimeFormat as TimeFormat);
}, []);
const handleMessageSendComboChange = useCallback((newCombo: string) => {

View File

@ -9,7 +9,7 @@ import type { ApiPasskey } from '../../../api/types';
import { IS_WEBAUTHN_SUPPORTED } from '../../../util/browser/windowEnvironment';
import buildClassName from '../../../util/buildClassName';
import { formatPastDatetime } from '../../../util/dates/dateFormat';
import { formatPastDatetime } from '../../../util/dates/oldDateFormat';
import { getNextArrowReplacement } from '../../../util/localization/format';
import { LOCAL_TGS_PREVIEW_URLS, LOCAL_TGS_URLS } from '../../common/helpers/animatedAssets';
import { REM } from '../../common/helpers/mediaDimensions';

View File

@ -28,7 +28,7 @@ import {
selectTabState,
} from '../../../global/selectors';
import buildClassName from '../../../util/buildClassName';
import { formatDateTimeToString } from '../../../util/dates/dateFormat';
import { formatDateTimeToString } from '../../../util/dates/oldDateFormat';
import { unique } from '../../../util/iteratees';
import renderText from '../../common/helpers/renderText';

View File

@ -25,7 +25,7 @@ import {
} from '../../../global/selectors';
import { selectPremiumLimit } from '../../../global/selectors/limits';
import buildClassName from '../../../util/buildClassName';
import { formatCountdownDays } from '../../../util/dates/dateFormat';
import { formatCountdownDays } from '../../../util/dates/oldDateFormat';
import { formatCurrency } from '../../../util/formatCurrency';
import { getStickerFromGift } from '../../common/helpers/gifts';
import { REM } from '../../common/helpers/mediaDimensions';

View File

@ -15,7 +15,7 @@ import { IS_TOUCH_ENV } from '../../util/browser/windowEnvironment';
import buildClassName from '../../util/buildClassName';
import buildStyle from '../../util/buildStyle';
import { captureEvents } from '../../util/captureEvents';
import { formatMediaDuration } from '../../util/dates/dateFormat';
import { formatMediaDuration } from '../../util/dates/oldDateFormat';
import getPointerPosition from '../../util/events/getPointerPosition';
import { clamp, round } from '../../util/math';
import StoryboardParser from '../../util/media/StoryboardParser';

View File

@ -12,7 +12,7 @@ import { getPeerTitle } from '../../global/helpers/peers';
import {
selectSender,
} from '../../global/selectors';
import { formatMediaDateTime } from '../../util/dates/dateFormat';
import { formatMediaDateTime } from '../../util/dates/oldDateFormat';
import { isUserId } from '../../util/entities/ids';
import renderText from '../common/helpers/renderText';

View File

@ -13,7 +13,7 @@ import type { IconName } from '../../types/icons';
import { IS_IOS, IS_TOUCH_ENV } from '../../util/browser/windowEnvironment';
import buildClassName from '../../util/buildClassName';
import { formatMediaDuration } from '../../util/dates/dateFormat';
import { formatMediaDuration } from '../../util/dates/oldDateFormat';
import useAppLayout from '../../hooks/useAppLayout';
import useCurrentTimeSignal from '../../hooks/useCurrentTimeSignal';

View File

@ -24,7 +24,7 @@ import {
} from '../../global/selectors';
import buildClassName from '../../util/buildClassName';
import buildStyle from '../../util/buildStyle';
import { formatPastDatetime, formatRegistrationMonth } from '../../util/dates/dateFormat';
import { formatPastDatetime, formatRegistrationMonth } from '../../util/dates/oldDateFormat';
import { isoToEmoji } from '../../util/emoji/emoji';
import { getCountryCodeByIso } from '../../util/phoneNumber';
import stopEvent from '../../util/stopEvent';

View File

@ -22,7 +22,7 @@ import {
import { getPeerTitle } from '../../global/helpers/peers';
import { selectChatMessage, selectSender } from '../../global/selectors';
import buildClassName from '../../util/buildClassName';
import { formatHumanDate, formatScheduledDateTime } from '../../util/dates/dateFormat';
import { formatHumanDate, formatScheduledDateTime } from '../../util/dates/oldDateFormat';
import { convertTonFromNanos } from '../../util/formatCurrency';
import { compact } from '../../util/iteratees';
import { formatStarsAsText, formatTonAsText } from '../../util/localization/format';

View File

@ -17,7 +17,7 @@ import {
} from '../../global/selectors';
import { selectSharedSettings } from '../../global/selectors/sharedState';
import buildClassName from '../../util/buildClassName';
import { formatDateAtTime } from '../../util/dates/dateFormat';
import { formatDateAtTime } from '../../util/dates/oldDateFormat';
import { unique } from '../../util/iteratees';
import { resolveTransitionName } from '../../util/resolveTransitionName';
import { formatIntegerCompact } from '../../util/textFormat';

View File

@ -4,7 +4,7 @@ import type { ApiAttachment } from '../../../api/types';
import { SUPPORTED_PHOTO_CONTENT_TYPES, SUPPORTED_VIDEO_CONTENT_TYPES } from '../../../config';
import buildClassName from '../../../util/buildClassName';
import { formatMediaDuration } from '../../../util/dates/dateFormat';
import { formatMediaDuration } from '../../../util/dates/oldDateFormat';
import { getFileExtension } from '../../common/helpers/documentInfo';
import { REM } from '../../common/helpers/mediaDimensions';

View File

@ -2,7 +2,7 @@ import type { ApiMessage } from '../../../api/types';
import type { IAlbum } from '../../../types';
import { isActionMessage } from '../../../global/helpers';
import { getDayStartAt } from '../../../util/dates/dateFormat';
import { getDayStartAt } from '../../../util/dates/oldDateFormat';
type SenderGroup = (ApiMessage | IAlbum)[];

View File

@ -27,7 +27,9 @@ import {
} from '../../../global/selectors';
import { selectThreadIdFromMessage } from '../../../global/selectors/threads';
import { ensureProtocol } from '../../../util/browser/url';
import { formatDateTimeToString, formatScheduledDateTime, formatShortDuration } from '../../../util/dates/dateFormat';
import {
formatDateTimeToString, formatScheduledDateTime, formatShortDuration,
} from '../../../util/dates/oldDateFormat';
import { formatCurrency } from '../../../util/formatCurrency';
import { convertTonFromNanos } from '../../../util/formatCurrency';
import { formatCurrencyAmountAsText, formatStarsAsText, formatTonAsText } from '../../../util/localization/format';

View File

@ -6,7 +6,7 @@ import type { ApiMessageStoryData, ApiTypeStory } from '../../../api/types';
import { getStoryMediaHash } from '../../../global/helpers';
import { IS_CANVAS_FILTER_SUPPORTED } from '../../../util/browser/windowEnvironment';
import buildClassName from '../../../util/buildClassName';
import { formatMediaDuration } from '../../../util/dates/dateFormat';
import { formatMediaDuration } from '../../../util/dates/oldDateFormat';
import useAppLayout from '../../../hooks/useAppLayout';
import useCanvasBlur from '../../../hooks/useCanvasBlur';

View File

@ -18,7 +18,7 @@ import {
selectGiftStickerForDuration,
} from '../../../global/selectors';
import buildClassName from '../../../util/buildClassName';
import { formatDateAtTime, formatDateTimeToString } from '../../../util/dates/dateFormat';
import { formatDateAtTime, formatDateTimeToString } from '../../../util/dates/oldDateFormat';
import { isoToEmoji } from '../../../util/emoji/emoji';
import { getServerTime } from '../../../util/serverTime';
import { callApi } from '../../../api/gramjs';

View File

@ -6,7 +6,7 @@ import type { ApiMessage } from '../../../api/types';
import { getMessageInvoice } from '../../../global/helpers';
import buildClassName from '../../../util/buildClassName';
import { formatMediaDuration } from '../../../util/dates/dateFormat';
import { formatMediaDuration } from '../../../util/dates/oldDateFormat';
import { formatCurrencyAsString } from '../../../util/formatCurrency';
import useInterval from '../../../hooks/schedulers/useInterval';

View File

@ -2,7 +2,7 @@ import { memo } from '../../../lib/teact/teact';
import type { ApiMessage } from '../../../api/types';
import { formatDateAtTime } from '../../../util/dates/dateFormat';
import { formatDateAtTime } from '../../../util/dates/oldDateFormat';
import useOldLang from '../../../hooks/useOldLang';

View File

@ -14,7 +14,7 @@ import {
isGeoLiveExpired,
} from '../../../global/helpers';
import buildClassName from '../../../util/buildClassName';
import { formatCountdownShort, formatLocationLastUpdate } from '../../../util/dates/dateFormat';
import { formatCountdownShort, formatLocationLastUpdate } from '../../../util/dates/oldDateFormat';
import {
getMetersPerPixel, getVenueColor, getVenueIconUrl,
} from '../../../util/map';

View File

@ -8,7 +8,7 @@ import type {
} from '../../../api/types';
import buildClassName from '../../../util/buildClassName';
import { formatDateTimeToString, formatPastTimeShort, formatTime } from '../../../util/dates/dateFormat';
import { formatDateTimeToString, formatPastTimeShort, formatTime } from '../../../util/dates/oldDateFormat';
import { formatStarsAsIcon } from '../../../util/localization/format';
import { getRepeatPeriodText } from '../../../util/scheduledMessages';
import { formatIntegerCompact } from '../../../util/textFormat';

View File

@ -7,7 +7,7 @@ import type { ApiMessageActionPhoneCall } from '../../../api/types/messageAction
import { ARE_CALLS_SUPPORTED } from '../../../util/browser/windowEnvironment';
import buildClassName from '../../../util/buildClassName';
import { formatTime, formatTimeDuration } from '../../../util/dates/dateFormat';
import { formatTime, formatTimeDuration } from '../../../util/dates/oldDateFormat';
import { getCallMessageKey } from './helpers/messageActions';
import useLastCallback from '../../../hooks/useLastCallback';

View File

@ -17,7 +17,7 @@ import type { ObserveFn } from '../../../hooks/useIntersectionObserver';
import type { OldLangFn } from '../../../hooks/useOldLang';
import { selectPeer } from '../../../global/selectors';
import { formatMediaDuration } from '../../../util/dates/dateFormat';
import { formatMediaDuration } from '../../../util/dates/oldDateFormat';
import { getMessageKey } from '../../../util/keys/messageKey';
import { getServerTime } from '../../../util/serverTime';
import { renderTextWithEntities } from '../../common/helpers/renderTextWithEntities';

View File

@ -3,7 +3,7 @@ import { getActions } from '../../../global';
import type { ApiMessage } from '../../../api/types';
import { formatDateAtTime } from '../../../util/dates/dateFormat';
import { formatDateAtTime } from '../../../util/dates/oldDateFormat';
import useOldLang from '../../../hooks/useOldLang';

View File

@ -17,7 +17,7 @@ import {
} from '../../../global/helpers';
import { stopCurrentAudio } from '../../../util/audioPlayer';
import buildClassName from '../../../util/buildClassName';
import { formatMediaDuration } from '../../../util/dates/dateFormat';
import { formatMediaDuration } from '../../../util/dates/oldDateFormat';
import safePlay from '../../../util/safePlay';
import { ROUND_VIDEO_DIMENSIONS_PX } from '../../common/helpers/mediaDimensions';

View File

@ -10,7 +10,7 @@ import {
getMediaFormat, getMediaThumbUri, getMediaTransferState, getVideoMediaHash,
} from '../../../global/helpers';
import buildClassName from '../../../util/buildClassName';
import { formatMediaDuration } from '../../../util/dates/dateFormat';
import { formatMediaDuration } from '../../../util/dates/oldDateFormat';
import * as mediaLoader from '../../../util/mediaLoader';
import { calculateExtendedPreviewDimensions, calculateVideoDimensions } from '../../common/helpers/mediaDimensions';
import { MIN_MEDIA_HEIGHT } from './helpers/mediaDimensions';

View File

@ -13,7 +13,7 @@ import {
selectGiftStickerForStars,
selectGiftStickerForTon,
} from '../../../../global/selectors';
import { formatCountdownDays } from '../../../../util/dates/dateFormat';
import { formatCountdownDays } from '../../../../util/dates/oldDateFormat';
import { formatCurrency } from '../../../../util/formatCurrency';
import { renderTextWithEntities } from '../../../common/helpers/renderTextWithEntities';

View File

@ -11,7 +11,7 @@ import {
selectGiftStickerForDuration,
selectGiftStickerForStars,
} from '../../../../global/selectors';
import { formatCountdownDays } from '../../../../util/dates/dateFormat';
import { formatCountdownDays } from '../../../../util/dates/oldDateFormat';
import { renderPeerLink } from '../helpers/messageActions';
import { type ObserveFn } from '../../../../hooks/useIntersectionObserver';

View File

@ -13,7 +13,7 @@ import {
} from '../../../../global/selectors';
import { IS_TOUCH_ENV } from '../../../../util/browser/windowEnvironment';
import buildClassName from '../../../../util/buildClassName';
import { formatShortHoursMinutes } from '../../../../util/dates/dateFormat';
import { formatShortHoursMinutes } from '../../../../util/dates/oldDateFormat';
import { formatCurrencyAmountAsText } from '../../../../util/localization/format';
import { getServerTime } from '../../../../util/serverTime';
import { getGiftAttributes, getStickerFromGift } from '../../../common/helpers/gifts';

View File

@ -11,7 +11,7 @@ import { selectIsMonoforumAdmin, selectMonoforumChannel,
selectReplyMessage,
selectSender } from '../../../../global/selectors';
import buildClassName from '../../../../util/buildClassName';
import { formatScheduledDateTime, formatShortDuration } from '../../../../util/dates/dateFormat';
import { formatScheduledDateTime, formatShortDuration } from '../../../../util/dates/oldDateFormat';
import { convertTonFromNanos } from '../../../../util/formatCurrency';
import { formatStarsAsText, formatTonAsText } from '../../../../util/localization/format';
import { getServerTime } from '../../../../util/serverTime';

View File

@ -34,7 +34,7 @@ import {
import { IS_IOS } from '../../../util/browser/windowEnvironment';
import buildClassName from '../../../util/buildClassName';
import captureEscKeyListener from '../../../util/captureEscKeyListener';
import { getDayStartAt } from '../../../util/dates/dateFormat';
import { getDayStartAt } from '../../../util/dates/oldDateFormat';
import focusEditableElement from '../../../util/focusEditableElement';
import focusNoScroll from '../../../util/focusNoScroll';
import { getSearchResultKey, parseSearchResultKey, type SearchResultKey } from '../../../util/keys/searchResultKey';

View File

@ -7,7 +7,7 @@ import type { TabState } from '../../../global/types';
import { getChatTitle, isChatAdmin, isChatChannel } from '../../../global/helpers';
import { selectChat, selectChatFullInfo, selectIsCurrentUserPremium } from '../../../global/selectors';
import buildClassName from '../../../util/buildClassName';
import { formatShortDuration } from '../../../util/dates/dateFormat';
import { formatShortDuration } from '../../../util/dates/oldDateFormat';
import { getServerTime } from '../../../util/serverTime';
import { getBoostProgressInfo } from '../../common/helpers/boostInfo';
import renderText from '../../common/helpers/renderText';

View File

@ -9,7 +9,7 @@ import type { ApiCountryCode } from '../../../api/types';
import type { TabState } from '../../../global/types';
import { copyTextToClipboard } from '../../../util/clipboard';
import { formatDateAtTime } from '../../../util/dates/dateFormat';
import { formatDateAtTime } from '../../../util/dates/oldDateFormat';
import { formatCurrencyAsString } from '../../../util/formatCurrency';
import { formatPhoneNumberWithCode } from '../../../util/phoneNumber';
import { LOCAL_TGS_URLS } from '../../common/helpers/animatedAssets';

View File

@ -5,7 +5,7 @@ import type { TabState } from '../../../global/types';
import { getMainUsername } from '../../../global/helpers';
import { selectUser } from '../../../global/selectors';
import { formatDateToString } from '../../../util/dates/dateFormat';
import { formatDateToString } from '../../../util/dates/oldDateFormat';
import { LOCAL_TGS_URLS } from '../../common/helpers/animatedAssets';
import formatUsername from '../../common/helpers/formatUsername';

View File

@ -16,7 +16,7 @@ import {
} from '../../../global/selectors';
import buildClassName from '../../../util/buildClassName';
import buildStyle from '../../../util/buildStyle';
import { formatCountdown } from '../../../util/dates/dateFormat';
import { formatCountdown } from '../../../util/dates/oldDateFormat';
import { HOUR } from '../../../util/dates/units';
import { formatCurrency } from '../../../util/formatCurrency';
import { formatStarsAsIcon, getNextArrowReplacement } from '../../../util/localization/format';

View File

@ -4,7 +4,7 @@ import { getActions } from '../../../global';
import type { TabState } from '../../../global/types';
import buildClassName from '../../../util/buildClassName';
import { formatDateTimeToString } from '../../../util/dates/dateFormat';
import { formatDateTimeToString } from '../../../util/dates/oldDateFormat';
import { formatStarsAsIcon, formatStarsAsText } from '../../../util/localization/format';
import useCurrentOrPrev from '../../../hooks/useCurrentOrPrev';

View File

@ -10,7 +10,7 @@ import type {
import { DEFAULT_STATUS_ICON_ID } from '../../../config';
import { STARS_CURRENCY_CODE } from '../../../config';
import { selectTabState, selectUser } from '../../../global/selectors';
import { formatDateAtTime } from '../../../util/dates/dateFormat';
import { formatDateAtTime } from '../../../util/dates/oldDateFormat';
import { getServerTime } from '../../../util/serverTime';
import useLang from '../../../hooks/useLang';

View File

@ -5,7 +5,7 @@ import type { ApiStarGiftAuctionAcquiredGift, ApiSticker } from '../../../../api
import type { TabState } from '../../../../global/types';
import { selectTabState } from '../../../../global/selectors';
import { formatDateTimeToString } from '../../../../util/dates/dateFormat';
import { formatDateTimeToString } from '../../../../util/dates/oldDateFormat';
import { formatStarsAsIcon } from '../../../../util/localization/format';
import useCurrentOrPrev from '../../../../hooks/useCurrentOrPrev';

View File

@ -9,7 +9,7 @@ import type { TabState } from '../../../../global/types';
import { TME_LINK_PREFIX } from '../../../../config';
import { selectTabState } from '../../../../global/selectors';
import { copyTextToClipboard } from '../../../../util/clipboard';
import { formatCountdown, formatDateTimeToString } from '../../../../util/dates/dateFormat';
import { formatCountdown, formatDateTimeToString } from '../../../../util/dates/oldDateFormat';
import { HOUR } from '../../../../util/dates/units';
import { formatStarsAsIcon } from '../../../../util/localization/format';
import { getServerTime } from '../../../../util/serverTime';

View File

@ -15,7 +15,7 @@ import { getMainUsername } from '../../../../global/helpers/users';
import { selectPeer, selectUser } from '../../../../global/selectors';
import buildClassName from '../../../../util/buildClassName';
import { copyTextToClipboard } from '../../../../util/clipboard';
import { formatDateTimeToString } from '../../../../util/dates/dateFormat';
import { formatDateTimeToString } from '../../../../util/dates/oldDateFormat';
import { formatCurrency, formatCurrencyAsString } from '../../../../util/formatCurrency';
import {
formatStarsAsIcon, formatStarsAsText, formatTonAsIcon, formatTonAsText,

View File

@ -3,7 +3,7 @@ import { getActions } from '../../../../global';
import type { TabState } from '../../../../global/types';
import { formatShortDuration } from '../../../../util/dates/dateFormat';
import { formatShortDuration } from '../../../../util/dates/oldDateFormat';
import { getServerTime } from '../../../../util/serverTime';
import { renderTextWithEntities } from '../../../common/helpers/renderTextWithEntities';

View File

@ -4,7 +4,7 @@ import { getActions } from '../../../../global';
import type { TabState } from '../../../../global/types';
import { formatDateToString } from '../../../../util/dates/dateFormat';
import { formatDateToString } from '../../../../util/dates/oldDateFormat';
import { formatCurrencyAsString } from '../../../../util/formatCurrency';
import { formatStarsAsIcon } from '../../../../util/localization/format';
import { getGiftAttributes } from '../../../common/helpers/gifts';

View File

@ -7,7 +7,7 @@ import type { TabState } from '../../../global/types';
import { TME_LINK_PREFIX } from '../../../config';
import { selectChatMessage, selectSender } from '../../../global/selectors';
import buildClassName from '../../../util/buildClassName';
import { formatCountdownDays, formatDateTimeToString } from '../../../util/dates/dateFormat';
import { formatCountdownDays, formatDateTimeToString } from '../../../util/dates/oldDateFormat';
import renderText from '../../common/helpers/renderText';
import useLang from '../../../hooks/useLang';

View File

@ -7,7 +7,7 @@ import type { TabState } from '../../../global/types';
import { getPeerTitle } from '../../../global/helpers/peers';
import { selectUser, selectUserFullInfo } from '../../../global/selectors';
import buildClassName from '../../../util/buildClassName';
import { formatShortDuration } from '../../../util/dates/dateFormat';
import { formatShortDuration } from '../../../util/dates/oldDateFormat';
import { getNextArrowReplacement } from '../../../util/localization/format';
import { getServerTime } from '../../../util/serverTime';

View File

@ -9,7 +9,7 @@ import type { GlobalState } from '../../../../global/types';
import { NNBSP } from '../../../../config';
import { getPeerTitle } from '../../../../global/helpers/peers';
import { selectPeer } from '../../../../global/selectors';
import { formatDateToString } from '../../../../util/dates/dateFormat';
import { formatDateToString } from '../../../../util/dates/oldDateFormat';
import { formatInteger } from '../../../../util/textFormat';
import renderText from '../../../common/helpers/renderText';

View File

@ -13,7 +13,7 @@ import {
selectPeer,
} from '../../../../global/selectors';
import buildClassName from '../../../../util/buildClassName';
import { formatDateTimeToString } from '../../../../util/dates/dateFormat';
import { formatDateTimeToString } from '../../../../util/dates/oldDateFormat';
import useLang from '../../../../hooks/useLang';
import useLastCallback from '../../../../hooks/useLastCallback';

View File

@ -15,7 +15,7 @@ import { buildStarsTransactionCustomPeer,
import { getPeerTitle } from '../../../../global/helpers/peers';
import { selectPeer } from '../../../../global/selectors';
import buildClassName from '../../../../util/buildClassName';
import { formatDateTimeToString } from '../../../../util/dates/dateFormat';
import { formatDateTimeToString } from '../../../../util/dates/oldDateFormat';
import { CUSTOM_PEER_PREMIUM } from '../../../../util/objects/customPeer';
import { getGiftAttributes, getStickerFromGift } from '../../../common/helpers/gifts';
import renderText from '../../../common/helpers/renderText';

View File

@ -24,7 +24,7 @@ import {
} from '../../../../global/selectors';
import buildClassName from '../../../../util/buildClassName';
import { copyTextToClipboard } from '../../../../util/clipboard';
import { formatDateTimeToString } from '../../../../util/dates/dateFormat';
import { formatDateTimeToString } from '../../../../util/dates/oldDateFormat';
import { formatStarsAsIcon } from '../../../../util/localization/format';
import { formatPercent } from '../../../../util/textFormat';
import { getGiftAttributes, getStickerFromGift } from '../../../common/helpers/gifts';

View File

@ -16,7 +16,7 @@ import {
import { selectIsMonoforumAdmin, selectPeer } from '../../../global/selectors';
import { selectDraft } from '../../../global/selectors/threads';
import buildClassName from '../../../util/buildClassName';
import { formatScheduledDateTime, formatShortDuration } from '../../../util/dates/dateFormat';
import { formatScheduledDateTime, formatShortDuration } from '../../../util/dates/oldDateFormat';
import { convertTonFromNanos, convertTonToNanos } from '../../../util/formatCurrency';
import {
formatStarsAsIcon,

View File

@ -10,7 +10,7 @@ import {
} from '../../../config';
import { getPeerFullTitle } from '../../../global/helpers/peers';
import { selectChatMessage, selectIsMonoforumAdmin, selectSender } from '../../../global/selectors';
import { formatScheduledDateTime, formatShortDuration } from '../../../util/dates/dateFormat';
import { formatScheduledDateTime, formatShortDuration } from '../../../util/dates/oldDateFormat';
import { convertTonFromNanos } from '../../../util/formatCurrency';
import { formatStarsAsText, formatTonAsText } from '../../../util/localization/format';
import renderText from '../../common/helpers/renderText';

View File

@ -6,7 +6,7 @@ import type { TabState } from '../../../global/types';
import { getUserFullName } from '../../../global/helpers';
import { selectUser } from '../../../global/selectors';
import { formatShortDuration } from '../../../util/dates/dateFormat';
import { formatShortDuration } from '../../../util/dates/oldDateFormat';
import { getServerTime } from '../../../util/serverTime';
import { REM } from '../../common/helpers/mediaDimensions';

View File

@ -14,7 +14,7 @@ import type {
import type { PollVote } from '../../global/types/tabState';
import { selectTabState } from '../../global/selectors';
import { formatMediaDateTime } from '../../util/dates/dateFormat';
import { formatMediaDateTime } from '../../util/dates/oldDateFormat';
import { isUserId } from '../../util/entities/ids';
import { renderTextWithEntities } from '../common/helpers/renderTextWithEntities';

View File

@ -7,7 +7,7 @@ import type { ApiUser } from '../../../api/types';
import { getUserFullName } from '../../../global/helpers';
import { selectUser } from '../../../global/selectors';
import { createClassNameBuilder } from '../../../util/buildClassName';
import { formatHumanDate, formatTime, isToday } from '../../../util/dates/dateFormat';
import { formatHumanDate, formatTime, isToday } from '../../../util/dates/oldDateFormat';
import { getServerTime } from '../../../util/serverTime';
import useOldLang from '../../../hooks/useOldLang';

View File

@ -7,7 +7,7 @@ import type { ApiExportedInvite } from '../../../api/types';
import { ManagementScreens } from '../../../types';
import { selectTabState } from '../../../global/selectors';
import { formatFullDate, formatTime } from '../../../util/dates/dateFormat';
import { formatFullDate, formatTime } from '../../../util/dates/oldDateFormat';
import { getServerTime } from '../../../util/serverTime';
import useFlag from '../../../hooks/useFlag';

View File

@ -6,7 +6,7 @@ import type { ApiChatInviteImporter, ApiExportedInvite } from '../../../api/type
import { isChatChannel } from '../../../global/helpers';
import { selectChat, selectTabState } from '../../../global/selectors';
import { formatFullDate, formatMediaDateTime, formatTime } from '../../../util/dates/dateFormat';
import { formatFullDate, formatMediaDateTime, formatTime } from '../../../util/dates/oldDateFormat';
import { getServerTime } from '../../../util/serverTime';
import useHistoryBack from '../../../hooks/useHistoryBack';

View File

@ -11,7 +11,7 @@ import { STICKER_SIZE_INVITES, TME_LINK_PREFIX } from '../../../config';
import { getMainUsername, isChatChannel } from '../../../global/helpers';
import { selectChat, selectTabState } from '../../../global/selectors';
import { copyTextToClipboard } from '../../../util/clipboard';
import { formatCountdown, MILLISECONDS_IN_DAY } from '../../../util/dates/dateFormat';
import { formatCountdown, MILLISECONDS_IN_DAY } from '../../../util/dates/oldDateFormat';
import { getServerTime } from '../../../util/serverTime';
import { LOCAL_TGS_URLS } from '../../common/helpers/animatedAssets';

View File

@ -10,7 +10,7 @@ import { isChatChannel } from '../../../global/helpers';
import { selectChat, selectIsGiveawayGiftsPurchaseAvailable, selectTabState } from '../../../global/selectors';
import { selectSharedSettings } from '../../../global/selectors/sharedState.ts';
import buildClassName from '../../../util/buildClassName';
import { formatDateAtTime } from '../../../util/dates/dateFormat';
import { formatDateAtTime } from '../../../util/dates/oldDateFormat';
import { resolveTransitionName } from '../../../util/resolveTransitionName.ts';
import { formatInteger } from '../../../util/textFormat';
import { getBoostProgressInfo } from '../../common/helpers/boostInfo';

View File

@ -8,7 +8,7 @@ import type {
} from '../../../api/types';
import buildClassName from '../../../util/buildClassName';
import { formatFullDate } from '../../../util/dates/dateFormat';
import { formatFullDate } from '../../../util/dates/oldDateFormat';
import { convertTonFromNanos } from '../../../util/formatCurrency';
import { formatInteger, formatIntegerCompact } from '../../../util/textFormat';

View File

@ -9,7 +9,7 @@ import {
getMessageVideo,
} from '../../../global/helpers';
import buildClassName from '../../../util/buildClassName';
import { formatDateTimeToString } from '../../../util/dates/dateFormat';
import { formatDateTimeToString } from '../../../util/dates/oldDateFormat';
import { type LangFn } from '../../../util/localization';
import { renderMessageSummary } from '../../common/helpers/renderMessageText';

View File

@ -10,7 +10,7 @@ import type { OldLangFn } from '../../../hooks/useOldLang';
import { getStoryMediaHash } from '../../../global/helpers';
import buildClassName from '../../../util/buildClassName';
import { formatDateTimeToString } from '../../../util/dates/dateFormat';
import { formatDateTimeToString } from '../../../util/dates/oldDateFormat';
import useLastCallback from '../../../hooks/useLastCallback';
import useMedia from '../../../hooks/useMedia';

View File

@ -8,7 +8,7 @@ import type { ApiTypeStory } from '../../api/types';
import { getStoryMediaHash } from '../../global/helpers';
import { selectChat, selectPinnedStories } from '../../global/selectors';
import buildClassName from '../../util/buildClassName';
import { formatMediaDuration } from '../../util/dates/dateFormat';
import { formatMediaDuration } from '../../util/dates/oldDateFormat';
import stopEvent from '../../util/stopEvent';
import { preventMessageInputBlurWithBubbling } from '../middle/helpers/preventMessageInputBlur';

View File

@ -33,7 +33,7 @@ import {
import { IS_SAFARI } from '../../util/browser/windowEnvironment';
import buildClassName from '../../util/buildClassName';
import captureKeyboardListeners from '../../util/captureKeyboardListeners';
import { formatMediaDuration, formatRelativePastTime } from '../../util/dates/dateFormat';
import { formatMediaDuration, formatRelativePastTime } from '../../util/dates/oldDateFormat';
import download from '../../util/download';
import { isUserId } from '../../util/entities/ids';
import { formatStarsAsIcon } from '../../util/localization/format';

View File

@ -6,7 +6,7 @@ import { StoryViewerOrigin } from '../../types';
import { getPeerTitle } from '../../global/helpers/peers';
import buildClassName from '../../util/buildClassName';
import { formatMediaDuration } from '../../util/dates/dateFormat';
import { formatMediaDuration } from '../../util/dates/oldDateFormat';
import { isUserId } from '../../util/entities/ids';
import { getServerTime } from '../../util/serverTime';
import { preventMessageInputBlurWithBubbling } from '../middle/helpers/preventMessageInputBlur';

View File

@ -9,7 +9,7 @@ import type { IconName } from '../../types/icons';
import { getUserFullName } from '../../global/helpers';
import { selectPeer } from '../../global/selectors';
import buildClassName from '../../util/buildClassName';
import { formatDateAtTime } from '../../util/dates/dateFormat';
import { formatDateAtTime } from '../../util/dates/oldDateFormat';
import { isUserId } from '../../util/entities/ids';
import { REM } from '../common/helpers/mediaDimensions';

View File

@ -0,0 +1,29 @@
.root {
overflow: auto;
overscroll-behavior: contain;
box-sizing: border-box;
height: 100%;
min-height: 0;
padding: 1rem;
background: var(--color-background);
}
.table {
border-collapse: collapse;
width: 100%;
margin-bottom: 1.5rem;
}
.cell {
padding: 0.375rem 0.5rem;
border: 1px solid var(--color-borders);
text-align: left;
vertical-align: top;
}
.code {
overflow-wrap: anywhere;
white-space: pre-wrap;
}

View File

@ -0,0 +1,128 @@
import type { FormatDateTimeOptions } from '../../util/localization/dateFormat';
import buildClassName from '../../util/buildClassName';
import { formatDateTime } from '../../util/localization/dateFormat';
import useLang from '../../hooks/useLang';
import styles from './TestDateFormat.module.scss';
type Row = {
label: string;
value: string;
};
const ANCHOR_DATE = new Date(2026, 2, 16, 12, 34, 56);
const ANCHOR_TIMESTAMP = ANCHOR_DATE.getTime();
const ABSOLUTE_CASES: Array<{ label: string; options: FormatDateTimeOptions }> = [
{ label: 'default', options: {} },
{ label: 'date: numeric', options: { date: 'numeric' } },
{ label: 'date: short', options: { date: 'short' } },
{ label: 'date: long', options: { date: 'long' } },
{ label: 'date: short, no year', options: { date: 'short', includeYear: false } },
{ label: 'date: short, no day', options: { date: 'short', includeDay: false } },
{ label: 'date: long, no year', options: { date: 'long', includeYear: false } },
{ label: 'date: long, no day', options: { date: 'long', includeDay: false } },
{ label: 'time: short', options: { time: 'short' } },
{ label: 'time: long', options: { time: 'long' } },
{ label: 'weekday: short', options: { weekday: 'short' } },
{ label: 'weekday: long', options: { weekday: 'long' } },
{ label: 'weekday: short + date: short', options: { weekday: 'short', date: 'short' } },
{ label: 'weekday: long + date: long', options: { weekday: 'long', date: 'long' } },
{ label: 'weekday: short + time: short', options: { weekday: 'short', time: 'short' } },
{ label: 'date: short + time: short', options: { date: 'short', time: 'short' } },
{ label: 'date: short + time: long', options: { date: 'short', time: 'long' } },
{ label: 'date: long + time: short', options: { date: 'long', time: 'short' } },
{ label: 'date: long + time: long', options: { date: 'long', time: 'long' } },
{
label: 'weekday + date: short + time: short',
options: { weekday: 'short', date: 'short', time: 'short' },
},
{
label: 'weekday: long + date: long + time: long',
options: { weekday: 'long', date: 'long', time: 'long' },
},
];
const RELATIVE_CASES = [
{ label: '30 seconds later', startDate: new Date(2026, 2, 16, 12, 35, 26) },
{ label: '5 minutes later', startDate: new Date(2026, 2, 16, 12, 39, 56) },
{ label: '3 hours later', startDate: new Date(2026, 2, 16, 15, 34, 56) },
{ label: 'tomorrow', startDate: new Date(2026, 2, 17, 12, 34, 56) },
{ label: '2 days later', startDate: new Date(2026, 2, 18, 12, 34, 56) },
{ label: '10 days later', startDate: new Date(2026, 2, 26, 12, 34, 56) },
{ label: '45 seconds earlier', startDate: new Date(2026, 2, 16, 12, 34, 11) },
{ label: '2 hours earlier', startDate: new Date(2026, 2, 16, 10, 34, 56) },
{ label: 'yesterday', startDate: new Date(2026, 2, 15, 12, 34, 56) },
{ label: '3 days earlier', startDate: new Date(2026, 2, 13, 12, 34, 56) },
];
function DebugTable({ rows }: { rows: Row[] }) {
return (
<table className={styles.table}>
<thead>
<tr>
<th className={styles.cell}>Case</th>
<th className={styles.cell}>Output</th>
</tr>
</thead>
<tbody>
{rows.map(({ label, value }) => (
<tr key={label}>
<td className={styles.cell}><code className={styles.code}>{label}</code></td>
<td className={styles.cell}><code className={styles.code}>{value}</code></td>
</tr>
))}
</tbody>
</table>
);
}
const DateFormatTest = () => {
const lang = useLang();
const languageInfo = lang.languageInfo;
const absoluteRows: Row[] = ABSOLUTE_CASES.map(({ label, options }) => ({
label,
value: formatDateTime(lang, ANCHOR_DATE, options),
}));
const relativeRows: Row[] = RELATIVE_CASES.map(({ label, startDate }) => {
const startDateLabel = startDate.toLocaleString();
return {
label: `${label} (${startDateLabel})`,
value: formatDateTime(lang, startDate, { relative: 'auto', anchorDate: ANCHOR_DATE }),
};
});
const contextRows: Row[] = [
{ label: 'lang.code', value: lang.code },
{ label: 'lang.rawCode', value: lang.rawCode },
{ label: 'lang.languageInfo ready', value: String(Boolean(languageInfo)) },
{ label: 'lang.languageInfo.pluralCode', value: languageInfo?.pluralCode || '' },
{ label: 'lang.timeFormat', value: lang.timeFormat },
{ label: 'anchorDate.toString()', value: ANCHOR_DATE.toString() },
{ label: 'anchorDate.toISOString()', value: ANCHOR_DATE.toISOString() },
{ label: 'anchorDate.getTime()', value: String(ANCHOR_TIMESTAMP) },
];
return (
<div className={buildClassName(styles.root, 'full-height', 'custom-scroll')}>
<h2>Date Format Test</h2>
<p>Formats one fixed date through the new localized date formatter in as many useful combinations as possible.</p>
<h3>Context</h3>
<DebugTable rows={contextRows} />
<h3>Absolute Options</h3>
<DebugTable rows={absoluteRows} />
<h3>Relative Formatting</h3>
<DebugTable rows={relativeRows} />
</div>
);
};
export default DateFormatTest;

View File

@ -0,0 +1,317 @@
import { useEffect, useState } from '../../lib/teact/teact';
import buildClassName from '../../util/buildClassName';
import {
formatDateTimeToString as oldFormatDateTimeToString,
formatDateToString as oldFormatDateToString,
formatPastTimeShort as oldFormatPastTimeShort,
formatTime as oldFormatTime,
} from '../../util/dates/oldDateFormat';
import { formatDateTime } from '../../util/localization/dateFormat';
import useLang from '../../hooks/useLang';
import useOldLang, { type OldLangFn } from '../../hooks/useOldLang';
import styles from './TestDateFormat.module.scss';
const BENCHMARK_COUNT = 10000;
const RANDOM_SEED = 123456789;
const DAY_IN_MS = 24 * 60 * 60 * 1000;
type NewLangFn = ReturnType<typeof useLang>;
type BenchmarkFormatter = (date: Date) => string;
type BenchmarkCase = {
name: string;
oldFormatter: BenchmarkFormatter;
newFormatter: BenchmarkFormatter;
};
type Measurement = {
totalMs: number;
perCallMs: number;
checksum: number;
sample: string;
};
type BenchmarkResult = {
name: string;
old: Measurement;
new: Measurement;
};
function createSeededRandom(seed: number) {
let value = seed >>> 0;
return () => {
value = (value * 1664525 + 1013904223) >>> 0;
return value / 0x100000000;
};
}
function generateRandomDates(count: number, now: Date) {
const random = createSeededRandom(RANDOM_SEED);
const dates: Date[] = [];
for (let i = 0; i < count; i++) {
const bucket = random();
let offsetMs: number;
if (bucket < 0.45) {
offsetMs = -Math.floor(random() * DAY_IN_MS);
} else if (bucket < 0.8) {
offsetMs = -Math.floor(random() * 7 * DAY_IN_MS);
} else if (bucket < 0.97) {
offsetMs = -Math.floor((7 + random() * 358) * DAY_IN_MS);
} else {
offsetMs = Math.floor(random() * 2 * DAY_IN_MS);
}
dates.push(new Date(now.getTime() + offsetMs));
}
return dates;
}
function getDayStart(date: Date) {
const result = new Date(date);
result.setHours(0, 0, 0, 0);
return result;
}
function formatPastTimeShortWithNewCore(lang: NewLangFn, date: Date) {
const time = formatDateTime(lang, date, { time: 'short' });
const today = getDayStart(new Date());
if (date >= today) {
return time;
}
const weekAgo = new Date(today);
weekAgo.setDate(today.getDate() - 7);
if (date >= weekAgo) {
return formatDateTime(lang, date, { weekday: 'short' });
}
return formatDateTime(lang, date, {
date: 'short',
includeYear: date.getFullYear() === today.getFullYear() ? false : undefined,
});
}
function createBenchmarkCases(oldLang: OldLangFn, lang: NewLangFn): BenchmarkCase[] {
return [
{
name: 'time short',
oldFormatter: (date) => oldFormatTime(oldLang, date),
newFormatter: (date) => formatDateTime(lang, date, { time: 'short' }),
},
{
name: 'past time short',
oldFormatter: (date) => oldFormatPastTimeShort(oldLang, date),
newFormatter: (date) => formatPastTimeShortWithNewCore(lang, date),
},
{
name: 'date short',
oldFormatter: (date) => oldFormatDateToString(date, oldLang.code, false, 'short'),
newFormatter: (date) => formatDateTime(lang, date, { date: 'short' }),
},
{
name: 'date + time short',
oldFormatter: (date) => oldFormatDateTimeToString(date, oldLang.code, true, oldLang.timeFormat),
newFormatter: (date) => formatDateTime(lang, date, { date: 'short', time: 'short' }),
},
];
}
function measureFormatting(dates: Date[], formatter: BenchmarkFormatter): Measurement {
let checksum = 0;
let sample = '';
const start = performance.now();
for (let i = 0; i < dates.length; i++) {
const value = formatter(dates[i]);
if (!sample) {
sample = value;
}
checksum = ((checksum * 33) + value.length + value.charCodeAt(0)) >>> 0;
}
const totalMs = performance.now() - start;
return {
totalMs,
perCallMs: totalMs / dates.length,
checksum,
sample,
};
}
function warmUp(dates: Date[], formatter: BenchmarkFormatter) {
const warmUpCount = Math.min(250, dates.length);
for (let i = 0; i < warmUpCount; i++) {
formatter(dates[i]);
}
}
function summarizeDates(dates: Date[]) {
const today = getDayStart(new Date()).getTime();
const weekAgo = today - (7 * DAY_IN_MS);
let todayCount = 0;
let lastWeekCount = 0;
let olderCount = 0;
let futureCount = 0;
for (let i = 0; i < dates.length; i++) {
const timestamp = dates[i].getTime();
if (timestamp >= today) {
if (timestamp >= Date.now()) {
futureCount++;
} else {
todayCount++;
}
continue;
}
if (timestamp >= weekAgo) {
lastWeekCount++;
continue;
}
olderCount++;
}
return {
today: todayCount,
lastWeek: lastWeekCount,
older: olderCount,
future: futureCount,
};
}
function logBenchmarkResults(
lang: NewLangFn,
oldLang: OldLangFn,
now: Date,
dates: Date[],
results: BenchmarkResult[],
) {
const formattedResults = Object.fromEntries(results.map((result) => {
return [result.name, {
old: {
totalMs: Number(result.old.totalMs.toFixed(2)),
perCallMs: Number(result.old.perCallMs.toFixed(8)),
checksum: result.old.checksum,
sample: result.old.sample,
},
new: {
totalMs: Number(result.new.totalMs.toFixed(2)),
perCallMs: Number(result.new.perCallMs.toFixed(8)),
checksum: result.new.checksum,
sample: result.new.sample,
},
newVsOld: Number((result.new.totalMs / result.old.totalMs).toFixed(2)),
}];
}));
const label = [
'[TestDateFormatPerf]',
`lang=${lang.code}`,
`oldLang=${oldLang.code}`,
`timeFormat=${lang.timeFormat}`,
`N=${BENCHMARK_COUNT}`,
].join(' ');
// eslint-disable-next-line no-console
console.group(label);
// eslint-disable-next-line no-console
console.log('dataset', {
seed: RANDOM_SEED,
generatedAt: now.toISOString(),
distribution: summarizeDates(dates),
});
// eslint-disable-next-line no-console
console.log('results', formattedResults);
// eslint-disable-next-line no-console
console.groupEnd();
}
const TestDateFormatPerf = () => {
const lang = useLang();
const oldLang = useOldLang();
const [lastRunAt, setLastRunAt] = useState<string>();
const [runId, setRunId] = useState(0);
useEffect(() => {
let isActive = true;
const runBenchmarks = () => {
const now = new Date();
const dates = generateRandomDates(BENCHMARK_COUNT, now);
const benchmarkCases = createBenchmarkCases(oldLang, lang);
const results: BenchmarkResult[] = benchmarkCases.map((benchmarkCase) => {
warmUp(dates, benchmarkCase.oldFormatter);
warmUp(dates, benchmarkCase.newFormatter);
return {
name: benchmarkCase.name,
old: measureFormatting(dates, benchmarkCase.oldFormatter),
new: measureFormatting(dates, benchmarkCase.newFormatter),
};
});
logBenchmarkResults(lang, oldLang, now, dates, results);
if (isActive) {
setLastRunAt(new Date().toLocaleTimeString());
}
};
const frameId = window.requestAnimationFrame(runBenchmarks);
return () => {
isActive = false;
if (frameId !== undefined) {
window.cancelAnimationFrame(frameId);
}
};
}, [lang, oldLang, runId]);
return (
<div className={buildClassName(styles.root, 'full-height', 'custom-scroll')}>
<h2>Date Format Perf</h2>
<p>Generates 10,000 random dates, benchmarks old and new formatting paths, and prints results to the console.</p>
<p>
Current context:
{' '}
<code>{`${lang.code} / ${lang.timeFormat}`}</code>
</p>
<p>
Benchmarks:
{' '}
<code>formatTime</code>
{', '}
<code>formatPastTimeShort</code>
{', '}
<code>date short</code>
{', '}
<code>date + time short</code>
</p>
{lastRunAt && (
<p>
Last run:
{' '}
<code>{lastRunAt}</code>
</p>
)}
<button type="button" onClick={() => setRunId((current) => current + 1)}>
Run benchmark again
</button>
</div>
);
};
export default TestDateFormatPerf;

View File

@ -1,7 +1,7 @@
import { memo, useEffect, useState } from '../../lib/teact/teact';
import buildClassName from '../../util/buildClassName';
import { formatCountdownShort } from '../../util/dates/dateFormat';
import { formatCountdownShort } from '../../util/dates/oldDateFormat';
import useInterval from '../../hooks/schedulers/useInterval';
import useOldLang from '../../hooks/useOldLang';

View File

@ -1,6 +1,6 @@
import { useEffect } from '../../lib/teact/teact';
import { formatMediaDuration } from '../../util/dates/dateFormat';
import { formatMediaDuration } from '../../util/dates/oldDateFormat';
import { getServerTime } from '../../util/serverTime';
import useInterval from '../../hooks/schedulers/useInterval';

View File

@ -250,7 +250,8 @@ export const DEFAULT_TOPIC_ICON_STICKER_ID = 'topic-default-icon';
export const DEFAULT_STATUS_ICON_ID = 'status-default-icon';
export const EMOJI_IMG_REGEX = /<img[^>]+alt="([^"]+)"(?![^>]*data-document-id)[^>]*>/gm;
export const BASE_EMOJI_KEYWORD_LANG = 'en';
export const FALLBACK_LANG_CODE = 'en';
export const BASE_EMOJI_KEYWORD_LANG = FALLBACK_LANG_CODE;
export const MENU_TRANSITION_DURATION = 200;
export const SLIDE_TRANSITION_DURATION = 450;

View File

@ -8,7 +8,7 @@ import type {
import type { ActionReturnType, GlobalState, TabArgs } from '../../types';
import { GLOBAL_SEARCH_SLICE, GLOBAL_TOPIC_SEARCH_SLICE } from '../../../config';
import { timestampPlusDay } from '../../../util/dates/dateFormat';
import { timestampPlusDay } from '../../../util/dates/oldDateFormat';
import { isDeepLink, tryParseDeepLink } from '../../../util/deepLinkParser';
import { toChannelId } from '../../../util/entities/ids';
import { getCurrentTabId } from '../../../util/establishMultitabRole';

View File

@ -16,7 +16,6 @@ import { toCredentialCreationOptions } from '../../../util/browser/passkeys';
import { getCurrentTabId } from '../../../util/establishMultitabRole';
import { buildCollectionByKey } from '../../../util/iteratees';
import { requestPermission, subscribe, unsubscribe } from '../../../util/notifications';
import { setTimeFormat } from '../../../util/oldLangProvider';
import requestActionTimeout from '../../../util/requestActionTimeout';
import { getServerTime } from '../../../util/serverTime';
import { callApi } from '../../../api/gramjs';
@ -642,7 +641,6 @@ addActionHandler('ensureTimeFormat', async (global, actions): Promise<void> => {
const timeFormat = COUNTRIES_WITH_12H_TIME_FORMAT
.has(global.auth.nearestCountry.toUpperCase()) ? '12h' : '24h';
actions.setSharedSettingOption({ timeFormat });
setTimeFormat(timeFormat);
}
if (selectSharedSettings(global).wasTimeFormatSetManually) {
@ -653,7 +651,6 @@ addActionHandler('ensureTimeFormat', async (global, actions): Promise<void> => {
if (nearestCountryCode) {
const timeFormat = COUNTRIES_WITH_12H_TIME_FORMAT.has(nearestCountryCode.toUpperCase()) ? '12h' : '24h';
actions.setSharedSettingOption({ timeFormat });
setTimeFormat(timeFormat);
}
});

View File

@ -12,6 +12,7 @@ import {
} from '../../../util/browser/windowEnvironment';
import { getCurrentTabId } from '../../../util/establishMultitabRole';
import generateUniqueId from '../../../util/generateUniqueId';
import { setTimeFormat as setLocalizedTimeFormat } from '../../../util/localization';
import { subscribe, unsubscribe } from '../../../util/notifications';
import { oldSetLanguage } from '../../../util/oldLangProvider';
import { decryptSessionByCurrentHash } from '../../../util/passcode';
@ -139,7 +140,9 @@ addCallback((global: GlobalState) => {
shouldInit: false,
}, tabState.id);
const { messageTextSize, language, shouldUseSystemTheme } = selectSharedSettings(global);
const {
messageTextSize, language, shouldUseSystemTheme, timeFormat,
} = selectSharedSettings(global);
const globalTheme = selectTheme(global);
const systemTheme = getSystemTheme();
@ -148,6 +151,7 @@ addCallback((global: GlobalState) => {
const performanceType = selectPerformanceSettings(global);
void oldSetLanguage(language as LangCode, undefined);
setLocalizedTimeFormat(timeFormat);
requestMutation(() => {
document.documentElement.style.setProperty(

View File

@ -7,7 +7,8 @@ import { requestMutation } from '../../../lib/fasterdom/fasterdom';
import { IS_IOS } from '../../../util/browser/windowEnvironment';
import { disableDebugConsole, initDebugConsole } from '../../../util/debugConsole';
import { getCurrentTabId } from '../../../util/establishMultitabRole';
import { oldSetLanguage, setTimeFormat } from '../../../util/oldLangProvider';
import { setTimeFormat as setLocalizedTimeFormat } from '../../../util/localization';
import { oldSetLanguage, setTimeFormat as setLegacyTimeFormat } from '../../../util/oldLangProvider';
import { applyPerformanceSettings } from '../../../util/perfomanceSettings';
import switchTheme from '../../../util/switchTheme';
import { updatePeerColors } from '../../../util/theme';
@ -59,7 +60,8 @@ addCallback((global: GlobalState) => {
}
if (sharedSettings.timeFormat !== oldSharedSettings.timeFormat) {
setTimeFormat(sharedSettings.timeFormat);
setLocalizedTimeFormat(sharedSettings.timeFormat);
setLegacyTimeFormat(sharedSettings.timeFormat);
}
if (sharedSettings.messageTextSize !== oldSharedSettings.messageTextSize) {

View File

@ -25,7 +25,7 @@ import {
ARCHIVED_FOLDER_ID, GENERAL_TOPIC_ID, REPLIES_USER_ID, TME_LINK_PREFIX,
VERIFICATION_CODES_USER_ID,
} from '../../config';
import { formatDateToString, formatTime } from '../../util/dates/dateFormat';
import { formatDateToString, formatTime } from '../../util/dates/oldDateFormat';
import { getPeerIdDividend, isUserId } from '../../util/entities/ids';
import { getServerTime } from '../../util/serverTime';
import { selectIsChatRestricted } from '../selectors';

Some files were not shown because too many files have changed in this diff Show More