src/datetime/_Private/Comparable.php (70 lines of code) (raw):
<?hh
/*
* Copyright (c) 2004-present, Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
*/
namespace HH\Lib\Experimental\_Private\_DateTime;
use namespace HH\Lib\Experimental\DateTime;
use type HH\Lib\Experimental\Time;
/**
* Comparison and operation methods shared by all classes that represent points
* in time (all timestamps as well as `DateTime\DateTime`).
*/
abstract class Comparable {
abstract const type TComparableTo;
//////////////////////////////////////////////////////////////////////////////
// comparisons
/**
* Returns 1 if this instance represents a point in time after `$other`,
* -1 if before, and 0 if they are equal.
*/
abstract public function compare(this::TComparableTo $other): int;
/**
* Returns true iff the provided object represents the same point in time.
* Implies that the timestamp of the two objects is equal, but for
* `DateTime\Zoned` objects, some date/time parts may differ if both don't
* have the same timezone.
*
* See also `DateTime\Zoned::isEqualIncludingTimezone()`.
*
* To compare `DateTime\Zoned` parts ignoring timezones, use:
* $a->withoutTimezone()->isAtTheSameTime($b->withoutTimezone())
*/
final public function isAtTheSameTime(this::TComparableTo $other): bool {
return $this->compare($other) === 0;
}
// note: 3pm in some timezone may be later than 2pm in another
final public function isBefore(this::TComparableTo $other): bool {
return $this->compare($other) < 0;
}
final public function isBeforeOrAtTheSameTime(
this::TComparableTo $other,
): bool {
return $this->compare($other) <= 0;
}
final public function isAfter(this::TComparableTo $other): bool {
return $this->compare($other) > 0;
}
final public function isAfterOrAtTheSameTime(
this::TComparableTo $other,
): bool {
return $this->compare($other) >= 0;
}
/**
* Returns true if this instance represents a point in time after `$a` but
* before `$b`, or vice-versa (before `$a` but after `$b`), or if this
* instance is equal to `$a` and/or `$b`. Returns false if this instance is
* before or after both `$a` and `$b`.
*/
final public function isBetweenInclusive(
this::TComparableTo $a,
this::TComparableTo $b,
): bool {
$a = $this->compare($a);
$b = $this->compare($b);
return $a === 0 || $a !== $b;
}
/**
* Returns true if this instance represents a point in time after `$a` but
* before `$b`, or vice-versa (before `$a` but after `$b`). Returns false if
* this instance is equal to `$a` and/or `$b`, or if this instance is before
* or after both `$a` and `$b`.
*/
final public function isBetweenExclusive(
this::TComparableTo $a,
this::TComparableTo $b,
): bool {
$a = $this->compare($a);
$b = $this->compare($b);
return $a !== 0 && $b !== 0 && $a !== $b;
}
//////////////////////////////////////////////////////////////////////////////
// operations
/**
* Returns a new instance representing the point in time that is exactly the
* specified amount of time *after* the current instance (or *before*, if the
* provided time interval is negative).
*/
abstract public function plus(Time $time): this;
/**
* Returns a new instance representing the point in time that is exactly the
* specified amount of time *before* the current instance (or *after*, if the
* provided time interval is negative).
*/
abstract public function minus(Time $time): this;
/**
* Returns a new instance representing the point in time that is exactly the
* specified number of hours *after* the current instance (or *before*, if the
* specified number of hours is negative).
*/
final public function plusHours(int $hours): this {
return $this->plus(Time::hours($hours));
}
/**
* Returns a new instance representing the point in time that is exactly the
* specified number of minutes *after* the current instance (or *before*, if
* the specified number of minutes is negative).
*/
final public function plusMinutes(int $minutes): this {
return $this->plus(Time::minutes($minutes));
}
/**
* Returns a new instance representing the point in time that is exactly the
* specified number of seconds *after* the current instance (or *before*, if
* the specified number of seconds is negative).
*/
final public function plusSeconds(int $seconds): this {
return $this->plus(Time::seconds($seconds));
}
/**
* Returns a new instance representing the point in time that is exactly the
* specified number of nanoseconds *after* the current instance (or *before*,
* if the specified number of nanoseconds is negative).
*/
final public function plusNanoseconds(int $nanoseconds): this {
return $this->plus(Time::nanoseconds($nanoseconds));
}
/**
* Returns a new instance representing the point in time that is exactly the
* specified number of hours *before* the current instance (or *after*, if the
* specified number of hours is negative).
*/
final public function minusHours(int $hours): this {
return $this->minus(Time::hours($hours));
}
/**
* Returns a new instance representing the point in time that is exactly the
* specified number of minutes *before* the current instance (or *after*, if
* the specified number of minutes is negative).
*/
final public function minusMinutes(int $minutes): this {
return $this->minus(Time::minutes($minutes));
}
/**
* Returns a new instance representing the point in time that is exactly the
* specified number of seconds *before* the current instance (or *after*, if
* the specified number of seconds is negative).
*/
final public function minusSeconds(int $seconds, int $nanoseconds = 0): this {
return $this->minus(Time::seconds($seconds));
}
/**
* Returns a new instance representing the point in time that is exactly the
* specified number of nanoseconds *before* the current instance (or *after*,
* if the specified number of nanoseconds is negative).
*/
final public function minusNanoseconds(int $nanoseconds): this {
return $this->minus(Time::nanoseconds($nanoseconds));
}
/**
* Returns a `Time` instance representing the amount of time elapsed between
* the provided instance and the current instance (`$this`).
*
* The result can be negative or zero if `$other` is not before `$this`.
*/
abstract public function timeSince(this::TComparableTo $other): Time;
}