質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

90.04%

日付の計算方法について

解決済

回答 5

投稿 編集

  • 評価
  • クリップ 1
  • VIEW 269

kinisinai

score 20

PHPにて西暦の計算をしたいと考えています。
外部のプラグインなしで実装したいのですがどうすれば良いかわからず困っています。

イメージとしては
2000年1月と2002年2月があったときに結果として2年1ヶ月というような結果が返ってくるのが理想です。

JavaScriptのMoment.jsなどが検索してきたら出てきたのですが上記にも記載しているように外部プラグインは使用しない方向で考えています。

追記

今回みなさまのコメントを見て自分の甘さを知りました。
今一度自分で仕様を見つめ直し色々試行錯誤して試しています。
後ほどもう一度改めてこちらに質問させていただきます。

追記

$t1 = date('Ym', strtotime('2018-12'));

$dayhikizan = intval(date('Ym')) - intval($t1);
$j = 0;
$t = 0;
$wari = floor($dayhikizan / 12);
for ($i = 0; $i < $wari; $i ++) {
    if ($i < 11) {
        $t ++;
        $itinenika = ($t) . 'か月';
    } else {}
}
echo $itinenika;

上記のようなものを考えてみたのですが1年以内のものはうまくカウントしてくれるのですが1年以上のものになる時の条件の絞り込み方が分からず詰まっております。ご教授いただければ幸いです。

  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

質問への追記・修正、ベストアンサー選択の依頼

  • kinisinai

    2019/11/09 15:27

    2000年1月1日と2002年2月1日の2年2ヶ月というのは僕の計算ミスです。すみません。修正します。

    日が要件から外れている点も修正します。申し訳ありません

    キャンセル

  • takepan1973

    2019/11/09 16:21

    自分でも組んでみたんですが、 Kosuke_Shibuyaさんのコードが簡潔ですね。
    ご確認を。

    キャンセル

  • kinisinai

    2019/11/09 23:22

    ありがとうございます。

    キャンセル

回答 5

checkベストアンサー

+5

https://www.php.net/manual/ja/class.datetime.php

<?php

$date1 = '2000-01-01';
$date2 = '2002-02-01';

$dt1 = new Datetime($date1);
$dt2 = new Datetime($date2);

$diff = $dt2->diff($dt1);

$res = sprintf("%d年%dヶ月\n", $diff->y, $diff->m);

echo $res;

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2019/11/09 23:23

    ありがとうございます。
    ベストアンサーにさせていただきます。

    キャンセル

  • 2019/11/10 12:46

    BA以外の回答くれた人に対して、何のリアクションもないの?

    キャンセル

+5

「2000年1月1日と2002年2月1日があったときに結果として2年2ヶ月というような結果が返ってくるのが理想です。」
もうこの時点で謎仕様ですよね。単純な日付の引き算であれば、
2002/02/01 - 2000/01/01 = 2/01
です。
なぜ2年1ヶ月ではないのか?

2000年1月1日から2000年1月31日までが1ヶ月であって、
2000年1月1日から2000年2月1日は1ヶ月を超えるので切り上げて2ヶ月だ、というのであれば、そういうことを書いてください、ということです。それが仕様です。

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

+3

日付の差分計算のやり方ならネット上に幾らでも転がっていると思います。
ただ、インプットが提示の形式なのかとか諸々詰めなければならない要件が沢山あります。
まずそこをまとめないことには何も進められません。

どうすれば良いかわからず困っています

仕様を確定させてください。


適当サンプルコード (超冗長版)
日数を主にするとこうなる例。

<?php
$from = '2000年1月';
$to= '2001年2月';

$from_time = strtotime(str_replace('年','/',str_replace('月','/',$from)).'01');
$to_time = strtotime(str_replace('年','/',str_replace('月','/',$to)).'01');

$diff = ($to_time-$from_time);
$day_diff = $diff/ (60 * 60 * 24);
echo $day_diff. '日'.PHP_EOL;
$year_diff = $day_diff/365;
echo $year_diff.'年'.PHP_EOL;

$yr = floor($year_diff);
if($yr >= 0){
    echo $yr."年";
}
$mr = ($year_diff-$yr)/(1/12);
if($mr >= 0){
    echo ceil($mr)."ヶ月";
}

結局のところ仕様確定待ち。

最初の方で「もっとパターンを出して」と突っ込まれている通り、
本人も気づいていない仕様の漏れが沢山あるので、もっと考察していく必要があります。
現場でもお客さんが気づいてない漏れとかがあるわけで、そこをヒアリングで詰めて要件定義をしていくわけですが、
ここでは質問者はお客さんではないので、様々なパターンケースを出していって仕様を改定した上で質問をする必要があります。
質問テンプレートの「前提・実現したいこと」の項目は実は質問本文で最も丁寧でしっかり書き込まれている必要があります。

1つのことを実現するためのコードは1つではないですが、
その「1つのこと」が決まっていないので無限の可能性からの中から赤の他人が模索する必要がある質問はとても良い質問とは言えませんし、解決に至らずどんどん時間が過ぎるだけになっていきます。

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2019/11/07 22:13

    仕様とはどの程度のことままででしょうか?

    キャンセル

  • 2019/11/07 22:26

    この程度のプログラムなんだから試しに作ってみて期待しない動作をする点や分からない所や改善したい所をピックアップして質問すれば大体の回答者は問題点を察して回答してくれますよ

    キャンセル

  • 2019/11/07 22:27 編集

    kinisinaiさん
    それを決めるのはあなたです。
    ただふわっとしたままではヌケモレがあったときに対応しきれません。
    既にコメントで指摘があるようにふわっとしすぎていて要件がほとんど詰められていないことは明白です。
    パターンをきちんと洗い出し、要件を確定させましょう。
    どういう形式のインプットがあり、パターンがどれだけあり、制限事項には何があり、そして、どうなるのか。どうしたいのか。
    それを持っているのはあなたであり他人ではありません。

    キャンセル

  • 2019/11/07 22:29

    hentaimanさん
    私も「まず組んでみて」と思ってます。それで気づく要件の漏れもあるでしょうしね。
    分からないなりに調べたこと試したことがあるはずですし。
    丸投げの印象を与えたままなのが一番よくないです。

    キャンセル

+1

外部のプラグインなしで実装したいのですがどうすれば良いかわからず困っています。

PHP標準でこんな↓に日時に関するものがあるのでお好みで使用ください。

(www.php.net)PHP マニュアル 関数リファレンス 日付および時刻関連 Date/Time - 日付・時刻 関数

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

0

まず、西暦1年1月1日からの通算日数を求めましょう
また、通算日数から年月日を求めれるようにもしましょう

#ぐぐればその方法は出てきます

それができたら、あとは加算減算でお好きにどうぞという話となります
これが日付計算の基本となりますな

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

15分調べてもわからないことは、teratailで質問しよう!

  • ただいまの回答率 90.04%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる