رفتن به محتوای اصلی

استاندارد زمان‌ها

زمان روی شبکه چطور است؟​

زمان روی wire همیشه رشتهٔ ISO است — نه epoch-millis عددی. پاسخ‌های sync زمان UTC برمی‌گردانند، مثل 2026-10-01T08:00:00.000Z. نمایش جلالی یا میلادی، فقط نمایش است و لحظهٔ ذخیره‌شده را عوض نمی‌کند.

اعتبارسنجی ورودی هر رشتهٔ قابل parse با Date.parse را می‌پذیرد، اما ISO UTC بفرستید. تاریخ غیرقابل parse قبل از ذخیره رد می‌شود و محل رد شدن بستگی به مسیر دارد:

مسیررفتار
pushخطای همان آیتم (invalid_item)؛ بقیهٔ آیتم‌ها مستقل ادامه می‌یابند
batch گزارش خطا400 برای کل درخواست، بدون درج هیچ آیتم

هیچ‌کدام از این دو، خطای 500 عمومی نیست.

فیلد sync ← ستون DBمالکیت
createdAt ← createdورودی اختیاری، فقط هنگام ساخت مؤثر؛ ویرایش بعدی تغییرش نمی‌دهد
updatedAt ← updatedسرور (trigger) هنگام هر نوشتن
deletedزمان حذف نرم یا null؛ با عملیات delete/restore تغییر می‌کند
versionرشتهٔ ده‌دهی از دنبالهٔ سرور — نه timestamp و نه عدد JSON

چرا ساعت یا روز جابه‌جا شد؟​

وب زمان ISO را با new Date() می‌خواند، ساعت فرم را در منطقهٔ زمانی دستگاه کاربر تفسیر می‌کند و با toISOString() به UTC تبدیل می‌کند. مثلاً 08:00Z در تهران ساعت 11:30 است — این دو نمایشِ یک لحظه‌اند، نه دو زمان متفاوت.

برای عیب‌یابی، سه چیز را کنار هم بگذارید: رشتهٔ ISO دریافتی، منطقهٔ زمانی دستگاه و تبدیلِ فرم. در رشتهٔ ISO دست نبرید (حذف Z یا اضافه‌کردن دوبارهٔ offset، داده را خراب می‌کند). اگر ذخیرهٔ محلی شما epoch-millis است، تبدیل را فقط در مرز شبکه انجام دهید.

منطقهٔ زمانی و تمام‌روز​

  • DTO فعلی رویداد فیلد timezone ندارد؛ ستون رزروشدهٔ schema هم تضمینی برای حفظ منطقهٔ IANA نیست.
  • allDay خودش زمان‌ها را جابه‌جا نمی‌کند؛ فقط نحوهٔ نمایش/تفسیر را علامت می‌زند.
  • رفتار فعلی فرم وب: شروع را ۰۰:۰۰ از روزِ شروعِ انتخابی و پایان را 23:59:00 از همان روزِ پایانِ انتخاب‌شده، در زمان محلی دستگاه می‌سازد. پایانِ فرم، نیمه‌شبِ انحصاریِ روز بعد نیست — وقتی محدودهٔ تمام‌روز واقعی را محاسبه می‌کنید، باید این را لحاظ کنید.
  • فیلتر بازه در وب، شرط event.start < range.end && event.end > range.start را می‌گذارد.

از این رفتارها، قرارداد RFC/iCal یا رفتار همهٔ کلاینت‌ها را نتیجه نگیرید.

تازگی داده​

از ساعت دستگاه برای تشخیص تازه‌بودن داده استفاده نکنید؛ معیار سروری version (برای ردیف) و cursor (برای پیشرفت pull) است — توضیح در همگام‌سازی. trigger به‌روزرسانی updated فقط برای چهار موجودیت Calendar/Event/Task/Reminder است.

منابع: apps/api/prisma/schema.prisma؛ در وب src/components/calendar-app/EventModal.tsx و src/features/events/mappers.ts و local.ts.