Weave Code
Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Duration Laravel Package

bitandblack/duration

bitandblack/duration provides a small PHP/Laravel utility for working with time spans: create, parse, and format durations in a readable way, convert between units, and simplify common duration calculations for apps, jobs, and reports.

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Steps

  1. Installation

    composer require bitandblack/duration
    

    The package is framework-agnostic but Laravel-friendly. No additional configuration is needed beyond autoloading.

  2. First Use Case: Creating and Using Durations

    use BitAndBlack\Duration\Duration;
    
    // Create a duration (e.g., 2 hours 30 minutes)
    $duration = Duration::create(2, 'hours')->add(Duration::create(30, 'minutes'));
    
    // Or from total seconds
    $duration = Duration::fromSeconds(9000); // 9000 seconds = 2.5 hours
    
    // Format for display
    echo $duration->format('H:i:s'); // Outputs: "02:30:00"
    
  3. Where to Look First

    • Core Class: Duration – The main class for all operations.
    • Factory Methods: Duration::create(), Duration::fromSeconds(), Duration::fromMinutes(), etc.
    • Common Units: 'seconds', 'minutes', 'hours', 'days', 'weeks', 'months', 'years'.
    • Helper Methods: add(), subtract(), multiply(), divide(), getSeconds(), format().

Implementation Patterns

Common Workflows

1. Creating Durations

// From units
$duration = new Duration(1, 'day');

// From total seconds
$duration = Duration::fromSeconds(3600); // 1 hour

// From a string (if supported)
$duration = Duration::fromString('2 hours 30 minutes');

2. Manipulating Durations

// Add/subtract durations
$total = $duration->add(Duration::create(30, 'minutes'));
$remaining = $duration->subtract(Duration::create(1, 'hour'));

// Scale durations
$doubled = $duration->multiply(2);
$halved = $duration->divide(2);

3. Comparing Durations

if ($duration->isGreaterThan(Duration::create(1, 'hour'))) {
    // Handle longer durations
}

if ($duration->equals(Duration::fromSeconds(3600))) {
    // Handle exact matches
}

4. Converting Between Units

$seconds = $duration->getSeconds(); // Total in seconds
$hours = $duration->getHours();     // Total in hours (fractional)
$minutes = $duration->getMinutes(); // Total in minutes (fractional)

5. Formatting for Display

// Human-readable format
echo $duration->format('H:i:s'); // "01:00:00" for 1 hour

// Custom format (e.g., for logs)
echo $duration->format('Y-m-d H:i:s'); // "00-00-01 01:00:00" for 1 day 1 hour

6. Integration with Laravel

  • Validation:
    use Illuminate\Support\Facades\Validator;
    
    $validator = Validator::make($request->all(), [
        'duration' => 'required|duration', // Custom rule for duration validation
    ]);
    
  • Database Storage:
    // Store as total seconds in a bigint column
    $model->duration_seconds = $duration->getSeconds();
    
  • API Responses:
    return response()->json([
        'duration' => [
            'seconds' => $duration->getSeconds(),
            'human'   => $duration->format('H:i:s'),
        ],
    ]);
    

7. Working with Carbon

use Carbon\Carbon;

$carbonDate = Carbon::now()->add($duration->toDateInterval());

Laravel-Specific Patterns

Service Provider Binding

Bind the Duration class to Laravel’s service container for dependency injection:

// app/Providers/AppServiceProvider.php
use BitAndBlack\Duration\Duration;

public function register()
{
    $this->app->bind(Duration::class, function () {
        return new Duration();
    });
}

Facade (Optional)

Create a facade for cleaner syntax:

// app/Facades/Duration.php
namespace App\Facades;

use Illuminate\Support\Facades\Facade;

class Duration extends Facade
{
    protected static function getFacadeAccessor()
    {
        return 'duration';
    }
}

Register the facade in config/app.php:

'Duration' => App\Facades\Duration::class,

Custom Rules for Validation

Extend Laravel’s validation rules:

