$countryCode, 'startDate' => $startDate, 'minutesDuration' => $minutesDuration, 'calculateWithWorkingDays' => $calculateWithWorkingDays, 'startWorkday' => $startWorkday, 'endWorkday' => $endWorkday, ], [ 'countryCode' => [new CountryCodeExists()], 'startDate' => ['required', new DateYMDHI()], 'minutesDuration' => 'integer|min:1', 'calculateWithWorkingDays' => 'boolean', 'startWorkday' => ['required', new DateHI()], 'endWorkday' => ['required', new DateHI()], ] ); if ($validator->fails()) { return response()->json(['errors' => $validator->errors()], 400); } $duration = Duration::parse(sprintf('P0DT%dM', $minutesDuration)); $startWorkday = LocalTime::parse($startWorkday); $startDate = \DateTimeImmutable::createFromFormat('Y-m-d H:i:s', $startDate . ":00"); $endWorkday = LocalTime::parse($endWorkday); if ($startDate === false) { return response()->json(['errors' => ['startDate' => ['validation.date_ymdhi']]], 400); } if (($result = $this->validateParsedData($startDate, $startWorkday, $endWorkday)) !== null) { return $result; } $workMinutes = $this->durationConvertor->convertIntoWorkDuration($duration, $startWorkday, $endWorkday, $startDate); if ($workMinutes->overlaps === true) { $dueDate = $startDate->setTime($startWorkday->getHour(), $startWorkday->getMinute(), $startWorkday->getSecond()) ->add(new \DateInterval(sprintf('PT%dM', $workMinutes->duration->toMinutes()))); } else { $dueDate = $startDate->add(new \DateInterval(sprintf('PT%dM', $workMinutes->duration->toMinutes()))); } // test if false startDate + startDate must be after startWorkday and before endWorkday if ($calculateWithWorkingDays) { $durationSolver = $this->durationSolverFactory->createDurationSolverForCountry($countryCode); $dueDate = $durationSolver->calculateDuration($startDate, $dueDate); } return response()->json([ 'estimation_date' => $dueDate->format('Y-m-d H:i:s'), ]); } private function validateParsedData(\DateTimeInterface $startDate, LocalTime $startWorkday, LocalTime $endWorkday): JsonResponse|null { if ($startWorkday->isAfter($endWorkday)) { return response()->json(['errors' => ['startWorkday' => ['validation.start_workday_must_be_before_end_workday']]], 400); } if ($startWorkday->isEqualTo($endWorkday)) { return response()->json(['errors' => ['startWorkday' => ['validation.start_workday_must_not_be_equal_to_end_workday']]], 400); } if ($startWorkday->isAfter(LocalTime::fromNativeDateTime($startDate))) { return response()->json(['errors' => ['startDate' => ['validation.start_workday_must_be_before_start_date']]], 400); } if ($endWorkday->isBefore(LocalTime::fromNativeDateTime($startDate))) { return response()->json(['errors' => ['endWorkday' => ['validation.end_workday_must_be_after_start_date']]], 400); } return null; } }