Skip to content

fix: round up trial duration to avoid Carbon float truncation#193

Open
dan2k3k4 wants to merge 2 commits into
devfrom
advisor/003-fix-trial-duration-carbon-truncation
Open

fix: round up trial duration to avoid Carbon float truncation#193
dan2k3k4 wants to merge 2 commits into
devfrom
advisor/003-fix-trial-duration-carbon-truncation

Conversation

@dan2k3k4

@dan2k3k4 dan2k3k4 commented Jul 1, 2026

Copy link
Copy Markdown
Member

Fixes trials being set up to a day short when calculated from an end date, caused by Carbon 3 returning a fractional day count that was truncated.

Greptile Summary

This PR fixes a one-day shortfall in trial durations when calculateAndSetTrialDatesFromEndDate is used, caused by Carbon 3's diffInDays() now returning a float that PHP's implicit int cast was silently truncating toward zero.

  • Core fix (PolydockAppInstance.php): wraps diffInDays() with ceil() so any fractional day is rounded up to the next whole day, ensuring the trial always covers at least the requested end date.
  • New test suite (TrialDateCalculationTest.php): adds three cases — exact whole-day end dates, partial-day end dates (regression for the rounding bug), and a past end date (guards the null-reset path, now properly primed with a live trial before the call).

Confidence Score: 5/5

Safe to merge — the change is a minimal one-line fix with correct rounding semantics and direct test coverage for the regression.

The fix correctly addresses Carbon 3's float return from diffInDays() by using ceil() instead of a truncating int cast. Behaviour for future dates (rounds up), exact whole-day dates (unchanged), and past dates (negative float still maps to ≤ 0, returning null) is all correct. The three new test cases exercise each path, including the previously-flagged null-reset path which is now properly primed.

No files require special attention.

Important Files Changed

Filename Overview
app/Models/PolydockAppInstance.php Single-line fix: wraps diffInDays() with ceil() to prevent float truncation in Carbon 3. Logic is correct for future, exact, and past dates.
tests/Unit/Models/TrialDateCalculationTest.php New test file with three cases covering whole days, partial-day rounding (regression), and past-date null-reset (properly primed per prior feedback).

Sequence Diagram

%%{init: {'theme': 'neutral'}}%%
sequenceDiagram
    participant Caller
    participant calculateAndSetTrialDatesFromEndDate
    participant Carbon
    participant calculateAndSetTrialDates

    Caller->>calculateAndSetTrialDatesFromEndDate: trialEndDateTime
    calculateAndSetTrialDatesFromEndDate->>Carbon: "now()->diffInDays(trialEndDateTime)"
    Carbon-->>calculateAndSetTrialDatesFromEndDate: float (e.g. 5.54)
    Note over calculateAndSetTrialDatesFromEndDate: ceil(float) → round up<br/>(was: int cast → truncate down)
    calculateAndSetTrialDatesFromEndDate->>calculateAndSetTrialDates: "durationDays = 6 (int)"
    alt "durationDays > 0"
        calculateAndSetTrialDates-->>Caller: "trial_ends_at = now() + 6 days"
    else "durationDays <= 0 (past date)"
        calculateAndSetTrialDates-->>Caller: "trial_ends_at = null"
    end
Loading
%%{init: {'theme': 'base', 'themeVariables': {"darkMode": true, "background": "#0d1117", "primaryColor": "#21262d", "primaryTextColor": "#e6edf3", "primaryBorderColor": "#8b949e", "lineColor": "#8b949e", "textColor": "#e6edf3", "edgeLabelBackground": "#161b22", "actorBkg": "#21262d", "actorBorder": "#8b949e", "actorTextColor": "#e6edf3", "actorLineColor": "#8b949e", "signalColor": "#8b949e", "signalTextColor": "#e6edf3", "noteBkgColor": "#373320", "noteBorderColor": "#d4a72c", "noteTextColor": "#f0e6c0", "labelBoxBkgColor": "#21262d", "labelBoxBorderColor": "#8b949e", "labelTextColor": "#e6edf3", "loopTextColor": "#e6edf3", "activationBkgColor": "#30363d", "activationBorderColor": "#8b949e"}}}%%
sequenceDiagram
    participant Caller
    participant calculateAndSetTrialDatesFromEndDate
    participant Carbon
    participant calculateAndSetTrialDates

    Caller->>calculateAndSetTrialDatesFromEndDate: trialEndDateTime
    calculateAndSetTrialDatesFromEndDate->>Carbon: "now()->diffInDays(trialEndDateTime)"
    Carbon-->>calculateAndSetTrialDatesFromEndDate: float (e.g. 5.54)
    Note over calculateAndSetTrialDatesFromEndDate: ceil(float) → round up<br/>(was: int cast → truncate down)
    calculateAndSetTrialDatesFromEndDate->>calculateAndSetTrialDates: "durationDays = 6 (int)"
    alt "durationDays > 0"
        calculateAndSetTrialDates-->>Caller: "trial_ends_at = now() + 6 days"
    else "durationDays <= 0 (past date)"
        calculateAndSetTrialDates-->>Caller: "trial_ends_at = null"
    end
Loading

Reviews (2): Last reviewed commit: "test: make past-date trial test exercise..." | Re-trigger Greptile

Comment thread tests/Unit/Models/TrialDateCalculationTest.php
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant