3行まとめ
- .NETで、ISO 8601の週番号を扱いたい場合、ISOWeekクラスを使えばOK
- ISOWeekクラスには、.NET 10で、DateOnlyのメソッド・オーバーロードが追加予定
- .NET 9において、週番号に対応した書式指定子はない。.NET 10 preview 1段階でもなさそう
※ 本投稿では、「ISO 8601」の週に関してのみを対象とします。
※ 本投稿は、明記しない場合.NET 9時点の情報について基づいて作成しています。
※ 本投稿は、一部.NET 10 Preview 1の情報を含みます。正式リリース前に変更の可能性がある点に注意してください。
前提
ISO 8601は、日付、時刻、継続時間を規定する国際規格です。
このISO 8601の中で、「その年の第何週」というものが定められています。
- 週の開始曜日は、月曜日
- その年の第1週は、その年の最初の木曜日を含む週です
2020年の年末・2021年の年始のカレンダーの一部は、次のような感じです。
2021年の1月1日・2日・3日は、2021年ですが「前年である2020年の第53週」に属していることに注目してください。
年と週 | 月 | 火 | 水 | 木 | 金 | 土 | 日 |
---|---|---|---|---|---|---|---|
2020年 第53週 | 12/28 | 12/29 | 12/30 | 12/31 | 1/1 | 1/2 | 1/3 |
2021年 第1週 | 1/4 | 1/5 | 1/6 | 1/7 | 1/8 | 1/9 | 1/10 |
2014年の年末・2015年の年始のカレンダーの一部は、次のような感じです。
2014年の12月29日・30日・31日は、2014年ですが「翌年である2015年の第1週」に属していることに注目してください。
年と週 | 月 | 火 | 水 | 木 | 金 | 土 | 日 |
---|---|---|---|---|---|---|---|
2014年 第52週 | 12/22 | 12/23 | 12/24 | 12/25 | 12/26 | 12/27 | 12/28 |
2015年 第1週 | 12/29 | 12/30 | 12/31 | 1/1 | 1/2 | 1/3 | 1/4 |
こんな感じで「その年の第何週」という概念、週番号があります。
ISOWeekクラスを使って週番号や年を求める
.NETのISOWeekクラスは、DateTime型に対してISO 8601の週番号を求めるGetWeekOfYearメソッドなどが定義されているクラスです。次にISOWeekクラスを使って、「〇〇年第XX週」のように表示するためのコードを示します。
DateTime date = DateTime.Parse("2021-01-01");
// 「2020年 第53週」と出力される
// 週番号を求めるには、GetWeekOfYearメソッドを使う
// その週の属する年を求めるときは、ISOWeek.GetYearメソッドを使うことに注意
Console.WriteLine(date.ToString($"{ISOWeek.GetYear(date)}年 第{ISOWeek.GetWeekOfYear(date)}週"));
DateTime型に対してISO 8601の週を求めて、「〇〇年第XX週」と表示する時は、「年」にも注意してください。Yearプロパティーを使って表示すると不具合を生んでしまいます。ISOWeekクラスのGetYearメソッドを使いましょう。
先に示した通り2021年1月1日は、2021年でありながら、前年である2020年の第53週に属しています。そのため、Yearプロパティーを使った次のようなコードでは、期待した「2020年 第53週」という出力をしてくれず、「2021年 第53週」と出力してしまいます。
DateTime date = DateTime.Parse("2021-01-01");
// 次のコードは間違い
// 「2021年 第53週」と出力されてしまう
// 2021年1月1日は、2020年の第53週なので間違い
Console.WriteLine(date.ToString($"{date.Year}年 第{ISOWeek.GetWeekOfYear(date)}週"));
ISOWeekクラスにはこれ以外にも、週関連の便利なメソッドが定義されています。
.NET 10で、DateOnly関連のオーバーロード・メソッドが加わりそう
※ 本節は、.NET 10 Preview 1の情報に基づいています。.NET 10の正式リリース前に変わる可能性がある点に注意してください。
.NET 10で、ISOWeekクラスに、DateOnly構造体を引数に取るオーバーロードとメソッドが加わる予定です。
DateOnly構造体は、.NET 6で追加されました。ISOWeekクラスは、.NET Core 3.0で追加されたクラスであり、登場時点でDateOnly構造体はまだなかったため、.NET 10での対応になったようです。
前節で紹介した
の引数としてDateTimeではなく、DateOnlyを引数に取るオーバーロードが追加される予定です。(確かにこのメソッド、意味的には時刻を司るDateTimeじゃなくて、日付を司るDateOnlyを引数に取る方が適切な気がしますね。)
DateOnly date = DateOnly.Parse("2021-01-01");
// 2021年 第53週
Console.WriteLine(date.ToString($"{ISOWeek.GetYear(date)}年 第{ISOWeek.GetWeekOfYear(date)}週"));
ISOWeekには、年・週番号・曜日を引数に取り、DateTime型を返す「ISOWeek.ToDateTime」メソッドがあります。
これとよく似たDateOnlyを返すメソッド「ISOWeek.ToDateOnly」が追加予定です。
DateTime dateTime = ISOWeek.ToDateTime(year: 2020, week: 53, dayOfWeek: DayOfWeek.Friday);
// 2021/01/01 0:00:00
Console.WriteLine(dateTime);
DateOnly dateOnly = ISOWeek.ToDateOnly(year: 2020, week: 53, dayOfWeek: DayOfWeek.Friday);
// 2021/01/01 0:00:00
Console.WriteLine(dateOnly);
週番号に対応した書式指定子はない
.NET 9において、週番号に対応した書式指定子はなさそうです。
.NET 10 Preview 1でも、コード見る限りはぱっと見なさそう。
(書式指定子って、後から足せるんだろうか?足したら破壊的な変更になるから、難しい?)
まとめ
- .NETで、ISO 8601の週番号を扱いたい場合、ISOWeekクラスを使えばOK
- ISOWeekクラスには、.NET 10で、DateOnlyのメソッド・オーバーロードが追加予定
- .NET 9において、週番号に対応した書式指定子はない。.NET 10 preview 1段階でもなさそう