HOW TO:在非西曆中顯示日期
更新:2007 年 11 月
DateTime 和 DateTimeOffset 型別會使用西曆做為預設月曆。這表示即使該日期和時間是使用其他月曆所建立,呼叫日期和時間值的 ToString 方法仍會使用西曆顯示該日期和時間的字串表示。以下範例中將說明這種情況,其中會使用兩種不同的方式建立波斯曆的日期和時間值,但是在呼叫 ToString 方法時,仍會以西曆顯示這些日期和時間值。這個範例會反映兩種常用來顯示特殊月曆之日期,但不正確的技術。
Dim persianCal As New PersianCalendar()
Dim persianDate As Date = persianCal.ToDateTime(1387, 3, 18, _
12, 0, 0, 0)
Console.WriteLine(persianDate.ToString())
persianDate = New DateTime(1387, 3, 18, persianCal)
Console.WriteLine(persianDate.ToString())
' The example displays the following output to the console:
' 6/7/2008 12:00:00 PM
' 6/7/2008 12:00:00 AM
PersianCalendar persianCal = new PersianCalendar();
DateTime persianDate = persianCal.ToDateTime(1387, 3, 18, 12, 0, 0, 0);
Console.WriteLine(persianDate.ToString());
persianDate = new DateTime(1387, 3, 18, persianCal);
Console.WriteLine(persianDate.ToString());
// The example displays the following output to the console:
// 6/7/2008 12:00:00 PM
// 6/7/2008 12:00:00 AM
兩種不同的技術可用來顯示特殊月曆的日期。第一種需要將該月曆設為特殊文化特性的預設月曆。第二種則可以使用任何月曆。
顯示文化特性預設月曆的日期
具現化衍生自 Calendar 類別的月曆物件,該物件代表要使用的月曆。
具現化 CultureInfo 物件,該物件代表的文化特性將用來顯示日期。
呼叫 Array.Exists<T> 方法,判斷月曆物件是否為 CultureInfo.OptionalCalendars 屬性所傳回陣列的成員。這表示該月曆可以做為 CultureInfo 物件的預設月曆。如果不是陣列成員,請依照<顯示任何月曆中的日期>一節中的指示進行。
將月曆物件指派給 CultureInfo.DateTimeFormat 屬性所傳回 DateTimeFormatInfo 物件的 Calendar 屬性。
注意事項: CultureInfo 類別也有 Calendar 屬性。不過該屬性是唯讀的常數,不會變更以反映指派給 DateTimeFormatInfo.Calendar 屬性的新預設月曆。
呼叫 ToString 或 ToString 方法,並將上一個步驟中修改其預設月曆的 CultureInfo 物件傳遞給該方法。
顯示任何月曆中的日期
具現化衍生自 Calendar 類別的月曆物件,該物件代表要使用的月曆。
決定應出現在日期和時間值的字串表示中的日期和時間項目。
針對您要顯示的每一個日期和時間項目,呼叫月曆物件的 Get… 方法。下列為可用的方法:
GetYear,用來顯示適當月曆中的年份。
GetMonth,用來顯示適當月曆中的月份。
GetDayOfMonth,用來顯示適當月曆中某個月份的日期數字。
GetHour,用來顯示適當月曆中某天的小時。
GetMinute,用來顯示適當月曆中某小時的分鐘。
GetSecond,用來顯示適當月曆中某分鐘的秒鐘。
GetMilliseconds,用來顯示適當月曆中某一秒的毫秒。
範例
這個範例顯示使用兩種不同月曆的日期。日期會在定義回曆做為 ar-JO 文化特性的預設月曆之後顯示,並且會使用波斯曆顯示日期,而波斯曆並不是 fa-IR 文化特性支援的選用月曆。
Imports System.Globalization
Public Class CalendarDates
Public Shared Sub Main()
Dim hijriCal As New HijriCalendar()
Dim hijriUtil As New CalendarUtility(hijriCal)
Dim hijriDate1 As Date = New Date(1429, 6, 29, hijriCal)
Dim hijriDate2 As DateTimeOffset = New DateTimeOffset(hijriDate1, _
TimeZoneInfo.Local.GetUtcOffset(hijriDate1))
Dim jc As CultureInfo = CultureInfo.CreateSpecificCulture("ar-JO")
' Display the date using the Gregorian calendar.
Console.WriteLine("Using the system default culture: {0}", _
hijriDate1.ToString("d"))
' Display the date using the ar-JO culture's original default calendar.
Console.WriteLine("Using the ar-JO culture's original default calendar: {0}", _
hijriDate1.ToString("d", jc))
' Display the date using the Hijri calendar.
Console.WriteLine("Using the ar-JO culture with Hijri as the default calendar:")
' Display a Date value.
Console.WriteLine(hijriUtil.DisplayDate(hijriDate1, jc))
' Display a DateTimeOffset value.
Console.WriteLine(hijriUtil.DisplayDate(hijriDate2, jc))
Console.WriteLine()
Dim persianCal As New PersianCalendar()
Dim persianUtil As New CalendarUtility(persianCal)
Dim ic As CultureInfo = CultureInfo.CreateSpecificCulture("fa-IR")
' Display the date using the ir-FA culture's default calendar.
Console.WriteLine("Using the ir-FA culture's default calendar: {0}", _
hijriDate1.ToString("d", ic))
' Display a Date value.
Console.WriteLine(persianUtil.DisplayDate(hijriDate1, ic))
' Display a DateTimeOffset value.
Console.WriteLine(persianUtil.DisplayDate(hijriDate2, ic))
End Sub
End Class
Public Class CalendarUtility
Private thisCalendar As Calendar
Private targetCulture As CultureInfo
Public Sub New(cal As Calendar)
Me.thisCalendar = cal
End Sub
Private Function CalendarExists(culture As CultureInfo) As Boolean
Me.targetCulture = culture
Return Array.Exists(Me.targetCulture.OptionalCalendars, _
AddressOf Me.HasSameName)
End Function
Private Function HasSameName(cal As Calendar) As Boolean
If cal.ToString() = thisCalendar.ToString() Then
Return True
Else
Return False
End If
End Function
Public Function DisplayDate(dateToDisplay As Date, _
culture As CultureInfo) As String
Dim displayOffsetDate As DateTimeOffset = dateToDisplay
Return DisplayDate(displayOffsetDate, culture)
End Function
Public Function DisplayDate(dateToDisplay As DateTimeOffset, _
culture As CultureInfo) As String
Dim specifier As String = "yyyy/MM/dd"
If Me.CalendarExists(culture) Then
Console.WriteLine("Displaying date in supported {0} calendar...", _
thisCalendar.GetType().Name)
culture.DateTimeFormat.Calendar = Me.thisCalendar
Return dateToDisplay.ToString(specifier, culture)
Else
Console.WriteLine("Displaying date in unsupported {0} calendar...", _
thisCalendar.GetType().Name)
Dim separator As String = targetCulture.DateTimeFormat.DateSeparator
Return thisCalendar.GetYear(dateToDisplay.DateTime).ToString("0000") & separator & _
thisCalendar.GetMonth(dateToDisplay.DateTime).ToString("00") & separator & _
thisCalendar.GetDayOfMonth(dateToDisplay.DateTime).ToString("00")
End If
End Function
End Class
' The example displays the following output to the console:
' Using the system default culture: 7/3/2008
' Using the ar-JO culture's original default calendar: 03/07/2008
' Using the ar-JO culture with Hijri as the default calendar:
' Displaying date in supported HijriCalendar calendar...
' 1429/06/29
' Displaying date in supported HijriCalendar calendar...
' 1429/06/29
'
' Using the ir-FA culture's default calendar: 7/3/2008
' Displaying date in unsupported PersianCalendar calendar...
' 1387/04/13
' Displaying date in unsupported PersianCalendar calendar...
' 1387/04/13
using System;
using System.Globalization;
public class CalendarDates
{
public static void Main()
{
HijriCalendar hijriCal = new HijriCalendar();
CalendarUtility hijriUtil = new CalendarUtility(hijriCal);
DateTime hijriDate1 = new DateTime(1429, 6, 29, hijriCal);
DateTimeOffset hijriDate2 = new DateTimeOffset(hijriDate1,
TimeZoneInfo.Local.GetUtcOffset(hijriDate1));
CultureInfo jc = CultureInfo.CreateSpecificCulture("ar-JO");
// Display the date using the Gregorian calendar.
Console.WriteLine("Using the system default culture: {0}",
hijriDate1.ToString("d"));
// Display the date using the ar-JO culture's original default calendar.
Console.WriteLine("Using the ar-JO culture's original default calendar: {0}",
hijriDate1.ToString("d", jc));
// Display the date using the Hijri calendar.
Console.WriteLine("Using the ar-JO culture with Hijri as the default calendar:");
// Display a Date value.
Console.WriteLine(hijriUtil.DisplayDate(hijriDate1, jc));
// Display a DateTimeOffset value.
Console.WriteLine(hijriUtil.DisplayDate(hijriDate2, jc));
Console.WriteLine();
PersianCalendar persianCal = new PersianCalendar();
CalendarUtility persianUtil = new CalendarUtility(persianCal);
CultureInfo ic = CultureInfo.CreateSpecificCulture("fa-IR");
// Display the date using the ir-FA culture's default calendar.
Console.WriteLine("Using the ir-FA culture's default calendar: {0}",
hijriDate1.ToString("d", ic));
// Display a Date value.
Console.WriteLine(persianUtil.DisplayDate(hijriDate1, ic));
// Display a DateTimeOffset value.
Console.WriteLine(persianUtil.DisplayDate(hijriDate2, ic));
}
}
public class CalendarUtility
{
private Calendar thisCalendar;
private CultureInfo targetCulture;
public CalendarUtility(Calendar cal)
{
this.thisCalendar = cal;
}
private bool CalendarExists(CultureInfo culture)
{
this.targetCulture = culture;
return Array.Exists(this.targetCulture.OptionalCalendars,
this.HasSameName);
}
private bool HasSameName(Calendar cal)
{
if (cal.ToString() == thisCalendar.ToString())
return true;
else
return false;
}
public string DisplayDate(DateTime dateToDisplay, CultureInfo culture)
{
DateTimeOffset displayOffsetDate = dateToDisplay;
return DisplayDate(displayOffsetDate, culture);
}
public string DisplayDate(DateTimeOffset dateToDisplay,
CultureInfo culture)
{
string specifier = "yyyy/MM/dd";
if (this.CalendarExists(culture))
{
Console.WriteLine("Displaying date in supported {0} calendar...",
this.thisCalendar.GetType().Name);
culture.DateTimeFormat.Calendar = this.thisCalendar;
return dateToDisplay.ToString(specifier, culture);
}
else
{
Console.WriteLine("Displaying date in unsupported {0} calendar...",
thisCalendar.GetType().Name);
string separator = targetCulture.DateTimeFormat.DateSeparator;
return thisCalendar.GetYear(dateToDisplay.DateTime).ToString("0000") +
separator +
thisCalendar.GetMonth(dateToDisplay.DateTime).ToString("00") +
separator +
thisCalendar.GetDayOfMonth(dateToDisplay.DateTime).ToString("00");
}
}
}
// The example displays the following output to the console:
// Using the system default culture: 7/3/2008
// Using the ar-JO culture's original default calendar: 03/07/2008
// Using the ar-JO culture with Hijri as the default calendar:
// Displaying date in supported HijriCalendar calendar...
// 1429/06/29
// Displaying date in supported HijriCalendar calendar...
// 1429/06/29
//
// Using the ir-FA culture's default calendar: 7/3/2008
// Displaying date in unsupported PersianCalendar calendar...
// 1387/04/13
// Displaying date in unsupported PersianCalendar calendar...
// 1387/04/13
每個 CultureInfo 物件都可以支援一個或多個月曆,由 OptionalCalendars 屬性表示。其中一個月曆會指定為文化特性的預設月曆,並且由唯讀 CultureInfo.Calendar 屬性傳回。另一個選用的月曆可以藉由指派代表該月曆的 Calendar 物件給 DateTimeFormatInfo.Calendar 屬性 (由 CultureInfo.DateTimeFormat 屬性傳回) 指定為預設值。不過,有些月曆 (例如 PersianCalendar 類別所代表的波斯曆) 無法做為任何文化特性的選用月曆。
這個範例會定義可重複使用的月曆公用程式類別 CalendarUtility,用來處理使用特殊月曆產生日期的字串表示時的許多細節。CalendarUtility 類別擁有下列成員:
參數化的建構函式,其單一參數為用來表示日期的 Calendar 物件。這個參數會指派給類別的私用欄位。
CalendarExists,傳回布林值的私用方法,表示傳遞至方法做為參數的 CultureInfo 物件是否支援 CalendarUtility 物件代表的月曆。這個方法會包裝 Array.Exists<T> 方法的呼叫,並且傳遞 CultureInfo.OptionalCalendars 陣列給該方法。
HasSameName,指派給 Predicate<T> 委派的私用方法,其會做為參數傳遞至 Array.Exists<T> 方法。每一個陣列成員都會傳遞至方法,直到方法傳回 true 為止。這個方法會判斷選用月曆的名稱是否與 CalendarUtility 物件代表的月曆相同。
DisplayDate,多載的公用方法,以下兩個參數會傳遞給這個方法:DateTime 或是 DateTimeOffset 值,用來在 CalendarUtility 物件代表的月曆中表達,以及要使用其格式化規則的文化特性。在傳回日期的字串表示時,其行為會根據文化特性是否支援要使用其格式化規則的目標月曆而定。
無論月曆在本範例中用來建立 DateTime 或 DateTimeOffset 值,該值通常都會以西曆日期表達。這是因為 DateTime 和 DateTimeOffset 型別不會保留任何月曆資訊。這兩個值會在內部表示為自 0001 年 1 月 1 日開始經過的刻度數。該數字的轉譯會根據月曆而定。大部分文化特性的預設月曆是西曆。
編譯程式碼
這個範例需要參考 System.Core.dll。
使用 csc.exe 或 vb.exe 在命令列編輯程式碼。若要編譯 Visual Studio 中的程式碼,請將程式碼放在主控台應用程式專案範本中。