暦の操作

日時の値は特定の時点を表しますが、その文字列形式はカルチャに依存し、特定のカルチャで日時の値の表示に使用される規則と、そのカルチャで使用される暦の両方に応じて決まります。 このトピックでは、.NET でサポートされる暦を紹介し、Calendar クラスを使用した日付の値の操作について説明します。

.NET の暦

.NET の暦はすべて、基本の暦の実装を提供する System.Globalization.Calendar クラスから派生します。 Calendar クラスを継承するクラスの 1 つに EastAsianLunisolarCalendar クラスがあります。これは、すべての太陰太陽暦の基本クラスです。 .NET には、次の暦の実装が含まれています。

暦は、次の 2 とおりの方法で使用できます。

  • 特定のカルチャで使用される暦として使用する。 CultureInfo オブジェクトにはそれぞれ、現在の暦 (オブジェクトで現在使用している暦) があります。 あらゆる日付と時刻の値の文字列形式には、現在のカルチャとその現在の暦が自動的に反映されます。 通常、現在の暦は、カルチャの既定の暦になります。 CultureInfo オブジェクトには、それ以外に、オプションの暦 (そのカルチャで使用できるその他の暦) も含まれています。

  • 特定のカルチャに依存しないスタンドアロンの暦として使用する。 この場合、暦が反映された値として日付を表すには、Calendar のメソッドを使用します。

ChineseLunisolarCalendarJapaneseLunisolarCalendarJulianCalendarKoreanLunisolarCalendarPersianCalendar、および TaiwanLunisolarCalendar の 6 つの Calendar クラスは、スタンドアロンの暦としてのみ使用できます。 これらは、どのカルチャでも、既定の暦またはオプションの暦としては使用されません。

暦とカルチャ

各カルチャには既定の暦があり、CultureInfo.Calendar プロパティで定義されます。 CultureInfo.OptionalCalendars プロパティは、特定のカルチャでサポートされるすべての暦を指定する Calendar オブジェクトの配列を返します。これには、そのカルチャの既定の暦も含まれます。

CultureInfo.Calendar プロパティと CultureInfo.OptionalCalendars プロパティの例を次に示します。 この例では、タイ語 (タイ) と日本語 (日本) のカルチャの CultureInfo オブジェクトをそれぞれ作成し、それらの既定の暦とオプションの暦を表示します。 どちらについても、カルチャの既定の暦は CultureInfo.OptionalCalendars コレクションにも含まれます。

using System;
using System.Globalization;

public class Example
{
   public static void Main()
   {
      // Create a CultureInfo for Thai in Thailand.
      CultureInfo th = CultureInfo.CreateSpecificCulture("th-TH");
      DisplayCalendars(th);

      // Create a CultureInfo for Japanese in Japan.
      CultureInfo ja = CultureInfo.CreateSpecificCulture("ja-JP");
      DisplayCalendars(ja);
   }

   static void DisplayCalendars(CultureInfo ci)
   {
      Console.WriteLine("Calendars for the {0} culture:", ci.Name);

      // Get the culture's default calendar.
      Calendar defaultCalendar = ci.Calendar;
      Console.Write("   Default Calendar: {0}", GetCalendarName(defaultCalendar));

      if (defaultCalendar is GregorianCalendar)
         Console.WriteLine(" ({0})",
                           ((GregorianCalendar) defaultCalendar).CalendarType);
      else
         Console.WriteLine();

      // Get the culture's optional calendars.
      Console.WriteLine("   Optional Calendars:");
      foreach (var optionalCalendar in ci.OptionalCalendars) {
         Console.Write("{0,6}{1}", "", GetCalendarName(optionalCalendar));
         if (optionalCalendar is GregorianCalendar)
            Console.Write(" ({0})",
                          ((GregorianCalendar) optionalCalendar).CalendarType);

         Console.WriteLine();
      }
      Console.WriteLine();
   }

   static string GetCalendarName(Calendar cal)
   {
      return cal.ToString().Replace("System.Globalization.", "");
   }
}
// The example displays the following output:
//       Calendars for the th-TH culture:
//          Default Calendar: ThaiBuddhistCalendar
//          Optional Calendars:
//             ThaiBuddhistCalendar
//             GregorianCalendar (Localized)
//
//       Calendars for the ja-JP culture:
//          Default Calendar: GregorianCalendar (Localized)
//          Optional Calendars:
//             GregorianCalendar (Localized)
//             JapaneseCalendar
//             GregorianCalendar (USEnglish)
Imports System.Globalization

Public Module Example
    Public Sub Main()
        ' Create a CultureInfo for Thai in Thailand.
        Dim th As CultureInfo = CultureInfo.CreateSpecificCulture("th-TH")
        DisplayCalendars(th)

        ' Create a CultureInfo for Japanese in Japan.
        Dim ja As CultureInfo = CultureInfo.CreateSpecificCulture("ja-JP")
        DisplayCalendars(ja)
    End Sub

    Sub DisplayCalendars(ci As CultureInfo)
        Console.WriteLine("Calendars for the {0} culture:", ci.Name)

        ' Get the culture's default calendar.
        Dim defaultCalendar As Calendar = ci.Calendar
        Console.Write("   Default Calendar: {0}", GetCalendarName(defaultCalendar))

        If TypeOf defaultCalendar Is GregorianCalendar Then
            Console.WriteLine(" ({0})",
                              CType(defaultCalendar, GregorianCalendar).CalendarType)
        Else
            Console.WriteLine()
        End If

        ' Get the culture's optional calendars.
        Console.WriteLine("   Optional Calendars:")
        For Each optionalCalendar In ci.OptionalCalendars
            Console.Write("{0,6}{1}", "", GetCalendarName(optionalCalendar))
            If TypeOf optionalCalendar Is GregorianCalendar Then
                Console.Write(" ({0})",
                              CType(optionalCalendar, GregorianCalendar).CalendarType)
            End If
            Console.WriteLine()
        Next
        Console.WriteLine()
    End Sub

    Function GetCalendarName(cal As Calendar) As String
        Return cal.ToString().Replace("System.Globalization.", "")
    End Function
End Module
' The example displays the following output:
'       Calendars for the th-TH culture:
'          Default Calendar: ThaiBuddhistCalendar
'          Optional Calendars:
'             ThaiBuddhistCalendar
'             GregorianCalendar (Localized)
'       
'       Calendars for the ja-JP culture:
'          Default Calendar: GregorianCalendar (Localized)
'          Optional Calendars:
'             GregorianCalendar (Localized)
'             JapaneseCalendar
'             GregorianCalendar (USEnglish)

特定の CultureInfo オブジェクトで現在使用されている暦は、カルチャの DateTimeFormatInfo.Calendar プロパティで定義されます。 カルチャの DateTimeFormatInfo オブジェクトは、CultureInfo.DateTimeFormat プロパティから返されます。 カルチャの作成時の既定値は CultureInfo.Calendar プロパティの値と同じですが、 カルチャの現在の暦は、CultureInfo.OptionalCalendars プロパティから返される配列に含まれる任意の暦に変更することができます。 現在の暦を CultureInfo.OptionalCalendars プロパティの値に含まれない暦に設定しようとすると、ArgumentException がスローされます。

アラビア語 (サウジアラビア) のカルチャで使用する暦を変更する例を次に示します。 まず、DateTime 値をインスタンス化し、現在のカルチャ (この例では英語 (米国)) と現在のカルチャの暦 (この例ではグレゴリオ暦) を使用して日付を表示します。 次に、現在のカルチャをアラビア語 (サウジアラビア) に変更し、そのカルチャの既定のウムアルクラ暦を使用して日付を表示します。 さらに、CalendarExists メソッドを呼び出して、アラビア語 (サウジアラビア) のカルチャで回教暦がサポートされているかどうかを判別します。 この暦はサポートされているため、現在の暦を回教暦に変更し、日付をもう一度表示します。 いずれの場合も、日付は、現在のカルチャの現在の暦を使用して表示されます。

using System;
using System.Globalization;
using System.Threading;

