【Ruby】日付・時刻操作まとめ:require

はじめに

Rubyで日付や時刻を扱うには、標準ライブラリの Date、DateTime、Time クラスを活用します。これらは require “date” や require “time” で使えるようになります。本記事では、それぞれのクラスが何を扱うか、どのようなメソッドで操作できるかを網羅的に解説します。

1. Time クラス(組み込み + require ‘time’)

1. 何を扱う?

  • 日付 + 時刻 + タイムゾーン情報
  • 秒・分・時間まで含む「現在時刻」や「特定の時刻」を表す

2. 主な使い方

p t = Time.now # 現在の時刻  例: 2025-04-06 21:46:31.430407 +0900
p t - 3600     # 1時間前    例: 2025-04-06 20:46:31.430407 +0900
p t + 60       # 60秒後     例: 2025-04-06 21:47:31.430407 +0900

p t.year # 2025
p t.month # 4
p t.day # 6
p t.strftime("%Y-%m-%d") # "2025-04-06"

3. require ‘time’ で拡張される機能

  • Time.parse(string) で文字列をパースできるようになる。「文字列をパースする」とは、文字列(String)を意味のあるデータ構造に変換することを指します。
  • Time.parse は人間がよく使う形式のいろんな書き方に対応しています:
require "time"
p Time.parse("2025-04-06 10:00:00")  # => Time オブジェクト 例: 2025-04-06 10:00:00 +0900
p Time.parse("06 Apr 2025 10:00:00") # => Time オブジェクト 例: 2025-04-06 10:00:00 +0900
p Time.parse("2025/04/06 10:00")     # => Time オブジェクト 例: 2025-04-06 10:00:00 +0900

# 特定フォーマットの文字列を Time に変換
p Time.iso8601("2025-04-06T10:00:00+09:00")      # => ISO 8601 形式  2025-04-06 10:00:00 +0900
p Time.rfc2822("Sun, 6 Apr 2025 10:00:00 +0900") # => RFC 2822 形式  2025-04-06 10:00:00 +0900
p Time.httpdate("Sun, 06 Apr 2025 01:00:00 GMT") # => HTTP 日付形式  2025-04-06 01:00:00 UTC

# Time オブジェクトをフォーマットに合わせた文字列に変換
p now = Time.now # => 2025-04-06 21:58:52.383212 +0900
p now.iso8601    # => "2025-04-06T21:58:52+09:00"
p now.rfc2822    # => "Sun, 06 Apr 2025 21:58:52 +0900"
p now.httpdate   # => "Sun, 06 Apr 2025 12:58:52 GMT"

補足1: ISO形式(ISO 8601形式)とは?

  • API通信(JSONの日付フィールド)や DBとのデータやり取りなどでよく使う。
  • 国際標準の「日付と時刻の書き方」
  • 基本の形(日時)YYYY-MM-DDThh:mm:ss±hh:mm 2025-04-06T10:00:00+09:00
  • 2025-04-06 → 日付(年-月-日)
  • T → 時間の区切り文字(Timeの「T」)
  • 10:00:00 → 時刻(時:分:秒)
  • +09:00 → タイムゾーン(日本時間はUTC+9)
    image.png

補足2: UTCとは?

  • 協定世界時(Coordinated Universal Time)のこと。
  • 地球上での「基準となる時間」で、全世界共通の“ゼロ基準の時間”です。
  • 地球基準の時計=UTC。時間のズレをなくすための世界共通の時間。経度0度(イギリス・グリニッジ)を基準。「GMT(グリニッジ標準時)」に近い(ほぼ同じと考えてOK)
  • 日本時間(JST)は UTCより9時間進んでいる ので:
    UTC:  2025-04-06T01:00:00Z
    JST:  2025-04-06T10:00:00+09:00
    
    • Z は「Zuluタイム」の略(=UTCのこと)
    • +09:00 は UTC からの時差を表してる

2. Date クラス(require ‘date’)

1. 何を扱う?

  • 日付のみ(時刻なし)
  • 年・月・日を操作するのに向いている