// app/Rules/DurationRule.php
namespace App\Rules;

use BitAndBlack\Duration\Duration;
use Illuminate\Contracts\Validation\Rule;

class DurationRule implements Rule
{
    public function passes($attribute, $value)
    {
        try {
            $duration = Duration::fromString($value);
            return true;
        } catch (\Exception $e) {
            return false;
        }
    }

    public function message()
    {
        return 'The :attribute must be a valid duration.';
    }
}

Usage:

$validator->rule(new DurationRule());

Gotchas and Tips

Pitfalls

  1. Unit Precision for Months/Years

    • Months and years are not fixed-length units (e.g., February has 28/29 days). Operations like add() or subtract() may yield unexpected results for these units.
    • Workaround: Use days for precise calculations or handle edge cases manually.
  2. Timezone Sensitivity

    • The package does not handle timezones natively. If integrating with Carbon, ensure timezone consistency:
      $carbonDate = Carbon::now()->setTimezone('UTC')->add($duration->toDateInterval());
      
  3. String Parsing Limitations

    • The fromString() method may not support all formats (e.g., "2h 30m" vs. "2 hours 30 minutes"). Test thoroughly with your expected inputs.
  4. Immutability

    • The package likely enforces immutability (methods like add() return new instances). This is good practice but requires adjusting to functional-style updates:
      $newDuration = $duration->add(Duration::create(1, 'hour'));
      // Original $duration remains unchanged
      
  5. Database Storage Quirks

    • Storing durations as objects in the database is not recommended. Use:
      • Total seconds (as bigint) for precision.
      • Human-readable strings (as text) for display purposes only.
  6. Performance with Large Durations

    • Operations on very large durations (e.g., centuries) may cause overflow or precision loss. Test with extreme values.

Debugging Tips

  1. Verify Unit Inputs

    • Ensure units are passed as strings (e.g., 'hours', not hours). Case-sensitive in some implementations.
  2. Check for Silent Failures

    • Some methods (e.g., fromString()) may throw exceptions for invalid inputs. Wrap in try-catch blocks:
      try {
          $duration = Duration::fromString($input);
      } catch (\InvalidArgumentException $e) {
          // Handle invalid duration
      }
      
  3. Log Duration Objects

    • Override __toString() for debugging:
      $duration->__toString(); // May not work by default; use $duration->format('H:i:s') instead.
      
  4. Validate Carbon Integration

    • When converting to DateInterval, ensure the result matches expectations:
      $interval = $duration->toDateInterval();
      var_dump($interval->format('%h hours %i minutes')); // Debug output
      

Extension Points

  1. Custom Units

    • Extend the package to support custom units (e.g., "workdays", "fortnights"):
      // Example: Add a "workday" unit (5 business hours)
      $duration->add(Duration::create(1, 'workday')); // Requires custom logic
      
  2. Localization

    • Override formatting for non-English locales:
      $duration->format('H:i:s', ['locale' => 'fr_FR']); // Hypothetical
      
  3. Serialization

    • Implement JsonSerializable for API responses:
      class Duration implements JsonSerializable
      {
          public function jsonSerialize()
          {
              return [
                  'seconds' => $this->getSeconds(),
                  'human'   => $this->format('H:i:s'),
              ];
          }
      }
      
  4. Laravel Events

    • Trigger events for duration changes (e.g., subscription renewals):
Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
takashato/laravel-vietqr
aitor24/laralang
kraenzle-ritter/entity-relations
dindigital/din-image
pomirleanu/image-colors
sawmainek/laravel-api-generator
delatbabel/jsonresponses
mouhamedfd/permissions-generator
eduplus/qr
laravel2580/idehelpers
delatbabel/viewpages
anavel/gettext
muhamadrezaar/highcharts
delatbabel/keylists
frankkessler/salesforce-laravel-oauth2-rest
anavel/foundation
wdmtech/enviricons
eii/laravel-captcha
muka/shape-reader
tdt/json