public class Example
{
   public static void Main()
   {
      DateTime date1 = new DateTime(2011, 6, 20);

      DisplayCurrentInfo();
      // Display the date using the current culture and calendar.
      Console.WriteLine(date1.ToString("d"));
      Console.WriteLine();

      CultureInfo arSA = CultureInfo.CreateSpecificCulture("ar-SA");

      // Change the current culture to Arabic (Saudi Arabia).
      Thread.CurrentThread.CurrentCulture = arSA;
      // Display date and information about the current culture.
      DisplayCurrentInfo();
      Console.WriteLine(date1.ToString("d"));
      Console.WriteLine();

      // Change the calendar to Hijri.
      Calendar hijri = new HijriCalendar();
      if (CalendarExists(arSA, hijri)) {
         arSA.DateTimeFormat.Calendar = hijri;
         // Display date and information about the current culture.
         DisplayCurrentInfo();
         Console.WriteLine(date1.ToString("d"));
      }
   }

   private static void DisplayCurrentInfo()
   {
      Console.WriteLine("Current Culture: {0}",
                        CultureInfo.CurrentCulture.Name);
      Console.WriteLine("Current Calendar: {0}",
                        DateTimeFormatInfo.CurrentInfo.Calendar);
   }

   private static bool CalendarExists(CultureInfo culture, Calendar cal)
   {
      foreach (Calendar optionalCalendar in culture.OptionalCalendars)
         if (cal.ToString().Equals(optionalCalendar.ToString()))
            return true;

      return false;
   }
}
// The example displays the following output:
//    Current Culture: en-US
//    Current Calendar: System.Globalization.GregorianCalendar
//    6/20/2011
//
//    Current Culture: ar-SA
//    Current Calendar: System.Globalization.UmAlQuraCalendar
//    18/07/32
//
//    Current Culture: ar-SA
//    Current Calendar: System.Globalization.HijriCalendar
//    19/07/32
Imports System.Globalization
Imports System.Threading

Module Example
    Public Sub Main()
        Dim date1 As Date = #6/20/2011#

        DisplayCurrentInfo()
        ' Display the date using the current culture and calendar.
        Console.WriteLine(date1.ToString("d"))
        Console.WriteLine()

        Dim arSA As CultureInfo = CultureInfo.CreateSpecificCulture("ar-SA")

        ' Change the current culture to Arabic (Saudi Arabia).
        Thread.CurrentThread.CurrentCulture = arSA
        ' Display date and information about the current culture.
        DisplayCurrentInfo()
        Console.WriteLine(date1.ToString("d"))
        Console.WriteLine()

        ' Change the calendar to Hijri.
        Dim hijri As Calendar = New HijriCalendar()
        If CalendarExists(arSA, hijri) Then
            arSA.DateTimeFormat.Calendar = hijri
            ' Display date and information about the current culture.
            DisplayCurrentInfo()
            Console.WriteLine(date1.ToString("d"))
        End If
    End Sub

    Private Sub DisplayCurrentInfo()
        Console.WriteLine("Current Culture: {0}",
                          CultureInfo.CurrentCulture.Name)
        Console.WriteLine("Current Calendar: {0}",
                          DateTimeFormatInfo.CurrentInfo.Calendar)
    End Sub

    Private Function CalendarExists(ByVal culture As CultureInfo,
                                    cal As Calendar) As Boolean
        For Each optionalCalendar As Calendar In culture.OptionalCalendars
            If cal.ToString().Equals(optionalCalendar.ToString()) Then Return True
        Next
        Return False
    End Function
End Module
' The example displays the following output:
'    Current Culture: en-US
'    Current Calendar: System.Globalization.GregorianCalendar
'    6/20/2011
'    
'    Current Culture: ar-SA
'    Current Calendar: System.Globalization.UmAlQuraCalendar
'    18/07/32
'    
'    Current Culture: ar-SA
'    Current Calendar: System.Globalization.HijriCalendar
'    19/07/32

日付とカレンダー

Calendar 型のパラメーターを含み、指定した暦の値を日付の要素 (月、日、および年) に反映できるコンストラクターは例外として、DateTimeDateTimeOffset の値は、どちらも常にグレゴリオ暦に基づきます。 つまり、たとえば DateTime.Year プロパティはグレゴリオ暦の年を返し、DateTime.Day プロパティはグレゴリオ暦の月の日付を返します。

重要

日付の値とその文字列形式で処理が異なることに注意してください。 日付の値はグレゴリオ暦に基づき、文字列形式は特定のカルチャの現在の暦に基づきます。

次の例は、DateTime のプロパティと、それに対応する Calendar のメソッドの違いを示しています。 この例では、現在のカルチャはアラビア語 (エジプト)、現在の暦はウムアルクラ暦です。 DateTime 値は、2011 年の 7 番目の月の 15 番目の日に設定されています。 この値は、明らかにグレゴリオ暦の日付と解釈されます。DateTime.ToString(String, IFormatProvider) メソッドでインバリアント カルチャの規則を使用した場合に、これらと同じ値が返されるためです。 現在のカルチャの規則を使用して書式指定された日付の文字列形式は 14/08/32 です。これは、この日付に相当するウムアルクラ暦の日付です。 次に、DateTimeCalendar のメンバーを使用して、DateTime 値の日、月、および年が返されます。 いずれの場合も、DateTime のメンバーから返される値にはグレゴリオ暦の値が反映され、UmAlQuraCalendar のメンバーから返される値にはウムアルクラ暦の値が反映されます。

using System;
using System.Globalization;
using System.Threading;

public class Example
{
   public static void Main()
   {
      // Make Arabic (Egypt) the current culture
      // and Umm al-Qura calendar the current calendar.
      CultureInfo arEG = CultureInfo.CreateSpecificCulture("ar-EG");
      Calendar cal = new UmAlQuraCalendar();
      arEG.DateTimeFormat.Calendar = cal;
      Thread.CurrentThread.CurrentCulture = arEG;

      // Display information on current culture and calendar.
      DisplayCurrentInfo();

      // Instantiate a date object.
      DateTime date1 = new DateTime(2011, 7, 15);

      // Display the string representation of the date.
      Console.WriteLine("Date: {0:d}", date1);
      Console.WriteLine("Date in the Invariant Culture: {0}",
                        date1.ToString("d", CultureInfo.InvariantCulture));
      Console.WriteLine();

      // Compare DateTime properties and Calendar methods.
      Console.WriteLine("DateTime.Month property: {0}", date1.Month);
      Console.WriteLine("UmAlQura.GetMonth: {0}",
                        cal.GetMonth(date1));
      Console.WriteLine();

      Console.WriteLine("DateTime.Day property: {0}", date1.Day);
      Console.WriteLine("UmAlQura.GetDayOfMonth: {0}",
                        cal.GetDayOfMonth(date1));
      Console.WriteLine();

      Console.WriteLine("DateTime.Year property: {0:D4}", date1.Year);
      Console.WriteLine("UmAlQura.GetYear: {0}",
                        cal.GetYear(date1));
      Console.WriteLine();
   }

   private static void DisplayCurrentInfo()
   {
      Console.WriteLine("Current Culture: {0}",
                        CultureInfo.CurrentCulture.Name);
      Console.WriteLine("Current Calendar: {0}",
                        DateTimeFormatInfo.CurrentInfo.Calendar);
   }
}
// The example displays the following output:
//    Current Culture: ar-EG
//    Current Calendar: System.Globalization.UmAlQuraCalendar
//    Date: 14/08/32
//    Date in the Invariant Culture: 07/15/2011
//
//    DateTime.Month property: 7
//    UmAlQura.GetMonth: 8
//
//    DateTime.Day property: 15
//    UmAlQura.GetDayOfMonth: 14
//
//    DateTime.Year property: 2011
//    UmAlQura.GetYear: 1432
Imports System.Globalization
Imports System.Threading

Module Example
    Public Sub Main()
        ' Make Arabic (Egypt) the current culture 
        ' and Umm al-Qura calendar the current calendar. 
        Dim arEG As CultureInfo = CultureInfo.CreateSpecificCulture("ar-EG")
        Dim cal As Calendar = New UmAlQuraCalendar()
        arEG.DateTimeFormat.Calendar = cal
        Thread.CurrentThread.CurrentCulture = arEG

        ' Display information on current culture and calendar.
        DisplayCurrentInfo()

        ' Instantiate a date object.
        Dim date1 As Date = #07/15/2011#

        ' Display the string representation of the date.
        Console.WriteLine("Date: {0:d}", date1)
        Console.WriteLine("Date in the Invariant Culture: {0}",
                          date1.ToString("d", CultureInfo.InvariantCulture))
        Console.WriteLine()

        ' Compare DateTime properties and Calendar methods.
        Console.WriteLine("DateTime.Month property: {0}", date1.Month)
        Console.WriteLine("UmAlQura.GetMonth: {0}",
                          cal.GetMonth(date1))
        Console.WriteLine()

        Console.WriteLine("DateTime.Day property: {0}", date1.Day)
        Console.WriteLine("UmAlQura.GetDayOfMonth: {0}",
                          cal.GetDayOfMonth(date1))
        Console.WriteLine()

        Console.WriteLine("DateTime.Year property: {0:D4}", date1.Year)
        Console.WriteLine("UmAlQura.GetYear: {0}",
                          cal.GetYear(date1))
        Console.WriteLine()
    End Sub

    Private Sub DisplayCurrentInfo()
        Console.WriteLine("Current Culture: {0}",
                          CultureInfo.CurrentCulture.Name)
        Console.WriteLine("Current Calendar: {0}",
                          DateTimeFormatInfo.CurrentInfo.Calendar)
    End Sub
End Module
' The example displays the following output:
'    Current Culture: ar-EG
'    Current Calendar: System.Globalization.UmAlQuraCalendar
'    Date: 14/08/32
'    Date in the Invariant Culture: 07/15/2011
'    
'    DateTime.Month property: 7
'    UmAlQura.GetMonth: 8
'    
'    DateTime.Day property: 15
'    UmAlQura.GetDayOfMonth: 14
'    
'    DateTime.Year property: 2011
'    UmAlQura.GetYear: 1432

暦に基づく日付のインスタンス化

DateTimeDateTimeOffset の値はグレゴリオ暦に基づくため、別の暦の日、月、または年の値を使用する場合は、Calendar 型のパラメーターを含むオーバーロードされたコンストラクターを呼び出して日付の値をインスタンス化する必要があります。 また、特定の暦の Calendar.ToDateTime メソッドのいずれかのオーバーロードを呼び出して、特定の暦の値に基づいて DateTime オブジェクトをインスタンス化することもできます。

次の例では、DateTime オブジェクトを HebrewCalendar コンストラクターに渡して 1 つの DateTime 値をインスタンス化し、DateTime メソッドを呼び出してもう 1 つの HebrewCalendar.ToDateTime(Int32, Int32, Int32, Int32, Int32, Int32, Int32, Int32) 値をインスタンス化しています。 2 つの値はヘブライ暦の同一の値を使用して作成されるため、DateTime.Equals メソッドを呼び出すと、2 つの DateTime 値が等しいことが示されます。

using System;
using System.Globalization;

public class Example
{
   public static void Main()
   {
      HebrewCalendar hc = new HebrewCalendar();

      DateTime date1 = new DateTime(5771, 6, 1, hc);
      DateTime date2 = hc.ToDateTime(5771, 6, 1, 0, 0, 0, 0);

      Console.WriteLine("{0:d} (Gregorian) = {1:d2}/{2:d2}/{3:d4} ({4}): {5}",
                        date1,
                        hc.GetMonth(date2),
                        hc.GetDayOfMonth(date2),
                        hc.GetYear(date2),
                        GetCalendarName(hc),
                        date1.Equals(date2));
   }

   private static string GetCalendarName(Calendar cal)
   {
      return cal.ToString().Replace("System.Globalization.", "").
                            Replace("Calendar", "");
   }
}
// The example displays the following output:
//    2/5/2011 (Gregorian) = 06/01/5771 (Hebrew): True
Imports System.Globalization

Module Example
    Public Sub Main()
        Dim hc As New HebrewCalendar()

        Dim date1 As New Date(5771, 6, 1, hc)
        Dim date2 As Date = hc.ToDateTime(5771, 6, 1, 0, 0, 0, 0)

        Console.WriteLine("{0:d} (Gregorian) = {1:d2}/{2:d2}/{3:d4} ({4}): {5}",
                          date1,
                          hc.GetMonth(date2),
                          hc.GetDayOfMonth(date2),
                          hc.GetYear(date2),
                          GetCalendarName(hc),
                          date1.Equals(date2))
    End Sub

    Private Function GetCalendarName(cal As Calendar) As String
        Return cal.ToString().Replace("System.Globalization.", "").
                              Replace("Calendar", "")
    End Function
End Module
' The example displays the following output:
'   2/5/2011 (Gregorian) = 06/01/5771 (Hebrew): True

現在の暦での日付の表現

日時書式指定メソッドでは、日付を文字列に変換する際に、常に現在の暦を使用します。 つまり、年、月、および日の文字列形式には現在の暦が反映され、必ずしもグレゴリオ暦が反映されるとは限りません。

次の例は、現在の暦が日付の文字列形式にどのように影響するかを示しています。 この例では、現在のカルチャを中国語 (繁体字、台湾) に変更し、日付の値をインスタンス化します。 その後、現在の暦と日付を表示し、現在の暦を TaiwanCalendar に変更して、現在の暦と日付をもう一度表示します。 最初に日付を表示したときは、日付がグレゴリオ暦の日付として表され、 2 回目に表示したときは、台湾暦の日付として表されます。

using System;
using System.Globalization;
using System.Threading;

public class Example
{
   public static void Main()
   {
      // Change the current culture to zh-TW.
      CultureInfo zhTW = CultureInfo.CreateSpecificCulture("zh-TW");
      Thread.CurrentThread.CurrentCulture = zhTW;
      // Define a date.
      DateTime date1 = new DateTime(2011, 1, 16);

      // Display the date using the default (Gregorian) calendar.
      Console.WriteLine("Current calendar: {0}",
                        zhTW.DateTimeFormat.Calendar);
      Console.WriteLine(date1.ToString("d"));

      // Change the current calendar and display the date.
      zhTW.DateTimeFormat.Calendar = new TaiwanCalendar();
      Console.WriteLine("Current calendar: {0}",
                        zhTW.DateTimeFormat.Calendar);
      Console.WriteLine(date1.ToString("d"));
   }
}
// The example displays the following output:
//    Current calendar: System.Globalization.GregorianCalendar
//    2011/1/16
//    Current calendar: System.Globalization.TaiwanCalendar
//    100/1/16
Imports System.Globalization
Imports System.Threading

Module Example
    Public Sub Main()
        ' Change the current culture to zh-TW.
        Dim zhTW As CultureInfo = CultureInfo.CreateSpecificCulture("zh-TW")
        Thread.CurrentThread.CurrentCulture = zhTW
        ' Define a date.
        Dim date1 As Date = #1/16/2011#

        ' Display the date using the default (Gregorian) calendar.
        Console.WriteLine("Current calendar: {0}",
                          zhTW.DateTimeFormat.Calendar)
        Console.WriteLine(date1.ToString("d"))

        ' Change the current calendar and display the date.
        zhTW.DateTimeFormat.Calendar = New TaiwanCalendar()
        Console.WriteLine("Current calendar: {0}",
                          zhTW.DateTimeFormat.Calendar)
        Console.WriteLine(date1.ToString("d"))
    End Sub
End Module
' The example displays the following output:
'    Current calendar: System.Globalization.GregorianCalendar
'    2011/1/16
'    Current calendar: System.Globalization.TaiwanCalendar
'    100/1/16

現在の暦以外での日付の表現

特定のカルチャの現在の暦以外の暦を使用して日付を表すには、その Calendar オブジェクトのメソッドを呼び出す必要があります。 たとえば、Calendar.GetYearCalendar.GetMonth、および Calendar.GetDayOfMonth の各メソッドは、それぞれ年、月、および日を、特定の暦を反映した値に変換します。

警告

一部の暦はどのカルチャのオプションの暦にもなっていないため、そのような暦で日付を表す場合は、常に Calendar のメソッドを呼び出す必要があります。 これは、EastAsianLunisolarCalendar クラス、JulianCalendar クラス、および PersianCalendar クラスから派生したすべての暦に当てはまります。

次の例では、JulianCalendar オブジェクトを使用して、ユリウス暦の 1905 年 1 月 9 日という日付をインスタンス化します。 この日付を既定の暦 (グレゴリオ暦) を使用して表示した場合は、1905 年 1 月 22 日と表されます。 JulianCalendar の各メソッドを呼び出すことで、この日付をユリウス暦で表すことができます。

using System;
using System.Globalization;