2. 主な使い方

require "date"

# 基本的な生成と取得
p Date.today                 # => 今日の日付 #
p Date.new(2025, 4, 1)       # => 2025-04-01 #
p Date.parse("2025-04-06")   # => 文字列から変換 #

puts "----------------------------"

# 日付の演算
d = Date.new(2025, 4, 6)

p d + 1            # => 翌日(2025-04-07) #
p d - 7            # => 1週間前(2025-03-30) #
p d.next_day(3)    # => 3日後(2025-04-09) #
p d.prev_month     # => 前の月(2025-03-06) #
p d.next_month(2)  # => 2ヶ月後(2025-06-06) #

puts "----------------------------"

# 曜日チェック
p d.wday        # => 0(日曜日)※0〜6(Sun〜Sat)
p d.sunday?     # => true
p d.monday?     # => false

puts "----------------------------"

# フォーマット変換(文字列
p d.strftime("%Y-%m-%d")      # => "2025-04-06"
p d.strftime("%B %d, %Y")     # => "April 06, 2025"
p d.strftime("%Y年%m月%d日")  # => "2025年04月06日"

puts "----------------------------"

# 文字列からの変換(フォーマット指定あり)
puts Date.strptime("06/04/2025", "%d/%m/%Y") # => 2025-04-06
puts Date.strptime("20250406", "%Y%m%d")     # => 2025-04-06

puts "----------------------------"

# 日付の比較
puts a = Date.new(2025, 4, 6) # 2025-04-06
puts b = Date.new(2025, 4, 1) # 2025-04-01

p a > b   # true
p a == b  # false

puts "----------------------------"

# 範囲を使ったループ
from_date = Date.new(2025, 4, 1)
to_date = Date.new(2025, 4, 5)

(from_date..to_date).each do |date|
  puts date.strftime("%Y-%m-%d")
end

# 出力:
# 2025-04-01
# 2025-04-02
# 2025-04-03
# 2025-04-04
# 2025-04-05

puts "----------------------------"

# 月末・月初

d = Date.new(2025, 4, 6)

puts Date.new(d.year, d.month, 1)    # => 2025-04-01
puts Date.new(d.year, d.month, -1)   # => 2025-04-30

3. DateTime クラス(require ‘date’)

1. 何を扱う?

  • 日付 + 時刻(でも Time より機能が少ない)
  • タイムゾーン操作など一部の場面では Time より使いやすいことも

2. 主な使い方

require "date"

p dt = DateTime.now # 現在の時刻 #

puts "----------------------------"

# 時刻の各要素を取得
puts dt = DateTime.new(2025, 4, 6, 15, 30, 45) # => 2025-04-06T15:30:45+00:00

puts dt.year    # => 2025
puts dt.month   # => 4
puts dt.day     # => 6
puts dt.hour    # => 15
puts dt.minute  # => 30
puts dt.second  # => 45

puts "----------------------------"

# 日付や時刻の加減算(演算)
puts dt + 1  # 翌日 => 2025-04-07T15:30:45+00:00
puts dt - 1  # 前日 => 2025-04-05T15:30:45+00:00

puts "----------------------------"

# フォーマット文字列の活用
puts dt.strftime("%Y/%m/%d %H:%M:%S")  # => "2025/04/06 15:30:00"
puts dt.strftime("%A, %d %B %Y")       # => "Sunday, 06 April 2025"
puts dt.strftime("%Y年%-m月%-d日 %H時%M分") # => "2025年4月6日 15時30分"

puts "----------------------------"

# 文字列からの変換
puts DateTime.parse("2025-04-06T15:30:00+09:00")  # 2025-04-06T15:30:00+09:00
puts DateTime.strptime("06/04/2025 15:30", "%d/%m/%Y %H:%M")  # 2025-04-06T15:30:00+00:00

puts "----------------------------"

# タイムゾーンの扱い(オフセット指定)
puts dt = DateTime.new(2025, 4, 6, 15, 30, 0, "+09:00")
puts dt.zone      # => "+09:00"
puts dt.offset    # => 3/8 (9/24)

