hhvm / hsl-experimental

Experimental features for the Hack Standard Library
MIT License
23 stars 10 forks source link

[ DateTime | Question ] How to represent the concept of time-as-read-from-a-clock? #188

Open lexidor opened 3 years ago

lexidor commented 3 years ago

You can use HH\Lib\Experimental\Time for this, but there are more valid values for it than actual time-as-read-from-a-clock. If you "abuse" HH\Lib\Experimental\Time to represent a time-as-read-from-a-clock, you end up having to use invariant_is_24h_clock_time() all over the place.

The vocabulary on HH\Lib\Experimental\Time makes it clear it is meant to be a duration, which makes the code read alien. You end up saying $x->isShorterThan($y), instead of $x->isBefore($y).

Here is a code snippet which shows what it is like to "abuse" HH\Lib\Experimental\Time for this purpose.

namespace _;

use namespace HH\Lib\Experimental\DateTime;
use type HH\Lib\Experimental\Time;

// Compares using an open range on the start time, but a closed range on the end time.
// So if your workday starts at 8:30, then 8:30:00.000000 would be during your workday.
// If you workday ends at 16:30, then 16:30.00.000000 would NOT be during your workday.
function is_during_work_hours(
  DateTime\Zoned $dt,
  Time $start_work_day,
  Time $end_work_day,
): bool {
  invariant_is_24h_clock_time($start_work_day);
  invariant_is_24h_clock_time($end_work_day);
  invariant(
    $start_work_day->isShorter($end_work_day),
    'Start work day (%s) must be before end work day (%s)',
    $start_work_day->__toString(0),
    $end_work_day->__toString(0),
  );
  $wall_time = Time::fromParts(...$dt->getTime());
  return $wall_time->isLongerOrEqual($start_work_day) &&
    $wall_time->isShorter($end_work_day);
}

function invariant_is_24h_clock_time(Time $time): void {
  invariant(
    ($time->isPositive() || $time->isZero()) && $time->getHours() < 24,
    '%s is not a valid time-as-read-from-a-clock',
    $time->__toString(0),
  );
}

<<__EntryPoint>>
function main(): void {
  require_once __DIR__.'/vendor/autoload.hack';
  \Facebook\AutoloadMap\initialize();
  \var_dump(is_during_work_hours(
    DateTime\Zoned::now(DateTime\Zone::AMERICA_LOS_ANGELES),
    Time::fromParts(8, 30),
    Time::fromParts(16, 30),
  ));
}
fredemmott commented 2 years ago

time-as-read-from-a-clock

I'm not certain what you mean here - are you looking for a type that's effectively a DateTime\Unzoned, but without the 'Date' part?