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:
@@ -0,0 +1,112 @@
|
||||
<?php
|
||||
|
||||
namespace App\Tests\Appointment;
|
||||
|
||||
use App\Doctor\Entity\Doctor;
|
||||
use App\Tests\ApiTestCase;
|
||||
|
||||
/**
|
||||
* تاریخ خاص و تعطیلات باید دقیقاً همان روزِ ارسالی را نگه دارند: timestamp روی
|
||||
* نیمهشبِ محلی و یک رشتهٔ `Y-m-d` کانونی در پاسخ، تا کلاینت مجبور به تبدیل
|
||||
* timestamp (و جابهجایی یکروزه بهخاطر UTC) نباشد.
|
||||
*/
|
||||
class SpecialDateBoundaryTest extends ApiTestCase
|
||||
{
|
||||
private function makeDoctor(): Doctor
|
||||
{
|
||||
$owner = $this->createUser(['ROLE_DOCTOR']);
|
||||
$doctor = new Doctor($owner, 'دکتر تاریخ');
|
||||
$this->em->persist($doctor);
|
||||
$this->em->flush();
|
||||
|
||||
return $doctor;
|
||||
}
|
||||
|
||||
public function testOverrideKeepsExactDayAndReturnsDateString(): void
|
||||
{
|
||||
$doctor = $this->makeDoctor();
|
||||
$date = date('Y-m-d', strtotime('+9 days'));
|
||||
|
||||
$body = $this->authJson('POST', '/api/v1/appointment-settings/date-override', $doctor->getUser(), [
|
||||
'doctor_uuid' => $doctor->getUuid(),
|
||||
'date' => $date,
|
||||
'active' => false,
|
||||
]);
|
||||
|
||||
self::assertSame(201, $this->responseCode());
|
||||
self::assertSame($date, $body['data']['data']['date_string']);
|
||||
self::assertSame((int) strtotime($date . ' 00:00:00'), $body['data']['data']['date']);
|
||||
self::assertSame($date, date('Y-m-d', $body['data']['data']['date']));
|
||||
}
|
||||
|
||||
public function testOverrideNormalizesTimestampWithTimeToLocalMidnight(): void
|
||||
{
|
||||
$doctor = $this->makeDoctor();
|
||||
$date = date('Y-m-d', strtotime('+10 days'));
|
||||
|
||||
// ورودی ISO با ساعت (مثل چیزی که toISOString مرورگر میسازد) نباید روز را جابهجا کند.
|
||||
$body = $this->authJson('POST', '/api/v1/appointment-settings/date-override', $doctor->getUser(), [
|
||||
'doctor_uuid' => $doctor->getUuid(),
|
||||
'date' => $date . ' 23:45:00',
|
||||
'active' => false,
|
||||
]);
|
||||
|
||||
self::assertSame(201, $this->responseCode());
|
||||
self::assertSame($date, $body['data']['data']['date_string']);
|
||||
self::assertSame((int) strtotime($date . ' 00:00:00'), $body['data']['data']['date']);
|
||||
}
|
||||
|
||||
public function testOverridePatchKeepsExactDay(): void
|
||||
{
|
||||
$doctor = $this->makeDoctor();
|
||||
$first = date('Y-m-d', strtotime('+11 days'));
|
||||
$second = date('Y-m-d', strtotime('+12 days'));
|
||||
|
||||
$created = $this->authJson('POST', '/api/v1/appointment-settings/date-override', $doctor->getUser(), [
|
||||
'doctor_uuid' => $doctor->getUuid(),
|
||||
'date' => $first,
|
||||
'active' => false,
|
||||
]);
|
||||
$uuid = $created['data']['data']['uuid'];
|
||||
|
||||
$patched = $this->authJson('PATCH', "/api/v1/appointment-settings/date-override/{$uuid}", $doctor->getUser(), [
|
||||
'date' => $second,
|
||||
]);
|
||||
|
||||
self::assertSame(200, $this->responseCode());
|
||||
self::assertSame($second, $patched['data']['data']['date_string']);
|
||||
}
|
||||
|
||||
public function testHolidayKeepsExactDaysAndReturnsDateStrings(): void
|
||||
{
|
||||
$doctor = $this->makeDoctor();
|
||||
$start = date('Y-m-d', strtotime('+13 days'));
|
||||
$end = date('Y-m-d', strtotime('+15 days'));
|
||||
|
||||
$body = $this->authJson('POST', '/api/v1/appointment-settings/holidays', $doctor->getUser(), [
|
||||
'doctor_uuid' => $doctor->getUuid(),
|
||||
'start_date' => $start,
|
||||
'end_date' => $end,
|
||||
'reason' => 'سفر',
|
||||
]);
|
||||
|
||||
self::assertSame(201, $this->responseCode());
|
||||
self::assertSame($start, $body['data']['data']['start_date_string']);
|
||||
self::assertSame($end, $body['data']['data']['end_date_string']);
|
||||
self::assertSame((int) strtotime($start . ' 00:00:00'), $body['data']['data']['start_date']);
|
||||
self::assertSame((int) strtotime($end . ' 00:00:00'), $body['data']['data']['end_date']);
|
||||
}
|
||||
|
||||
public function testInvalidDateIsRejected(): void
|
||||
{
|
||||
$doctor = $this->makeDoctor();
|
||||
|
||||
$this->authJson('POST', '/api/v1/appointment-settings/date-override', $doctor->getUser(), [
|
||||
'doctor_uuid' => $doctor->getUuid(),
|
||||
'date' => 'not-a-date',
|
||||
'active' => false,
|
||||
]);
|
||||
|
||||
self::assertSame(422, $this->responseCode());
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user