Summary
After a comprehensive comparison with Carbon, here are features that could be valuable additions to Chronos while maintaining its minimal, immutable-only philosophy.
So:
Which of the following are useful enough to warrant their implementation?
It helps to close the gap, but at the same time we only want to include actually useful things.
Very High Priority (Quick Wins)
These are small, high-value additions:
Factory Methods
Validation
Serialization
Timezone
Boundary Methods
Comparison Methods
High Priority
Rounding Methods
Safe Creation
Difference Methods
DST-Safe Operations
Navigation
Generic Boundary Methods
Medium Priority
Comparison Methods
Properties
Serialization
Calendar Format
Lower Priority (Specialized)
Precision Support
Additional Boundaries
Out of Scope (By Design)
These Carbon features are intentionally not planned for Chronos to maintain its minimal footprint:
- ❌ Macro system (
macro(), mixin())
- ❌ 824 locale files - Chronos has basic English only
- ❌ Mutable class - Chronos is immutable-only
- ❌ CarbonInterval - Chronos uses plain DateInterval
- ❌ Full localization with Symfony Translation
- ❌ PHP 8.1 Unit/WeekDay/Month enums
Related PRs
References
Summary
After a comprehensive comparison with Carbon, here are features that could be valuable additions to Chronos while maintaining its minimal, immutable-only philosophy.
So:
Which of the following are useful enough to warrant their implementation?
It helps to close the gap, but at the same time we only want to include actually useful things.
Very High Priority (Quick Wins)
These are small, high-value additions:
Factory Methods
createFromTimestampMs(int $timestamp)- Create from millisecond timestamp (JavaScript interop)createFromTimestampMsUTC(int $timestamp)- Create from ms timestamp in UTCValidation
hasFormat(string $date, string $format): bool- Check if string matches a date formatcanBeCreatedFromFormat(string $date, string $format): bool- Validate format match without throwingSerialization
toArray(): array- Convert to associative array (['year' => 2024, 'month' => 1, ...])toIso8601ZuluString(): string- UTC ISO8601 withZsuffix (common for APIs)toDateTimeLocalString(): string- HTML5datetime-localinput formatTimezone
utc(): static- Convenience method for->setTimezone('UTC')shiftTimezone(DateTimeZone|string $tz): static- Change timezone keeping local time (different fromsetTimezonewhich converts)Boundary Methods
startOfHour(): static- Reset to hour start (X:00:00)endOfHour(): static- Set to hour end (X:59:59.999999)Comparison Methods
isStartOfDay(): bool- Check if time is 00:00:00isEndOfDay(): bool- Check if time is 23:59:59isMidnight(): bool- Alias for isStartOfDayisMidday(): bool- Check if time is 12:00:00High Priority
Rounding Methods
round(string $unit, int $precision = 1): static- Round to nearest unitfloor(string $unit, int $precision = 1): static- Floor to unitceil(string $unit, int $precision = 1): static- Ceil to unitSafe Creation
createSafe(int $year, int $month, int $day, ...): static- Throws on invalid dates instead of silent overflow (e.g., Feb 31 throws instead of becoming Mar 3)Difference Methods
diffInMilliseconds(?DateTimeInterface $other = null, bool $absolute = true): intdiffInMicroseconds(?DateTimeInterface $other = null, bool $absolute = true): intDST-Safe Operations
addRealUnit(string $unit, int $value): static- Add without DST adjustmentsubRealUnit(string $unit, int $value): static- Subtract without DST adjustmentNavigation
nextWeekday(): static- Move to next Monday-FridaypreviousWeekday(): static- Move to previous Monday-FridaynextWeekendDay(): static- Move to next Saturday/SundaypreviousWeekendDay(): static- Move to previous Saturday/SundayGeneric Boundary Methods
startOf(string $unit): static- Generic start of any unitendOf(string $unit): static- Generic end of any unitisStartOf(string $unit): bool- Check if at start of unitisEndOf(string $unit): bool- Check if at end of unitMedium Priority
Comparison Methods
isNowOrFuture(): bool- True if now or in the futureisNowOrPast(): bool- True if now or in the pastisLongYear(): bool- Check if year has 53 weeksisSameQuarter(DateTimeInterface $date, bool $ofSameYear = true): boolisSameUnit(string $unit, DateTimeInterface $date): bool- Generic same-unit checkProperties
$daysInYearproperty - Days in the year (365 or 366)$dayOfYearproperty - Day of year (1-366)Serialization
getTimestampMs(): int- Millisecond timestampvalueOf(): int- JavaScript Date valueOf (ms timestamp)toObject(): stdClass- Convert to stdClassCalendar Format
calendar(?DateTimeInterface $referenceTime = null): string- Calendar-relative format ("Today at 2:00 PM", "Yesterday at 3:00 PM", "Last Monday")Lower Priority (Specialized)
Precision Support
toTimeString(string $precision = 'second'): string- Time with precision (minute/second/ms/us)toDateTimeString(string $precision = 'second'): string- DateTime with precisionAdditional Boundaries
startOfMinute(): static/endOfMinute(): staticstartOfSecond(): static/endOfSecond(): staticmidDay(): static- Set to 12:00:00Out of Scope (By Design)
These Carbon features are intentionally not planned for Chronos to maintain its minimal footprint:
macro(),mixin())Related PRs
withTestNow()for scoped time mockingReferences