public class Example
{
   public static void Main()
   {
      JulianCalendar julian = new JulianCalendar();
      DateTime date1 = new DateTime(1905, 1, 9, julian);

      Console.WriteLine("Date ({0}): {1:d}",
                        CultureInfo.CurrentCulture.Calendar,
                        date1);
      Console.WriteLine("Date in Julian calendar: {0:d2}/{1:d2}/{2:d4}",
                        julian.GetMonth(date1),
                        julian.GetDayOfMonth(date1),
                        julian.GetYear(date1));
   }
}
// The example displays the following output:
//    Date (System.Globalization.GregorianCalendar): 1/22/1905
//    Date in Julian calendar: 01/09/1905
Imports System.Globalization

Module Example
    Public Sub Main()
        Dim julian As New JulianCalendar()
        Dim date1 As New Date(1905, 1, 9, julian)

        Console.WriteLine("Date ({0}): {1:d}",
                          CultureInfo.CurrentCulture.Calendar,
                          date1)
        Console.WriteLine("Date in Julian calendar: {0:d2}/{1:d2}/{2:d4}",
                          julian.GetMonth(date1),
                          julian.GetDayOfMonth(date1),
                          julian.GetYear(date1))
    End Sub
End Module
' The example displays the following output:
'    Date (System.Globalization.GregorianCalendar): 1/22/1905
'    Date in Julian calendar: 01/09/1905

暦と日付範囲

暦でサポートされている最も古い日付は、暦の Calendar.MinSupportedDateTime プロパティによって示されます。 GregorianCalendar クラスでは、その日付は西暦 0001 年 1 月 1 日 です。.NET の他のほとんどの暦では、それより後の日付がサポートされています。 暦でサポートされている最も古い日付より前の日付と時刻の値を処理しようとすると、ArgumentOutOfRangeException 例外がスローされます。

ただし、重要な例外が 1 つあります。 DateTime オブジェクトと DateTimeOffset オブジェクトの既定の (初期化されていない) 値は、GregorianCalendar.MinSupportedDateTime 値と同じです。 西暦 0001 年 1 月 1 日をサポートしていない暦でこの日付を書式設定しようとすると、書式指定子を指定しない場合、書式設定メソッドは "G" (一般の日付と時刻のパターン) 書式指定子でなく、"s" (並べ替え可能な日付と時刻のパターン) 書式指定子を使用します。 その結果、書式設定操作は ArgumentOutOfRangeException 例外をスローしません。 代わりに、サポートされていない日付を返します。 この問題を、次の例で説明します。この例は、現在のカルチャが日本語 (日本) に設定されていれば和暦で、アラビア語 (エジプト) に設定されていればウムアルクラ暦で、DateTime.MinValue の値を表示します。 また、現在のカルチャを英語 (米国) に設定し、これらの各 DateTime.ToString(IFormatProvider) オブジェクトで CultureInfo メソッドを呼び出します。 どの場合も、並べ替え可能な日付と時刻のパターンを使用して、日付が表示されます。

using System;
using System.Globalization;
using System.Threading;

public class Example
{
   public static void Main()
   {
      DateTime dat = DateTime.MinValue;

      // Change the current culture to ja-JP with the Japanese Calendar.
      CultureInfo jaJP = CultureInfo.CreateSpecificCulture("ja-JP");
      jaJP.DateTimeFormat.Calendar = new JapaneseCalendar();
      Thread.CurrentThread.CurrentCulture = jaJP;
      Console.WriteLine("Earliest supported date by {1} calendar: {0:d}",
                        jaJP.DateTimeFormat.Calendar.MinSupportedDateTime,
                        GetCalendarName(jaJP));
      // Attempt to display the date.
      Console.WriteLine(dat.ToString());
      Console.WriteLine();

      // Change the current culture to ar-EG with the Um Al Qura calendar.
      CultureInfo arEG = CultureInfo.CreateSpecificCulture("ar-EG");
      arEG.DateTimeFormat.Calendar = new UmAlQuraCalendar();
      Thread.CurrentThread.CurrentCulture = arEG;
      Console.WriteLine("Earliest supported date by {1} calendar: {0:d}",
                        arEG.DateTimeFormat.Calendar.MinSupportedDateTime,
                        GetCalendarName(arEG));
      // Attempt to display the date.
      Console.WriteLine(dat.ToString());
      Console.WriteLine();

      // Change the current culture to en-US.
      Thread.CurrentThread.CurrentCulture = CultureInfo.CreateSpecificCulture("en-US");
      Console.WriteLine(dat.ToString(jaJP));
      Console.WriteLine(dat.ToString(arEG));
      Console.WriteLine(dat.ToString("d"));
   }

   private static string GetCalendarName(CultureInfo culture)
   {
      Calendar cal = culture.DateTimeFormat.Calendar;
      return cal.GetType().Name.Replace("System.Globalization.", "").Replace("Calendar", "");
   }
}
// The example displays the following output:
//       Earliest supported date by Japanese calendar: 明治 1/9/8
//       0001-01-01T00:00:00
//
//       Earliest supported date by UmAlQura calendar: 01/01/18
//       0001-01-01T00:00:00
//
//       0001-01-01T00:00:00
//       0001-01-01T00:00:00
//       1/1/0001
Imports System.Globalization
Imports System.Threading

Module Example
    Public Sub Main()
        Dim dat As Date = DateTime.MinValue

        ' Change the current culture to ja-JP with the Japanese Calendar.
        Dim jaJP As CultureInfo = CultureInfo.CreateSpecificCulture("ja-JP")
        jaJP.DateTimeFormat.Calendar = New JapaneseCalendar()
        Thread.CurrentThread.CurrentCulture = jaJP
        Console.WriteLine("Earliest supported date by {1} calendar: {0:d}",
                          jaJP.DateTimeFormat.Calendar.MinSupportedDateTime,
                          GetCalendarName(jaJP))
        ' Attempt to display the date.
        Console.WriteLine(dat.ToString())
        Console.WriteLine()

        ' Change the current culture to ar-EG with the Um Al Qura calendar.
        Dim arEG As CultureInfo = CultureInfo.CreateSpecificCulture("ar-EG")
        arEG.DateTimeFormat.Calendar = New UmAlQuraCalendar()
        Thread.CurrentThread.CurrentCulture = arEG
        Console.WriteLine("Earliest supported date by {1} calendar: {0:d}",
                          arEG.DateTimeFormat.Calendar.MinSupportedDateTime,
                          GetCalendarName(arEG))
        ' Attempt to display the date.
        Console.WRiteLine(dat.ToString())
        Console.WRiteLine()

        ' Change the current culture to en-US.
        Thread.CurrentThread.CurrentCulture = CultureInfo.CreateSpecificCulture("en-US")
        Console.WriteLine(dat.ToString(jaJP))
        Console.WriteLine(dat.ToString(arEG))
        Console.WriteLine(dat.ToString("d"))
    End Sub

    Private Function GetCalendarName(culture As CultureInfo) As String
        Dim cal As Calendar = culture.DateTimeFormat.Calendar
        Return cal.GetType().Name.Replace("System.Globalization.", "").Replace("Calendar", "")
    End Function
End Module
' The example displays the following output:
'       Earliest supported date by Japanese calendar: 明治 1/9/8
'       0001-01-01T00:00:00
'       
'       Earliest supported date by UmAlQura calendar: 01/01/18
'       0001-01-01T00:00:00
'       
'       0001-01-01T00:00:00
'       0001-01-01T00:00:00
'       1/1/0001

時代 (年号) の使用

暦では通常、日付が時代 (年号) に分けられます。 ただし、.NET の Calendar クラスでは、暦で定義されるすべての時代 (年号) がサポートされているわけではなく、ほとんどの Calendar クラスでは 1 つの時代 (年号) しかサポートされていません。 複数の時代 (年号) をサポートしているのは、JapaneseCalendar クラスと JapaneseLunisolarCalendar クラスだけです。

重要

JapaneseCalendarJapaneseLunisolarCalendar の新しい時代 (年号) である令和は、2019 年 5 月 1 日に始まります。 この変更は、これらのカレンダーを使用するすべてのアプリケーションに影響します。 詳細については、次の記事を参照してください。

  • .NET における和暦の新しい時代 (年号) の処理。複数の時代 (年号) を持つ暦をサポートするために .NET に追加された機能と、複数の時代 (年号) の暦を処理するときのベスト プラクティスについて説明しています。
  • アプリケーションの新元号対応。改元への対応状況を確認するために Windows でアプリケーションをテストすることに関する情報を提供しています。
  • .NET Framework の新しい日本の元号の更新の概要。新しい日本の元号に関連する Windows の各バージョン向けの .NET Framework 更新プログラムの一覧を掲載し、複数の時代 (年号) をサポートする .NET Framework の新機能について説明し、アプリケーションをテストする際の注意事項も記載しています。

