![]() |
彷徨的机器人 · stringvar转变成str ...· 1 月前 · |
![]() |
留胡子的汤圆 · SharePoint 搜索 REST ...· 4 周前 · |
![]() |
没有腹肌的开水瓶 · Exception in thread ...· 4 周前 · |
![]() |
冷冷的胡萝卜 · SpringBoot学习笔记(八)——JWT ...· 1 周前 · |
![]() |
刀枪不入的马铃薯 · ASP.NET Core 中的配置 | ...· 昨天 · |
![]() |
淡定的墨镜 · 左公子微密_哔哩哔哩_bilibili· 8 月前 · |
![]() |
幸福的红酒 · 原来罗纳尔多女友“抢眼包”?家人在葡萄牙度假 ...· 11 月前 · |
![]() |
爱热闹的小狗 · 剧情不够 外景来凑,《疾速追杀 ...· 1 年前 · |
![]() |
无邪的单杠 · 打破细分市场空白,雷诺江铃首款新能源轿车来了 ...· 1 年前 · |
![]() |
小胡子的蛋挞 · 纽约联储主席杜德利:美联储不会撤回QE2 ...· 1 年前 · |
public value class DateTime : IComparable, IComparable<DateTime>, IConvertible, IEquatable<DateTime>, IFormattable
public value class DateTime : IComparable, IComparable<DateTime>, IConvertible, IEquatable<DateTime>, IFormattable, System::Runtime::Serialization::ISerializable
public value class DateTime : IComparable, IComparable<DateTime>, IConvertible, IEquatable<DateTime>, ISpanFormattable, System::Runtime::Serialization::ISerializable
public value class DateTime : IComparable, IConvertible, IFormattable
public value class DateTime : IComparable, IComparable<DateTime>, IEquatable<DateTime>, IFormattable
public struct DateTime : IComparable, IComparable<DateTime>, IConvertible, IEquatable<DateTime>, IFormattable
public struct DateTime : IComparable, IComparable<DateTime>, IConvertible, IEquatable<DateTime>, IFormattable, System.Runtime.Serialization.ISerializable
public struct DateTime : IComparable, IComparable<DateTime>, IConvertible, IEquatable<DateTime>, ISpanFormattable, System.Runtime.Serialization.ISerializable
[System.Serializable]
public struct DateTime : IComparable, IConvertible, IFormattable
[System.Serializable]
public struct DateTime : IComparable, IComparable<DateTime>, IConvertible, IEquatable<DateTime>, IFormattable, System.Runtime.Serialization.ISerializable
public struct DateTime : IComparable, IComparable<DateTime>, IEquatable<DateTime>, IFormattable
type DateTime = struct
interface IConvertible
interface IFormattable
type DateTime = struct
interface IConvertible
interface IFormattable
interface ISerializable
type DateTime = struct
interface IConvertible
interface ISpanFormattable
interface IFormattable
interface ISerializable
[<System.Serializable>]
type DateTime = struct
interface IFormattable
interface IConvertible
[<System.Serializable>]
type DateTime = struct
interface IFormattable
interface IConvertible
interface ISerializable
type DateTime = struct
interface IFormattable
Public Structure DateTime
Implements IComparable, IComparable(Of DateTime), IConvertible, IEquatable(Of DateTime), IFormattable
Public Structure DateTime
Implements IComparable, IComparable(Of DateTime), IConvertible, IEquatable(Of DateTime), IFormattable, ISerializable
Public Structure DateTime
Implements IComparable, IComparable(Of DateTime), IConvertible, IEquatable(Of DateTime), ISerializable, ISpanFormattable
Public Structure DateTime
Implements IComparable, IConvertible, IFormattable
Public Structure DateTime
Implements IComparable, IComparable(Of DateTime), IEquatable(Of DateTime), IFormattable
DateTime
日本历法中的年号是根据天皇统治来命名的,因此预计会发生变化。 例如,2019 年 5 月 1 日在 JapaneseCalendar 和 JapaneseLunisolarCalendar 中标志着令和年号的开始。 这种年号的变化会影响使用这些日历的所有应用程序。 有关详细信息以及如何确定应用程序是否受影响,请参阅在 .net 中的日式日历中处理新时代 。 若要了解如何在 Windows 系统上测试应用程序以确保其应用程序更改的就绪性,请参阅 准备应用程序以进行日本时代更改 。 对于 .NET 中支持多个纪元的日历的功能,以及在处理支持多个纪元的日历时的最佳做法,请参阅使用 纪元 。
本文中的一些 C# 示例运行在 Try.NET 内联代码运行程序和演练环境中。 选择“运行”按钮以在交互窗口中运行示例。 执行代码后,可通过再次选择“运行”来修改它并运行已修改的代码。 已修改的代码要么在交互窗口中运行,要么编译失败时,交互窗口将显示所有 C# 编译器错误消息。
Try.NET 内联代码运行程序和演练环境的 本地时区 是协调世界时 (UTC)。 这可能会影响用于说明 DateTime 、 DateTimeOffset 和 TimeZoneInfo 类型及其成员的示例的行为和输出。
本文包含几个使用 类型
DateTime
的示例:
初始化示例
将
DateTime
对象格式化为字符串
将字符串分析为
DateTime
对象
Parse
或
TryParse
将字符串转换为日期和时间
ParseExact
或
TryParseExact
以已知格式转换字符串
DateTime
分辨率
区域性和日历
XmlSerializer
BinaryFormatter
本部分包含有关结构的许多常见
DateTime
用途的主题:
DateTime
对象
值类型表示日期和时间,其值范围为 0001 年 1 月 1 日午夜 DateTime ) 00:00:00 ( (Anno Domini (Common Era) 到 9999 年 12 月 31 日下午 11:59:59。 晚上 11:59:59。
时间值以 100 纳秒为单位(称为时钟周期)进行度量。 特定日期是自 0001 年 1 月 1 日午夜 12:00 以来的滴答数。 (日历) C.E.) 。 GregorianCalendar 该数字不包括将按闰秒添加的刻度。 例如,时钟周期值 31241376000000000L 表示星期五,0100 年 1 月 1 日午夜 12:00:00。 DateTime 值始终在显式或默认日历的上下文中表示。
如果要使用要转换为其他时间间隔(如分钟或秒)的刻度值,则应该使用 、 或 常量
TimeSpan.TicksPerDay
TimeSpan.TicksPerHour
TimeSpan.TicksPerMinute
TimeSpan.TicksPerSecond
TimeSpan.TicksPerMillisecond
来执行转换。 例如,若要将指定刻度数表示的秒数添加到值的 分量中,
Second
DateTime
可以使用表达式
dateValue.Second + nTicks/Timespan.TicksPerSecond
。
可以在 GitHub 上的文档存储库中的 Visual Basic 或 C# 中查看本文中整个示例集的GitHub。
用于处理 DateTime 特定时区中的日期和时间值的结构的替代方法是 DateTimeOffset 结构。 结构将日期和时间信息存储在私有字段中,以及该日期和时间在私有字段中不同于 DateTimeOffset DateTime UTC 的 Int16 分钟数。 这使值能够反映特定时区的时间,而值可以明确反映 UTC 和本地 DateTimeOffset DateTime 时区的时间。 有关使用日期和时间值时何时使用 结构的讨论,请参阅 DateTime DateTimeOffset 在 DateTime、DateTimeOffset、TimeSpan 和 TimeZoneInfo 之间选择 。
可以通过许多不同的方式将初始
DateTime
值分配给新值:
DateTime
分配给属性或方法的返回值。
DateTime
字符串表示形式分析值。
DateTime
。
以下代码片段显示了每个代码片段的示例:
调用构造函数的任何重载,这些重载指定日期和时间值元素 (如年、月、日或日期的刻度 DateTime 数) 。 以下代码使用构造函数创建指定年、月、 DateTime 日、小时、分钟和秒的特定日期。
Dim date1 As New Date(2008, 5, 1, 8, 30, 52)
var date1 = new DateTime(2008, 5, 1, 8, 30, 52);
Console.WriteLine(date1);
若要将 初始化为其默认值,请调用结构的隐式无
DateTime
DateTime
参数构造函数。 (有关值类型的隐式无参数构造函数的详细信息,请参阅值类型
.)
某些编译器还支持声明值,而无需显式为其赋值
DateTime
。 创建不带显式初始化的值也会导致默认值。 以下示例演示 C# 和 Visual Basic 中的隐式无参数构造函数,以及未在 Visual Basic
DateTime
DateTime
中赋值的声明。
Dim dat1 As DateTime
' The following method call displays 1/1/0001 12:00:00 AM.
Console.WriteLine(dat1.ToString(System.Globalization.CultureInfo.InvariantCulture))
' The following method call displays True.
Console.WriteLine(dat1.Equals(Date.MinValue))
Dim dat2 As New DateTime()
' The following method call displays 1/1/0001 12:00:00 AM.
Console.WriteLine(dat2.ToString(System.Globalization.CultureInfo.InvariantCulture))
' The following method call displays True.
Console.WriteLine(dat2.Equals(Date.MinValue))
var dat1 = new DateTime();
// The following method call displays 1/1/0001 12:00:00 AM.
Console.WriteLine(dat1.ToString(System.Globalization.CultureInfo.InvariantCulture));
// The following method call displays True.
Console.WriteLine(dat1.Equals(DateTime.MinValue));
分配计算值
你可以为
DateTime
对象分配属性或方法返回的日期和时间值。 以下示例将当前日期和时间、当前 协调世界时 (UTC) 日期和时间以及当前日期分配给三个新
DateTime
变量。
Dim date1 As Date = Date.Now
Dim date2 As Date = Date.UtcNow
Dim date3 As Date = Date.Today
DateTime date1 = DateTime.Now;
DateTime date2 = DateTime.UtcNow;
DateTime date3 = DateTime.Today;
分析表示 DateTime 的字符串
、、
Parse
ParseExact
和
TryParse
TryParseExact
方法均将字符串转换为其等效的日期和时间值。 以下示例使用 和
Parse
ParseExact
方法分析字符串并将其转换为
DateTime
值。 第二种格式使用
ISO 8601
标准支持的表单来表示字符串格式的日期和时间。 此标准表示形式通常用于在 Web 服务中传输日期信息。
Dim dateString As String = "5/1/2008 8:30:52 AM"
Dim date1 As Date = Date.Parse(dateString,
System.Globalization.CultureInfo.InvariantCulture)
Dim iso8601String As String = "20080501T08:30:52Z"
Dim dateISO8602 As Date = DateTime.ParseExact(iso8601String, "yyyyMMddTHH:mm:ssZ",
System.Globalization.CultureInfo.InvariantCulture)
Console.WriteLine(dateISO8602)
var dateString = "5/1/2008 8:30:52 AM";
DateTime date1 = DateTime.Parse(dateString,
System.Globalization.CultureInfo.InvariantCulture);
var iso8601String = "20080501T08:30:52Z";
DateTime dateISO8602 = DateTime.ParseExact(iso8601String, "yyyyMMddTHH:mm:ssZ",
System.Globalization.CultureInfo.InvariantCulture);
TryParse
和
TryParseExact
方法指示字符串是否是值的有效表示形式,如果是,
DateTime
则执行转换。
特定于语言的语法Visual Basic
下面的 Visual Basic 语句初始化新
DateTime
值。
Dim date1 As Date = #5/1/2008 8:30:52AM#
DateTime 值及其字符串表示形式
在内部,所有值都表示为自
DateTime
20001 年 1 月 1 (日午夜 12:00:00 以来) 100 纳秒间隔数的刻度数。 实际
DateTime
值与该值在显示时显示的方式无关。 值的外观是格式设置操作的结果,该操作将
DateTime
值转换为其字符串表示形式。
日期和时间值的外观取决于区域性、国际标准、应用程序要求和个人偏好。 结构
DateTime
通过 重载灵活设置日期和时间值的格式
ToString
。 默认方法使用当前区域性的短日期和时间模式返回日期和时间值的
DateTime.ToString()
字符串表示形式。 下面的示例使用默认
DateTime.ToString()
方法。 它使用当前区域性的短日期和时间模式显示日期和时间。 en-US 区域性是运行示例的计算机上的当前区域性。
var date1 = new DateTime(2008, 3, 1, 7, 0, 0);
Console.WriteLine(date1.ToString());
// For en-US culture, displays 3/1/2008 7:00:00 AM
Dim date1 As Date = #3/1/2008 7:00AM#
Console.WriteLine(date1.ToString())
' For en-US culture, displays 3/1/2008 7:00:00 AM
可能需要设置特定区域性的日期格式,以支持 Web 方案,其中服务器可能与客户端采用不同的区域性。 使用 方法指定区域性,以创建特定区域性中的短日期
DateTime.ToString(IFormatProvider)
和长时间表示形式。 下面的示例使用
DateTime.ToString(IFormatProvider)
方法来显示使用 fr-fr 区域性的短日期和长时间模式的日期和时间。
var date1 = new DateTime(2008, 3, 1, 7, 0, 0);
Console.WriteLine(date1.ToString(System.Globalization.CultureInfo.CreateSpecificCulture("fr-FR")));
// Displays 01/03/2008 07:00:00
Dim date1 As Date = #3/1/2008 7:00AM#
Console.WriteLine(date1.ToString(System.Globalization.CultureInfo.CreateSpecificCulture("fr-FR")))
' Displays 01/03/2008 07:00:00
其他应用程序可能需要日期的不同字符串表示形式。
DateTime.ToString(String)
方法使用当前区域性的格式设置约定返回由标准或自定义格式说明符定义的字符串表示形式。 下面的示例使用
DateTime.ToString(String)
方法来显示 en-us 区域性(运行该示例的计算机上的当前区域性)的完整日期和时间模式。
var date1 = new DateTime(2008, 3, 1, 7, 0, 0);
Console.WriteLine(date1.ToString("F"));
// Displays Saturday, March 01, 2008 7:00:00 AM
Dim date1 As Date = #3/1/2008 7:00AM#
Console.WriteLine(date1.ToString("F"))
' Displays Saturday, March 01, 2008 7:00:00 AM
最后,可以使用方法指定区域性和格式
DateTime.ToString(String, IFormatProvider)
。 下面的示例使用
DateTime.ToString(String, IFormatProvider)
方法显示 fr-fr 区域性的完整日期和时间模式。
var date1 = new DateTime(2008, 3, 1, 7, 0, 0);
Console.WriteLine(date1.ToString("F", new System.Globalization.CultureInfo("fr-FR")));
// Displays samedi 1 mars 2008 07:00:00
Dim date1 As Date = #3/1/2008 7:00AM#
Console.WriteLine(date1.ToString("F", New System.Globalization.CultureInfo("fr-FR")))
' Displays samedi 1 mars 2008 07:00:00
DateTime.ToString(String)
重载还可与自定义格式字符串一起用于指定其他格式。 下面的示例演示如何使用通常用于 web 服务的
ISO 8601
标准格式来设置字符串的格式。 Iso 8601 格式没有对应的标准格式字符串。
var date1 = new DateTime(2008, 3, 1, 7, 0, 0);
Console.WriteLine(date1.ToString("yyyyMMddTHH:mm:ssZ"));
// Displays 20080301T07:00:00Z
Dim date1 As Date = #3/1/2008 7:00AM#
Console.WriteLine(date1.ToString("yyyyMMddTHH:mm:ssZ"))
' Displays 20080301T07:00:00Z
有关设置值格式的详细信息
DateTime
,请参阅
标准日期和时间格式字符串
和
自定义日期和时间格式字符串
。
分析字符串中的日期时间值
分析将日期和时间的字符串表示形式转换为
DateTime
值。 通常,在应用程序中,日期和时间字符串具有两种不同的用法:
日期和时间采用各种形式,并反映了当前区域性或特定区域性的约定。 例如,应用程序允许其当前区域性为 en-us 的用户将日期值输入为 "12/15/2013" 或 "12 月15日,2013"。 它允许当前区域性为 en 的用户将日期值输入为 "15/12/2013" 或 "15 12 月12日 2013"。
日期和时间以预定义的格式表示。 例如,应用程序将日期序列化为 "20130103",而不考虑应用运行的区域性。 应用程序可能需要以当前区域性的短日期格式输入日期。
使用
Parse
或方法可以
TryParse
将字符串从区域性使用的一个通用日期和时间格式转换为一个
DateTime
值。 下面的示例演示如何使用将
TryParse
不同区域性特定格式的日期字符串转换为
DateTime
值。 它将当前区域性更改为英语 (英国) ,并调用
GetDateTimeFormats()
方法来生成日期和时间字符串的数组。 然后,它将数组中的每个元素传递给
TryParse
方法。 该示例的输出显示,分析方法能够成功转换每个特定于区域性的日期和时间字符串。
System.Threading.Thread.CurrentThread.CurrentCulture =
System.Globalization.CultureInfo.CreateSpecificCulture("en-GB");
var date1 = new DateTime(2013, 6, 1, 12, 32, 30);
var badFormats = new List<String>();
Console.WriteLine($"{"Date String",-37} {"Date",-19}\n");
foreach (var dateString in date1.GetDateTimeFormats())
DateTime parsedDate;
if (DateTime.TryParse(dateString, out parsedDate))
Console.WriteLine($"{dateString,-37} {DateTime.Parse(dateString),-19}");
badFormats.Add(dateString);
// Display strings that could not be parsed.
if (badFormats.Count > 0)
Console.WriteLine("\nStrings that could not be parsed: ");
foreach (var badFormat in badFormats)
Console.WriteLine($" {badFormat}");
// Press "Run" to see the output.
Thread.CurrentThread.CurrentCulture = CultureInfo.CreateSpecificCulture("en-GB")
Dim date1 As New DateTime(2013, 6, 1, 12, 32, 30)
Dim badFormats As New List(Of String)
Console.WriteLine($"{"Date String",-37} {"Date",-19}")
Console.WriteLine()
For Each dateString As String In date1.GetDateTimeFormats()
Dim parsedDate As DateTime
If DateTime.TryParse(dateString, parsedDate) Then
Console.WriteLine($"{dateString,-37} {DateTime.Parse(dateString),-19:g}")
badFormats.Add(dateString)
End If
' Display strings that could not be parsed.
If badFormats.Count > 0 Then
Console.WriteLine()
Console.WriteLine("Strings that could not be parsed: ")
For Each badFormat In badFormats
Console.WriteLine($" {badFormat}")
End If
' The example displays the following output:
' Date String Date
' 01/06/2013 01/06/2013 00:00:00
' 01/06/13 01/06/2013 00:00:00
' 1/6/13 01/06/2013 00:00:00
' 1.6.13 01/06/2013 00:00:00
' 2013-06-01 01/06/2013 00:00:00
' 01 June 2013 01/06/2013 00:00:00
' 1 June 2013 01/06/2013 00:00:00
' 01 June 2013 12:32 01/06/2013 12:32:00
' 01 June 2013 12:32 01/06/2013 12:32:00
' 01 June 2013 12:32 PM 01/06/2013 12:32:00
' 01 June 2013 12:32 PM 01/06/2013 12:32:00
' 1 June 2013 12:32 01/06/2013 12:32:00
' 1 June 2013 12:32 01/06/2013 12:32:00
' 1 June 2013 12:32 PM 01/06/2013 12:32:00
' 1 June 2013 12:32 PM 01/06/2013 12:32:00
' 01 June 2013 12:32:30 01/06/2013 12:32:30
' 01 June 2013 12:32:30 01/06/2013 12:32:30
' 01 June 2013 12:32:30 PM 01/06/2013 12:32:30
' 01 June 2013 12:32:30 PM 01/06/2013 12:32:30
' 1 June 2013 12:32:30 01/06/2013 12:32:30
' 1 June 2013 12:32:30 01/06/2013 12:32:30
' 1 June 2013 12:32:30 PM 01/06/2013 12:32:30
' 1 June 2013 12:32:30 PM 01/06/2013 12:32:30
' 01/06/2013 12:32 01/06/2013 12:32:00
' 01/06/2013 12:32 01/06/2013 12:32:00
' 01/06/2013 12:32 PM 01/06/2013 12:32:00
' 01/06/2013 12:32 PM 01/06/2013 12:32:00
' 01/06/13 12:32 01/06/2013 12:32:00
' 01/06/13 12:32 01/06/2013 12:32:00
' 01/06/13 12:32 PM 01/06/2013 12:32:00
' 01/06/13 12:32 PM 01/06/2013 12:32:00
' 1/6/13 12:32 01/06/2013 12:32:00
' 1/6/13 12:32 01/06/2013 12:32:00
' 1/6/13 12:32 PM 01/06/2013 12:32:00
' 1/6/13 12:32 PM 01/06/2013 12:32:00
' 1.6.13 12:32 01/06/2013 12:32:00
' 1.6.13 12:32 01/06/2013 12:32:00
' 1.6.13 12:32 PM 01/06/2013 12:32:00
' 1.6.13 12:32 PM 01/06/2013 12:32:00
' 2013-06-01 12:32 01/06/2013 12:32:00
' 2013-06-01 12:32 01/06/2013 12:32:00
' 2013-06-01 12:32 PM 01/06/2013 12:32:00
' 2013-06-01 12:32 PM 01/06/2013 12:32:00
' 01/06/2013 12:32:30 01/06/2013 12:32:30
' 01/06/2013 12:32:30 01/06/2013 12:32:30
' 01/06/2013 12:32:30 PM 01/06/2013 12:32:30
' 01/06/2013 12:32:30 PM 01/06/2013 12:32:30
' 01/06/13 12:32:30 01/06/2013 12:32:30
' 01/06/13 12:32:30 01/06/2013 12:32:30
' 01/06/13 12:32:30 PM 01/06/2013 12:32:30
' 01/06/13 12:32:30 PM 01/06/2013 12:32:30
' 1/6/13 12:32:30 01/06/2013 12:32:30
' 1/6/13 12:32:30 01/06/2013 12:32:30
' 1/6/13 12:32:30 PM 01/06/2013 12:32:30
' 1/6/13 12:32:30 PM 01/06/2013 12:32:30
' 1.6.13 12:32:30 01/06/2013 12:32:30
' 1.6.13 12:32:30 01/06/2013 12:32:30
' 1.6.13 12:32:30 PM 01/06/2013 12:32:30
' 1.6.13 12:32:30 PM 01/06/2013 12:32:30
' 2013-06-01 12:32:30 01/06/2013 12:32:30
' 2013-06-01 12:32:30 01/06/2013 12:32:30
' 2013-06-01 12:32:30 PM 01/06/2013 12:32:30
' 2013-06-01 12:32:30 PM 01/06/2013 12:32:30
' 01 June 01/06/2013 00:00:00
' 01 June 01/06/2013 00:00:00
' 2013-06-01T12:32:30.0000000 01/06/2013 12:32:30
' 2013-06-01T12:32:30.0000000 01/06/2013 12:32:30
' Sat, 01 Jun 2013 12:32:30 GMT 01/06/2013 05:32:30
' Sat, 01 Jun 2013 12:32:30 GMT 01/06/2013 05:32:30
' 2013-06-01T12:32:30 01/06/2013 12:32:30
' 12:32 22/04/2013 12:32:00
' 12:32 22/04/2013 12:32:00
' 12:32 PM 22/04/2013 12:32:00
' 12:32 PM 22/04/2013 12:32:00
' 12:32:30 22/04/2013 12:32:30
' 12:32:30 22/04/2013 12:32:30
' 12:32:30 PM 22/04/2013 12:32:30
' 12:32:30 PM 22/04/2013 12:32:30
' 2013-06-01 12:32:30Z 01/06/2013 05:32:30
' 01 June 2013 19:32:30 01/06/2013 19:32:30
' 01 June 2013 19:32:30 01/06/2013 19:32:30
' 01 June 2013 07:32:30 PM 01/06/2013 19:32:30
' 01 June 2013 7:32:30 PM 01/06/2013 19:32:30
' 1 June 2013 19:32:30 01/06/2013 19:32:30
' 1 June 2013 19:32:30 01/06/2013 19:32:30
' 1 June 2013 07:32:30 PM 01/06/2013 19:32:30
' 1 June 2013 7:32:30 PM 01/06/2013 19:32:30
' June 2013 01/06/2013 00:00:00
' June 2013 01/06/2013 00:00:00
使用
ParseExact
和
TryParseExact
方法可将必须与特定格式或格式匹配的字符串转换为
DateTime
值。 将一个或多个日期和时间格式字符串指定为分析方法的参数。 下面的示例使用
TryParseExact(String, String[], IFormatProvider, DateTimeStyles, DateTime)
方法将必须以 "yyyyMMdd" 格式或 "HHmmss" 格式的字符串转换为
DateTime
值。
string[] formats = { "yyyyMMdd", "HHmmss" };
string[] dateStrings = { "20130816", "20131608", " 20130816 ",
"115216", "521116", " 115216 " };
DateTime parsedDate;
foreach (var dateString in dateStrings)
if (DateTime.TryParseExact(dateString, formats, null,
System.Globalization.DateTimeStyles.AllowWhiteSpaces |
System.Globalization.DateTimeStyles.AdjustToUniversal,
out parsedDate))
Console.WriteLine($"{dateString} --> {parsedDate:g}");
Console.WriteLine($"Cannot convert {dateString}");
// The example displays the following output:
// 20130816 --> 8/16/2013 12:00 AM
// Cannot convert 20131608
// 20130816 --> 8/16/2013 12:00 AM
// 115216 --> 4/22/2013 11:52 AM
// Cannot convert 521116
// 115216 --> 4/22/2013 11:52 AM
Dim formats() As String = {"yyyyMMdd", "HHmmss"}
Dim dateStrings() As String = {"20130816", "20131608",
" 20130816 ", "115216",
"521116", " 115216 "}
Dim parsedDate As DateTime
For Each dateString As String In dateStrings
If DateTime.TryParseExact(dateString, formats, Nothing,
DateTimeStyles.AllowWhiteSpaces Or
DateTimeStyles.AdjustToUniversal,
parsedDate) Then
Console.WriteLine($"{dateString} --> {parsedDate:g}")
Console.WriteLine($"Cannot convert {dateString}")
End If
' The example displays the following output:
' 20130816 --> 8/16/2013 12:00 AM
' Cannot convert 20131608
' 20130816 --> 8/16/2013 12:00 AM
' 115216 --> 4/22/2013 11:52 AM
' Cannot convert 521116
' 115216 --> 4/22/2013 11:52 AM
的一个常见用途
ParseExact
是转换 web 服务的字符串表示形式,通常采用
ISO 8601
标准格式。 下面的代码显示要使用的正确格式字符串:
var iso8601String = "20080501T08:30:52Z";
DateTime dateISO8602 = DateTime.ParseExact(iso8601String, "yyyyMMddTHH:mm:ssZ",
System.Globalization.CultureInfo.InvariantCulture);
Console.WriteLine($"{iso8601String} --> {dateISO8602:g}");
Dim iso8601String As String = "20080501T08:30:52Z"
Dim dateISO8602 As DateTime = DateTime.ParseExact(iso8601String, "yyyyMMddTHH:mm:ssZ", CultureInfo.InvariantCulture)
Console.WriteLine($"{iso8601String} --> {dateISO8602:g}")
如果无法分析字符串,则
Parse
和方法会
ParseExact
引发异常。
TryParse
和
TryParseExact
方法返回一个
Boolean
值,该值指示转换是成功还是失败。
TryParse
TryParseExact
在性能非常重要的情况下,应使用或方法。 日期和时间字符串的分析操作往往会产生较高的故障率,并且异常处理开销较高。 如果用户输入字符串或来自未知源,请使用这些方法。
有关分析日期和时间值的详细信息,请参阅
分析日期和时间字符串
。
DateTime 值
类型中时间值的说明
DateTime
通常使用协调世界时 (UTC) 标准来表示。 协调世界时是格林尼治标准时间 (GMT) 的国际公认的名称。 协调世界时是指以零度经度(UTC 原点)度量的时间。 夏令时不适用于 UTC。
本地时间相对于特定时区。 时区与时区偏移量关联。 时区偏移量是从 UTC 原点开始,以小时为单位的时间范围的位移。 此外,还可以根据夏令时(添加或减去时间间隔调整)来影响本地时间。 本地时间是通过将时区偏移量添加到 UTC 并调整夏令时(如有必要)来计算的。 UTC 原点的时区偏移量为零。
UTC 时间适用于计算、比较以及在文件中存储日期和时间。 本地时间适用于桌面应用程序的用户界面。 时区感知应用程序 (例如许多 Web 应用程序,) 还需要使用一些其他时区。
如果
Kind
对象的属性
DateTime
为,则
DateTimeKind.Unspecified
指示表示的时间是本地时间、UTC 时间还是其他某个时区中的时间。
日期时间解析
作为对值执行日期和时间算法
DateTime
以测量运行时间的替代方法,可以使用
Stopwatch
类。
Ticks
属性表示日期和时间值,单位为 1 10-秒秒。
Millisecond
属性返回日期和时间值的秒数的分之几秒。 使用对属性的重复调用
DateTime.Now
来度量经过的时间取决于系统时钟。 Windows 7 和 Windows 8 系统上的系统时钟的分辨率约为15毫秒。 此分辨率会影响小于100毫秒的小时间间隔。
下面的示例演示了当前日期和时间值对系统时钟的分辨率的依赖关系。 在此示例中,外部循环重复了20次,而内层循环用于延迟外部循环。 如果外部循环计数器的值为10,则调用
Thread.Sleep
方法会引入5毫秒的延迟。 下面的示例演示了在对的调用后,属性更改返回的毫秒数
DateTime.Now.Milliseconds
Thread.Sleep
。
string output = "";
for (int ctr = 0; ctr <= 20; ctr++)
output += String.Format($"{DateTime.Now.Millisecond}\n");
// Introduce a delay loop.
for (int delay = 0; delay <= 1000; delay++)
if (ctr == 10)
output += "Thread.Sleep called...\n";
System.Threading.Thread.Sleep(5);
Console.WriteLine(output);
// Press "Run" to see the output.
Dim output As String = ""
For ctr As Integer = 0 To 20
output += Date.Now.Millisecond.ToString() + vbCrLf
' Introduce a delay loop.
For delay As Integer = 0 To 1000
If ctr = 10 Then
output += "Thread.Sleep called..." + vbCrLf
Thread.Sleep(5)
End If
Console.WriteLine(output)
' The example displays output like the following:
' 111
' 111
' 111
' 111
' 111
' 111
' 111
' 111
' 111
' 111
' 111
' Thread.Sleep called...
' 143
' 143
' 143
' 143
' 143
' 143
' 143
' 143
' 143
' 143
DateTime 操作
使用
DateTime
结构(如或)的计算
Add
Subtract
不会修改结构的值。 相反,计算返回一个新的
DateTime
结构,其值为计算结果。
时区之间的转换操作 (如 UTC 和本地时间之间,或在一个时区与另一个) 之间进行转换,则需要夏令时,但算术和比较运算不会考虑到这一点。
DateTime
结构本身为从一个时区转换到另一个时区提供有限的支持。 您可以使用
ToLocalTime
方法将 UTC 转换为本地时间,也可以使用
ToUniversalTime
方法将本地时间转换为 UTC。 但是,类中提供了一组完整的时区转换方法
TimeZoneInfo
。 您可以使用这些方法将世界上任一时区中的时间转换为任何其他时区中的时间。
DateTime
仅当对象表示相同时区中的时间时,对象的计算和比较才有意义。 可以使用
TimeZoneInfo
对象来表示
DateTime
值的时区,尽管这两个值是松散耦合的。
DateTime
对象没有返回对象的属性,该对象表示日期和时间值的时区。
Kind
属性指示
DateTime
表示 UTC、本地时间还是未指定。 在时区感知应用程序中,必须依赖于某些外部机制来确定
DateTime
创建对象的时区。 可以使用一个封装
DateTime
值和
TimeZoneInfo
表示
DateTime
值的时区的对象的结构。 有关在计算中使用 UTC 和值的比较的详细信息
DateTime
,请参阅使用
日期和时间执行算术运算
。
每个
DateTime
成员都隐式使用公历来执行其操作。 异常是隐式指定日历的方法。 其中包括用于指定日历的构造函数,以及使用派生自的参数的方法
IFormatProvider
,例如
System.Globalization.DateTimeFormatInfo
。
类型成员的操作将考虑
DateTime
闰年和一个月中的天数等详细信息。
DateTime 值和日历
.NET Framework 类库包含多个 calendar 类,它们都派生自
Calendar
类。 它们是:
ChineseLunisolarCalendar
类。
EastAsianLunisolarCalendar
类。
GregorianCalendar
类。
HebrewCalendar
类。
HijriCalendar
类。
JapaneseCalendar
类。
JapaneseLunisolarCalendar
类。
JulianCalendar
类。
KoreanCalendar
类。
KoreanLunisolarCalendar
类。
PersianCalendar
类。
TaiwanCalendar
类。
TaiwanLunisolarCalendar
类。
ThaiBuddhistCalendar
类。
UmAlQuraCalendar
类。
日本历法中的年号是根据天皇统治来命名的,因此预计会发生变化。 例如,2019 年 5 月 1 日在
JapaneseCalendar
和
JapaneseLunisolarCalendar
中标志着令和年号的开始。 这种年号的变化会影响使用这些日历的所有应用程序。 有关详细信息以及如何确定应用程序是否受影响,请参阅在
.net 中的日式日历中处理新时代
。 若要了解如何在 Windows 系统上测试应用程序以确保其应用程序更改的就绪性,请参阅
准备应用程序以进行日本时代更改
。 对于 .NET 中支持多个纪元的日历的功能,以及在处理支持多个纪元的日历时的最佳做法,请参阅使用
纪元
。
每个区域性都使用由其只读属性定义的默认日历
CultureInfo.Calendar
。 每个区域性都可以支持由其只读属性定义的一个或多个日历
CultureInfo.OptionalCalendars
。 特定对象当前使用的
CultureInfo
日历由其 属性
DateTimeFormatInfo.Calendar
定义。 它必须是数组中的日历之
CultureInfo.OptionalCalendars
一。
区域性的当前日历用于该区域性的所有格式设置操作。 例如,泰语区域性的默认日历是泰语纪元日历,它由 类
ThaiBuddhistCalendar
表示。 在日期和时间格式设置操作中使用表示泰语区域性的 对象时,默认情况下使用
CultureInfo
泰语纪元日历。 只有在更改区域性的 属性时,才使用公历,
DateTimeFormatInfo.Calendar
如以下示例所示:
var thTH = new System.Globalization.CultureInfo("th-TH");
var value = new DateTime(2016, 5, 28);
Console.WriteLine(value.ToString(thTH));
thTH.DateTimeFormat.Calendar = new System.Globalization.GregorianCalendar();
Console.WriteLine(value.ToString(thTH));
// The example displays the following output:
// 28/5/2559 0:00:00
// 28/5/2016 0:00:00
Dim thTH As New CultureInfo("th-TH")
Dim value As New DateTime(2016, 5, 28)
Console.WriteLine(value.ToString(thTH))
thTH.DateTimeFormat.Calendar = New GregorianCalendar()
Console.WriteLine(value.ToString(thTH))
' The example displays the following output:
' 28/5/2559 0:00:00
' 28/5/2016 0:00:00
区域性的当前日历也用于该区域性的所有分析操作,如以下示例所示。
var thTH = new System.Globalization.CultureInfo("th-TH");
var value = DateTime.Parse("28/05/2559", thTH);
Console.WriteLine(value.ToString(thTH));
thTH.DateTimeFormat.Calendar = new System.Globalization.GregorianCalendar();
Console.WriteLine(value.ToString(thTH));
// The example displays the following output:
// 28/5/2559 0:00:00
// 28/5/2016 0:00:00
Private Sub ThaiBuddhistEraParse()
Dim thTH As New CultureInfo("th-TH")
Dim value As DateTime = DateTime.Parse("28/5/2559", thTH)
Console.WriteLine(value.ToString(thTH))
thTH.DateTimeFormat.Calendar = New GregorianCalendar()
Console.WriteLine(value.ToString(thTH))
' The example displays the following output:
' 28/5/2559 0:00:00
' 28/5/2016 0:00:00
End Sub
通过使用日期和时间元素实例化值 (特定日历的年、月、日) 数,可以调用包含 参数的
DateTime
DateTime
构造函数,并传递给它一个表示该日历的对象。
calendar
Calendar
以下示例使用日历中的日期和时间
ThaiBuddhistCalendar
元素。
var thTH = new System.Globalization.CultureInfo("th-TH");
var dat = new DateTime(2559, 5, 28, thTH.DateTimeFormat.Calendar);
Console.WriteLine($"Thai Buddhist era date: {dat.ToString("d", thTH)}");
Console.WriteLine($"Gregorian date: {dat:d}");
// The example displays the following output:
// Thai Buddhist Era Date: 28/5/2559
// Gregorian Date: 28/05/2016
Dim thTH As New CultureInfo("th-TH")
Dim dat As New DateTime(2559, 5, 28, thTH.DateTimeFormat.Calendar)
Console.WriteLine($"Thai Buddhist Era date: {dat.ToString("d", thTH)}")
Console.WriteLine($"Gregorian date: {dat:d}")
' The example displays the following output:
' Thai Buddhist Era Date: 28/5/2559
' Gregorian Date: 28/05/2016
DateTime
不包含 参数的构造函数假定日期和时间元素以公历中的单位
calendar
表示。
所有其他
DateTime
属性和方法都使用公历。 例如, 属性返回公历中的年份,并且 方法假定 参数是公历中的
DateTime.Year
DateTime.IsLeapYear(Int32)
year
年份。 使用
DateTime
公历的每个成员都有使用特定日历
Calendar
的 类的相应成员。 例如, 方法返回特定日历中的年份,并且 方法将 参数解释为特定日历
Calendar.GetYear
Calendar.IsLeapYear
year
中的年份号。 下面的示例同时使用 和
DateTime
类的相应
ThaiBuddhistCalendar
成员。
var thTH = new System.Globalization.CultureInfo("th-TH");
var cal = thTH.DateTimeFormat.Calendar;
var dat = new DateTime(2559, 5, 28, cal);
Console.WriteLine("Using the Thai Buddhist Era calendar:");
Console.WriteLine($"Date: {dat.ToString("d", thTH)}");
Console.WriteLine($"Year: {cal.GetYear(dat)}");
Console.WriteLine($"Leap year: {cal.IsLeapYear(cal.GetYear(dat))}\n");
Console.WriteLine("Using the Gregorian calendar:");
Console.WriteLine($"Date: {dat:d}");
Console.WriteLine($"Year: {dat.Year}");
Console.WriteLine($"Leap year: {DateTime.IsLeapYear(dat.Year)}");
// The example displays the following output:
// Using the Thai Buddhist Era calendar
// Date : 28/5/2559
// Year: 2559
// Leap year : True
// Using the Gregorian calendar
// Date : 28/05/2016
// Year: 2016
// Leap year : True
Dim thTH As New CultureInfo("th-TH")
Dim cal As Calendar = thTH.DateTimeFormat.Calendar
Dim dat As New DateTime(2559, 5, 28, cal)
Console.WriteLine("Using the Thai Buddhist Era calendar:")
Console.WriteLine($"Date: {dat.ToString("d", thTH)}")
Console.WriteLine($"Year: {cal.GetYear(dat)}")
Console.WriteLine($"Leap year: {cal.IsLeapYear(cal.GetYear(dat))}")
Console.WriteLine()
Console.WriteLine("Using the Gregorian calendar:")
Console.WriteLine($"Date: {dat:d}")
Console.WriteLine($"Year: {dat.Year}")
Console.WriteLine($"Leap year: {DateTime.IsLeapYear(dat.Year)}")
' The example displays the following output:
' Using the Thai Buddhist Era calendar
' Date : 28/5/2559
' Year: 2559
' Leap year : True
' Using the Gregorian calendar
' Date : 28/05/2016
' Year: 2016
' Leap year : True
DateTime
结构包括
DayOfWeek
一个 属性,该属性返回公历中星期日期。 它不包括允许检索一年中的周数的成员。 若要检索一年中的星期,请调用单个日历的
Calendar.GetWeekOfYear
方法。 下面的示例进行了这方面的演示。
var thTH = new System.Globalization.CultureInfo("th-TH");
var thCalendar = thTH.DateTimeFormat.Calendar;
var dat = new DateTime(1395, 8, 18, thCalendar);
Console.WriteLine("Using the Thai Buddhist Era calendar:");
Console.WriteLine($"Date: {dat.ToString("d", thTH)}");
Console.WriteLine($"Day of Week: {thCalendar.GetDayOfWeek(dat)}");
Console.WriteLine($"Week of year: {thCalendar.GetWeekOfYear(dat, System.Globalization.CalendarWeekRule.FirstDay, DayOfWeek.Sunday)}\n");
var greg = new System.Globalization.GregorianCalendar();
Console.WriteLine("Using the Gregorian calendar:");
Console.WriteLine($"Date: {dat:d}");
Console.WriteLine($"Day of Week: {dat.DayOfWeek}");
Console.WriteLine($"Week of year: {greg.GetWeekOfYear(dat, System.Globalization.CalendarWeekRule.FirstDay,DayOfWeek.Sunday)}");
// The example displays the following output:
// Using the Thai Buddhist Era calendar
// Date : 18/8/1395
// Day of Week: Sunday
// Week of year: 34
// Using the Gregorian calendar
// Date : 18/08/0852
// Day of Week: Sunday
// Week of year: 34
Dim thTH As New CultureInfo("th-TH")
Dim thCalendar As Calendar = thTH.DateTimeFormat.Calendar
Dim dat As New DateTime(1395, 8, 18, thCalendar)
Console.WriteLine("Using the Thai Buddhist Era calendar:")
Console.WriteLine($"Date: {dat.ToString("d", thTH)}")
Console.WriteLine($"Day of Week: {thCalendar.GetDayOfWeek(dat)}")
Console.WriteLine($"Week of year: {thCalendar.GetWeekOfYear(dat, CalendarWeekRule.FirstDay, DayOfWeek.Sunday)}")
Console.WriteLine()
Dim greg As Calendar = New GregorianCalendar()
Console.WriteLine("Using the Gregorian calendar:")
Console.WriteLine($"Date: {dat:d}")
Console.WriteLine($"Day of Week: {dat.DayOfWeek}")
Console.WriteLine($"Week of year: {greg.GetWeekOfYear(dat, CalendarWeekRule.FirstDay, DayOfWeek.Sunday)}")
' The example displays the following output:
' Using the Thai Buddhist Era calendar
' Date : 18/8/1395
' Day of Week: Sunday
' Week of year: 34
' Using the Gregorian calendar
' Date : 18/08/0852
' Day of Week: Sunday
' Week of year: 34
有关日期和日历详细信息,请参阅
使用日历
。
保留 DateTime 值
可以通过四
DateTime
种方式保留值:
将它们
转换为字符串并
保留字符串。
将它们
转换为 64 位
整数值 (属性值转换为)
Ticks
并保留整数。
序列
化 DateTime 值
。
将
DateTime 值与时区信息 一起序列化
。
无论选择哪种技术,都必须确保还原值的例程不会丢失数据或引发
DateTime
异常。
DateTime
值应往返。 也就是说,原始值和还原的值应相同。 如果原始
DateTime
值表示单个时刻,则它应标识还原时相同的时刻。
将值保留为字符串
若要成功
DateTime
还原保留为字符串的值,请遵循以下规则:
还原字符串时,对特定于区域性的格式设置做出与保留字符串时相同的假设。 若要确保可以在当前区域性不同于保存字符串的系统区域性的系统中还原字符串,请调用 重载,以使用固定区域性的约定保存字符串。
ToString
调用
Parse(String, IFormatProvider, DateTimeStyles)
或
TryParse(String, IFormatProvider, DateTimeStyles, DateTime)
重载,以使用固定区域性的约定还原字符串。 切勿使用
ToString()
Parse(String)
、 或
TryParse(String, DateTime)
重载,它们使用当前区域性的约定。
如果日期表示单个时刻,请确保它表示还原时相同的时刻,即使在不同的时区中也表示。 保存值
DateTime
之前,协调世界时 (UTC) 值。 还可以序列化值以及时区信息。 有关此方法的信息,请参阅
序列化日期/时间和时区数据
。
将值保留为字符串时,最常见的错误是依赖于默认或当前
DateTime
区域性的格式设置约定。 如果保存和还原字符串时当前区域性不同,则会出现问题。 下面的示例阐释了这些问题。 它使用当前区域性的格式设置约定保存五个日期,本例中为英语 (美国) 。 它使用不同区域性的格式设置约定还原日期,本例中为英语 (英国) 。 由于两个区域性的格式设置约定不同,因此无法还原其中两个日期,并且其余三个日期解释不正确。 此外,如果原始日期和时间值表示单个时刻,则还原时间不正确,因为时区信息丢失。
public static void PersistAsLocalStrings()
SaveLocalDatesAsString();
RestoreLocalDatesFromString();
private static void SaveLocalDatesAsString()
DateTime[] dates = { new DateTime(2014, 6, 14, 6, 32, 0),
new DateTime(2014, 7, 10, 23, 49, 0),
new DateTime(2015, 1, 10, 1, 16, 0),
new DateTime(2014, 12, 20, 21, 45, 0),
new DateTime(2014, 6, 2, 15, 14, 0) };
string output = null;
Console.WriteLine($"Current Time Zone: {TimeZoneInfo.Local.DisplayName}");
Console.WriteLine($"The dates on an {Thread.CurrentThread.CurrentCulture.Name} system:");
for (int ctr = 0; ctr < dates.Length; ctr++)
Console.WriteLine(dates[ctr].ToString("f"));
output += dates[ctr].ToString() + (ctr != dates.Length - 1 ? "|" : "");
var sw = new StreamWriter(filenameTxt);
sw.Write(output);
sw.Close();
Console.WriteLine("Saved dates...");
private static void RestoreLocalDatesFromString()
TimeZoneInfo.ClearCachedData();
Console.WriteLine($"Current Time Zone: {TimeZoneInfo.Local.DisplayName}");
Thread.CurrentThread.CurrentCulture = CultureInfo.CreateSpecificCulture("en-GB");
StreamReader sr = new StreamReader(filenameTxt);
string[] inputValues = sr.ReadToEnd().Split(new char[] { '|' },
StringSplitOptions.RemoveEmptyEntries);
sr.Close();
Console.WriteLine("The dates on an {0} system:",
Thread.CurrentThread.CurrentCulture.Name);
foreach (var inputValue in inputValues)
DateTime dateValue;
if (DateTime.TryParse(inputValue, out dateValue))
Console.WriteLine($"'{inputValue}' --> {dateValue:f}");
Console.WriteLine("Cannot parse '{inputValue}'");
Console.WriteLine("Restored dates...");
// When saved on an en-US system, the example displays the following output:
// Current Time Zone: (UTC-08:00) Pacific Time (US & Canada)
// The dates on an en-US system:
// Saturday, June 14, 2014 6:32 AM
// Thursday, July 10, 2014 11:49 PM
// Saturday, January 10, 2015 1:16 AM
// Saturday, December 20, 2014 9:45 PM
// Monday, June 02, 2014 3:14 PM
// Saved dates...
// When restored on an en-GB system, the example displays the following output:
// Current Time Zone: (UTC) Dublin, Edinburgh, Lisbon, London
// The dates on an en-GB system:
// Cannot parse //6/14/2014 6:32:00 AM//
// //7/10/2014 11:49:00 PM// --> 07 October 2014 23:49
// //1/10/2015 1:16:00 AM// --> 01 October 2015 01:16
// Cannot parse //12/20/2014 9:45:00 PM//
// //6/2/2014 3:14:00 PM// --> 06 February 2014 15:14
// Restored dates...
Public Sub PersistAsLocalStrings()
SaveDatesAsStrings()
RestoreDatesAsStrings()
End Sub
Private Sub SaveDatesAsStrings()
Dim dates As Date() = {#6/14/2014 6:32AM#, #7/10/2014 11:49PM#,
#1/10/2015 1:16AM#, #12/20/2014 9:45PM#,
#6/2/2014 3:14PM#}
Dim output As String = Nothing
Console.WriteLine($"Current Time Zone: {TimeZoneInfo.Local.DisplayName}")
Console.WriteLine($"The dates on an {Thread.CurrentThread.CurrentCulture.Name} system:")
For ctr As Integer = 0 To dates.Length - 1
Console.WriteLine(dates(ctr).ToString("f"))
output += dates(ctr).ToString() + If(ctr <> dates.Length - 1, "|", "")
Dim sw As New StreamWriter(filenameTxt)
sw.Write(output)
sw.Close()
Console.WriteLine("Saved dates...")
End Sub
Private Sub RestoreDatesAsStrings()
TimeZoneInfo.ClearCachedData()
Console.WriteLine($"Current Time Zone: {TimeZoneInfo.Local.DisplayName}")
Thread.CurrentThread.CurrentCulture = CultureInfo.CreateSpecificCulture("en-GB")
Dim sr As New StreamReader(filenameTxt)
Dim inputValues As String() = sr.ReadToEnd().Split({"|"c}, StringSplitOptions.RemoveEmptyEntries)
sr.Close()
Console.WriteLine($"The dates on an {Thread.CurrentThread.CurrentCulture.Name} system:")
For Each inputValue In inputValues
Dim dateValue As Date
If DateTime.TryParse(inputValue, dateValue) Then
Console.WriteLine($"'{inputValue}' --> {dateValue:f}")
Console.WriteLine($"Cannot parse '{inputValue}'")
End If
Console.WriteLine("Restored dates...")
End Sub
' When saved on an en-US system, the example displays the following output:
' Current Time Zone: (UTC-08:00) Pacific Time (US & Canada)
' The dates on an en-US system:
' Saturday, June 14, 2014 6:32 AM
' Thursday, July 10, 2014 11:49 PM
' Saturday, January 10, 2015 1:16 AM
' Saturday, December 20, 2014 9:45 PM
' Monday, June 02, 2014 3:14 PM
' Saved dates...
' When restored on an en-GB system, the example displays the following output:
' Current Time Zone: (UTC) Dublin, Edinburgh, Lisbon, London
' The dates on an en-GB system:
' Cannot parse '6/14/2014 6:32:00 AM'
' '7/10/2014 11:49:00 PM' --> 07 October 2014 23:49
' '1/10/2015 1:16:00 AM' --> 01 October 2015 01:16
' Cannot parse '12/20/2014 9:45:00 PM'
' '6/2/2014 3:14:00 PM' --> 06 February 2014 15:14
' Restored dates...
若要成功往返
DateTime
值,请执行以下步骤:
如果值表示单个时刻,则通过调用 方法将它们从本地时间转换为
ToUniversalTime
UTC。
通过调用 或 重载,将日期转换为其
ToString(String, IFormatProvider)
字符串
String.Format(IFormatProvider, String, Object[])
表示形式。 通过指定 作为参数,使用固定区域性
CultureInfo.InvariantCulture
的格式
provider
设置约定。 使用"O"或"R"标准格式字符串指定值应往返。
若要还原持久化
DateTime
值而不丢失数据,请执行以下步骤:
通过调用 或 重载来
ParseExact
分析
TryParseExact
数据。 指定
CultureInfo.InvariantCulture
作为
provider
参数,并使用在转换过程中用于参数的相同
format
标准格式字符串。 在
DateTimeStyles.RoundtripKind
参数中包括
styles
值。
如果
DateTime
值表示单个时刻,请调用 方法,将分析日期
ToLocalTime
从 UTC 转换为本地时间。
下面的示例使用固定区域性和"O"标准格式字符串来确保保存和还原的值表示相同的时刻,而不考虑源和目标系统的系统、区域性或
DateTime
时区。
public static void PersistAsInvariantStrings()
SaveDatesAsInvariantStrings();
RestoreDatesAsInvariantStrings();
private static void SaveDatesAsInvariantStrings()
DateTime[] dates = { new DateTime(2014, 6, 14, 6, 32, 0),
new DateTime(2014, 7, 10, 23, 49, 0),
new DateTime(2015, 1, 10, 1, 16, 0),
new DateTime(2014, 12, 20, 21, 45, 0),
new DateTime(2014, 6, 2, 15, 14, 0) };
string output = null;
Console.WriteLine($"Current Time Zone: {TimeZoneInfo.Local.DisplayName}");
Console.WriteLine($"The dates on an {Thread.CurrentThread.CurrentCulture.Name} system:");
for (int ctr = 0; ctr < dates.Length; ctr++)
Console.WriteLine(dates[ctr].ToString("f"));
output += dates[ctr].ToUniversalTime().ToString("O", CultureInfo.InvariantCulture)
+ (ctr != dates.Length - 1 ? "|" : "");
var sw = new StreamWriter(filenameTxt);
sw.Write(output);
sw.Close();
Console.WriteLine("Saved dates...");
private static void RestoreDatesAsInvariantStrings()
TimeZoneInfo.ClearCachedData();
Console.WriteLine("Current Time Zone: {0}",
TimeZoneInfo.Local.DisplayName);
Thread.CurrentThread.CurrentCulture = CultureInfo.CreateSpecificCulture("en-GB");
StreamReader sr = new StreamReader(filenameTxt);
string[] inputValues = sr.ReadToEnd().Split(new char[] { '|' },
StringSplitOptions.RemoveEmptyEntries);
sr.Close();
Console.WriteLine("The dates on an {0} system:",
Thread.CurrentThread.CurrentCulture.Name);
foreach (var inputValue in inputValues)
DateTime dateValue;
if (DateTime.TryParseExact(inputValue, "O", CultureInfo.InvariantCulture,
DateTimeStyles.RoundtripKind, out dateValue))
Console.WriteLine($"'{inputValue}' --> {dateValue.ToLocalTime():f}");
Console.WriteLine("Cannot parse '{0}'", inputValue);
Console.WriteLine("Restored dates...");
// When saved on an en-US system, the example displays the following output:
// Current Time Zone: (UTC-08:00) Pacific Time (US & Canada)
// The dates on an en-US system:
// Saturday, June 14, 2014 6:32 AM
// Thursday, July 10, 2014 11:49 PM
// Saturday, January 10, 2015 1:16 AM
// Saturday, December 20, 2014 9:45 PM
// Monday, June 02, 2014 3:14 PM
// Saved dates...
// When restored on an en-GB system, the example displays the following output:
// Current Time Zone: (UTC) Dublin, Edinburgh, Lisbon, London
// The dates on an en-GB system:
// '2014-06-14T13:32:00.0000000Z' --> 14 June 2014 14:32
// '2014-07-11T06:49:00.0000000Z' --> 11 July 2014 07:49
// '2015-01-10T09:16:00.0000000Z' --> 10 January 2015 09:16
// '2014-12-21T05:45:00.0000000Z' --> 21 December 2014 05:45
// '2014-06-02T22:14:00.0000000Z' --> 02 June 2014 23:14
// Restored dates...
Public Sub PersistAsInvariantStrings()
SaveDatesAsInvariantStrings()
RestoreDatesAsInvariantStrings()
End Sub
Private Sub SaveDatesAsInvariantStrings()
Dim dates As Date() = {#6/14/2014 6:32AM#, #7/10/2014 11:49PM#,
#1/10/2015 1:16AM#, #12/20/2014 9:45PM#,
#6/2/2014 3:14PM#}
Dim output As String = Nothing
Console.WriteLine($"Current Time Zone: {TimeZoneInfo.Local.DisplayName}")
Console.WriteLine($"The dates on an {Thread.CurrentThread.CurrentCulture.Name} system:")
For ctr As Integer = 0 To dates.Length - 1
Console.WriteLine(dates(ctr).ToString("f"))
output += dates(ctr).ToUniversalTime().ToString("O", CultureInfo.InvariantCulture) +
If(ctr <> dates.Length - 1, "|", "")
Dim sw As New StreamWriter(filenameTxt)
sw.Write(output)
sw.Close()
Console.WriteLine("Saved dates...")
End Sub
Private Sub RestoreDatesAsInvariantStrings()
TimeZoneInfo.ClearCachedData()
Console.WriteLine("Current Time Zone: {0}",
TimeZoneInfo.Local.DisplayName)
Thread.CurrentThread.CurrentCulture = CultureInfo.CreateSpecificCulture("en-GB")
Dim sr As New StreamReader(filenameTxt)
Dim inputValues As String() = sr.ReadToEnd().Split({"|"c}, StringSplitOptions.RemoveEmptyEntries)
sr.Close()
Console.WriteLine($"The dates on an {Thread.CurrentThread.CurrentCulture.Name} system:")
For Each inputValue In inputValues
Dim dateValue As Date
If DateTime.TryParseExact(inputValue, "O", CultureInfo.InvariantCulture,
DateTimeStyles.RoundtripKind, dateValue) Then
Console.WriteLine($"'{inputValue}' --> {dateValue.ToLocalTime():f}")
Console.WriteLine($"Cannot parse '{inputValue}'")
End If
Console.WriteLine("Restored dates...")
End Sub
' When saved on an en-US system, the example displays the following output:
' Current Time Zone: (UTC-08:00) Pacific Time (US & Canada)
' The dates on an en-US system:
' Saturday, June 14, 2014 6:32 AM
' Thursday, July 10, 2014 11:49 PM
' Saturday, January 10, 2015 1:16 AM
' Saturday, December 20, 2014 9:45 PM
' Monday, June 02, 2014 3:14 PM
' Saved dates...
' When restored on an en-GB system, the example displays the following output:
' Current Time Zone: (UTC) Dublin, Edinburgh, Lisbon, London
' The dates on an en-GB system:
' '2014-06-14T13:32:00.0000000Z' --> 14 June 2014 14:32
' '2014-07-11T06:49:00.0000000Z' --> 11 July 2014 07:49
' '2015-01-10T09:16:00.0000000Z' --> 10 January 2015 09:16
' '2014-12-21T05:45:00.0000000Z' --> 21 December 2014 05:45
' '2014-06-02T22:14:00.0000000Z' --> 02 June 2014 23:14
' Restored dates...
将值保留为整数
可以将日期和时间保留为
Int64
表示刻度数的值。 在这种情况下,不必考虑值持久保存和还原的系统
DateTime
区域性。
将值
DateTime
保留为整数:
如果值
DateTime
表示一个时刻,请通过调用 方法将其转换为
ToUniversalTime
UTC。
从其 属性中检索值
DateTime
表示的刻度
Ticks
数。
还原
DateTime
已保留为整数的值:
通过向构造函数
DateTime
传递值
Int64
来实例化新
DateTime(Int64)
对象。
如果
DateTime
值表示一个时刻,请通过调用 方法将其从 UTC 转换为本地
ToLocalTime
时间。
以下示例将值数组保留为美国太平洋时区
DateTime
中的系统上的整数。 它会在 UTC 区域中的系统上还原它。 包含整数的文件包含一个值,该值指示紧随它
Int32
Int64
之后的值的总数。
public static void PersistAsIntegers()
SaveDatesAsInts();
RestoreDatesAsInts();
private static void SaveDatesAsInts()
DateTime[] dates = { new DateTime(2014, 6, 14, 6, 32, 0),
new DateTime(2014, 7, 10, 23, 49, 0),
new DateTime(2015, 1, 10, 1, 16, 0),
new DateTime(2014, 12, 20, 21, 45, 0),
new DateTime(2014, 6, 2, 15, 14, 0) };
Console.WriteLine($"Current Time Zone: {TimeZoneInfo.Local.DisplayName}");
Console.WriteLine($"The dates on an {Thread.CurrentThread.CurrentCulture.Name} system:");
var ticks = new long[dates.Length];
for (int ctr = 0; ctr < dates.Length; ctr++)
Console.WriteLine(dates[ctr].ToString("f"));
ticks[ctr] = dates[ctr].ToUniversalTime().Ticks;
var fs = new FileStream(filenameInts, FileMode.Create);
var bw = new BinaryWriter(fs);
bw.Write(ticks.Length);
foreach (var tick in ticks)
bw.Write(tick);
bw.Close();
Console.WriteLine("Saved dates...");
private static void RestoreDatesAsInts()
TimeZoneInfo.ClearCachedData();
Console.WriteLine($"Current Time Zone: {TimeZoneInfo.Local.DisplayName}");
Thread.CurrentThread.CurrentCulture = CultureInfo.CreateSpecificCulture("en-GB");
FileStream fs = new FileStream(filenameInts, FileMode.Open);
BinaryReader br = new BinaryReader(fs);
int items;
DateTime[] dates;
items = br.ReadInt32();
dates = new DateTime[items];
for (int ctr = 0; ctr < items; ctr++)
long ticks = br.ReadInt64();
dates[ctr] = new DateTime(ticks).ToLocalTime();
catch (EndOfStreamException)
Console.WriteLine("File corruption detected. Unable to restore data...");
return;
catch (IOException)
Console.WriteLine("Unspecified I/O error. Unable to restore data...");
return;
// Thrown during array initialization.
catch (OutOfMemoryException)
Console.WriteLine("File corruption detected. Unable to restore data...");
return;
finally
br.Close();
Console.WriteLine($"The dates on an {Thread.CurrentThread.CurrentCulture.Name} system:");
foreach (var value in dates)
Console.WriteLine(value.ToString("f"));
Console.WriteLine("Restored dates...");
// When saved on an en-US system, the example displays the following output:
// Current Time Zone: (UTC-08:00) Pacific Time (US & Canada)
// The dates on an en-US system:
// Saturday, June 14, 2014 6:32 AM
// Thursday, July 10, 2014 11:49 PM
// Saturday, January 10, 2015 1:16 AM
// Saturday, December 20, 2014 9:45 PM
// Monday, June 02, 2014 3:14 PM
// Saved dates...
// When restored on an en-GB system, the example displays the following output:
// Current Time Zone: (UTC) Dublin, Edinburgh, Lisbon, London
// The dates on an en-GB system:
// 14 June 2014 14:32
// 11 July 2014 07:49
// 10 January 2015 09:16
// 21 December 2014 05:45
// 02 June 2014 23:14
// Restored dates...
Public Sub PersistAsIntegers()
SaveDatesAsIntegers()
RestoreDatesAsIntegers()
End Sub
Private Sub SaveDatesAsIntegers()
Dim dates As Date() = {#6/14/2014 6:32AM#, #7/10/2014 11:49PM#,
#1/10/2015 1:16AM#, #12/20/2014 9:45PM#,
#6/2/2014 3:14PM#}
Console.WriteLine($"Current Time Zone: {TimeZoneInfo.Local.DisplayName}")
Console.WriteLine($"The dates on an {Thread.CurrentThread.CurrentCulture.Name} system:")
Dim ticks(dates.Length - 1) As Long
For ctr As Integer = 0 To dates.Length - 1
Console.WriteLine(dates(ctr).ToString("f"))
ticks(ctr) = dates(ctr).ToUniversalTime().Ticks
Dim fs As New FileStream(filenameInts, FileMode.Create)
Dim bw As New BinaryWriter(fs)
bw.Write(ticks.Length)
For Each tick In ticks
bw.Write(tick)
bw.Close()
Console.WriteLine("Saved dates...")
End Sub
Private Sub RestoreDatesAsIntegers()
TimeZoneInfo.ClearCachedData()
Console.WriteLine($"Current Time Zone: {TimeZoneInfo.Local.DisplayName}")
Thread.CurrentThread.CurrentCulture = CultureInfo.CreateSpecificCulture("en-GB")
Dim fs As New FileStream(filenameInts, FileMode.Open)
Dim br As New BinaryReader(fs)
Dim items As Integer
Dim dates As DateTime()
items = br.ReadInt32()
ReDim dates(items - 1)
For ctr As Integer = 0 To items - 1
Dim ticks As Long = br.ReadInt64()
dates(ctr) = New DateTime(ticks).ToLocalTime()
Catch e As EndOfStreamException
Console.WriteLine("File corruption detected. Unable to restore data...")
Exit Sub
Catch e As IOException
Console.WriteLine("Unspecified I/O error. Unable to restore data...")
Exit Sub
Catch e As OutOfMemoryException 'Thrown in array initialization.
Console.WriteLine("File corruption detected. Unable to restore data...")
Exit Sub
Finally
br.Close()
End Try
Console.WriteLine($"The dates on an {Thread.CurrentThread.CurrentCulture.Name} system:")
For Each value In dates
Console.WriteLine(value.ToString("f"))
Console.WriteLine("Restored dates...")
End Sub
' When saved on an en-US system, the example displays the following output:
' Current Time Zone: (UTC-08:00) Pacific Time (US & Canada)
' The dates on an en-US system:
' Saturday, June 14, 2014 6:32 AM
' Thursday, July 10, 2014 11:49 PM
' Saturday, January 10, 2015 1:16 AM
' Saturday, December 20, 2014 9:45 PM
' Monday, June 02, 2014 3:14 PM
' Saved dates...
' When restored on an en-GB system, the example displays the following output:
' Current Time Zone: (UTC) Dublin, Edinburgh, Lisbon, London
' The dates on an en-GB system:
' 14 June 2014 14:32
' 11 July 2014 07:49
' 10 January 2015 09:16
' 21 December 2014 05:45
' 02 June 2014 23:14
' Restored dates...
序列化 DateTime 值
可以通过序列
DateTime
化将值持久化到流或文件,然后通过反序列化还原这些值。
DateTime
数据以某种指定的对象格式进行序列化。 反反化对象时,将还原这些对象。 格式化程序或序列化程序(如
XmlSerializer
或
BinaryFormatter
)处理序列化和反序列化的过程。 有关序列化和序列化支持的类型.NET Framework,
请参阅序列化
。
下面的示例使用 类
XmlSerializer
来序列化和反序列化
DateTime
值。 这些值表示二十一世纪的所有闰年天数。 如果示例在当前区域性为英语的系统中运行,则输出 (英国) 。 由于已反化对象本身,因此代码不必处理日期和时间
DateTime
格式的文化差异。
public static void PersistAsXML()
// Serialize the data.
var leapYears = new List<DateTime>();
for (int year = 2000; year <= 2100; year += 4)
if (DateTime.IsLeapYear(year))
leapYears.Add(new DateTime(year, 2, 29));
DateTime[] dateArray = leapYears.ToArray();
var serializer = new XmlSerializer(dateArray.GetType());
TextWriter sw = new StreamWriter(filenameXml);
serializer.Serialize(sw, dateArray);
catch (InvalidOperationException e)
Console.WriteLine(e.InnerException.Message);
finally
if (sw != null) sw.Close();
// Deserialize the data.
DateTime[] deserializedDates;
using (var fs = new FileStream(filenameXml, FileMode.Open))
deserializedDates = (DateTime[])serializer.Deserialize(fs);
// Display the dates.
Console.WriteLine($"Leap year days from 2000-2100 on an {Thread.CurrentThread.CurrentCulture.Name} system:");
int nItems = 0;
foreach (var dat in deserializedDates)
Console.Write($" {dat:d} ");
nItems++;
if (nItems % 5 == 0)
Console.WriteLine();
// The example displays the following output:
// Leap year days from 2000-2100 on an en-GB system:
// 29/02/2000 29/02/2004 29/02/2008 29/02/2012 29/02/2016
// 29/02/2020 29/02/2024 29/02/2028 29/02/2032 29/02/2036
// 29/02/2040 29/02/2044 29/02/2048 29/02/2052 29/02/2056
// 29/02/2060 29/02/2064 29/02/2068 29/02/2072 29/02/2076
// 29/02/2080 29/02/2084 29/02/2088 29/02/2092 29/02/2096
Public Sub PersistAsXml()
' Serialize the data.
Dim leapYears As New List(Of DateTime)()
For year As Integer = 2000 To 2100 Step 4
If Date.IsLeapYear(year) Then
leapYears.Add(New Date(year, 2, 29))
End If
Dim dateArray As DateTime() = leapYears.ToArray()
Dim serializer As New XmlSerializer(dateArray.GetType())
Dim sw As TextWriter = New StreamWriter(filenameXml)
serializer.Serialize(sw, dateArray)
Catch e As InvalidOperationException
Console.WriteLine(e.InnerException.Message)
Finally
If sw IsNot Nothing Then sw.Close()
End Try
' Deserialize the data.
Dim deserializedDates As Date()
Using fs As New FileStream(filenameXml, FileMode.Open)
deserializedDates = CType(serializer.Deserialize(fs), Date())
End Using
' Display the dates.
Console.WriteLine($"Leap year days from 2000-2100 on an {Thread.CurrentThread.CurrentCulture.Name} system:")
Dim nItems As Integer
For Each dat In deserializedDates
Console.Write($" {dat:d} ")
nItems += 1
If nItems Mod 5 = 0 Then Console.WriteLine()
End Sub
' The example displays the following output:
' Leap year days from 2000-2100 on an en-GB system:
' 29/02/2000 29/02/2004 29/02/2008 29/02/2012 29/02/2016
' 29/02/2020 29/02/2024 29/02/2028 29/02/2032 29/02/2036
' 29/02/2040 29/02/2044 29/02/2048 29/02/2052 29/02/2056
' 29/02/2060 29/02/2064 29/02/2068 29/02/2072 29/02/2076
' 29/02/2080 29/02/2084 29/02/2088 29/02/2092 29/02/2096
前面的示例不包括时间信息。 如果值表示一个时刻,并且表示为本地时间,则先将其从本地时间转换为
DateTime
UTC,然后再通过调用 方法序列
ToUniversalTime
化它。 反初始化后,通过调用 方法将其从 UTC 转换为本地
ToLocalTime
时间。 以下示例使用 类在美国太平洋标准时区中的系统上序列化数据,并在美国中部标准区域中的系统上反序列
BinaryFormatter
DateTime
化该数据。
public static void PersistBinary()
SaveDatesBinary();
RestoreDatesBinary();
private static void SaveDatesBinary()
DateTime[] dates = { new DateTime(2014, 6, 14, 6, 32, 0),
new DateTime(2014, 7, 10, 23, 49, 0),
new DateTime(2015, 1, 10, 1, 16, 0),
new DateTime(2014, 12, 20, 21, 45, 0),
new DateTime(2014, 6, 2, 15, 14, 0) };
var fs = new FileStream(filenameBin, FileMode.Create);
var bin = new BinaryFormatter();
Console.WriteLine($"Current Time Zone: {TimeZoneInfo.Local.DisplayName}");
Console.WriteLine($"The dates on an {Thread.CurrentThread.CurrentCulture.Name} system:");
for (int ctr = 0; ctr < dates.Length; ctr++)
Console.WriteLine(dates[ctr].ToString("f"));
dates[ctr] = dates[ctr].ToUniversalTime();
bin.Serialize(fs, dates);
fs.Close();
Console.WriteLine("Saved dates...");
private static void RestoreDatesBinary()
TimeZoneInfo.ClearCachedData();
Console.WriteLine($"Current Time Zone: {TimeZoneInfo.Local.DisplayName}");
Thread.CurrentThread.CurrentCulture = CultureInfo.CreateSpecificCulture("en-GB");
FileStream fs = new FileStream(filenameBin, FileMode.Open);
BinaryFormatter bin = new BinaryFormatter();
var dates = (DateTime[])bin.Deserialize(fs);
fs.Close();
Console.WriteLine($"The dates on an {Thread.CurrentThread.CurrentCulture.Name} system:");
foreach (var value in dates)
Console.WriteLine(value.ToLocalTime().ToString("f"));
Console.WriteLine("Restored dates...");
// When saved on an en-US system, the example displays the following output:
// Current Time Zone: (UTC-08:00) Pacific Time (US & Canada)
// The dates on an en-US system:
// Saturday, June 14, 2014 6:32 AM
// Thursday, July 10, 2014 11:49 PM
// Saturday, January 10, 2015 1:16 AM
// Saturday, December 20, 2014 9:45 PM
// Monday, June 02, 2014 3:14 PM
// Saved dates...
// When restored on an en-GB system, the example displays the following output:
// Current Time Zone: (UTC-6:00) Central Time (US & Canada)
// The dates on an en-GB system:
// 14 June 2014 08:32
// 11 July 2014 01:49
// 10 January 2015 03:16
// 20 December 2014 23:45
// 02 June 2014 17:14
// Restored dates...
Public Sub PersistBinary()
SaveDatesBinary()
RestoreDatesBinary()
End Sub
Private Sub SaveDatesBinary()
Dim dates As Date() = {#6/14/2014 6:32AM#, #7/10/2014 11:49PM#,
#1/10/2015 1:16AM#, #12/20/2014 9:45PM#,
#6/2/2014 3:14PM#}
Dim fs As New FileStream(filenameBin, FileMode.Create)
Dim bin As New BinaryFormatter()
Console.WriteLine($"Current Time Zone: {TimeZoneInfo.Local.DisplayName}")
Console.WriteLine("The dates on an {Thread.CurrentThread.CurrentCulture.Name} system:")
For ctr As Integer = 0 To dates.Length - 1
Console.WriteLine(dates(ctr).ToString("f"))
dates(ctr) = dates(ctr).ToUniversalTime()
bin.Serialize(fs, dates)
fs.Close()
Console.WriteLine("Saved dates...")
End Sub
Private Sub RestoreDatesBinary()
TimeZoneInfo.ClearCachedData()
Console.WriteLine("Current Time Zone: {TimeZoneInfo.Local.DisplayName}")
Thread.CurrentThread.CurrentCulture = CultureInfo.CreateSpecificCulture("en-GB")
Dim fs As New FileStream(filenameBin, FileMode.Open)
Dim bin As New BinaryFormatter()
Dim dates As DateTime() = DirectCast(bin.Deserialize(fs), Date())
fs.Close()
Console.WriteLine("The dates on an {Thread.CurrentThread.CurrentCulture.Name} system:")
For Each value In dates
Console.WriteLine(value.ToLocalTime().ToString("f"))
Console.WriteLine("Restored dates...")
End Sub
' When saved on an en-US system, the example displays the following output:
' Current Time Zone: (UTC-08:00) Pacific Time (US & Canada)
' The dates on an en-US system:
' Saturday, June 14, 2014 6:32 AM
' Thursday, July 10, 2014 11:49 PM
' Saturday, January 10, 2015 1:16 AM
' Saturday, December 20, 2014 9:45 PM
' Monday, June 02, 2014 3:14 PM
' Saved dates...
' When restored on an en-GB system, the example displays the following output:
' Current Time Zone: (UTC-6:00) Central Time (US & Canada)
' The dates on an en-GB system:
' 14 June 2014 08:32
' 11 July 2014 01:49
' 10 January 2015 03:16
' 20 December 2014 11:45
' 02 June 2014 17:14
' Restored dates...
序列化 DateTime 和时区数据
前面的示例都假定
DateTime
值表示为本地时间。 代码转换了 UTC 和本地时间之间的值,因此它们反映了源系统和目标系统上相同的时刻。
DateTime
值还可以反映时区中除本地和 UTC 外的时间时刻。 由于
DateTime
结构不是时区感知型,因此必须序列化值和
DateTime
TimeZoneInfo
表示其时区的对象。 创建其字段同时包含
DateTime
值及其时区的类型。 下面的示例定义 一个
DateWithTimeZone
结构。
using System;
namespace DateTimeExtensions
[Serializable]
public struct DateWithTimeZone
private TimeZoneInfo tz;
private DateTime dt;
public DateWithTimeZone(DateTime dateValue, TimeZoneInfo timeZone)
dt = dateValue;
tz = timeZone ?? TimeZoneInfo.Local;
public TimeZoneInfo TimeZone
get { return (tz); }
set { tz = value; }
public DateTime DateTime
get { return (dt); }
set { dt = value; }
Namespace DateTimeExtensions
<Serializable> Public Structure DateWithTimeZone
Private tz As TimeZoneInfo
Private dt As DateTime
Public Sub New(dateValue As DateTime, timeZone As TimeZoneInfo)
dt = dateValue
tz = If(timeZone, TimeZoneInfo.Local)
End Sub
Public Property TimeZone As TimeZoneInfo
Return tz
End Get
tz = Value
End Set
End Property
Public Property DateTime As Date
Return dt
End Get
dt = Value
End Set
End Property
End Structure
End Namespace
DateWithTimeZone
结构用于接下来的两个示例,这些示例序列化并反序列化 对象
DateWithTimeZone
数组。 可以在 Visual Basic 上的文档存储库中查看本文中整个示例集的Visual Basic
C#
GitHub。
然后,可以使用 结构
DateWithTimeZone
保留日期和时间以及时区信息。 下面的示例使用 类
BinaryFormatter
序列化 对象的
DateWithTimeZone
数组。
public static void SaveDateWithTimeZone()
DateWithTimeZone[] dates = { new DateWithTimeZone(new DateTime(2014, 8, 9, 19, 30, 0),
TimeZoneInfo.FindSystemTimeZoneById("Eastern Standard Time")),
new DateWithTimeZone(new DateTime(2014, 8, 15, 19, 0, 0),
TimeZoneInfo.FindSystemTimeZoneById("Pacific Standard Time")),
new DateWithTimeZone(new DateTime(2014, 8, 22, 19, 30, 0),
TimeZoneInfo.FindSystemTimeZoneById("Eastern Standard Time")),
new DateWithTimeZone(new DateTime(2014, 8, 28, 19, 0, 0),
TimeZoneInfo.FindSystemTimeZoneById("Eastern Standard Time")) };
var fs = new FileStream(@".\Schedule.bin", FileMode.Create);
var formatter = new BinaryFormatter();
formatter.Serialize(fs, dates);
// Display dates.
foreach (var date in dates)
TimeZoneInfo tz = date.TimeZone;
Console.WriteLine($"{date.DateTime} {(tz.IsDaylightSavingTime(date.DateTime) ? tz.DaylightName : tz.StandardName)}");
catch (SerializationException e)
Console.WriteLine($"Serialization failed. Reason: {e.Message}");
finally
if (fs != null) fs.Close();
// The example displays the following output:
// 8/9/2014 7:30:00 PM Eastern Daylight Time
// 8/15/2014 7:00:00 PM Pacific Daylight Time
// 8/22/2014 7:30:00 PM Eastern Daylight Time
// 8/28/2014 7:00:00 PM Eastern Daylight Time
Public Sub SaveDateWithTimeZone()
Dim dates As DateWithTimeZone() = {New DateWithTimeZone(#8/9/2014 7:30PM#,
TimeZoneInfo.FindSystemTimeZoneById("Eastern Standard Time")),
New DateWithTimeZone(#8/15/2014 7:00PM#,
TimeZoneInfo.FindSystemTimeZoneById("Pacific Standard Time")),
New DateWithTimeZone(#8/22/2014 7:30PM#,
TimeZoneInfo.FindSystemTimeZoneById("Eastern Standard Time")),
New DateWithTimeZone(#8/28/2014 7:00PM#,
TimeZoneInfo.FindSystemTimeZoneById("Eastern Standard Time"))}
Dim fs As New FileStream(".\Schedule.bin", FileMode.Create)
Dim formatter As New BinaryFormatter()
formatter.Serialize(fs, dates)
Catch e As SerializationException
Console.WriteLine($"Serialization failed. Reason: {e.Message}")
Finally
If fs IsNot Nothing Then fs.Close()
End Try
' Display dates.
For Each dateInfo In dates
Dim tz As TimeZoneInfo = dateInfo.TimeZone
Console.WriteLine($"{dateInfo.DateTime} {If(tz.IsDaylightSavingTime(dateInfo.DateTime), tz.DaylightName, tz.StandardName)}")
End Sub
' The example displays the following output:
' 8/9/2014 7:30:00 PM Eastern Daylight Time
' 8/15/2014 7:00:00 PM Pacific Daylight Time
' 8/22/2014 7:30:00 PM Eastern Daylight Time
' 8/28/2014 7:00:00 PM Eastern Daylight Time
然后,下面的示例调用
BinaryFormatter.Deserialize
方法来反初始化它。
public static void RestoreDateWithTimeZone()
const string filename = @".\Schedule.bin";
FileStream fs;
if (File.Exists(filename))
fs = new FileStream(filename, FileMode.Open);
Console.WriteLine("Unable to find file to deserialize.");
return;
var formatter = new BinaryFormatter();
DateWithTimeZone[] dates;
dates = (DateWithTimeZone[])formatter.Deserialize(fs);
// Display dates.
foreach (var date in dates)
TimeZoneInfo tz = date.TimeZone;
Console.WriteLine($"{ date.DateTime} {(tz.IsDaylightSavingTime(date.DateTime) ? tz.DaylightName : tz.StandardName)}");
catch (SerializationException e)
Console.WriteLine($"Deserialization failed. Reason: {e.Message}");
finally
if (fs != null) fs.Close();
// The example displays the following output:
// 8/9/2014 7:30:00 PM Eastern Daylight Time
// 8/15/2014 7:00:00 PM Pacific Daylight Time
// 8/22/2014 7:30:00 PM Eastern Daylight Time
// 8/28/2014 7:00:00 PM Eastern Daylight Time
Public Sub RestoreDateWithTimeZone()
Dim fs As FileStream
If File.Exists(filename) Then
fs = New FileStream(filename, FileMode.Open)
Console.WriteLine("Unable to find file to deserialize.")
Exit Sub
End If
Dim formatter As New BinaryFormatter()
Dim dates As DateWithTimeZone ()= Nothing
dates = DirectCast(formatter.Deserialize(fs), DateWithTimeZone())
' Display dates.
For Each dateInfo In dates
Dim tz As TimeZoneInfo = dateInfo.TimeZone
Console.WriteLine($"{dateInfo.DateTime} {If(tz.IsDaylightSavingTime(dateInfo.DateTime), tz.DaylightName, tz.StandardName)}")
Catch e As SerializationException
Console.WriteLine("Deserialization failed. Reason: {e.Message}")
Finally
If fs IsNot Nothing Then fs.Close()
End Try
End Sub
' The example displays the following output:
' 8/9/2014 7:30:00 PM Eastern Daylight Time
' 8/15/2014 7:00:00 PM Pacific Daylight Time
' 8/22/2014 7:30:00 PM Eastern Daylight Time
' 8/28/2014 7:00:00 PM Eastern Daylight Time
DateTime 与 TimeSpan
和
DateTime
TimeSpan
值类型不同,因为 表示
DateTime
时刻,而
TimeSpan
表示时间间隔。 可以从另一个实例中减去 一个实例,
DateTime
以获取
TimeSpan
表示它们之间的时间间隔的 对象。 或者,可以将正值
TimeSpan
添加到当前 ,
DateTime
以获取
DateTime
表示未来日期的值。
可以从对象添加或减去时间间隔
DateTime
。 时间间隔可以是负数也可以是正数,它们可以用时间刻度、秒数或
TimeSpan
对象表示。
在容错范围内比较是否相等
值的相等比较
DateTime
是精确的。 这意味着两个值必须表示为相同的刻度数,才能视为相等。 对于许多应用程序而言,这种精度通常是不必要的,甚至不正确。 通常,您需要测试
DateTime
对象是否
大致相等
。
下面的示例演示如何比较大致等效
DateTime
值。 当将它们声明为相等时,它将接受较小的差别。
public static bool RoughlyEquals(DateTime time, DateTime timeWithWindow, int windowInSeconds, int frequencyInSeconds)
long delta = (long)((TimeSpan)(timeWithWindow - time)).TotalSeconds % frequencyInSeconds;
delta = delta > windowInSeconds ? frequencyInSeconds - delta : delta;
return Math.Abs(delta) < windowInSeconds;
public static void TestRoughlyEquals()
int window = 10;
int freq = 60 * 60 * 2; // 2 hours;
DateTime d1 = DateTime.Now;
DateTime d2 = d1.AddSeconds(2 * window);
DateTime d3 = d1.AddSeconds(-2 * window);
DateTime d4 = d1.AddSeconds(window / 2);
DateTime d5 = d1.AddSeconds(-window / 2);
DateTime d6 = (d1.AddHours(2)).AddSeconds(2 * window);
DateTime d7 = (d1.AddHours(2)).AddSeconds(-2 * window);
DateTime d8 = (d1.AddHours(2)).AddSeconds(window / 2);
DateTime d9 = (d1.AddHours(2)).AddSeconds(-window / 2);
Console.WriteLine($"d1 ({d1}) ~= d1 ({d1}): {RoughlyEquals(d1, d1, window, freq)}");
Console.WriteLine($"d1 ({d1}) ~= d2 ({d2}): {RoughlyEquals(d1, d2, window, freq)}");
Console.WriteLine($"d1 ({d1}) ~= d3 ({d3}): {RoughlyEquals(d1, d3, window, freq)}");
Console.WriteLine($"d1 ({d1}) ~= d4 ({d4}): {RoughlyEquals(d1, d4, window, freq)}");
Console.WriteLine($"d1 ({d1}) ~= d5 ({d5}): {RoughlyEquals(d1, d5, window, freq)}");
Console.WriteLine($"d1 ({d1}) ~= d6 ({d6}): {RoughlyEquals(d1, d6, window, freq)}");
Console.WriteLine($"d1 ({d1}) ~= d7 ({d7}): {RoughlyEquals(d1, d7, window, freq)}");
Console.WriteLine($"d1 ({d1}) ~= d8 ({d8}): {RoughlyEquals(d1, d8, window, freq)}");
Console.WriteLine($"d1 ({d1}) ~= d9 ({d9}): {RoughlyEquals(d1, d9, window, freq)}");
// The example displays output similar to the following:
// d1 (1/28/2010 9:01:26 PM) ~= d1 (1/28/2010 9:01:26 PM): True
// d1 (1/28/2010 9:01:26 PM) ~= d2 (1/28/2010 9:01:46 PM): False
// d1 (1/28/2010 9:01:26 PM) ~= d3 (1/28/2010 9:01:06 PM): False
// d1 (1/28/2010 9:01:26 PM) ~= d4 (1/28/2010 9:01:31 PM): True
// d1 (1/28/2010 9:01:26 PM) ~= d5 (1/28/2010 9:01:21 PM): True
// d1 (1/28/2010 9:01:26 PM) ~= d6 (1/28/2010 11:01:46 PM): False
// d1 (1/28/2010 9:01:26 PM) ~= d7 (1/28/2010 11:01:06 PM): False
// d1 (1/28/2010 9:01:26 PM) ~= d8 (1/28/2010 11:01:31 PM): True
// d1 (1/28/2010 9:01:26 PM) ~= d9 (1/28/2010 11:01:21 PM): True
Public Shared Function RoughlyEquals(time As DateTime, timeWithWindow As DateTime,
windowInSeconds As Integer,
frequencyInSeconds As Integer) As Boolean
Dim delta As Long = (timeWithWindow.Subtract(time)).TotalSeconds _
Mod frequencyInSeconds
If delta > windowInSeconds Then
delta = frequencyInSeconds - delta
End If
Return Math.Abs(delta) < windowInSeconds
End Function
Public Shared Sub TestRoughlyEquals()
Dim window As Integer = 10
Dim freq As Integer = 60 * 60 * 2 ' 2 hours;
Dim d1 As DateTime = DateTime.Now
Dim d2 As DateTime = d1.AddSeconds(2 * window)
Dim d3 As DateTime = d1.AddSeconds(-2 * window)
Dim d4 As DateTime = d1.AddSeconds(window / 2)
Dim d5 As DateTime = d1.AddSeconds(-window / 2)
Dim d6 As DateTime = d1.AddHours(2).AddSeconds(2 * window)
Dim d7 As DateTime = d1.AddHours(2).AddSeconds(-2 * window)
Dim d8 As DateTime = d1.AddHours(2).AddSeconds(window / 2)
Dim d9 As DateTime = d1.AddHours(2).AddSeconds(-window / 2)
Console.WriteLine($"d1 ({d1}) ~= d1 ({d1}): {RoughlyEquals(d1, d1, window, freq)}")
Console.WriteLine($"d1 ({d1}) ~= d2 ({d2}): {RoughlyEquals(d1, d2, window, freq)}")
Console.WriteLine($"d1 ({d1}) ~= d3 ({d3}): {RoughlyEquals(d1, d3, window, freq)}")
Console.WriteLine($"d1 ({d1}) ~= d4 ({d4}): {RoughlyEquals(d1, d4, window, freq)}")
Console.WriteLine($"d1 ({d1}) ~= d5 ({d5}): {RoughlyEquals(d1, d5, window, freq)}")
Console.WriteLine($"d1 ({d1}) ~= d6 ({d6}): {RoughlyEquals(d1, d6, window, freq)}")
Console.WriteLine($"d1 ({d1}) ~= d7 ({d7}): {RoughlyEquals(d1, d7, window, freq)}")
Console.WriteLine($"d1 ({d1}) ~= d8 ({d8}): {RoughlyEquals(d1, d8, window, freq)}")
Console.WriteLine($"d1 ({d1}) ~= d9 ({d9}): {RoughlyEquals(d1, d9, window, freq)}")
End Sub
' The example displays output similar to the following:
' d1 (1/28/2010 9:01:26 PM) ~= d1 (1/28/2010 9:01:26 PM): True
' d1 (1/28/2010 9:01:26 PM) ~= d2 (1/28/2010 9:01:46 PM): False
' d1 (1/28/2010 9:01:26 PM) ~= d3 (1/28/2010 9:01:06 PM): False
' d1 (1/28/2010 9:01:26 PM) ~= d4 (1/28/2010 9:01:31 PM): True
' d1 (1/28/2010 9:01:26 PM) ~= d5 (1/28/2010 9:01:21 PM): True
' d1 (1/28/2010 9:01:26 PM) ~= d6 (1/28/2010 11:01:46 PM): False
' d1 (1/28/2010 9:01:26 PM) ~= d7 (1/28/2010 11:01:06 PM): False
' d1 (1/28/2010 9:01:26 PM) ~= d8 (1/28/2010 11:01:31 PM): True
' d1 (1/28/2010 9:01:26 PM) ~= d9 (1/28/2010 11:01:21 PM): True
COM 互操作注意事项
如果某个
DateTime
值已传输到 COM 应用程序,则会传输回托管应用程序,这被称为往返。 但是,
DateTime
仅指定时间的值不会像预期的那样往返。
如果只往返时间(如下午3点),则最终日期和时间为公元1899年12月30日 在下午3:00,而不是公元0001年1月1日 下午3:00 在仅指定时间时,.NET Framework 和 COM 将假定为默认日期。 但是,COM 系统假定基准日期为公元1899年12月30日,而 .NET Framework 假设基准日期为公元0001年1月1日。
当只将时间从 .NET Framework 传递到 com 时,会执行特殊处理,将时间转换为 com 使用的格式。 如果仅将时间从 COM 传递到 .NET Framework,则不会执行任何特殊处理,因为这样会损坏1899年12月30日或之前的合法日期和时间。 如果日期从 COM 开始往返,则 .NET Framework 和 com 将保留日期。
.NET Framework 和 COM 的行为意味着,如果你的应用程序往返
DateTime
仅指定时间,则你的应用程序必须记得修改或忽略最后一个对象中的错误日期
DateTime
。
线程安全性
此类型的所有成员都是线程安全的。 看似修改实例状态的成员实际上返回用新值初始化的新实例。 与任何其他类型一样,读取和写入包含此类型的实例的共享变量时,必须通过锁保护以保证线程安全。
DateTimeOffset
TimeSpan
Calendar
GetUtcOffset(DateTime)
TimeZoneInfo
在 DateTime、DateTimeOffset、TimeSpan 和 TimeZoneInfo 之间进行选择
示例:.NET Core WinForms 格式设置实用工具 (C#)
示例:.NET Core WinForms 格式设置实用工具 (Visual Basic)
![]() |
没有腹肌的开水瓶 · Exception in thread “main“ org.apache.spark.sql.AnalysisException: Cannot write incompatible data to 4 周前 |
![]() |
淡定的墨镜 · 左公子微密_哔哩哔哩_bilibili 8 月前 |