2012-05-26 279 views
7

Estoy tratando de obtener la fecha y la duración del tiempo entre el préstamo tomado y la fecha de pago. Usé las funciones de fecha y hora de PHP, pero no siempre es preciso. ¿Cómo puedo hacer esto con precisión en MySQL?¿Cómo convertir una cantidad dada de días a años, meses y días en MySQL?

Que asuma dos fechas, el préstamo tomado fecha

2009-05-24

y la de regreso Préstamo

2012-04-30

Escribo una consulta MySQL

SELECT DATEDIFF('2012-04-30', '2009-05-24') `total_days`; 

return 1072 días, que es aproximadamente 2 años, 11 meses, 12 días.

Por favor, no responda con el código PHP, ya lo intento. Aquí está el código .

La función siguiente utiliza PHP> = 5.3 funciones y convierte días a años, meses y días.

function date_interval($date1, $date2) 
{ 
    $date1 = new DateTime($date1); 
    $date2 = new DateTime($date2); 

    $interval = date_diff($date2, $date1); 
    return ((($y = $interval->format('%y')) > 0) ? $y . ' Year' . ($y > 1 ? 's' : '') . ', ' : '') . ((($m = $interval->format('%m')) > 0) ? $m . ' Month' . ($m > 1 ? 's' : '') . ', ' : '') . ((($d = $interval->format('%d')) > 0) ? $d . ' Day' . ($d > 1 ? 's' : '') : ''); 
} 

Ésta función utiliza PHP> = 5.2 Funciones y convertir días a años, meses y días.

function date_interval($date1, $date2) 
{ 
    $diff = abs(strtotime($date2) - strtotime($date1)); 

    $years = floor($diff/(365 * 60 * 60 * 24)); 
    $months = floor(($diff - $years * 365 * 60 * 60 * 24)/(30 * 60 * 60 * 24)); 
    $days = floor(($diff - $years * 365 * 60 * 60 * 24 - $months * 30 * 60 * 60 * 24)/(60 * 60 * 24)); 

    return (($years > 0) ? $years . ' Year' . ($years > 1 ? 's' : '') . ', ' : '') . (($months > 0) ? $months . ' Month' . ($months > 1 ? 's' : '') . ', ' : '') . (($days > 0) ? $days . ' Day' . ($days > 1 ? 's' : '') : ''); 
} 
+3

¿Cuántos días hay en un mes? 28? 29? 30? 31? – liquorvicar

+0

Probablemente necesitará un procedimiento almacenado o una función para hacer eso en MySQL. – liquorvicar

Respuesta

5

El principal problema es el siguiente:

  1. el fin de encontrar la diferencia entre los días necesarios para utilizar datediff()
  2. datediff() devuelve la diferencia en días.
  3. el fin de convertir días a una fecha, para que pueda obtener el número de años, etc es necesario utilizar from_days()
  4. from_days() no funciona muy bien antes de 1582, para citar a partir de la documentación:

    "Use FROM_DAYS() con precaución en las fechas de edad. no es para uso con valores que preceden a la aparición del calendario gregoriano (1582)"

    el mínimo es de 1582 ya que este era el que Europa convertida de el calendario juliano al gregoriano.

  5. 0000-00-00 + 6 días es 0000-01-06, que es anterior a 1582.

Esto significa efectivamente que MySQL fecha-funciones son inútiles para usted.

Usted pide que esto se haga en MySQL "con precisión".Como no puede usar las funciones de fecha, tendrá que hacer las suyas propias. Este no será sea preciso. ¿Cuántos días hay en un año? Ciertamente no siempre es 365. ¿Cuántos días hay en un mes?

Recomiendo encarecidamente hacerlo en PHP.

Sin embargo, como está convencido de que no quiere hacerlo, tendrá que hacer trampa.

Agregue la fecha 1600-01-01 a todo. Luego elimine 1600 años, 1 mes y 1 día de su respuesta al final. Solo uso esta fecha porque es mayor que 1582 y es un buen número redondo. Cualquier cosa funcionaría realmente, pero cuanto antes mejor será así para no tener problemas.

Suponiendo que hemos construido la siguiente tabla:

create table dates (a date, b date); 
insert into dates 
values (str_to_date('2012-04-30','%Y-%m-%d') 
     , str_to_date('2012-04-24','%Y-%m-%d') 
     ); 

insert into dates 
values (str_to_date('2012-04-30','%Y-%m-%d') 
     , str_to_date('2009-05-24','%Y-%m-%d') 
     ); 

La siguiente consulta obtendrá lo que quiere:

select extract(year from from_days(days)) - 1600 
    , extract(month from from_days(days)) - 1 
    , extract(day from from_days(days)) - 1 
    from (select to_days(a) - to_days(b) + 
       to_days(str_to_date('1600-01-01', '%Y-%m-%d')) as days 
      from dates) as b 

Here's a SQL Fiddle to prove it.

Una vez más, esto es bastante raro y no muy recomendable. TIMESTAMPDIFF() función de

+0

Es bastante extraño mysql no tiene nada fácil de configurar para este problema. Espero que extiendan la funcionalidad pronto :) –

+0

@Adrius, lo dudo :-). – Ben

+0

Usó la versión de PHP. En 2014. – topher

0
SELECT DATE_FORMAT(FROM_DAYS(DATEDIFF('2012-04-30', '2009-05-24')), '%Y-%m-%d') AS `total_days` 
+1

La función no parece funcionar si la diferencia es menos de un año o.O no estaba al tanto de eso. –

4

Uso de MySQL:

SELECT TIMESTAMPDIFF(YEAR 
     , '2009-05-24' 
     , '2012-04-30' 
     ) AS Years, 
     TIMESTAMPDIFF(MONTH 
     , '2009-05-24' 
      + INTERVAL TIMESTAMPDIFF(YEAR, '2009-05-24', '2012-04-30') YEAR 
     , '2012-04-30' 
     ) AS Months, 
     TIMESTAMPDIFF(DAY 
     , '2009-05-24' 
      + INTERVAL TIMESTAMPDIFF(YEAR, '2009-05-24', '2012-04-30') YEAR 
      + INTERVAL TIMESTAMPDIFF(YEAR, '2009-05-24', '2012-04-30') MONTH 
     , '2012-04-30' 
     ) AS Days 

verlo en sqlfiddle.

2

He utilizado este:

SELECT TIMESTAMPDIFF(YEAR 
     , '2010-08-29' 
     , '2014-09-18' 
     ) AS Years, 
     TIMESTAMPDIFF(MONTH 
     , '2010-08-29' 
      + INTERVAL TIMESTAMPDIFF(YEAR, '2010-08-29', '2014-09-18') YEAR 
     , '2014-09-18' 
     ) AS Months, 
     TIMESTAMPDIFF(DAY 
     , '2010-08-29' 
      + INTERVAL TIMESTAMPDIFF(MONTH, '2010-08-29', '2014-09-18') MONTH 
     , '2014-09-18' 
     ) AS Days 
Cuestiones relacionadas