briannesbitt / Carbon

A simple PHP API extension for DateTime.
https://carbon.nesbot.com/
MIT License
16.53k stars 1.28k forks source link

Add `today` to `ONE_DAY_WORDS` option for `diffForHumans()` #2788

Closed bilogic closed 1 year ago

bilogic commented 1 year ago

Hello,

I encountered an issue with the following code:

echo Carbon::now()->diffForHumans(['options' => Carbon::ONE_DAY_WORDS]); // 0 seconds ago
echo Carbon::now()->shortRelativeDiffForHumans(); // 0s ago

Carbon version: 2.66.0

PHP version: 8.1.18

I expected to get:

today

But I actually get:

0 seconds ago
0s ago

We need to explain how a series of payments will be collected:

  1. $10 - today
  2. $10 - in 1 month

1. $10 - 0 seconds ago or 1. $10 - just now is not suitable because we have not collected the payments yet.

Thanks!

kylekatarnls commented 1 year ago

Hello,

I recommend to handle it on your side. diffForHumans() actually call forHumans() on the result interval. So it does not have the notion of what is the start and end point, only the duration between and it makes the approximation

But if you want to be accurate, today is not about how far is it from now, it's about being in the given 00:00:00-23:59:59 range as per seen by the user (i.e. in their timezone).

Carbon::setTestNow('2023-05-08T01:23:45.678912Z');

$userTimezone = 'America/Los_Angeles';
$paymentDateTime = Carbon::parse('2023-05-08T12:00:00Z')->tz($userTimezone);
$now = Carbon::now()->tz($userTimezone);

if ($paymentDateTime->isSameDay($now)) {
    echo "Today\n";
} else {
    echo $paymentDateTime->diffForHumans() . "\n";
}

In this example, payment is 10 hours from now for someone in Los Angeles.

Keeping the exact timeline but considering $userTimezone = 'Europe/Berlin'; then it will show Today.

I recommend this approach as it tends to reflect more accurately your case. If you know that the payment is not actually happening right now, then I would avoid to use Carbon::now() to represent it and bend the wording of it.

If payment occurs at an unknown time in a given period, it's still not guaranteed to be "Today" and you can still represent using the same logic than above using 2 Carbon objects, one for the earliest possible moment, and the other for the latest one.

As there is a wide variety of usages (precision needed and timezone consideration), I would avoid to add more options for wording in diffForHumans() it tends just to create the illusion of simplicity while those kind of payments logic more typically vary from a business to another so they more often need to be handled specifically.

Thanks.

bilogic commented 1 year ago

ok thanks for letting me know