ほとんどの暦の時代 (年号) は、非常に長い期間を表します。 たとえば、グレゴリオ暦では、現在の時代 (年号) は 2 千年を超える範囲にまたがります。 複数の時代 (年号) をサポートする 2 つの暦である JapaneseCalendarJapaneseLunisolarCalendar では、それは当てはまりません。 時代 (年号) は、天皇の在位期間に対応します。 複数の時代 (年号) をサポートするにあたっては、特に現在の時代 (年号) の上限が不明な場合に、特別な課題が生じます。

時代 (年号) とその名前

.NET では、特定の暦の実装でサポートされる時代 (年号) を表す整数が、Calendar.Eras 配列に逆順で格納されています。 現在の時代 (最新の時間の範囲を含む時代) のインデックスは 0 で、複数の時代 (年号) をサポートする Calendar クラスの場合は、後に続く各インデックスが前の時代 (年号) に対応します。 Calendar.CurrentEra 配列における現在の時代 (年号) のインデックスは、静的な Calendar.Eras プロパティで定義されます。これは定数であり、値は常に 0 になります。 個々の Calendar クラスには、現在の時代 (年号) の値を返す静的フィールドも含まれています。 これらを次の表に示します。

Calendar クラス 現在の時代 (年号) のフィールド
ChineseLunisolarCalendar ChineseEra
GregorianCalendar ADEra
HebrewCalendar HebrewEra
HijriCalendar HijriEra
JapaneseLunisolarCalendar JapaneseEra
JulianCalendar JulianEra
KoreanCalendar KoreanEra
KoreanLunisolarCalendar GregorianEra
PersianCalendar PersianEra
ThaiBuddhistCalendar ThaiBuddhistEra
UmAlQuraCalendar UmAlQuraEra

特定の時代 (年号) を表す数値に対応する名前は、その数値を DateTimeFormatInfo.GetEraName メソッドまたは DateTimeFormatInfo.GetAbbreviatedEraName メソッドに渡すことで取得できます。 次の例では、これらのメソッドを呼び出して、GregorianCalendar クラスでサポートされる時代 (年号) に関する情報を取得しています。 現在の時代 (年号) の 2 年 1 月 1 日に対応するグレゴリオ暦の日付と、サポートされている和暦の各時代 (年号) の 2 年 1 月 1 日に対応するグレゴリオ暦の日付を表示します。

using System;
using System.Globalization;

public class Example
{
   public static void Main()
   {
      int year = 2;
      int month = 1;
      int day = 1;
      Calendar cal = new JapaneseCalendar();

      Console.WriteLine("\nDate instantiated without an era:");
      DateTime date1 = new DateTime(year, month, day, 0, 0, 0, 0, cal);
      Console.WriteLine("{0}/{1}/{2} in Japanese Calendar -> {3:d} in Gregorian",
                        cal.GetMonth(date1), cal.GetDayOfMonth(date1),
                        cal.GetYear(date1), date1);

      Console.WriteLine("\nDates instantiated with eras:");
      foreach (int era in cal.Eras) {
         DateTime date2 = cal.ToDateTime(year, month, day, 0, 0, 0, 0, era);
         Console.WriteLine("{0}/{1}/{2} era {3} in Japanese Calendar -> {4:d} in Gregorian",
                           cal.GetMonth(date2), cal.GetDayOfMonth(date2),
                           cal.GetYear(date2), cal.GetEra(date2), date2);
      }
   }
}
Imports System.Globalization

Module Example
    Public Sub Main()
        Dim year As Integer = 2
        Dim month As Integer = 1
        Dim day As Integer = 1
        Dim cal As New JapaneseCalendar()

        Console.WriteLine("Date instantiated without an era:")
        Dim date1 As New Date(year, month, day, 0, 0, 0, 0, cal)
        Console.WriteLine("{0}/{1}/{2} in Japanese Calendar -> {3:d} in Gregorian",
                          cal.GetMonth(date1), cal.GetDayOfMonth(date1),
                          cal.GetYear(date1), date1)
        Console.WriteLine()

        Console.WriteLine("Dates instantiated with eras:")
        For Each era As Integer In cal.Eras
            Dim date2 As Date = cal.ToDateTime(year, month, day, 0, 0, 0, 0, era)
            Console.WriteLine("{0}/{1}/{2} era {3} in Japanese Calendar -> {4:d} in Gregorian",
                              cal.GetMonth(date2), cal.GetDayOfMonth(date2),
                              cal.GetYear(date2), cal.GetEra(date2), date2)
        Next
    End Sub
End Module

また、"g" カスタム日時書式指定文字列では、日付と時刻の文字列形式に暦の時代 (年号) の名前が含まれます。 詳しくは、「カスタム日時形式文字列」をご覧ください。

時代 (年号) を含む日付のインスタンスを作成する

複数の時代 (年号) をサポートする 2 つの Calendar クラスでは、特定の年、月、日の値で構成される日付があいまいになることがあります。 たとえば、JapaneseCalendar でサポートされているすべての時代 (年号) には、番号が 1 である年が存在します。 通常、時代 (年号) が指定されていない場合は、日時および暦のどちらのメソッドでも、値が現在の時代 (年号) に属すると見なされます。 これは、型 Calendar のパラメーターを含む DateTimeDateTimeOffset のコンストラクターのほか、JapaneseCalendar.ToDateTime および JapaneseLunisolarCalendar.ToDateTime メソッドの場合に当てはまります。 次の例では、指定されていない時代 (年号) の 2 年目の 1 月 1 日を表す日付をインスタンス化します。 令和が現在の時代 (年号) である場合にこの例を実行すると、日付は令和 2 年として解釈されます。 DateTime.ToString(String, IFormatProvider) メソッドによって返される文字列の年の前には時代 (年号) として令和が付き、グレゴリオ暦の 2020 年 1 月 1 日に対応します。 (令和は、グレゴリオ暦の 2019 年から始まります)。

using System;
using System.Globalization;

public class Example
{
    public static void Main()
    {
        var japaneseCal = new JapaneseCalendar();
        var jaJp = new CultureInfo("ja-JP");
        jaJp.DateTimeFormat.Calendar = japaneseCal;

        var date = new DateTime(2, 1, 1, japaneseCal);
        Console.WriteLine($"Gregorian calendar date: {date:d}");
        Console.WriteLine($"Japanese calendar date: {date.ToString("d", jaJp)}");
    }
}
Imports System.Globalization

Public Module Example
    Public Sub Main()
        Dim japaneseCal = New JapaneseCalendar()
        Dim jaJp = New CultureInfo("ja-JP")
        jaJp.DateTimeFormat.Calendar = japaneseCal

        Dim dat = New DateTime(2, 1, 1, japaneseCal)
        Console.WriteLine($"Gregorian calendar dat: {dat:d}")
        Console.WriteLine($"Japanese calendar dat: {dat.ToString("d", jaJp)}")
    End Sub
End Module

ただし、時代 (年号) が変わると、このコードの目的はあいまいになります。 この日付は、現在の時代 (年号) の 2 年目を表しているのでしょうか? それとも、平成 2 年を表しているのでしょうか? このあいまいさを回避するには、次の 2 つの方法があります。

  • 既定の GregorianCalendar クラスを使用して日時の値をインスタンス化します。 その後、次の例に示すように、日付の文字列表現として和暦または日本の太陰太陽暦の暦を使用できます。

    using System;
    using System.Globalization;
    
    public class Example
    {
        public static void Main()
        {
            var japaneseCal = new JapaneseCalendar();
            var jaJp = new CultureInfo("ja-JP");
            jaJp.DateTimeFormat.Calendar = japaneseCal;
    
            var date = new DateTime(1905, 2, 12);
            Console.WriteLine($"Gregorian calendar date: {date:d}");
    
            // Call the ToString(IFormatProvider) method.
            Console.WriteLine($"Japanese calendar date: {date.ToString("d", jaJp)}");
    
            // Use a FormattableString object.
            FormattableString fmt = $"{date:d}";
            Console.WriteLine($"Japanese calendar date: {fmt.ToString(jaJp)}");
    
            // Use the JapaneseCalendar object.
            Console.WriteLine($"Japanese calendar date: {jaJp.DateTimeFormat.GetEraName(japaneseCal.GetEra(date))}" +
                              $"{japaneseCal.GetYear(date)}/{japaneseCal.GetMonth(date)}/{japaneseCal.GetDayOfMonth(date)}");
    
            // Use the current culture.
            CultureInfo.CurrentCulture = jaJp;
            Console.WriteLine($"Japanese calendar date: {date:d}");
        }
    }
    // The example displays the following output:
    //   Gregorian calendar date: 2/12/1905
    //   Japanese calendar date: 明治38/2/12
    //   Japanese calendar date: 明治38/2/12
    //   Japanese calendar date: 明治38/2/12
    //   Japanese calendar date: 明治38/2/12
    
    Imports System.Globalization
    
    Public Module Example
        Public Sub Main()
            Dim japaneseCal = New JapaneseCalendar()
            Dim jaJp = New CultureInfo("ja-JP")
            jaJp.DateTimeFormat.Calendar = japaneseCal
    
            Dim dat = New DateTime(1905, 2, 12)
            Console.WriteLine($"Gregorian calendar date: {dat:d}")
    
            ' Call the ToString(IFormatProvider) method.
            Console.WriteLine($"Japanese calendar date: {dat.ToString("d", jaJp)}")
    
            ' Use a FormattableString object.
            Dim fmt As FormattableString = $"{dat:d}"
            Console.WriteLine($"Japanese calendar date: {fmt.ToString(jaJp)}")
    
            ' Use the JapaneseCalendar object.
            Console.WriteLine($"Japanese calendar date: {jaJp.DateTimeFormat.GetEraName(japaneseCal.GetEra(dat))}" +
                              $"{japaneseCal.GetYear(dat)}/{japaneseCal.GetMonth(dat)}/{japaneseCal.GetDayOfMonth(dat)}")
    
            ' Use the current culture.
            CultureInfo.CurrentCulture = jaJp
            Console.WriteLine($"Japanese calendar date: {dat:d}")
        End Sub
    End Module
    ' The example displays the following output:
    '   Gregorian calendar date: 2/12/1905
    '   Japanese calendar date: 明治38/2/12
    '   Japanese calendar date: 明治38/2/12
    '   Japanese calendar date: 明治38/2/12
    '   Japanese calendar date: 明治38/2/12
    
    
    
  • 時代 (年号) を明示的に指定する日時メソッドを呼び出します。 これには次のメソッドが含まれます。

    次の例では、これら 3 つのメソッドを使用して、1868 年 9 月 8 日に始まり、1912 年 7 月 29 日に終わった明治の日時をインスタンス化します。

    using System;
    using System.Globalization;
    
    public class Example
    {
        public static void Main()
        {
            var japaneseCal = new JapaneseCalendar();
            var jaJp = new CultureInfo("ja-JP");
            jaJp.DateTimeFormat.Calendar = japaneseCal;
    
            // We can get the era index by calling DateTimeFormatInfo.GetEraName.
            int eraIndex = 0;
    
            for (int ctr = 0; ctr < jaJp.DateTimeFormat.Calendar.Eras.Length; ctr++)
               if (jaJp.DateTimeFormat.GetEraName(ctr) == "明治")
                  eraIndex = ctr;
            var date1 = japaneseCal.ToDateTime(23, 9, 8, 0, 0, 0, 0, eraIndex);
            Console.WriteLine($"{date1.ToString("d", jaJp)} (Gregorian {date1:d})");
    
            try {
                var date2 = DateTime.Parse("明治23/9/8", jaJp);
                Console.WriteLine($"{date2.ToString("d", jaJp)} (Gregorian {date2:d})");
            }
            catch (FormatException)
            {
                Console.WriteLine("The parsing operation failed.");
            }
    
            try {
                var date3 = DateTime.ParseExact("明治23/9/8", "gyy/M/d", jaJp);
                Console.WriteLine($"{date3.ToString("d", jaJp)} (Gregorian {date3:d})");
            }
            catch (FormatException)
            {
                Console.WriteLine("The parsing operation failed.");
            }
        }
    }
    // The example displays the following output:
    //   明治23/9/8 (Gregorian 9/8/1890)
    //   明治23/9/8 (Gregorian 9/8/1890)
    //   明治23/9/8 (Gregorian 9/8/1890)
    
    Imports System.Globalization
    
    Public Module Example
        Public Sub Main()
            Dim japaneseCal = New JapaneseCalendar()
            Dim jaJp = New CultureInfo("ja-JP")
            jaJp.DateTimeFormat.Calendar = japaneseCal
    
            ' We can get the era index by calling DateTimeFormatInfo.GetEraName.
            Dim eraIndex As Integer = 0
    
            For ctr As Integer = 0 To jaJp.DateTimeFormat.Calendar.Eras.Length - 1
                If jaJp.DateTimeFormat.GetEraName(ctr) = "明治" Then eraIndex = ctr
            Next
            Dim date1 = japaneseCal.ToDateTime(23, 9, 8, 0, 0, 0, 0, eraIndex)
            Console.WriteLine($"{date1.ToString("d", jaJp)} (Gregorian {date1:d})")
    
            Try
                Dim date2 = DateTime.Parse("明治23/9/8", jaJp)
                Console.WriteLine($"{date2.ToString("d", jaJp)} (Gregorian {date2:d})")
            Catch e As FormatException
                Console.WriteLine("The parsing operation failed.")
            End Try
    
            Try
                Dim date3 = DateTime.ParseExact("明治23/9/8", "gyy/M/d", jaJp)
                Console.WriteLine($"{date3.ToString("d", jaJp)} (Gregorian {date3:d})")
            Catch e As FormatException
                Console.WriteLine("The parsing operation failed.")
            End Try
        End Sub
    End Module
    ' The example displays the following output:
    '   明治23/9/8 (Gregorian 9/8/1890)
    '   明治23/9/8 (Gregorian 9/8/1890)
    '   明治23/9/8 (Gregorian 9/8/1890)
    

ヒント

複数の時代 (年号) をサポートする暦を使用する場合は、日付をインスタンス化するためにグレゴリオ暦の日付を "常に" 使用するか、その暦に基づいて日時をインスタンス化するときに時代 (年号) を指定します。

ToDateTime(Int32, Int32, Int32, Int32, Int32, Int32, Int32, Int32) メソッドに時代 (年号) を指定する場合は、暦の Eras プロパティに時代 (年号) のインデックスを指定します。 ただし、時代 (年号) が変わる暦では、これらのインデックスは定数値ではありません。現在の時代 (年号) はインデックス 0 で、最も古い時代 (年号) はインデックス Eras.Length - 1 になります。 新しい時代 (年号) が暦に追加されると、以前の時代 (年号) のインデックスが 1 つずつ増えます。 適切な時代 (年号) インデックスを指定するには、次のようにします。

  • 現在の時代 (年号) の日付の場合は、常に暦の CurrentEra プロパティを使用します。

  • 特定の時代 (年号) の日付については、DateTimeFormatInfo.GetEraName メソッドを使用して、指定した時代 (年号) 名に対応するインデックスを取得します。 これを行うには、JapaneseCalendar が、ja-JP カルチャを表す CultureInfo オブジェクトの現在の暦である必要があります。 (この技法は、JapaneseLunisolarCalendar でも機能します。JapaneseCalendar と同じ時代 (年号) をサポートしているからです。)前の例に、このアプローチが示されています。

暦、時代 (時代 (年号) )、日付範囲: 緩やかな範囲のチェック

個々の暦にサポートされる日付範囲があるのとまったく同様に、JapaneseCalendar および JapaneseLunisolarCalendar クラスの時代 (年号) にもサポートされる範囲があります。 以前は、.NET では厳密な時代 (年号) の範囲チェックを使用して、時代 (年号) に固有の日付がその時代 (年号) の範囲内にあることを確認していました。 つまり、日付が指定された時代 (年号) の範囲外にある場合、メソッドは ArgumentOutOfRangeException をスローします。 現在、.NET では、既定で緩やかな範囲のチェックが使用されています。 .NET のすべてのバージョンに対する更新プログラムにより、緩やかな時代 (年号) の範囲チェックが導入されました。指定された時代 (年号) の範囲外にある時代 (年号) に固有の日付をインスタンス化しようとすると、次の時代 (年号) に "オーバーフロー" し、例外はスローされません。

