Simple problems require simple solutions
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 

3.3 KiB

Date Duration Calculation

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.

General Decisions made

  • 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).

General Code Structure

  1. routes/web.php

    • Defines the POST request route
  2. app/Http/Controllers/CalculateDurationController.php

    • Handles the POST request
  3. app/Http/Requests/CalculateDurationRequest.php

    • Performs validation on the POST request data
  4. app/Http/Resources/CalculateDurationResource.php

    • Returns the calculated durations
  5. app/Services/CalculateDuration.php

    • Calculates the duration, and converts to the DurationModifier if required
  6. app/Enums/DurationModifier.php

    • Enum for the possible conversions, also used to validated the convert_to POST request parameter
  7. app/DTO/DurationResult.php

    • Data transfer object, so we aren't parsing around arrays, and needing to assume the array keys exist.
  8. tests/* Unit and integration tests.

Room for improvement

There are two things I would probably improve, if this was intended for production

  1. 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.

  2. Tests relating to timezones are lacking, due to the aforementioned redundancy.

Running the code

All is well, as all is dockerized.

composer install

./vendor/bin/sail up
./vendor/bin/sail test

Testing manually

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"