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.
 
 
 
Tovi Jaeschke-Rogers c55303af1f feat: add readme.md 4 months ago
app feat: Add API endpoint to calculate duration between two dates 4 months ago
bootstrap feat: add readme.md 4 months ago
config feat: Add API endpoint to calculate duration between two dates 4 months ago
database feat: Add API endpoint to calculate duration between two dates 4 months ago
public feat: Add API endpoint to calculate duration between two dates 4 months ago
resources feat: Add API endpoint to calculate duration between two dates 4 months ago
routes feat: Add API endpoint to calculate duration between two dates 4 months ago
storage feat: Add API endpoint to calculate duration between two dates 4 months ago
tests feat: Add API endpoint to calculate duration between two dates 4 months ago
.editorconfig feat: Add API endpoint to calculate duration between two dates 4 months ago
.env.example feat: Add API endpoint to calculate duration between two dates 4 months ago
.gitattributes feat: Add API endpoint to calculate duration between two dates 4 months ago
.gitignore feat: Add API endpoint to calculate duration between two dates 4 months ago
README.md feat: add readme.md 4 months ago
artisan feat: Add API endpoint to calculate duration between two dates 4 months ago
composer.json feat: Add API endpoint to calculate duration between two dates 4 months ago
composer.lock feat: Add API endpoint to calculate duration between two dates 4 months ago
docker-compose.yml feat: Add API endpoint to calculate duration between two dates 4 months ago
package.json feat: Add API endpoint to calculate duration between two dates 4 months ago
phpunit.xml feat: Add API endpoint to calculate duration between two dates 4 months ago
vite.config.js feat: Add API endpoint to calculate duration between two dates 4 months ago

README.md

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"