# UTC変換
puts dt.new_offset(0)  # => UTC時刻(+00:00)に変換 2025-04-06T06:30:00+00:00

puts "----------------------------"

dt1 = DateTime.parse("2025-04-06T10:00:00")
dt2 = DateTime.parse("2025-04-07T10:00:00")

p dt1  dt2  # => true
p (dt1..dt2).cover?(DateTime.parse("2025-04-06T12:00:00"))  # => true

puts "----------------------------"

# 日付・時刻だけ取り出したいとき

puts dt = DateTime.now # => 2025-04-06T22:37:28+09:00

puts dt.to_date    # => 2025-04-06
puts dt.to_time    # => 2025-04-06 22:37:28 +0900

4. クラスの使い分けまとめ

image.png

5. 実践問題

Q1. 今日が週の何日目かを数値と文字列で出力せよ

# 出力例: 0 (Sunday)
# 出力例: Sunday

回答

require "date"

today = Date.today
puts today.wday         # => 0〜6(0は日曜)
puts today.strftime("%A") # => "Sunday"など英語の曜日

Q2. 指定された年月に含まれる土日の日数を求めよ

# 入力: 2025年4月
# 出力: 土日が何日あるか

回答

require "date"

def weekend_count(year, month)
  first_day = Date.new(year, month, 1)
  last_day = Date.new(year, month, -1)

  (first_day..last_day).count { |d| d.saturday? || d.sunday? }
end

puts weekend_count(2025, 4)  # => 8

Q3. 2つの日付の間にある平日・休日の数を数えよ

# 入力: Date型2つ
# 出力: 平日と休日の数(祝日は無視)

回答

require "date"

def count_weekdays_and_weekends(from, to)
  weekdays = 0
  weekends = 0

  (from..to).each do |date|
    if date.saturday? || date.sunday?
      weekends += 1
    else
      weekdays += 1
    end
  end

  { weekdays: weekdays, weekends: weekends }
end

start_date = Date.parse("2025-04-01")
end_date = Date.parse("2025-04-10")

result = count_weekdays_and_weekends(start_date, end_date)
puts result
# => {:weekdays=>8, :weekends=>2}

Q4. 日付の配列から、最も未来に近い日を求めよ

# 入力: Date配列
# 出力: 今日より未来のうち、最も近い日付

回答

require "date"

def nearest_future_date(dates)
  today = Date.today
  future_dates = dates.select { |d| d > today }
  future_dates.min
end

dates = [
  Date.new(2025, 4, 10),
  Date.new(2025, 4, 5),
  Date.new(2025, 4, 8)
]

puts nearest_future_date(dates)
# 今日が2025-04-06 なら => 2025-04-08

Q5. 「yyyy-mm-dd」形式の文字列配列から、昇順でソートせよ

# 入力: ["2025-04-10", "2023-01-01", "2024-12-31"]
# 出力: ["2023-01-01", "2024-12-31", "2025-04-10"]

回答

require "date"

def sort_date_strings(array)
  array.map { |s| Date.parse(s) }
      .sort
      .map(&:to_s)
end

dates = ["2025-04-10", "2023-01-01", "2024-12-31"]
puts sort_date_strings(dates)
# => ["2023-01-01", "2024-12-31", "2025-04-10"]

おわりに

Rubyは Time と Date をしっかり使い分けることで、複雑な日付処理も簡潔に書くことができます。標準ライブラリながら強力な機能を活かして、実務でも使えるコードをどんどん書いていきましょう!

また、株式会社シンシアでは、実務未経験のエンジニアの方や学生エンジニアインターンを採用し一緒に働いています。
※ シンシアにおける働き方の様子はこちら

弊社には年間100人程度の実務未経験の方に応募いただき、技術面接を実施しております。
この記事が少しでも学びになったという方は、ぜひ wantedly のストーリーもご覧いただけるととても嬉しいです!



フラッグシティパートナーズ海外不動産投資セミナー 【DMM FX】入金

Source link