refactor: normalize date handling to Tehran timezone

- Updated date handling in BlogSeoFields and ScheduleSection to use Tehran timezone utilities for consistency.
- Introduced `toTehranClockTime`, `tehranWallClockToUnix`, and `todayIso` functions for accurate date representation.
- Modified various components to utilize these new utilities, ensuring that date strings are correctly formatted and timestamps are accurately converted.
- Enhanced API documentation to clarify the handling of date fields, emphasizing the importance of server-local midnight.
- Added tests to verify that date overrides and holidays maintain the correct day without shifting due to timezone discrepancies.
This commit is contained in:
hamed
2026-07-27 19:37:44 +03:30
parent 2963e2ac74
commit b423a0ae4d
21 changed files with 267 additions and 57 deletions
@@ -10,7 +10,7 @@ import SearchableSelect from '../ui/SearchableSelect';
import PersianDateInput from '../ui/PersianDateInput';
import { UserTick, FilesServiceAddCard, ClockP, TrashRed } from '../icons/FilesServiceIcons';
import { useAuthStore } from '../../stores/authStore';
import { digitsOnly } from '../../lib/utils';
import { digitsOnly, todayIso } from '../../lib/utils';
import {
DEFAULT_SERVICE_CATEGORY, contractPercentFor, patientShareOf,
type CoverageRule as Rule, type TenantContract,
@@ -29,7 +29,7 @@ const VISIT_SERVICE_CATEGORY = DEFAULT_SERVICE_CATEGORY;
// مصرف‌کنندگان قبلی (و تست‌ها) نشکنند.
export { patientShareOf };
const todayISO = () => new Date().toISOString().slice(0, 10);
const todayISO = todayIso;
const nowHHMM = () => {
const d = new Date();
return `${String(d.getHours()).padStart(2, '0')}:${String(d.getMinutes()).padStart(2, '0')}`;
@@ -5,7 +5,7 @@ import { toast } from 'sonner';
import { api } from '../../lib/api';
import type { ApiResponse } from '../../lib/api';
import { PencilIcon, TrashIcon } from '@heroicons/react/24/outline';
import { formatRial, formatDateTime, tomanToRial, rialToToman } from '../../lib/utils';
import { formatRial, formatDateTime, tomanToRial, rialToToman, todayIso } from '../../lib/utils';
import type { DiscountSuggestion } from '../../types';
import type { SessionCardData } from '../SessionServiceCard';
import SearchableSelect from '../ui/SearchableSelect';
@@ -26,7 +26,7 @@ export const METHOD_LABELS: Record<string, string> = {
wallet: 'پرداخت از کیف پول', pos: 'پرداخت کارتخوان', cash: 'پرداخت نقدی', card: 'کارت به کارت',
};
const todayISO = () => new Date().toISOString().slice(0, 10);
const todayISO = todayIso;
/** YYYY-MM-DD → unix (ظهر همان روز تا با هر timezone یک روز بماند) */
const isoToUnix = (iso: string) => Math.floor(new Date(`${iso}T12:00:00`).getTime() / 1000);