561: Replace SpoonDate#442
Conversation
Reviewer's GuideReplaces legacy SpoonDate usage with IntlDateFormatter and native PHP date functions, and adds language helper methods for parameterized labels/messages/errors, ensuring locale-aware date formatting across backend and frontend components. Sequence diagram for the updated getTimeAgo date formatting flowsequenceDiagram
participant Caller
participant DataGridFunctions
participant BackendLanguage
participant Language
participant IntlDateFormatter
Caller->>DataGridFunctions: getTimeAgo(timestamp)
alt [timestamp === 0]
DataGridFunctions-->>Caller: ""
else [timestamp > 0]
DataGridFunctions->>BackendLanguage: getInterfaceLanguage()
BackendLanguage-->>DataGridFunctions: locale
DataGridFunctions->>IntlDateFormatter: __construct(locale, NONE, NONE, null, null, "yyyy-MM-dd HH:mm:ss")
DataGridFunctions->>IntlDateFormatter: format(timestamp)
IntlDateFormatter-->>DataGridFunctions: formattedDateTime
DataGridFunctions->>IntlDateFormatter: __construct(locale, NONE, NONE, null, null, "d MMMM yyyy HH:mm")
DataGridFunctions->>IntlDateFormatter: format(timestamp)
IntlDateFormatter-->>DataGridFunctions: formattedTitle
DataGridFunctions-->>DataGridFunctions: compute seconds, minutes, hours, days, months, years
alt [count <= 0]
DataGridFunctions->>Language: lbl(TimeAgoEmpty)
Language-->>DataGridFunctions: label
else [count > 0]
alt [count === 1]
DataGridFunctions->>Language: lbl(keySingular)
Language-->>DataGridFunctions: timeAgo
else [count > 1]
DataGridFunctions->>Language: lblWithParameters(keyPlural, [count])
Language-->>DataGridFunctions: timeAgo
end
end
DataGridFunctions-->>Caller: "<time ...>" + timeAgo
end
File-Level Changes
Tips and commandsInteracting with Sourcery
Customizing Your ExperienceAccess your dashboard to:
Getting Help
|
There was a problem hiding this comment.
Hey - I've found 1 issue, and left some high level feedback:
- The repeated instantiation of
IntlDateFormatterwith identical patterns (e.g. ingetDate,getLongDate,getTime, blog archive title/breadcrumb, and form export) could be centralized in a small helper/factory to avoid duplication and make future format or locale changes easier. - In
DataGridFunctions::getTimeAgo, consider using an ISO-8601-compliant format (e.g.DateTimeImmutable->format(DATE_ATOM)orc) for the<time datetime="...">attribute instead of a localizedIntlDateFormatterpattern, so the markup is consistently machine-readable regardless of locale.
Prompt for AI Agents
Please address the comments from this code review:
## Overall Comments
- The repeated instantiation of `IntlDateFormatter` with identical patterns (e.g. in `getDate`, `getLongDate`, `getTime`, blog archive title/breadcrumb, and form export) could be centralized in a small helper/factory to avoid duplication and make future format or locale changes easier.
- In `DataGridFunctions::getTimeAgo`, consider using an ISO-8601-compliant format (e.g. `DateTimeImmutable->format(DATE_ATOM)` or `c`) for the `<time datetime="...">` attribute instead of a localized `IntlDateFormatter` pattern, so the markup is consistently machine-readable regardless of locale.
## Individual Comments
### Comment 1
<location path="src/Frontend/Modules/Blog/Actions/Archive.php" line_range="174-180" />
<code_context>
}
- $format = 'j F Y';
+ $date = new IntlDateFormatter(
+ BackendLanguage::getInterfaceLanguage(),
+ IntlDateFormatter::NONE,
</code_context>
<issue_to_address>
**suggestion:** The IntlDateFormatter instantiation is duplicated and could be shared between methods.
Both `setPageTitle()` and `addPageToBreadcrumb()` construct the same `IntlDateFormatter` for the month label. Please extract this into a private helper (e.g. `formatMonthName(DateTimeInterface $date): string`) and call it from both methods to remove duplication and keep future changes (pattern/locale) in one place.
Suggested implementation:
```
if ($this->hasMonth) {
$this->header->setPageTitle(
$this->formatMonthName($this->startDate)
);
}
```
`.
Here are the edits:
<file_operations>
<file_operation operation="edit" file_path="src/Frontend/Modules/Blog/Actions/Archive.php">
<<<<<<< SEARCH
if ($this->hasMonth) {
$date = new IntlDateFormatter(
LANGUAGE,
IntlDateFormatter::NONE,
IntlDateFormatter::NONE,
null,
null,
'MMMM'
)->format($this->startDate->getTimestamp());
$this->header->setPageTitle(
$date
);
}
=======
if ($this->hasMonth) {
$this->header->setPageTitle(
$this->formatMonthName($this->startDate)
);
}
>>>>>>> REPLACE
</file_operation>
</file_operations>
<additional_changes>
To fully implement the refactor you described, you should also:
1. Add a private helper method on the `Archive` class to encapsulate the `IntlDateFormatter` logic, for example:
```php
private function formatMonthName(\DateTimeInterface $date): string
{
return (new IntlDateFormatter(
LANGUAGE,
IntlDateFormatter::NONE,
IntlDateFormatter::NONE,
null,
null,
'MMMM'
))->format($date->getTimestamp());
}
```
- Place this method alongside the other private helper methods in the `Archive` class.
- If the file does not already import `DateTimeInterface`, either fully qualify it as above or add `use DateTimeInterface;` at the top and then use `DateTimeInterface` in the signature.
2. Find the duplicated `IntlDateFormatter` instantiation in `addPageToBreadcrumb()` (it should look very similar or identical to the block that was just replaced) and refactor it to use the helper as well, e.g.:
```php
$monthLabel = $this->formatMonthName($this->startDate);
// use $monthLabel where the formatted month was previously used
```
3. Ensure both `setPageTitle()` usage (the one shown in your snippet) and the breadcrumb code now rely solely on `formatMonthName()`, so future changes to locale/pattern only need to be applied in one place.
</issue_to_address>Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.
| $date = new IntlDateFormatter( | ||
| LANGUAGE, | ||
| IntlDateFormatter::NONE, | ||
| IntlDateFormatter::NONE, | ||
| null, | ||
| null, | ||
| 'MMMM' |
There was a problem hiding this comment.
suggestion: The IntlDateFormatter instantiation is duplicated and could be shared between methods.
Both setPageTitle() and addPageToBreadcrumb() construct the same IntlDateFormatter for the month label. Please extract this into a private helper (e.g. formatMonthName(DateTimeInterface $date): string) and call it from both methods to remove duplication and keep future changes (pattern/locale) in one place.
Suggested implementation:
if ($this->hasMonth) {
$this->header->setPageTitle(
$this->formatMonthName($this->startDate)
);
}
`.
Here are the edits:
<file_operations>
<file_operation operation="edit" file_path="src/Frontend/Modules/Blog/Actions/Archive.php">
<<<<<<< SEARCH
if ($this->hasMonth) {
$date = new IntlDateFormatter(
LANGUAGE,
IntlDateFormatter::NONE,
IntlDateFormatter::NONE,
null,
null,
'MMMM'
)->format($this->startDate->getTimestamp());
$this->header->setPageTitle(
$date
);
}
if ($this->hasMonth) {
$this->header->setPageTitle(
$this->formatMonthName($this->startDate)
);
}
REPLACE
</file_operation>
</file_operations>
<additional_changes>
To fully implement the refactor you described, you should also:
-
Add a private helper method on the
Archiveclass to encapsulate theIntlDateFormatterlogic, for example:private function formatMonthName(\DateTimeInterface $date): string { return (new IntlDateFormatter( LANGUAGE, IntlDateFormatter::NONE, IntlDateFormatter::NONE, null, null, 'MMMM' ))->format($date->getTimestamp()); }
- Place this method alongside the other private helper methods in the
Archiveclass. - If the file does not already import
DateTimeInterface, either fully qualify it as above or adduse DateTimeInterface;at the top and then useDateTimeInterfacein the signature.
- Place this method alongside the other private helper methods in the
-
Find the duplicated
IntlDateFormatterinstantiation inaddPageToBreadcrumb()(it should look very similar or identical to the block that was just replaced) and refactor it to use the helper as well, e.g.:$monthLabel = $this->formatMonthName($this->startDate); // use $monthLabel where the formatted month was previously used
-
Ensure both
setPageTitle()usage (the one shown in your snippet) and the breadcrumb code now rely solely onformatMonthName(), so future changes to locale/pattern only need to be applied in one place.
Type
Pull request description
Replaces SpoonDate with IntlDateFormatter to format dates and timestamps where language is used, replace by date where language does not matter.
Summary by Sourcery
Replace legacy SpoonDate usage with IntlDateFormatter-based date handling and add helper methods for parameterized translations.
Enhancements: