年齢を計算するには?[C#/VB]:.NET TIPS
ある日付(今日の日付など)と誕生日から、年齢(満年齢、数え年)を計算する方法として、DateTime構造体を使う方法と8桁整数を使う方法を紹介する。
簡単そうで意外と面倒なのが、2つの年月日の間の経過時間を(全部で〇〇日間ではなく)「〇年〇カ月と〇日」のように求めることだ。本稿では、その代表的な例として生年月日から年齢を求める年齢計算(すなわち、誕生日から今日までの経過時間を切り捨てで「〇年」として求める方法)を解説する。
特定のトピックをすぐに知りたいという方は以下のリンクを活用してほしい。
なお、いずれの算出アルゴリズムも.NET Frameworkバージョン1.0から利用できるが、本稿に掲載したサンプルコードをそのまま試すにはVisual Studio 2017以降が必要である。また、サンプルコードはコンソールアプリの一部であり、コードの冒頭に以下の宣言が必要となる。
using System;
using static System.Console;
Imports System.Console
DateTimeを使って満年齢を求めるには?
DateTime構造体(System名前空間)を利用すると、次のコードのように書ける。
var birthDay = new DateTime(1996, 2, 29);
var today = new DateTime(2017, 2, 28);
// 年の差を求める
int age = today.Year - birthDay.Year;
// 誕生日より前の月日だったら年齢から1を引く
// ここでは「age年を減算した日付を調べて、それが誕生日より前だったら
// 年齢から1を引く」という処理をしている
if (birthDay > today.AddYears(-age))
age--;
// 注意:
// if (birthDay.AddYears(age) > today)
// としてしまうと、誕生日が2月29日の場合に誤った結果になる
// (ある年の2月29日にage年を加算したときに、得られた年がうるう年
// でないと加算結果はその年の2月28日を表す値となるため)
WriteLine($"年齢:満{age}歳");
// 出力; 年齢:満20歳
Dim birthDay = New DateTime(1996, 2, 29)
Dim today = New DateTime(2017, 2, 28)
' 年の差を求める
Dim age As Integer = today.Year - birthDay.Year
' 誕生日より前の月日だったら年齢から1を引く
' ここでは「age年を減算した日付を調べて、それが誕生日より前だったら
' 年齢から1を引く」という処理をしている
If (birthDay > today.AddYears(-age)) Then
age -= 1
End If
' 注意
' If (birthDay.AddYears(age) > today) Then
' としてしまうと、誕生日が2月29日の場合に誤った結果になる
' (ある年の2月29日にage年を加算したときに、得られた年がうるう年
' でないと加算結果はその年の2月28日を表す値となるため)
WriteLine($"年齢:満{age}歳")
' 出力; 年齢:満20歳
2つのDateTime構造体を引き算するとTimeSpan構造体(System名前空間)が得られるが、それでは年齢計算ができない。TimeSpan構造体には経過時間を「〇日と〇時間〇分」などと表すためのプロパティはあるのだが、年と月はサポートされていないからである。そのため上記のようなロジックを書く必要がある。
なお、上のコードで「誕生日より前の月日だったら年齢から1を引く」とコメントした部分は、次のコードのようにした方が(長くはなるものの)分かりやすいかもしれない。
// 誕生日より前の月日だったら年齢から1を引く
if (today.Month < birthDay.Month)
age--;
else if (today.Month == birthDay.Month)
if (today.Day < birthDay.Day)
age--;
' 誕生日より前の月日だったら年齢から1を引く
If (today.Month < birthDay.Month) Then
age -= 1
ElseIf (today.Month = birthDay.Month) Then
If (today.Day < birthDay.Day) Then
age -= 1
End If
End If
整数表現を使って満年齢を求めるには?
日付を8桁の整数として計算する方法もある(次のコード)。データベースに8桁の整数や文字列として日付を格納している場合には、こちらを使うとよいだろう。
var birthDay = new DateTime(1996, 2, 29);
var today = new DateTime(2017, 2, 28);
// DateTime型を8桁の整数(yyyyMMdd形式)に変換する関数
int ToN8(DateTime dt) => dt.Year * 10000 + dt.Month * 100 + dt.Day;
// 与えられた日付を8桁の整数に直す
int birthdayN = ToN8(birthDay);
int todayN = ToN8(today);
// 8桁の整数で表された日付を引き算して下4桁を捨てる
int age = (todayN - birthdayN) / 10000;
WriteLine($"年齢:満{age}歳");
// 出力; 年齢:満20歳
Dim birthDay = New DateTime(1996, 2, 29)
Dim today = New DateTime(2017, 2, 28)
' DateTime型を8桁の整数(yyyyMMdd形式)に変換する関数
Dim ToN8 As Func(Of DateTime, Integer) _
= Function(dt) dt.Year * 10000 + dt.Month * 100 + dt.Day
' 与えられた日付を8桁の整数に直す
Dim birthdayN As Integer = ToN8(birthDay)
Dim todayN As Integer = ToN8(today)
' 8桁の整数で表された日付を引き算して下4桁を捨てる
Dim age As Integer = (todayN - birthdayN) \ 10000
WriteLine($"年齢:満{age}歳")
' 出力; 年齢:満20歳
この方法でなぜ求められるのかは、次のような筆算の形で考えてみると分かりやすいかもしれない。
yyyyMMdd(今日の日付)
−年年年年月月日日(誕生日)
・ 今日の月日が誕生日の月日と同じかそれより後なら(MMdd≧月月日日)、下4桁の引き算には繰り下がりが発生しないので、上4桁の結果(=年齢)は(yyyy−年年年年)となる
・ 今月と誕生日の月が同じで(MM=月月)、今日の日が誕生日の日より前なら(dd<日日)、日の2桁で繰り下がりが発生し、すると(MM=月月なので)月の2桁では繰り下がりを解消できず、上4桁にも繰り下がりが及ぶので、年齢は(yyyy−年年年年−1)となる
・ 今月が誕生日の月より前なら(MM<月月)、月の2桁で発生した繰り下がりによって、上4桁の年齢は(yyyy−年年年年−1)となる
なお、C#のコード中のToN8は、C#7で導入されたローカル関数をラムダ式で記述したものである(VBの方は従来のデリゲート)。ローカル関数について詳しくは「特集:C# 7の新機能詳説:第1回 明瞭なコーディングのために」を参照していただきたい。
2月29日の扱い
本稿では、うるう年の2月29日に生まれた人の誕生日は平年では3月1日になるとしている。これは「年齢計算ニ関スル法律」と「民法第百四十三条」によるものだ(参考:参議院法制局「うるう年をめぐる法令」)。
法律によっては(例えば道路交通法)、平年は2月28日を誕生日と見なすとしているものもある(参考:同上)。
数え年を求めるには?
数え年というのは、生まれたら1歳、新年を迎えたら2歳という年齢の数え方だ。数え年で年齢を求めるには、2つの年の差に1を足せばよい(次のコード)。
var birthDay = new DateTime(1996, 2, 29);
var today = new DateTime(2017, 2, 28);
// 年の差を求めて1を足す
int age = today.Year - birthDay.Year + 1;
WriteLine($"年齢:{age}歳(数え年)");
// 出力; 年齢:22歳(数え年)
Dim birthDay = New DateTime(1996, 2, 29)
Dim today = New DateTime(2017, 2, 28)
' 年の差を求めて1を足す
Dim age As Integer = today.Year - birthDay.Year + 1
WriteLine($"年齢:{age}歳(数え年)")
' 出力; 年齢:22歳(数え年)
まとめ
満年齢の計算では、誕生日の月日と今日の月日を比較して必要なら1減算するという処理が必要になる。そのようなロジックを組むか、日付を8桁の整数で表現して引き算の繰り下がりを利用する。
数え年の計算は、年同士を引いてから1を足すだけである。
利用可能バージョン:.NET Framework 1.0以降
カテゴリ:クラス・ライブラリ 処理対象:日付と時刻
使用ライブラリ:DateTime構造体(System名前空間)
関連TIPS:毎月のプレミアムフライデーを算出するには?[C#/VB]
関連TIPS:月初/月末の日付を求めるには?[C#、VB]
関連TIPS:日時や時間間隔の加減算を行うには?
関連TIPS:週の始まりの日付を求めるには?
関連TIPS:西暦年が閏(うるう)年かどうかを判別するには?[C#、VB]
関連TIPS:n日後、nカ月後、n年後の日付を求めるには?[C#、VB]
関連TIPS:指定した月から特定の曜日の日付を取得するには?[C#、VB]
関連TIPS:構文:メソッドやプロパティをラムダ式で簡潔に実装するには?[C# 6.0/7.0]
関連TIPS:構文:クラス名を書かずに静的メソッドを呼び出すには?[C# 6.0]
関連TIPS:VB.NETでクラス名を省略してメソッドや定数を利用するには?
関連TIPS:数値を右詰めや0埋めで文字列化するには?[C#、VB]
Copyright© Digital Advantage Corp. All Rights Reserved.