C# Tips | 日付・時間処理:年初取得

C# C#
スポンサーリンク

はじめに 「年初取得」は“年間ロジックのスタートライン”

月初・月末が「月次処理の基準点」だとしたら、
年初は「年間処理の基準点」です。

例えば、
「今年の売上集計」「今年の有給残高」「今年度の評価期間」
こういうロジックを書くときに、
“この日付が属する年の、1月1日” をサッと取れるかどうかで、コードの見通しがかなり変わります。

C# では、DateTimeYear を使って
new DateTime(year, 1, 1, …) を作る、というシンプルな考え方で実現できます。

ここから、
基本の年初取得 → ユーティリティ化 → 「今年・昨年・来年」の年初 → 会計年度との違い → UTC/ローカルの意識
という流れで、初心者向けにかみ砕いて説明していきます。


基本の考え方:年と「1月1日」から年初を作る

どんな日付でも「その年の1月1日」にそろえる

まずは、ある DateTime が与えられたときに、
「その日付が属する年の年初(1月1日)」を求める一番基本的な方法です。

using System;

DateTime any = new DateTime(2026, 5, 10, 15, 30, 0); // 2026/05/10 15:30

DateTime yearStart = new DateTime(any.Year, 1, 1);

Console.WriteLine(any);       // 2026/05/10 15:30:00
Console.WriteLine(yearStart); // 2026/01/01 0:00:00
C#

ポイントは、any.Year をそのまま使い、
月を 1、日を 1 に固定して new DateTime(year, 1, 1) を作ることです。

これで「その年の1月1日 0:00:00」の DateTime が得られます。

「今年の集計は 1/1 から始まる」という前提なら、
この年初を基準に「今年の期間」を組み立てていくことができます。


ユーティリティメソッドとしての「年初取得」

任意の日付から年初を求めるメソッド

毎回 new DateTime(d.Year, 1, 1) と書いてもいいのですが、
「これは年初を取っているんだ」と一目で分かるように、
ユーティリティメソッドにしてしまうのがおすすめです。

public static class YearUtil
{
    public static DateTime GetYearStart(DateTime date)
    {
        return new DateTime(date.Year, 1, 1, 0, 0, 0, date.Kind);
    }
}
C#

ここでは、Kind(Local / Utc / Unspecified)を引き継ぎつつ、
時刻は 0:00:00 にそろえています。

使い方はとてもシンプルです。

DateTime d = new DateTime(2026, 5, 10, 15, 30, 0, DateTimeKind.Local);

DateTime yearStart = YearUtil.GetYearStart(d);

Console.WriteLine(yearStart); // 2026/01/01 0:00:00 (Local)
C#

「このメソッドを通せば“その年の年初”が返ってくる」という約束が、
コード上にハッキリ見えるのが大事です。


「今年」「昨年」「来年」の年初を取る

今年の年初

「今年の年初」は、DateTime.Today を使うと分かりやすく書けます。

public static class YearUtil
{
    public static DateTime GetThisYearStartLocal()
    {
        DateTime today = DateTime.Today; // Local, 0:00
        return new DateTime(today.Year, 1, 1, 0, 0, 0, DateTimeKind.Local);
    }
}
C#

使い方の例です。

DateTime thisYearStart = YearUtil.GetThisYearStartLocal();
Console.WriteLine(thisYearStart); // 2026/01/01 0:00:00
C#

昨年・来年の年初

「昨年」「来年」は、年を ±1 するだけです。

public static class YearUtil
{
    public static DateTime GetThisYearStartLocal()
    {
        DateTime today = DateTime.Today;
        return new DateTime(today.Year, 1, 1, 0, 0, 0, DateTimeKind.Local);
    }

    public static DateTime GetNextYearStartLocal()
    {
        DateTime today = DateTime.Today;
        return new DateTime(today.Year + 1, 1, 1, 0, 0, 0, DateTimeKind.Local);
    }

    public static DateTime GetPreviousYearStartLocal()
    {
        DateTime today = DateTime.Today;
        return new DateTime(today.Year - 1, 1, 1, 0, 0, 0, DateTimeKind.Local);
    }
}
C#

使い方の例です。

DateTime thisYear  = YearUtil.GetThisYearStartLocal();
DateTime nextYear  = YearUtil.GetNextYearStartLocal();
DateTime prevYear  = YearUtil.GetPreviousYearStartLocal();

Console.WriteLine(thisYear); // 2026/01/01
Console.WriteLine(nextYear); // 2027/01/01
Console.WriteLine(prevYear); // 2025/01/01
C#

「今年の年初」を基準に、
「昨年」「来年」を相対的に扱えるようにしておくと、
年間ロジックがとても書きやすくなります。


年初とセットでよく使う「年末取得」と「年間期間」

年末は「翌年の年初 − 1日」で求める

月末と同じ発想で、
年末は「翌年の年初から1日引く」という形で求められます。

public static class YearUtil
{
    public static DateTime GetYearStart(DateTime date)
    {
        return new DateTime(date.Year, 1, 1, 0, 0, 0, date.Kind);
    }

    public static DateTime GetYearEnd(DateTime date)
    {
        DateTime yearStart     = GetYearStart(date);
        DateTime nextYearStart = yearStart.AddYears(1);
        DateTime yearEnd       = nextYearStart.AddDays(-1);
        return yearEnd;
    }
}
C#

使い方の例です。

DateTime d = new DateTime(2026, 5, 10);

DateTime yearStart = YearUtil.GetYearStart(d);
DateTime yearEnd   = YearUtil.GetYearEnd(d);

Console.WriteLine(yearStart); // 2026/01/01
Console.WriteLine(yearEnd);   // 2026/12/31
C#

「その年の期間」をひとまとめにする

月のときと同じように、
「年初〜年末」をひとまとめにした型を用意しておくと便利です。

public readonly struct YearRange
{
    public DateTime Start { get; }
    public DateTime End   { get; }

    public YearRange(DateTime start, DateTime end)
    {
        Start = start;
        End   = end;
    }
}

public static class YearUtil
{
    public static YearRange GetYearRange(DateTime any)
    {
        DateTime start = GetYearStart(any);
        DateTime end   = GetYearEnd(any);
        return new YearRange(start, end);
    }
}
C#

使い方の例です。

DateTime target = new DateTime(2026, 5, 10);

YearRange range = YearUtil.GetYearRange(target);

Console.WriteLine($"開始: {range.Start}"); // 2026/01/01
Console.WriteLine($"終了: {range.End}");   // 2026/12/31
C#

この YearRange
「今年の売上集計の対象期間」「今年の勤怠集計の対象期間」などにそのまま使えるようにしておくと、
年間ロジックのコードがかなり整理されます。


会計年度・事業年度との違いに注意する

「年初=1月1日」とは限らない世界

ここまで話してきた「年初」は、
暦年(カレンダー上の年)の話です。

でも、業務によっては
「会計年度は4月1日スタート」
「事業年度は7月1日スタート」
のように、「年の始まり」が1月1日ではないこともよくあります。

その場合は、
「会計年度の年初取得ユーティリティ」を別で定義するのが安全です。

例えば「4月始まりの会計年度」の年初を求めるなら、
こんなイメージになります。

public static class FiscalYearUtil
{
    // 4月始まりの会計年度の年初を求める
    public static DateTime GetFiscalYearStart(DateTime date)
    {
        int year = date.Year;

        // 1〜3月は「前の年の4月1日」が会計年度の年初
        if (date.Month < 4)
        {
            year -= 1;
        }

        return new DateTime(year, 4, 1, 0, 0, 0, date.Kind);
    }
}
C#

暦年の年初(1月1日)と、
会計年度の年初(4月1日など)は、
別物としてユーティリティを分けるのがポイントです。


UTCとローカル、どの時間軸の年初を扱うか

「どのタイムゾーンの“年初”か」を意識する

年初も、UTCとローカルで意味が変わります。

例えば、「日本時間での今年の年初」を基準にしたい場合は、
まずUTCから日本時間に変換してから年初を取る、という流れになります。

using System;

public static class YearUtil
{
    public static DateTime GetThisYearStartJstFromUtcNow()
    {
        DateTime utcNow = DateTime.UtcNow;

        TimeZoneInfo jst = TimeZoneInfo.FindSystemTimeZoneById("Tokyo Standard Time");
        DateTime nowJst  = TimeZoneInfo.ConvertTimeFromUtc(utcNow, jst);

        DateTime yearStartJst = new DateTime(nowJst.Year, 1, 1, 0, 0, 0, DateTimeKind.Unspecified);

        return yearStartJst;
    }
}
C#

「どのタイムゾーンの年初か」をユーティリティ名やコメントに明示しておくと、
後から読んだ人が迷わずに済みます。


まとめ 「年初取得ユーティリティ」は“年間ロジックの基準点”

年初取得は、
年間売上、年間勤怠、年間評価、年間レポートなど、
「1年単位で考えるロジック」の基準点になります。

押さえておきたいポイントは、次のようなイメージです。

  • 任意の日付の年初は new DateTime(date.Year, 1, 1, …) で作れる。
  • 「今年」「昨年」「来年」の年初は、Today.Year を基準に ±1 して組み立てると分かりやすい。
  • 年初と年末をセットにした「年間期間」型(YearRange など)を用意しておくと、集計やレポートのコードが読みやすくなる。
  • 会計年度・事業年度など、「年の始まりが1月1日ではない」ケースは、専用のユーティリティ(FiscalYearUtil など)として分けて設計する。
  • UTC基準かローカル基準か(どのタイムゾーンの年初か)を意識し、ユーティリティ名にもそれを反映しておくと安全。

ここを押さえておくと、
「その場しのぎで年をいじっている」状態から一歩進んで、
“年間ロジックの基準点をきれいに定義した、実務で使える日付・時間ユーティリティ”を
自分のC#コードの中に自然に組み込めるようになっていきます。

タイトルとURLをコピーしました