次の例では、1926 年 12 月 25 日に始まり、1989 年 1 月 7 日に終わった昭和 65 年の日付をインスタンス化しようとしています。 この日付は、1990 年 1 月 9 日に相当し、JapaneseCalendar では昭和の範囲外にあります。 例の出力が示すように、この例で表示される日付は 1990 年 1 月 9 日になり、平成 2 年です。

using System;
using System.Globalization;

public class Example
{
   public static void Main()
   {
      var jaJp = new CultureInfo("ja-JP");
      var cal = new JapaneseCalendar();
      jaJp.DateTimeFormat.Calendar = cal;
      string showaEra = "昭和";

      var dt = cal.ToDateTime(65, 1, 9, 15, 0, 0, 0, GetEraIndex(showaEra));
      FormattableString fmt = $"{dt:d}";

      Console.WriteLine($"Japanese calendar date: {fmt.ToString(jaJp)}");
      Console.WriteLine($"Gregorian calendar date: {fmt}");

      int GetEraIndex(string eraName)
      {
         foreach (var ctr in cal.Eras)
            if (jaJp.DateTimeFormat.GetEraName(ctr) == eraName)
               return ctr;

         return 0;
      }
   }
}
// The example displays the following output:
//   Japanese calendar date: 平成2/1/9
//   Gregorian calendar date: 1/9/1990
Imports System.Globalization

Public Module Example
    Dim jaJp As CultureInfo
    Dim cal As Calendar

    Public Sub Main()
        jaJp = New CultureInfo("ja-JP")
        cal = New JapaneseCalendar()
        jaJp.DateTimeFormat.Calendar = cal
        Dim showaEra = "昭和"

        Dim dt = cal.ToDateTime(65, 1, 9, 15, 0, 0, 0, GetEraIndex(showaEra))
        Dim fmt As FormattableString = $"{dt:d}"
        Console.WriteLine($"Japanese calendar date: {fmt.ToString(jaJp)}")
        Console.WriteLine($"Gregorian calendar date: {fmt}")
    End Sub

    Private Function GetEraIndex(eraName As String) As Integer
        For Each ctr As Integer In cal.Eras
            If jaJp.DateTimeFormat.GetEraName(ctr) = eraName Then Return ctr
        Next
        Return 0
    End Function
End Module
' The example displays the following output:
'   Japanese calendar date: 平成2/1/9
'   Gregorian calendar date: 1/9/1990

緩やかな範囲のチェックが望ましくない場合は、アプリケーションが実行されている .NET のバージョンに応じて、いくつかの方法で厳密な範囲のチェックを復元できます。

  • .NET Core: 次の内容を .netcore.runtime.json 構成ファイルに追加します。

    "runtimeOptions": {
      "configProperties": {
          "Switch.System.Globalization.EnforceJapaneseEraYearRanges": true
      }
    }
    
  • .NET Framework 4.6 以降:app.config ファイルに、次の AppContext スイッチを設定します。

    <?xml version="1.0" encoding="utf-8"?>
    <configuration>
      <runtime>
        <AppContextSwitchOverrides value="Switch.System.Globalization.EnforceJapaneseEraYearRanges=true" />
      </runtime>
    </configuration>
    
  • .NET Framework 4.5.2 以前: 次のレジストリ値を設定します。

    キー HKEY_LOCAL_MACHINE\Software\Microsoft\.NETFramework\AppContext
    エントリ Switch.System.Globalization.EnforceJapaneseEraYearRanges
    Type REG_SZ
    true

厳密な範囲のチェックが有効になっている場合、前の例では ArgumentOutOfRangeException がスローされ、次のような出力が表示されます。

Unhandled Exception: System.ArgumentOutOfRangeException: Valid values are between 1 and 64, inclusive.
Parameter name: year
   at System.Globalization.GregorianCalendarHelper.GetYearOffset(Int32 year, Int32 era, Boolean throwOnError)
   at System.Globalization.GregorianCalendarHelper.ToDateTime(Int32 year, Int32 month, Int32 day, Int32 hour, Int32 minute, Int32 second, Int32 millisecond, Int32 era)
   at Example.Main()

複数の時代 (年号) がある暦で日付を表現する

Calendar オブジェクトの現在の暦が、時代 (年号) をサポートする CultureInfo オブジェクトである場合は、完全な日付と時刻、長い日付、および短い日付の各パターンにおいて、日付と時刻の値の文字列形式に時代 (年号) が含まれます。 それらの日付パターンを表示する例を次に示します。現在のカルチャは日本 (日本語)、現在の暦は和暦です。

using System;
using System.Globalization;
using System.IO;
using System.Threading;

public class Example
{
   public static void Main()
   {
      StreamWriter sw = new StreamWriter(@".\eras.txt");
      DateTime dt = new DateTime(2012, 5, 1);

      CultureInfo culture = CultureInfo.CreateSpecificCulture("ja-JP");
      DateTimeFormatInfo dtfi = culture.DateTimeFormat;
      dtfi.Calendar = new JapaneseCalendar();
      Thread.CurrentThread.CurrentCulture = culture;

      sw.WriteLine("\n{0,-43} {1}", "Full Date and Time Pattern:", dtfi.FullDateTimePattern);
      sw.WriteLine(dt.ToString("F"));
      sw.WriteLine();

      sw.WriteLine("\n{0,-43} {1}", "Long Date Pattern:", dtfi.LongDatePattern);
      sw.WriteLine(dt.ToString("D"));

      sw.WriteLine("\n{0,-43} {1}", "Short Date Pattern:", dtfi.ShortDatePattern);
      sw.WriteLine(dt.ToString("d"));
      sw.Close();
    }
}
// The example writes the following output to a file:
//    Full Date and Time Pattern:                 gg y'年'M'月'd'日' H:mm:ss
//    平成 24年5月1日 0:00:00
//
//    Long Date Pattern:                          gg y'年'M'月'd'日'
//    平成 24年5月1日
//
//    Short Date Pattern:                         gg y/M/d
//    平成 24/5/1
Imports System.Globalization
Imports System.IO
Imports System.Threading

Module Example
    Public Sub Main()
        Dim sw As New StreamWriter(".\eras.txt")
        Dim dt As Date = #05/01/2012#

        Dim culture As CultureInfo = CultureInfo.CreateSpecificCulture("ja-JP")
        Dim dtfi As DateTimeFormatInfo = culture.DateTimeFormat
        dtfi.Calendar = New JapaneseCalendar()
        Thread.CurrentThread.CurrentCulture = culture

        sw.WriteLine("{0,-43} {1}", "Full Date and Time Pattern:", dtfi.FullDateTimePattern)
        sw.WriteLine(dt.ToString("F"))
        sw.WriteLine()

        sw.WriteLine("{0,-43} {1}", "Long Date Pattern:", dtfi.LongDatePattern)
        sw.WriteLine(dt.ToString("D"))
        sw.WriteLine()

        sw.WriteLine("{0,-43} {1}", "Short Date Pattern:", dtfi.ShortDatePattern)
        sw.WriteLine(dt.ToString("d"))
        sw.WriteLine()
        sw.Close()
    End Sub
End Module
' The example writes the following output to a file:
'    Full Date and Time Pattern:                 gg y'年'M'月'd'日' H:mm:ss
'    平成 24年5月1日 0:00:00
'    
'    Long Date Pattern:                          gg y'年'M'月'd'日'
'    平成 24年5月1日
'    
'    Short Date Pattern:                         gg y/M/d
'    平成 24/5/1 

警告

JapaneseCalendar クラスは、.NET において、複数の時代 (年号) の日付をサポートし、かつ CultureInfo オブジェクト (特に、日本語 (日本) カルチャを表す CultureInfo オブジェクト) の現在の暦にすることができる唯一の暦クラスです。

どの暦の場合も、"g" カスタム書式指定子の結果の文字列には時代 (年号) が含まれます。 次の例では、"MM-dd-yyyy g" というカスタム書式指定文字列を使用して、結果の文字列に時代 (年号) を含めています。現在の暦はグレゴリオ暦です。

   DateTime dat = new DateTime(2012, 5, 1);
   Console.WriteLine("{0:MM-dd-yyyy g}", dat);
