如何:用非公历日历显示日期
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 对象分配给 CultureInfo.DateTimeFormat 属性返回的 DateTimeFormatInfo.Calendar 属性。 但是,某些日历(例如由 PersianCalendar 类表示的波斯历)不能作为任何区域性的可选日历。
该示例定义了一个可重用的日历实用工具类 CalendarUtility,目的是处理用特定日历生成日期的字符串表示形式时的很多细节。 CalendarUtility 类具有下列成员:
一个参数化构造函数,它唯一的参数是要用于表示日期的 Calendar 对象。 它将被分配给该类的私有字段。
CalendarExists,此私有方法将返回一个布尔值,用于指示由 CalendarUtility 对象表示的日历是否受以参数形式传递给该方法的 CultureInfo 对象支持。 该方法包装对 Array.Exists<T> 方法的调用,并向其传递 CultureInfo.OptionalCalendars 数组。
HasSameName,此私有方法被分配给以参数形式传递给 Array.Exists<T> 方法的 Predicate<T> 委托。 将向该方法传递数组的每个成员,直至该方法返回 true。 该方法确定可选日历是否与 CalendarUtility 对象表示的日历同名。
DisplayDate,此重载的公共方法将获得两个参数:一个是 DateTime 或 DateTimeOffset 值(以便用 CalendarUtility 对象表示的日历表示),另一个是要使用其格式化规则的区域性。 其返回日期字符串表示形式的行为取决于目标日历是否受要使用其格式化规则的区域性支持。
在此示例中,无论使用何种日历创建 DateTime 或 DateTimeOffset 值,该值通常都将表示为公历日期。 这是因为,DateTime 和 DateTimeOffset 类型并不保留任何日历信息。 在内部,它们表示为从 0001 年 1 月 1 日午夜算起已过去的时间。 该数字的具体解释取决于所使用的日历。 大多数区域性的默认日历都是公历。
编译代码
此示例需要引用 System.Core.dll。
在命令行处使用 csc.exe 或 vb.exe 编译代码。 若要在 Visual Studio 中编译代码,请将代码置于控制台应用程序项目模板中。