This Laravel application calculates the duration between two provided dates, and outputs the number of days, week days, and weeks.
A conversion parameter can also be provided to the endpoint to convert the result to seconds, minutes, hours, or years.
I've used Laravel for this, as its PHP, and something I am familiar with.
The endpoint is a POST request to /calculate-duration
, this was done in
order to leverage Laravel's validation rules. This also allows the end user to
specify their data in JSON, which can be easier than managing query parameters.
Due to the specifications detailing that the duration should be initially calculated in days, week days, and weeks, and then convert it to the another value, the timezone requirement seemed redundant. This is because the most granular interval the specifications allows is a day. If, after more discussion, the requirement changed to needing the seconds between two datetimes, I would have changed the CalculateDuration service class to calculate the duration with the granularity of a second.
The weeks are calculated using $start->diff($end)
, as opposed to using the
PHP DateInterval
and DatePeriod
classes. This is primarily due to the
rounding issues I experienced during dev, i.e 2024-08-01 2024-08-17 equals 4
weeks, as the duration exists over 3 weeks, but does not span the whole of
the 3 weeks. The duration of the interval is then also added $this->end
property during the calculation (in order to include the final day in the
calculation when using P1D for the DateInterval
).
routes/web.php
app/Http/Controllers/CalculateDurationController.php
app/Http/Requests/CalculateDurationRequest.php
app/Http/Resources/CalculateDurationResource.php
app/Services/CalculateDuration.php
DurationModifier
if requiredapp/Enums/DurationModifier.php
convert_to
POST request parameterapp/DTO/DurationResult.php
tests/*
Unit and integration tests.
There are two things I would probably improve, if this was intended for production
I'd like to avoid the ternary on CalculateDuration.php:56, although I couldn't think of a quick way to simplify it. Its been a long day.
Tests relating to timezones are lacking, due to the aforementioned redundancy.
All is well, as all is dockerized.
composer install
./vendor/bin/sail up
./vendor/bin/sail test
You can the convert_to value to second
, minute
, hour
, year
, or omit the key entirely.
read -r -d '' VAR << EOM
{
"start": {
"date": "2024-08-01"
},
"end": {
"date": "2024-08-21"
},
"convert_to": null
}
EOM
curl -v \
--data "${VAR}" \
-H "Content-Type: application/json" \
-H "Accept: application/json" \
"http://localhost:80/calculate-duration"