8

ローンの実行日と支払い日の間の日付と期間を取得しようとしています。PHPの日付と時刻の関数を使用しましたが、常に正確であるとは限りません。MySQLでこれを正確に行うにはどうすればよいですか?

2つの日付を想定します。ローンの取得日

2009-05-24

とローンの返済日

2012-04-30

MySQLクエリを作成します

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

1072日を返します。これは、およそ2年、11か月、12日です。

PHPコードで答えないでください、私はすでにそれを試しています。これがコードです。

以下の関数はPHP>=5.3関数を使用し、日を年、月、日に変換します。

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' : '') : '');
}

以下の関数はPHP>=5.2関数を使用し、日を年、月、日に変換します。

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' : '') : '');
}
4

4 に答える 4

7

主な問題は次のとおりです。

  1. 使用する必要がある日の違いを見つけるためにdatediff()
  2. datediff()差を日数で返します。
  3. 日を日付に変換するために、使用する必要がある年数などを取得できます from_days()
  4. from_days()ドキュメントから引用すると、1582年より前は実際には機能しません。

    「FROM_DAYS() は古い日付には注意して使用してください。グレゴリオ暦 (1582) の出現より前の値での使用は意図されていません」

    ヨーロッパがユリウス暦からグレゴリオ暦に変換したのは 1582 年であるため、最小値は 1582 年です。

  5. 0000-00-00 + 6 日は 0000-01-06 で、1582 年より前です。

これは事実上、MySQL の日付関数が役に立たないことを意味します。

これを MySQL で「正確に」実行するように要求します。日付関数を使用できないため、独自に作成する必要があります。これは正確ではありません。1年は何日ありますか?確かに 365 日とは限りません。1 か月は何日ですか?

PHPでこれを行うことを強くお勧めします。

ただし、そうしたくないと断言しているので、ごまかす必要があります。

すべてに日付 1600-01-01 を追加します。次に、最後の答えから 1600 年と 1 か月と 1 日を削除します。私がこの日付を使用するのは、それが 1582 よりも大きく、適切な丸め数であるためです。何でも実際に機能しますが、問題が発生しないように、早いほど良いです。

次のテーブルを作成したと仮定します。

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')
        );

次のクエリは、必要なものを取得します。

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

それを証明する SQL Fiddle を次に示します

繰り返しますが、これは非常にハックであり、あまりお勧めできません。

于 2012-05-26T13:30:18.693 に答える
4

MySQL のTIMESTAMPDIFF()関数を使用します。

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

sqlfiddleで参照してください。

于 2012-05-29T10:48:57.273 に答える
-1
SELECT DATE_FORMAT(FROM_DAYS(DATEDIFF('2012-04-30', '2009-05-24')), '%Y-%m-%d') AS `total_days`
于 2012-05-26T12:11:57.190 に答える