// The example displays the following output:
//     05-01-2012 A.D.
Dim dat As Date = #05/01/2012#
Console.WriteLine("{0:MM-dd-yyyy g}", dat)
' The example displays the following output:
'     05-01-2012 A.D.      

日付の文字列形式を現在の暦以外の暦で表す場合は、Calendar クラスの Calendar.GetEra メソッドを Calendar.GetYearCalendar.GetMonth、および Calendar.GetDayOfMonth の各メソッドと一緒に使用して、日付とそれが属する時代 (年号) を明確に示すことができます。 JapaneseLunisolarCalendar クラスを使用した具体的な例を次に示します。 ただし、時代 (年号) を表す整数ではなく、名前または省略形を結果の文字列に含めるには、DateTimeFormatInfo オブジェクトをインスタンス化し、その現在の暦を JapaneseCalendar にする必要があります (JapaneseLunisolarCalendar 暦をカルチャの現在の暦にすることはできませんが、この場合は 2 つの暦で同じ時代 (年号) が共有されます)。

using System;
using System.Globalization;

public class Example
{
   public static void Main()
   {
      DateTime date1 = new DateTime(2011, 8, 28);
      Calendar cal = new JapaneseLunisolarCalendar();

      Console.WriteLine("{0} {1:d4}/{2:d2}/{3:d2}",
                        cal.GetEra(date1),
                        cal.GetYear(date1),
                        cal.GetMonth(date1),
                        cal.GetDayOfMonth(date1));

      // Display eras
      CultureInfo culture = CultureInfo.CreateSpecificCulture("ja-JP");
      DateTimeFormatInfo dtfi = culture.DateTimeFormat;
      dtfi.Calendar = new JapaneseCalendar();

      Console.WriteLine("{0} {1:d4}/{2:d2}/{3:d2}",
                        dtfi.GetAbbreviatedEraName(cal.GetEra(date1)),
                        cal.GetYear(date1),
                        cal.GetMonth(date1),
                        cal.GetDayOfMonth(date1));
   }
}
// The example displays the following output:
//       4 0023/07/29
//       平 0023/07/29
Imports System.Globalization

Module Example
    Public Sub Main()
        Dim date1 As Date = #8/28/2011#
        Dim cal As New JapaneseLunisolarCalendar()
        Console.WriteLine("{0} {1:d4}/{2:d2}/{3:d2}",
                          cal.GetEra(date1),
                          cal.GetYear(date1),
                          cal.GetMonth(date1),
                          cal.GetDayOfMonth(date1))

        ' Display eras
        Dim culture As CultureInfo = CultureInfo.CreateSpecificCulture("ja-JP")
        Dim dtfi As DateTimeFormatInfo = culture.DateTimeFormat
        dtfi.Calendar = New JapaneseCalendar()

        Console.WriteLine("{0} {1:d4}/{2:d2}/{3:d2}",
                          dtfi.GetAbbreviatedEraName(cal.GetEra(date1)),
                          cal.GetYear(date1),
                          cal.GetMonth(date1),
                          cal.GetDayOfMonth(date1))
    End Sub
End Module
' The example displays the following output:
'       4 0023/07/29
'       平 0023/07/29

和暦では、時代 (年号) の最初の年は元年と呼ばれます。 たとえば、平成最初の年は、平成 1 年ではなく、平成元年と記述することができます。 .NET では、次の標準またはカスタム日時書式指定文字列で書式指定された日時の書式設定操作を、JapaneseCalendar クラスを使用して Japanese-Japan ("ja-JP") カルチャを表す CultureInfo オブジェクトと共に使用した場合に、この規則が適用されます。

たとえば、次の例では、JapaneseCalendar での平成元年の日付を表示します。

using System;
using System.Globalization;

public class Example
{
    public static void Main()
    {
         var enUs = new CultureInfo("en-US");
        var japaneseCal = new JapaneseCalendar();
        var jaJp = new CultureInfo("ja-JP");
        jaJp.DateTimeFormat.Calendar = japaneseCal;
        string heiseiEra = "平成";

        var date = japaneseCal.ToDateTime(1, 8, 18, 0, 0, 0, 0, GetEraIndex(heiseiEra));
        FormattableString fmt = $"{date:D}";
        Console.WriteLine($"Japanese calendar date: {fmt.ToString(jaJp)} (Gregorian: {fmt.ToString(enUs)})");

        int GetEraIndex(string eraName)
        {
           foreach (var ctr in japaneseCal.Eras)
              if (jaJp.DateTimeFormat.GetEraName(ctr) == eraName)
                 return ctr;

           return 0;
        }
    }
}
// The example displays the following output:
//    Japanese calendar date: 平成元年8月18日 (Gregorian: Friday, August 18, 1989)
Imports System.Globalization

Module Program
    Dim jaJp As CultureInfo
    Dim japaneseCal As Calendar

    Sub Main()
        Dim enUs = New CultureInfo("en-US")
        japaneseCal = New JapaneseCalendar()
        jaJp = New CultureInfo("ja-JP")
        jaJp.DateTimeFormat.Calendar = japaneseCal
        Dim heiseiEra = "平成"

        Dim dat = japaneseCal.ToDateTime(1, 8, 18, 0, 0, 0, 0, GetEraIndex(heiseiEra))
        Dim fmt As FormattableString = $"{dat:D}"
        Console.WriteLine($"Japanese calendar date: {fmt.ToString(jaJp)} (Gregorian: {fmt.ToString(enUs)})")
    End Sub

    Private Function GetEraIndex(eraName As String) As Integer
        For Each ctr In japaneseCal.Eras
            If jaJp.DateTimeFormat.GetEraName(ctr) = eraName Then
                Return ctr
            End If
        Next
        Return 0
    End Function
End Module
' The example displays the following output:
'    Japanese calendar date: 平成元年8月18日 (Gregorian: Friday, August 18, 1989)

書式設定操作でこの動作が望ましくない場合は、.NET のバージョンに応じて次の操作を行うことで、以前の動作を復元し、常に時代 (年号) の最初の年を "元年" ではなく "1" として表現するようにできます。

  • .NET Core: 次の内容を .netcore.runtime.json 構成ファイルに追加します。

    "runtimeOptions": {
      "configProperties": {
          "Switch.System.Globalization.FormatJapaneseFirstYearAsANumber": true
      }
    }
    
  • .NET Framework 4.6 以降:app.config ファイルに、次の AppContext スイッチを設定します。

    <?xml version="1.0" encoding="utf-8"?>
    <configuration>
      <runtime>
        <AppContextSwitchOverrides value="Switch.System.Globalization.FormatJapaneseFirstYearAsANumber=true" />
      </runtime>
    </configuration>
    
  • .NET Framework 4.5.2 以前: 次のレジストリ値を設定します。

    キー HKEY_LOCAL_MACHINE\Software\Microsoft\.NETFramework\AppContext
    エントリ Switch.System.Globalization.FormatJapaneseFirstYearAsANumber
    Type REG_SZ
    true

書式設定操作で元年のサポートが無効になっている場合、前の例では次の出力が表示されます。

Japanese calendar date: 平成1年8月18日 (Gregorian: Friday, August 18, 1989)

また、.NET は、日時の解析操作で、"1" または "元年" として表現されている年を含む文字列がサポートされるようにも更新されています。 これを行う必要はないはずですが、以前の動作を復元して、時代 (年号) の最初の年として "1" だけを認識するようにできます。 それには、.NET のバージョンに応じて、次のようにします。

  • .NET Core: 次の内容を .netcore.runtime.json 構成ファイルに追加します。

    "runtimeOptions": {
      "configProperties": {
          "Switch.System.Globalization.EnforceLegacyJapaneseDateParsing": true
      }
    }
    
  • .NET Framework 4.6 以降:app.config ファイルに、次の AppContext スイッチを設定します。

    <?xml version="1.0" encoding="utf-8"?>
    <configuration>
      <runtime>
        <AppContextSwitchOverrides value="Switch.System.Globalization.EnforceLegacyJapaneseDateParsing=true" />
      </runtime>
    </configuration>
    
  • .NET Framework 4.5.2 以前: 次のレジストリ値を設定します。

    キー HKEY_LOCAL_MACHINE\Software\Microsoft\.NETFramework\AppContext
    エントリ Switch.System.Globalization.EnforceLegacyJapaneseDateParsing
    Type REG_SZ
    true

関連項目