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

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

ただいまの
回答率

87.50%

○ヶ月○日と表示させたい

解決済

回答 2

投稿 編集

  • 評価
  • クリップ 0
  • VIEW 533

score 64

日付の差分を出して○ヶ月○日というように表示させたいです。
月に応じて31日だったり30日だったりを考慮した日付を出したいです。
ExcelでいうDAYTDIF関数のような表示のさせ方です。

a = 2020/7/3
b = 2020/8/11

b - a = 1ヶ月9日(40日)

日数はこれで得られますが、
(b - a + 1).to_i

これを1ヶ月9日と表示させたいです。

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

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

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

    クリップを取り消します

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

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

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

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

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

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

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

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

    質問の評価を下げる

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

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

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

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

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

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

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

    詳細な説明はこちら

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

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

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

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

  • winterboum

    2020/08/12 18:43

    39日になるとおもうのですが、両端を入れる?
    8/2までを一ヶ月として、8/3は1ヶ月1日ですか?
    それとも8/3は1ヶ月0日?

    キャンセル

  • makox0105

    2020/08/12 18:46

    コメントありがとうございます。
    1ヶ月1日です。

    キャンセル

  • gouf

    2020/08/12 19:09

    表示させたいのは「経過した月日」のみですか? 起点とする日付以前を表示させることはありますか?

    キャンセル

  • makox0105

    2020/08/12 20:48

    コメントありがとうございます。期間なので、経過した月日のみということになります。

    キャンセル

回答 2

+1

「開始日から終了日までの間隔を変えずに、開始日をその月の初日に平行移動させる」というイメージで書くと以下になるでしょうか。ただ、両端の処理については、質問文からすると意図通りではないかもしれません……。

# frozen_string_literal: true

def date_diff(former, latter)
  require 'date'

  a = Date.parse(former)
  b = Date.parse(latter)

  a_new = Date.new(a.year, a.month, 1)
  b_new = a_new + (b - a).to_i

  month = b_new.month - a_new.month
  day = b_new.day - 1

  %(#{month}ヶ月#{day}日)
end

a = '2020/7/3'
b = '2020/8/11'
puts date_diff(a, b) #=> 1ヶ月8日

c = '2020/07/01'
d = '2020/07/02'
puts date_diff(c, d) #=> 0ヶ月1日

e = '2020/07/31'
f = '2020/08/01'
puts date_diff(e, f) #=> 0ヶ月1日

投稿

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

  • 2020/08/12 21:08

    すみません、VIEWで表示させるには、これをHelperに書けば良いですか?初歩的な質問で申し訳ありません。

    キャンセル

  • 2020/08/12 21:29

    私はこれまで Ruby on Rails に触れたことがなく、お答えできません。ごめんなさい。

    キャンセル

  • 2020/08/12 21:39

    いえいえ、ありがとうございました。

    キャンセル

checkベストアンサー

0

それっぽく動くコードを書いてみました

require 'active_support'
require 'active_support/core_ext'

def date_duration(base_date, after_date)
  duration_parts =
    ActiveSupport::Duration.build(after_date.to_i - base_date.to_i).parts
  # 起点日も 1日としてカウントする (+1)
  duration_in_days = (after_date - base_date).to_i + 1

  years, months, days, weeks =
    duration_parts[:years], duration_parts[:months], duration_parts[:days], duration_parts[:weeks]

  # * n週 に吸収された値を還元 (n weeks * 7 days)
  # * 起点日も 1日としてカウントする (+1)
  days += weeks * 7 + 1

  case [years, months, days]
  in [0, 0, 0] then "今日"
  in [0, 0, _] then                        "#{days}日後"
  in [0, _, 0] then           "#{months}ヶ月後"    +  "(#{duration_in_days}日)"
  in [0, _, _] then           "#{months}ヶ月#{days}日後(#{duration_in_days}日)"
  in [_, 0, 0] then "#{years}年後"                 +  "(#{duration_in_days}日)"
  in [_, _, 0] then "#{years}#{months}ヶ月後"    +  "(#{duration_in_days}日)"
  in [_, 0, _] then "#{years}年"    +      "#{days}日後(#{duration_in_days}日)"
  else              "#{years}#{months}ヶ月#{days}日後(#{duration_in_days}日)"
  end
end

date_time_args = [
    2020, # year
       7, # month
       3, # day
       0, # hour
       0, # min
       0, # sec
 '+09:00' # time zone
]

base_date  = DateTime.new(*date_time_args)
after_date = base_date.advance(years: 0, months: 1, days: 8)

# For debug
format = '%Y/%m/%d'
pp [base_date, after_date].map { |x| x.strftime(format) }
# => ["2020/07/03", "2020/08/11"]

pp date_duration(base_date, after_date)
# => "1ヶ月9日後(40日)"

地獄のようなコードを書いた気がしますが、なにか参考になれば幸いです

(※ Ruby 2.7 系のパターンマッチングは実験的な機能なので、今後うごかなくなるかもしれません)

Link

投稿

編集

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

  • 2020/08/13 15:25

    ArgumentError: invalid byte sequence in UTF-8
    とも出てます。

    キャンセル

  • 2020/08/13 15:29

    proguram全体を見る必要がありそうですね。
    logのその辺りにどのふぃぇのどの行か出ているはずですから、
    そのfileとlogの該当部分を載せて質問しましょう・
    ただ、「この質問」とは別の質問になりますから、goufさんの回答で納得でしたら、ここは閉めたほうがよいでしょう。

    キャンセル

  • 2020/08/13 16:01

    わかりました。ありがとうございます!

    キャンセル

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

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

関連した質問

同じタグがついた質問を見る