1 <?php /* vim: set binary expandtab tabstop=4 shiftwidth=4 textwidth=80:
2 -------------------------------------------------------------------------------
5 -------------------------------------------------------------------------------
6 This file is part of meconlib.
8 meconlib is free software; you can redistribute it and/or modify it under
9 the terms of the GNU General Public License as published by the Free
10 Software Foundation; either version 2 of the License, or (at your option)
13 meconlib is distributed in the hope that it will be useful, but WITHOUT
14 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
15 FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License; if not,
18 write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330,
19 Boston, MA 02111-1307 USA
20 -------------------------------------------------------------------------------
21 Creado: mié abr 10 18:05:33 ART 2002 |
22 Autor: Leandro Lucarella <llucar@mecon.gov.ar>
23 -------------------------------------------------------------------------------
25 -----------------------------------------------------------------------------*/
27 require_once 'Date.php';
28 require_once 'Date/Span.php';
29 require_once 'PEAR.php';
32 * Información sobre feriados.
34 * Abstracción para hacer ABM sobre la información de los días feriados.
35 * También sirve para hacer consultas y búsquedas.
39 * @author Leandro Lucarella <llucar@mecon.gov.ar>
40 * @todo Probar. Agregar _updateDBInfo() a todas las funciones de Date que
41 * modifiquen la fecha.
43 class MECON_Feriado extends Date {
46 * Base de datos a usar para las consultas.
52 * Tipo de día (Feriado, Laborable o No Laborable).
57 /// Hora en la que empieza el feriado.
60 /// Descripción del feriado.
63 function MECON_Feriado($db, $date = null) {
68 function setDate($date = null) {
69 parent::setDate($date);
70 $this->_updateDBInfo($date);
73 function copy($date) {
76 $this->_tipo = $date->_tipo;
77 $this->desde = $date->desde;
78 $this->descripcion = $date->descripcion;
80 $this->_updateDBInfo();
84 function setYear($y) {
86 $this->_updateDBInfo();
89 function setMonth($m) {
91 $this->_updateDBInfo();
96 $this->_updateDBInfo();
99 function setHour($h) {
101 $this->_updateDBInfo();
104 function setMinute($m) {
105 parent::setMinute($m);
106 $this->_updateDBInfo();
109 function setSecond($s) {
110 parent::setSecond($s);
111 $this->_updateDBInfo();
114 function _updateDBInfo() {
117 $this->descripcion = null;
118 // Se fija según el tipo de día.
119 $dia = $this->format('%w');
122 $this->_tipo = 'feriado';
125 $tipo = 'no laborable';
126 // sigue abajo, no hay break.
127 default: // Cualquier día.
128 $this->_tipo = isset($tipo) ? $tipo : 'laborable';
129 // Verificamos si hay algo en la DB.
130 $fecha = $this->getDate();
131 $datos = $this->_db->getRow("SELECT * FROM novedades.feriados WHERE fecha = '$fecha'", null, DB_FETCHMODE_ASSOC);
132 // Si hay un error, lo pasamos a quien nos llama.
133 if (DB::isError($datos)) {
135 // Si hay un resultado, actualizamos los datos.
137 $this->_tipo = $datos['tipo'];
138 $this->desde = $datos['desde'];
139 $this->descripcion = $datos['descripcion'];
146 * Obtiene el tipo de día (teniendo en cuenta la hora).
148 * Si el día es asueto se fija la hora almacenada en esta fecha y devuelve
149 * 'asueto' o 'laborable' dependiendo de a partir de qué hora se declaró el
152 * @return 'laborable', 'no laborable', 'asueto' o 'feriado'.
155 if ($this->_tipo == 'asueto') {
156 $desde = new Date_Span($this->desde);
157 $hora = new Date_Span($this->format('%H:%M'));
158 if ($hora->greaterEqual($desde)) {
161 // Posible pitfall, en teoría sólo puede declararse asueto un
171 * Indica si un día es laborable.
173 * @return bool false si no es laborable (o hubo error).
177 function esLaborable() {
178 return $this->getTipo() == 'laborable';
182 * Indica si un día es no laborable.
184 * @return bool false si no es no laborable (o hubo error).
188 function esNoLaborable() {
189 return $this->getTipo() == 'no laborable';
193 * Indica si un día es feriado.
195 * @return bool false si no es feriado (o hubo error).
199 function esFeriado() {
200 return $this->getTipo() == 'feriado';
204 * Indica si un día es asueto.
206 * @param string $fecha Fecha de a chequear (el día actual por
208 * @param string $hora Hora en la que se quiere chequear.
210 * @return bool false si no es asueto (o hubo error).
214 function esAsueto() {
215 return $this->getTipo() == 'asueto';
219 * Busca feriados que se encuentren en un rango de fechas.
223 * if ($feriado->buscarRango('2002/10/01', '2002/12/31')) {
224 * while ($f = $feriado->siguiente())
226 * } elseif ($feriado->error()) {
227 * trigger_error('Errores: ' . $feriado->errores(), E_USER_ERROR);
229 * echo 'No se encontraron feriados en ese rango de fechas';
233 * @param string $ini Fecha de inicio del rango en donde buscar (por
234 * defecto el primer día del mes en curso).
235 * @param string $fin Fecha de fin del rango en donde buscar (por
236 * defecto el último día del mes en curso).
237 * @param array $orden Órden de los resultados. Es un array
238 * asociativo con el campo por el cual ordenar
239 * como clave y si es descendente o ascendente
240 * como valor. Por defecto se toma fecha
243 * @return bool false si no se encontró nada (o hubo error).
245 * @todo Pasar a método estático y usar Date en vez de strings para las fechas.
247 function buscarRango($ini = '', $fin = '', $orden = null ) {
249 $ini = empty( $ini ) ? strftime( '%Y/01/01', time() ) : $ini;
250 $fin = empty( $fin ) ? strftime( '%Y/12/31', time() ) : $fin;
251 $ord = ( $ord != 'fecha' and $ord != 'descripcion' and $ord != 'tipo' ) ? 'fecha' : $ord;
253 // Valida ambas fechas y que una sea anterior a la otra.
254 if ( ! $this->_es_anterior( $ini, $fin ) )
257 // Si no se especifica orden lo inicializa.
258 if ( is_null( $orden ) )
259 $orden = array('fecha' => HE_DB_ASC);
261 // Genera un array con las clausulas del ORDER BY del query
263 foreach ( $orden as $campo => $ord )
264 $order[] = sprintf( "%s %s", $campo, $ord );
266 // Si no son arrays sale con error.
267 if ( ! is_array( $campos ) or ! is_array( $orden ) ) {
268 $this->raiseError( 'Parámetro incorrecto, no es un array', HE_ERROR );
272 // Prepara el query con el rango de fechas
283 $this->_db->quote( $ini ),
284 $this->_db->quote( $fin ),
285 $order ? ( ' ORDER BY ' . join( ',', $order ) ) : ''
288 $resultado =& $this->_db->query( $query );
289 if ( DB::isError( $resultado ) ) { // Hubo un error
290 $this->_error->agregar( $resultado );
292 } elseif ( $resultado->numRows() ) { // Tiene algún resultado
293 $this->_resultado =& $resultado;
302 * Busca dias habiles en un rango de fechas y los devuelve en un array.
306 * $diasHabiles = $feriado->buscarDiasHabiles('2002/10/01', '2002/12/31');
307 * if (count($diasHabiles)) {
308 * echo 'Cantidad de dias habiles en le rango: '. count($diasHabiles);
309 * foreach ($diasHabiles as $diaHabil) {
310 * print '<PRE>';var_dump($diaHabil);print '</PRE>';
315 * @param DB $db Conexión a la base de datos.
316 * @param mixed $ini Fecha de inicio del rango en donde buscar (por
317 * defecto el primer día del mes en curso). Puede ser
319 * @param mixed $fin Fecha de fin del rango en donde buscar (por
320 * defecto el día del mes en curso). Puede ser un
326 function buscarDiasHabiles($db, $ini = '', $fin = '') {
327 //Acomodo las fechas pasadas por parametro
328 $ini = empty( $ini ) ? strftime( '%Y-%m-01', time() ) : $ini;
329 $fin = empty( $fin ) ? strftime( '%Y-%m-%d', time() ) : $fin;
330 $ini = (is_string($ini)) ? new Date($ini) : $ini;
331 $fin = (is_string($fin)) ? new Date($fin) : $fin;
333 //Valido que $ini < $fin
334 if ($ini->after($fin)) {
335 return new PEAR_Error ('La fecha de fin debe ser anterior a la '.
339 //Obtener los dias feriados entre $ini y $fin
340 $sql = "SELECT fecha FROM novedades.feriados WHERE YEAR(fecha) = ".
341 $db->quote($ini->format("%Y")) . " OR YEAR(fecha) = " .
342 $db->quote($ini->format("%Y"));
344 $feriados = $db->getCol($sql);
345 if (DB::IsError($feriados)) {
349 //Verifico fecha por fecha si es o no un dia habil
350 $ini =& $ini->getPrevDay();
351 while (!$ini->equals($fin)) {
352 $ini =& $ini->getNextDay();
353 //Verifico que la fecha no sea feriado ni sabado o domingo.
354 if (!in_array($ini->format("%Y-%m-%d"), $feriados) &&
355 ($ini->getDayOfWeek() != 0) &&
356 ($ini->getDayOfWeek() != 6)) {