• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

h4kuna / data-type / 6168971271

13 Sep 2023 06:48AM UTC coverage: 96.581% (-0.03%) from 96.614%
6168971271

push

github

h4kuna
- update tests
- add LazyBuilder
- add Time for better DateTime::setTime()
- add Easter

92 of 92 new or added lines in 8 files covered. (100.0%)

452 of 468 relevant lines covered (96.58%)

0.97 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

98.25
/src/Date/Parser.php
1
<?php declare(strict_types=1);
2

3
namespace h4kuna\DataType\Date;
4

5
use DateTime;
6
use DateTimeImmutable;
7
use h4kuna\DataType\Basic\Arrays;
8
use h4kuna\DataType\Exceptions\InvalidArgumentsException;
9
use Nette\Utils\Strings;
10
use Nette\Utils\Validators;
11

12
final class Parser
13
{
14
        /** @var array<string> */
15
        public static array $formats = ['d.m. H:i', 'm-d H:i', 'd.m.Y H:i', 'Y-m-d H:i', 'd.m.Y H:i:s', 'Y-m-d H:i:s'];
16

17
        /**
18
         * @param string $any
19
         * @param DateTime|DateTimeImmutable|null $dateTime
20
         * @return ($dateTime is DateTime ? DateTime : DateTimeImmutable)
21
         */
22
        public static function fromString(
1✔
23
                string $any,
24
                DateTime|DateTimeImmutable|null $dateTime = null
25
        ): DateTime|DateTimeImmutable
26
        {
27
                if ($dateTime === null) {
1✔
28
                        $dateTime = new DateTimeImmutable();
1✔
29
                }
30

31
                $time = ltrim($any, '0');
1✔
32
                if ($time === '') {
1✔
33
                        return $dateTime;
1✔
34
                }
35
                $dateTime = clone $dateTime;
1✔
36
                $prepareFloat = strtr($any, [',' => '.']);
1✔
37

38
                return match (true) {
39
                        $any === 'now' => $dateTime instanceof DateTime ? new DateTime() : new DateTimeImmutable(),
1✔
40
                        Validators::isNumericInt($any) => self::isModification($any) ? $dateTime->modify(sprintf('%s hour', $any)) : $dateTime->setTime((int) $any, 0),
1✔
41
                        Validators::isNumeric($prepareFloat) => $dateTime->modify(self::modifierFromFloat((float) $prepareFloat)),
1✔
42
                        self::isTimeFormat($any) => self::fromTimeFormat($any, $dateTime),
1✔
43
                        default => self::fromFormat($any, $dateTime instanceof DateTime),
1✔
44
                };
45
        }
46

47

48
        private static function modifierFromFloat(float $value): string
1✔
49
        {
50
                $way = $value < 0 ? -1 : 1;
1✔
51
                [$hour, $minute] = explode('.', (string) $value);
1✔
52

53
                $minute = intval($minute);
1✔
54
                $hour = intval($hour);
1✔
55
                if ($minute !== 0) {
1✔
56
                        $minute = (int) round(6 / (1 / $minute));
1✔
57
                }
58

59
                return self::modifier($hour, $minute * $way);
1✔
60
        }
61

62

63
        private static function modifier(int $hour, int $minute, int $second = 0): string
1✔
64
        {
65
                return sprintf('%s hour, %s minute, %s second', $hour, $minute, $second);
1✔
66
        }
67

68

69
        private static function isTimeFormat(string $any): bool
1✔
70
        {
71
                return Strings::match($any, '/^[+-]?\d+:\d*(:\d*)?$/') !== null;
1✔
72
        }
73

74

75
        /**
76
         * @return ($date is DateTime ? DateTime : DateTimeImmutable)
77
         */
78
        private static function fromTimeFormat(string $any, DateTime|DateTimeImmutable $date): DateTime|DateTimeImmutable
1✔
79
        {
80
                ['hour' => $hour, 'minute' => $minute, 'second' => $second, 'modify' => $modify] = self::explodeTime($any);
1✔
81
                if ($modify) {
1✔
82
                        $x = $date->modify(self::modifier($hour, $minute, $second));
1✔
83
                        assert($x !== false);
84

85
                        return $x;
1✔
86
                }
87

88
                return $date->setTime($hour, $minute, $second);
1✔
89
        }
90

91

92
        /**
93
         * @return ($isDateTime is true ? DateTime : DateTimeImmutable)
94
         */
95
        private static function fromFormat(string $any, bool $isDateTime): DateTime|DateTimeImmutable
1✔
96
        {
97
                $callback = static fn (string $format, string $any) => $isDateTime
1✔
98
                        ? DateTime::createFromFormat($format, $any)
1✔
99
                        : DateTimeImmutable::createFromFormat($format, $any);
1✔
100

101
                foreach (self::$formats as $format) {
1✔
102
                        $date = $callback($format, $any);
1✔
103
                        if ($date !== false) {
1✔
104
                                return $date;
1✔
105
                        }
106
                }
107

108
                throw new InvalidArgumentsException(sprintf('Unknown option format date. "%s"', $any));
×
109
        }
110

111

112
        private static function isModification(string $string): bool
1✔
113
        {
114
                return Arrays::startWith($string, '+', '-');
1✔
115
        }
116

117

118
        /**
119
         * @return array{hour: int, minute: int, second: int, modify: bool}
120
         */
121
        private static function explodeTime(string $time): array
1✔
122
        {
123
                $char = substr($time, 0, 1);
1✔
124
                $way = 1;
1✔
125
                $modify = true;
1✔
126
                if ($char === '-') {
1✔
127
                        $way = -1;
1✔
128
                        $time = substr($time, 1);
1✔
129
                } elseif ($char === '+') {
1✔
130
                        $time = substr($time, 1);
1✔
131
                } else {
132
                        $modify = false;
1✔
133
                }
134

135
                [$hour, $minute, $second] = explode(':', $time . ':0:0');
1✔
136

137
                return [
138
                        'hour' => (int) $hour * $way,
1✔
139
                        'minute' => (int) $minute * $way,
1✔
140
                        'second' => (int) $second * $way,
1✔
141
                        'modify' => $modify,
1✔
142
                ];
143
        }
144
}
145

146

147

148

STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc