Skip to content

Commit 50cddd1

Browse files
Refatoração da classe StrfTime para Solid, e padronizado os testes unitarios padrao executado pela comunidade no nome dos arquivos
1 parent 22b288b commit 50cddd1

18 files changed

Lines changed: 381 additions & 176 deletions

src/DependencyInjection/FormatAux.php

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -258,7 +258,13 @@ private static function processIntegerPart(
258258

259259
$position = $totalParts - 1 - $index;
260260
$extensiveString = self::addScaleToExtensiveString($extensiveString, $part, $position, $words);
261-
$extensiveString = self::addSpecialThousandSuffix($extensiveString, $position, $zeroCounter, $integerParts, $words);
261+
$extensiveString = self::addSpecialThousandSuffix(
262+
$extensiveString,
263+
$position,
264+
$zeroCounter,
265+
$integerParts,
266+
$words
267+
);
262268

263269
$newZeroCounter = $zeroCounter > 0 ? $zeroCounter - 1 : 0;
264270

src/DependencyInjection/StrfTime.php

Lines changed: 146 additions & 160 deletions
Original file line numberDiff line numberDiff line change
@@ -11,184 +11,170 @@
1111

1212
class StrfTime
1313
{
14-
public static function strftime(
15-
string $format,
16-
DateTimeInterface|int|string|null $timestamp = null,
17-
?string $locale = null
18-
): string {
19-
if (!($timestamp instanceof DateTimeInterface)) {
20-
$timestamp = is_int($timestamp) ? '@' . $timestamp : (string) $timestamp;
21-
22-
try {
23-
$timestamp = new DateTime($timestamp);
24-
} catch (Exception $e) {
25-
throw new InvalidArgumentException('$timestamp argument is neither a valid UNIX timestamp,
26-
a valid date-time string or a DateTime object.', 0, $e);
27-
}
14+
private const INTL_FORMATS = [
15+
'%a' => 'EEE',
16+
'%A' => 'EEEE',
17+
'%b' => 'MMM',
18+
'%B' => 'MMMM',
19+
'%h' => 'MMM',
20+
];
21+
private const SIMPLE_FORMATS = [
22+
'%d' => 'd',
23+
'%u' => 'N',
24+
'%w' => 'w',
25+
'%V' => 'W',
26+
'%m' => 'm',
27+
'%G' => 'o',
28+
'%y' => 'y',
29+
'%Y' => 'Y',
30+
'%H' => 'H',
31+
'%I' => 'h',
32+
'%M' => 'i',
33+
'%p' => 'A',
34+
'%P' => 'a',
35+
'%r' => 'h:i:s A',
36+
'%R' => 'H:i',
37+
'%S' => 's',
38+
'%T' => 'H:i:s',
39+
'%z' => 'O',
40+
'%Z' => 'T',
41+
'%D' => 'm/d/Y',
42+
'%F' => 'Y-m-d',
43+
'%s' => 'U',
44+
];
45+
private const INTL_FORMAT_KEYS = ['%a', '%A', '%b', '%B', '%h', '%X', '%c', '%x'];
46+
47+
private static function parseTimestamp(DateTimeInterface|int|string|null $timestamp): DateTimeInterface
48+
{
49+
if ($timestamp instanceof DateTimeInterface) {
50+
return $timestamp;
2851
}
52+
$timestamp = is_int($timestamp) ? '@' . $timestamp : (string) $timestamp;
53+
try {
54+
return new DateTime($timestamp);
55+
} catch (Exception $e) {
56+
throw new InvalidArgumentException(
57+
'$timestamp argument is neither a valid UNIX timestamp, ' .
58+
'a valid date-time string or a DateTime object.',
59+
0,
60+
$e,
61+
);
62+
}
63+
}
64+
65+
private static function parseLocale(?string $locale): string
66+
{
2967
if (empty($locale)) {
3068
$locale = setlocale(LC_TIME, '0');
3169
}
32-
$locale = preg_replace('/[^\w-].*$/', '', (string) $locale);
33-
34-
$intlFormats = [
35-
'%a' => 'EEE',
36-
'%A' => 'EEEE',
37-
'%b' => 'MMM',
38-
'%B' => 'MMMM',
39-
'%h' => 'MMM',
40-
];
41-
42-
$intlFormatter = function (DateTimeInterface $timestamp, string $format) use ($intlFormats, $locale) {
43-
$tz = $timestamp->getTimezone();
44-
$dateType = IntlDateFormatter::FULL;
45-
$timeType = IntlDateFormatter::FULL;
46-
$pattern = '';
47-
48-
switch ($format) {
49-
case '%c':
50-
$dateType = IntlDateFormatter::LONG;
51-
$timeType = IntlDateFormatter::SHORT;
52-
break;
53-
case '%x':
54-
$dateType = IntlDateFormatter::SHORT;
55-
$timeType = IntlDateFormatter::NONE;
56-
break;
57-
case '%X':
58-
$dateType = IntlDateFormatter::NONE;
59-
$timeType = IntlDateFormatter::MEDIUM;
60-
break;
61-
default:
62-
$pattern = $intlFormats[$format];
63-
}
64-
$calendar = IntlGregorianCalendar::createInstance();
65-
$calendar->setGregorianChange(PHP_INT_MIN);
70+
return (string) preg_replace('/[^\w-].*$/', '', (string) $locale);
71+
}
6672

67-
return (new IntlDateFormatter($locale, $dateType, $timeType, $tz, $calendar, $pattern))->format($timestamp);
68-
};
73+
private static function formatIntl(DateTimeInterface $timestamp, string $format, string $locale): string
74+
{
75+
$tz = $timestamp->getTimezone();
76+
$dateType = IntlDateFormatter::FULL;
77+
$timeType = IntlDateFormatter::FULL;
78+
$pattern = '';
79+
if ($format === '%c') {
80+
$dateType = IntlDateFormatter::LONG;
81+
$timeType = IntlDateFormatter::SHORT;
82+
} elseif ($format === '%x') {
83+
$dateType = IntlDateFormatter::SHORT;
84+
$timeType = IntlDateFormatter::NONE;
85+
} elseif ($format === '%X') {
86+
$dateType = IntlDateFormatter::NONE;
87+
$timeType = IntlDateFormatter::MEDIUM;
88+
} else {
89+
$pattern = self::INTL_FORMATS[$format];
90+
}
91+
$calendar = IntlGregorianCalendar::createInstance();
92+
$calendar->setGregorianChange(PHP_INT_MIN);
93+
$formatter = new IntlDateFormatter($locale, $dateType, $timeType, $tz, $calendar, $pattern);
94+
return (string) $formatter->format($timestamp);
95+
}
6996

70-
$translateTable = [
71-
// Day
72-
'%a' => $intlFormatter,
73-
'%A' => $intlFormatter,
74-
'%d' => 'd',
75-
'%e' => function ($timestamp) {
76-
assert($timestamp instanceof DateTimeInterface);
77-
return sprintf('% 2u', $timestamp->format('j'));
78-
},
79-
'%j' => function ($timestamp) {
80-
// Day number in year, 001 to 366
81-
assert($timestamp instanceof DateTimeInterface);
82-
return sprintf('%03d', $timestamp->format('z') + 1);
83-
},
84-
'%u' => 'N',
85-
'%w' => 'w',
97+
private static function formatPadded(DateTimeInterface $timestamp, string $dateFormat): string
98+
{
99+
return sprintf('% 2u', $timestamp->format($dateFormat));
100+
}
86101

87-
// Week
88-
'%U' => function ($timestamp) {
89-
// Number of weeks between date and first Sunday of year
90-
assert($timestamp instanceof DateTimeInterface);
91-
$day = new DateTime(sprintf('%d-01 Sunday', $timestamp->format('Y')));
92-
return sprintf('%02u', 1 + ((int)$timestamp->format('z') - (int)$day->format('z')) / 7);
93-
},
94-
'%V' => 'W',
95-
'%W' => function ($timestamp) {
96-
// Number of weeks between date and first Monday of year
97-
assert($timestamp instanceof DateTimeInterface);
98-
$day = new DateTime(sprintf('%d-01 Monday', $timestamp->format('Y')));
99-
return sprintf('%02u', 1 + ((int)$timestamp->format('z') - (int)$day->format('z')) / 7);
100-
},
102+
private static function formatDayOfYear(DateTimeInterface $timestamp): string
103+
{
104+
return sprintf('%03d', ((int) $timestamp->format('z')) + 1);
105+
}
101106

102-
// Month
103-
'%b' => $intlFormatter,
104-
'%B' => $intlFormatter,
105-
'%h' => $intlFormatter,
106-
'%m' => 'm',
107+
private static function formatWeekNumber(DateTimeInterface $timestamp, string $dayName): string
108+
{
109+
$day = new DateTime(sprintf('%d-01 %s', $timestamp->format('Y'), $dayName));
110+
$diff = ((int) $timestamp->format('z')) - ((int) $day->format('z'));
111+
return sprintf('%02u', 1 + ($diff / 7));
112+
}
107113

108-
// Year
109-
'%C' => function ($timestamp) {
110-
// Century (-1): 19 for 20th century
111-
assert($timestamp instanceof DateTimeInterface);
112-
return floor((int)$timestamp->format('Y') / 100);
113-
},
114-
'%g' => function ($timestamp) {
115-
assert($timestamp instanceof DateTimeInterface);
116-
return substr($timestamp->format('o'), -2);
117-
},
118-
'%G' => 'o',
119-
'%y' => 'y',
120-
'%Y' => 'Y',
114+
private static function formatCentury(DateTimeInterface $timestamp): string
115+
{
116+
return (string) floor(((int) $timestamp->format('Y')) / 100);
117+
}
121118

122-
// Time
123-
'%H' => 'H',
124-
'%k' => function ($timestamp) {
125-
assert($timestamp instanceof DateTimeInterface);
126-
return sprintf('% 2u', $timestamp->format('G'));
127-
},
128-
'%I' => 'h',
129-
'%l' => function ($timestamp) {
130-
assert($timestamp instanceof DateTimeInterface);
131-
return sprintf('% 2u', $timestamp->format('g'));
132-
},
133-
'%M' => 'i',
134-
'%p' => 'A', // AM PM (this is reversed on purpose!)
135-
'%P' => 'a', // am pm
136-
'%r' => 'h:i:s A', // %I:%M:%S %p
137-
'%R' => 'H:i', // %H:%M
138-
'%S' => 's',
139-
'%T' => 'H:i:s',
140-
'%X' => $intlFormatter,
119+
private static function formatIsoYearShort(DateTimeInterface $timestamp): string
120+
{
121+
return substr($timestamp->format('o'), -2);
122+
}
141123

142-
// Timezone
143-
'%z' => 'O',
144-
'%Z' => 'T',
124+
private static function getTranslateValue(
125+
string $pattern,
126+
DateTimeInterface $timestamp,
127+
string $locale
128+
): string {
129+
if (in_array($pattern, self::INTL_FORMAT_KEYS, true)) {
130+
return self::formatIntl($timestamp, $pattern, $locale);
131+
}
132+
if (isset(self::SIMPLE_FORMATS[$pattern])) {
133+
return $timestamp->format(self::SIMPLE_FORMATS[$pattern]);
134+
}
135+
return match ($pattern) {
136+
'%e' => self::formatPadded($timestamp, 'j'),
137+
'%j' => self::formatDayOfYear($timestamp),
138+
'%U' => self::formatWeekNumber($timestamp, 'Sunday'),
139+
'%W' => self::formatWeekNumber($timestamp, 'Monday'),
140+
'%C' => self::formatCentury($timestamp),
141+
'%g' => self::formatIsoYearShort($timestamp),
142+
'%k' => self::formatPadded($timestamp, 'G'),
143+
'%l' => self::formatPadded($timestamp, 'g'),
144+
'%n' => "\n",
145+
'%t' => "\t",
146+
default => throw new InvalidArgumentException(
147+
sprintf('Format "%s" is unknown in time format', $pattern),
148+
),
149+
};
150+
}
145151

146-
// Time and Date Stamps
147-
'%c' => $intlFormatter,
148-
'%D' => 'm/d/Y',
149-
'%F' => 'Y-m-d',
150-
'%s' => 'U',
151-
'%x' => $intlFormatter,
152-
];
152+
private static function applyPrefix(string $prefix, string $result): string
153+
{
154+
return match ($prefix) {
155+
'_' => (string) preg_replace('/\G0(?=.)/', ' ', $result),
156+
'#', '-' => (string) preg_replace('/^0+(?=.)/', '', $result),
157+
default => $result,
158+
};
159+
}
153160

161+
public static function strftime(
162+
string $format,
163+
DateTimeInterface|int|string|null $timestamp = null,
164+
?string $locale = null
165+
): string {
166+
$timestamp = self::parseTimestamp($timestamp);
167+
$locale = self::parseLocale($locale);
154168
$out = preg_replace_callback(
155169
'/(?<!%)%([_#-]?)([a-zA-Z])/',
156-
function (array $match) use ($translateTable, $timestamp): string {
170+
function (array $match) use ($timestamp, $locale): string {
157171
$prefix = $match[1];
158-
$char = $match[2];
159-
$pattern = '%' . $char;
160-
if ($pattern === '%n') {
161-
return "\n";
162-
} elseif ($pattern === '%t') {
163-
return "\t";
164-
}
165-
166-
if (!isset($translateTable[$pattern])) {
167-
throw new InvalidArgumentException(sprintf('Format "%s" is unknown in time format', $pattern));
168-
}
169-
170-
$replace = $translateTable[$pattern];
171-
172-
if (is_string($replace)) {
173-
$result = $timestamp->format($replace);
174-
} else {
175-
$result = $replace($timestamp, $pattern);
176-
}
177-
$result = (string)$result;
178-
179-
switch ($prefix) {
180-
case '_':
181-
return (string)preg_replace('/\G0(?=.)/', ' ', $result);
182-
case '#':
183-
case '-':
184-
return (string)preg_replace('/^0+(?=.)/', '', $result);
185-
default:
186-
return $result;
187-
}
172+
$pattern = '%' . $match[2];
173+
$result = self::getTranslateValue($pattern, $timestamp, $locale);
174+
return self::applyPrefix($prefix, $result);
188175
},
189-
(string)$format
176+
$format,
190177
);
191-
192178
return str_replace('%%', '%', (string) $out);
193179
}
194180
}
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
use PHPUnit\Framework\TestCase;
1010
use SimpleXMLElement;
1111

12-
class UnitArrayTest extends TestCase
12+
class ArrayTest extends TestCase
1313
{
1414
private const VEGETABLE_RUCULA = 'Rúcula';
1515

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
use DevUtils\Compare;
88
use PHPUnit\Framework\TestCase;
99

10-
class UnitCompareTest extends TestCase
10+
class CompareTest extends TestCase
1111
{
1212
public function testDaysDifferenceBetweenData(): void
1313
{
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
use DevUtils\Format;
99
use PHPUnit\Framework\TestCase;
1010

11-
class UnitFormatTest extends TestCase
11+
class FormatTest extends TestCase
1212
{
1313
public static function setUpBeforeClass(): void
1414
{
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
use DevUtils\Validator;
88
use PHPUnit\Framework\TestCase;
99

10-
class UnitIntegerTest extends TestCase
10+
class IntegerTest extends TestCase
1111
{
1212
private function assembleArrayForTests(): array
1313
{
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
use DevUtils\Validator;
88
use PHPUnit\Framework\TestCase;
99

10-
class UnitRuleTest extends TestCase
10+
class RuleTest extends TestCase
1111
{
1212
private function validate(array $data, array $rules): Validator
1313
{

0 commit comments

Comments
 (0)