DEV Community

loading...
Cover image for Human readable Intervals

Human readable Intervals

gummibeer profile image Tom Witkowski Originally published at gummibeer.dev ・2 min read

Every Laravel application has several configuration values that represent a given amount of seconds or minutes.
Like the session.lifetime, auth.password_timeout, queue.connections.*.retry_after and a lot more.
By default all these values are a single integer like 10800, some of them even missing the unit in the description.

Multiplication

I bet that most of you know and have already done the easiest way - replace the single integer with a multiplication like 3 * 60 * 60 which is the same as 10800.
Another benefit is that you can guess what's the interval as it's days * minutes * seconds.
But there are still problems:

  1. it requires brain capacity to parse the multiplication
  2. not all intervals are seconds - how would you differentiate between 10 * 60 (10 hours in minutes) and 10 * 60 (10 minutes in seconds)
  3. it gets even harder when you need an interval like "2 days 6 hours" in seconds (2 * 24 * 60 * 60) + (6 * 60 * 60)

Luckily there's a solution for both issues.

Carbon Interval

Some time ago @marcelpociot posted this solution on Twitter.

If you don't know the class already - the nesbot/carbon (required by Laravel itself) provides the \Carbon\CarbonInterval class (docs).

This class comes with a human-readable fluent API to write your interval however you want.
The important part is the magic property totalSeconds - similar properties exist for minutes, days and so on.

use Carbon\CarbonInterval;

CarbonInterval::days(2)->hours(6)->totalSeconds;
Enter fullscreen mode Exit fullscreen mode

This is helpful in every part of your application - not only the configuration but also the real app code, for example cache TTL, signed URL expiration and wherever you need a given amount of seconds, minutes or other time units.

Constants

@devfrey asked how this works with constants.

Short: it doesn't.

I would recommend using the multiplication or single integer solution with an explanatory comment. I'm always using two comments - one above the const which describes the value and one at the end of the line that contains the unit.

// 5 minutes
const DEFAULT_TTL = 5 * 60; // seconds

// 7 days
const REMINDER_DELAY = 7 * 24 * 60; // minutes
Enter fullscreen mode Exit fullscreen mode

Environment Variables

In some cases you possibly want to use a .env variable to define your config interval and it should be possible to change the insert units - for example for development/testing purposes.
So by default it's 7 days but you want to be able to set it to 5 minutes without adjusting your code or complex conditions.
The solution is the static \Carbon\CarbonInterval::fromString() method that accepts a string, similar but different to strtotime() function.

In one of our projects we had to prevent password reset for 7 days after it was successfully reset. But for sure we had to use something like 5-10 minutes on our local machines and several hours on our staging system.

use Carbon\CarbonInterval;

return [
    // ...

    'password_reset_decay' => CarbonInterval::fromString(env('PASSWORD_RESET_DECAY', '7 days'))->totalSeconds,

    // ...
];
Enter fullscreen mode Exit fullscreen mode

And in your .env file you can define the values like the following.

# production
PASSWORD_RESET_DECAY="7 days"
# staging
PASSWORD_RESET_DECAY="1 day"
# development
PASSWORD_RESET_DECAY="6 hours"
# local
PASSWORD_RESET_DECAY="10 minutes"
Enter fullscreen mode Exit fullscreen mode

Discussion (0)

pic
Editor guide