Passed
Push — master ( 52294c...1352e7 )
by Esteban De La Fuente
04:30
created

Date::validate()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 7
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 6

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 2
eloc 2
c 1
b 0
f 0
nc 2
nop 2
dl 0
loc 7
ccs 0
cts 3
cp 0
crap 6
rs 10
1
<?php
2
3
declare(strict_types=1);
4
5
/**
6
 * Derafu: Biblioteca PHP (Núcleo).
7
 * Copyright (C) Derafu <https://www.derafu.org>
8
 *
9
 * Este programa es software libre: usted puede redistribuirlo y/o modificarlo
10
 * bajo los términos de la Licencia Pública General Affero de GNU publicada por
11
 * la Fundación para el Software Libre, ya sea la versión 3 de la Licencia, o
12
 * (a su elección) cualquier versión posterior de la misma.
13
 *
14
 * Este programa se distribuye con la esperanza de que sea útil, pero SIN
15
 * GARANTÍA ALGUNA; ni siquiera la garantía implícita MERCANTIL o de APTITUD
16
 * PARA UN PROPÓSITO DETERMINADO. Consulte los detalles de la Licencia Pública
17
 * General Affero de GNU para obtener una información más detallada.
18
 *
19
 * Debería haber recibido una copia de la Licencia Pública General Affero de GNU
20
 * junto a este programa.
21
 *
22
 * En caso contrario, consulte <http://www.gnu.org/licenses/agpl.html>.
23
 */
24
25
namespace Derafu\Lib\Core\Helper;
26
27
use Carbon\Carbon;
28
use Carbon\Exceptions\InvalidFormatException;
29
use DateTime;
30
use InvalidArgumentException;
31
32
/**
33
 * Clase para trabajar con fecha en PHP.
34
 *
35
 * Extiende las funcionalidades de Carbon
36
 */
37
class Date extends Carbon
38
{
39
    /**
40
     * Días de la semana en español.
41
     *
42
     * @var array
43
     */
44
    private const DAYS = [
45
        'domingo',
46
        'lunes',
47
        'martes',
48
        'miércoles',
49
        'jueves',
50
        'viernes',
51
        'sábado',
52
    ];
53
54
    /**
55
     * Meses del año en español.
56
     *
57
     * @var array
58
     */
59
    private const MONTHS = [
60
        'enero',
61
        'febrero',
62
        'marzo',
63
        'abril',
64
        'mayo',
65
        'junio',
66
        'julio',
67
        'agosto',
68
        'septiembre',
69
        'octubre',
70
        'noviembre',
71
        'diciembre',
72
    ];
73
74
    /**
75
     * Formatea una fecha en formato YYYY-MM-DD a un string en español.
76
     *
77
     * @param string $date
78
     * @param bool $showDay
79
     * @return string
80
     */
81 1
    public static function formatSpanish(string $date, bool $showDay = true): string
82
    {
83 1
        $unixtime = strtotime($date);
84 1
        $string = date('j \d\e \M\O\N\T\H \d\e\l Y', $unixtime);
85 1
        if ($showDay) {
86 1
            $string = 'DAY ' . $string;
87
        }
88 1
        $day = self::DAYS[date('w', $unixtime)];
89 1
        $month = self::MONTHS[date('n', $unixtime) - 1];
90
91 1
        return str_replace(['DAY', 'MONTH'], [$day, $month], $string);
92
    }
93
94
    /**
95
     * Formatea un periodo pasado en formato YYYYMM a su representación en
96
     * español del mes.
97
     *
98
     * El resultado para 202501 será "Enero de 2025".
99
     *
100
     * @param int $period
101
     * @return string
102
     */
103
    public static function formatPeriodSpanish(int $period): string
104
    {
105
        // Extraer año y mes.
106
        $year = substr((string) $period, 0, 4);
107
        $month = substr((string) $period, 4, 2);
108
109
        // Validar el mes.
110
        $index = (int) $month - 1;
111
        if (!isset(self::MONTHS[$index])) {
112
            throw new InvalidArgumentException(sprintf(
113
                'Mes inválido: %s.',
114
                $month
115
            ));
116
        }
117
118
        // Retornar el mes y el año formateados.
119
        return ucfirst(self::MONTHS[$index]) . ' de ' . $year;
120
    }
121
122
    /**
123
     * Valida si la fecha es o no válida según el formato.
124
     *
125
     * @param string $date Fecha que se quiere validar.
126
     * @param string $format Formato que se quiere validar.
127
     * @return bool `true` Si la fecha está ok.
128
     */
129
    public static function validate(
130
        string $date,
131
        string $format = 'Y-m-d'
132
    ): bool {
133
        $dt = DateTime::createFromFormat($format, $date);
134
135
        return $dt !== false && !array_sum($dt->getLastErrors());
136
    }
137
138
    /**
139
     * Valida si una fecha está en el formato Y-m-d y la convierte a un nuevo
140
     * formato.
141
     *
142
     * @param string $date
143
     * @return string|null
144
     */
145 4
    public static function validateAndConvert(
146
        string $date,
147
        string $format = 'd/m/Y'
148
    ): ?string {
149
        try {
150
151 4
            $carbonDate = self::createFromFormat('Y-m-d', $date);
152
            if (
153 3
                $carbonDate === null
154 3
                || $carbonDate->format('Y-m-d') !== $date
155 3
                || $carbonDate->getLastErrors()['error_count'] > 0
156
            ) {
157 1
                return null;
158
            }
159 2
            return $carbonDate->format($format);
160 2
        } catch (InvalidFormatException $e) {
161 2
            return null;
162
        }
163
    }
164
165
    /**
166
     * Entrega el último día de un período.
167
     *
168
     * @param int|null $period
169
     * @return string
170
     */
171
    public static function lastDayPeriod(int $period = null): string
172
    {
173
        if ($period === null) {
174
            $period = date('Ym');
175
        }
176
177
        $year = substr((string) $period, 0, 4);
178
        $month = substr((string) $period, 4, 2);
179
180
        $date = DateTime::createFromFormat('Y-m-d', "$year-$month-01");
181
        $lastDay = $date->format('t');
182
183
        return "$year-$month-$lastDay";
184
    }
185
}
186