はじめに
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)
補足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 # => 今日の日付 #<Date: 2025-04-06 ((2460772j,0s,0n),+0s,2299161j)>
p Date.new(2025, 4, 1) # => 2025-04-01 #<Date: 2025-04-01 ((2460767j,0s,0n),+0s,2299161j)>
p Date.parse("2025-04-06") # => 文字列から変換 #<Date: 2025-04-06 ((2460772j,0s,0n),+0s,2299161j)>
puts "----------------------------"
# 日付の演算
d = Date.new(2025, 4, 6)
p d + 1 # => 翌日(2025-04-07) #<Date: 2025-04-07 ((2460773j,0s,0n),+0s,2299161j)>
p d - 7 # => 1週間前(2025-03-30) #<Date: 2025-03-30 ((2460765j,0s,0n),+0s,2299161j)>
p d.next_day(3) # => 3日後(2025-04-09) #<Date: 2025-04-09 ((2460775j,0s,0n),+0s,2299161j)>
p d.prev_month # => 前の月(2025-03-06) #<Date: 2025-03-06 ((2460741j,0s,0n),+0s,2299161j)>
p d.next_month(2) # => 2ヶ月後(2025-06-06) #<Date: 2025-06-06 ((2460833j,0s,0n),+0s,2299161j)>
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 # 現在の時刻 #<DateTime: 2025-04-06T22:28:32+09:00 ((2460772j,48512s,198739000n),+32400s,2299161j)>
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. クラスの使い分けまとめ
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 のストーリーもご覧いただけるととても嬉しいです!