DateTimeHasher   A
last analyzed

Complexity

Total Complexity 7

Size/Duplication

Total Lines 90
Duplicated Lines 0 %

Coupling/Cohesion

Components 0
Dependencies 1

Test Coverage

Coverage 100%

Importance

Changes 0
Metric Value
dl 0
loc 90
c 0
b 0
f 0
wmc 7
lcom 0
cbo 1
ccs 19
cts 19
cp 1
rs 10

4 Methods

Rating   Name   Duplication   Size   Complexity  
A equals() 0 4 1
A equivalent() 0 19 3
A hash() 0 8 1
A assertDateTime() 0 6 2
1
<?php
2
3
/**
4
 * This file is part of the phpcommon/comparison package.
5
 *
6
 * (c) Marcos Passos <[email protected]>
7
 *
8
 * For the full copyright and license information, please view the LICENSE file
9
 * that was distributed with this source code.
10
 */
11
12
namespace PhpCommon\Comparison\Hasher;
13
14
use PhpCommon\Comparison\Equatable;
15
use PhpCommon\Comparison\Hasher;
16
use PhpCommon\Comparison\UnexpectedTypeException;
17
use DateTimeInterface as DateTime;
18
19
/**
20
 * An equivalence relation to determine whether two instances of
21
 * DateTime have the same date, time and time zone.
22
 *
23
 * @author Marcos Passos <[email protected]>
24
 */
25
class DateTimeHasher implements Hasher
26
{
27
    /**
28
     * Checks whether the current relation is considered equal to another.
29
     *
30
     * Since this class is stateless, its instances will always be considered
31
     * equal if they are of the same type.
32
     */
33 4
    public function equals(Equatable $other)
34
    {
35 4
        return self::class === get_class($other);
36
    }
37
38
    /**
39
     * Checks whether the given values are considered equivalent.
40
     *
41
     * This equivalence relation considers two instances of {@link DateTime} to
42
     * be equivalent if they have the same date, time and time zone.
43
     *
44
     * @param DateTime $left  The date/time to compare.
45
     * @param mixed    $right The value to compare.
46
     *
47
     * @return boolean Returns `true` if the date/time are considered
48
     *                 equivalent, `false` otherwise.
49
     */
50 34
    public function equivalent($left, $right)
51
    {
52 34
        $this->assertDateTime($left);
53
54 32
        if (!$right instanceof DateTime) {
55 2
            return false;
56
        }
57
        
58 30
        $leftTimezone = $left->getTimezone();
59 30
        $rightTimezone = $right->getTimezone();
60
61
        // Compare the date and time
62 30
        if ($left->getTimestamp() !== $right->getTimestamp()) {
63 8
            return false;
64
        }
65
66
        // Compare the timezone
67 22
        return $leftTimezone->getName() === $rightTimezone->getName();
68
    }
69
70
    /**
71
     * Returns a hash code for the given DateTime instance.
72
     *
73
     * The resulting hash code is guaranteed to be _coherent_ with the
74
     * {@link equivalent()} method, which means that for any references
75
     * `$x` and `$y`, if `equivalent($x, $y)`, then `hash($x) === hash($y)`.
76
     * It is computed by summing the values returned by the methods
77
     * {@link \DateTimeInterface::getTimestamp()} and
78
     * {@link \DateTimeInterface::getOffset()}, as shown in the following
79
     * expression:
80
     *
81
     * ```php
82
     * $hashCode = $date->getTimestamp() + $date->getOffset();
83
     * ```
84
     *
85
     * @param DateTime $value The date/time to compare.
86
     *
87
     * @return integer The hash code.
88
     *
89
     * @see equivalent()
90
     */
91 10
    public function hash($value)
92
    {
93 10
        $this->assertDateTime($value);
94
95 10
        $timezone = $value->getTimezone();
96
97 10
        return $value->getTimestamp() + crc32($timezone->getName());
98
    }
99
100
    /**
101
     * Asserts the given value is an instance of {@link DateTime}.
102
     *
103
     * @param mixed $value The value to assert.
104
     *
105
     * @throws UnexpectedTypeException If the given value is not an instance of
106
     *                                 {@link DateTime}.
107
     */
108 34
    protected function assertDateTime($value)
109
    {
110 34
        if (!$value instanceof DateTime) {
111 2
            throw UnexpectedTypeException::forType(DateTime::class, $value);
112
        }
113 32
    }
114
}
115