C# 时间教程:何时、何物和如何
作者: 社区 / 开发者
2023 年 11 月 22 日
导航至
时间操作是编程的基础。无论您最喜欢的编程语言是什么,这都是事实:Python、Java、Kotlin、Ruby,等等。C# 当然也不例外,这就是为什么今天我们为您带来一份全面而平易近人的 C# 时间操作指南。
我们将以 C# 编程中时间处理的概览来开始这篇文章。之后,我们将深入一点,为您提供更多可操作的技巧。您将了解 C# 中主要的与时间相关的函数——它们是什么以及如何使用它们。
在结束之前,我们将介绍 C# 中时间处理的实际应用,以便您了解如何以最能为您的项目创造价值的方式使用本文中的所有信息。
先决条件
如果您想跟随这篇文章,并在学习过程中测试代码示例,您将需要
- 您的机器上安装了 .NET SDK 的版本——我们推荐 .NET 7
- 一些 IDE 或文本编辑器——Visual Studio Code 是一个不错的选择
- 至少具备 C# 基础知识
时间在 C# 编程中是如何使用的?
在 C# 和 .NET 中,时间处理是一等公民。要使您的程序能够处理时间和日期,您无需执行任何特殊操作,例如添加 using 语句或安装 NuGet 包。您将看到,处理时间问题所需的类型都位于 System 命名空间中,因此您已经可以访问它们。
考虑到 C# 是一种(主要是)面向对象的语言,因此它的时间相关功能是通过使用对象来提供的,这应该不足为奇。您将使用的主要对象是 theDateTimetype。DateTime 类型是一个结构——也就是说,它是一个值类型而不是引用类型——并且是不可变的。由于其值永远不会改变,因此可以以更安全、更可预测的方式使用它,从而产生更健壮的代码。
DateTime 表示日期和时间。但它的接口也提供了许多有用的时间相关操作,例如
- 执行时间算术运算,例如将分钟、小时、天或其他时间段添加到给定日期
- 比较两个日期
- 根据无数的日期和时间格式格式化日期
尽管 DateTime 是 C# 中最著名的与时间相关的类型,但它远非唯一。其他有用的类型包括 DateTimeOffset、TimeSpan、DateOnly、TimeOnly 和 TimeZoneInfo。
现在让我们更多地了解如何在实践中使用其中一些函数。
C# 中与时间相关的函数:它们是什么,何时以及如何使用它们
现在是时候学习如何在 C# 中实际使用与时间相关的功能了。在本节中,我们将使用 FAQ 格式。我们将以问题的形式列出常见场景,并立即回答它们。
如何在 C# 中获取当前时间?
在 C# 中获取当前时间和日期的最简单方法是使用 DateTime 类型的 Now 属性。它返回一个 DateTime 值,其中包含程序运行所在系统的时钟的当前日期和时间。下面是一个简单的程序,它根据一天中的时间向用户问好
DateTime currentTime = DateTime.Now;
int hour = currentTime.Hour;
if (hour >= 8 && hour < 12)
{
Console.WriteLine("Good morning!");
}
else if (hour >= 12 && hour < 18)
{
Console.WriteLine("Good afternoon!");
}
else
{
Console.WriteLine("Good evening!");
}
如您所见,代码还使用了返回的 DateTime 上的 Hour 属性来仅获取当前值的小时部分。还有其他属性用于值的不同部分
int minute = currentTime.Minute;
int second = currentTime.Second;
int day = currentTime.Day;
int month = currentTime.Month;
int year = currentTime.Year;
int microsecond = currentTime.Microsecond;
int milisecond = currentTime.Millisecond;
int dayOfYear = currentTime.DayOfYear;
C# 中是否有时间数据类型?
在它存在的大部分时间里,C# 没有提供一种仅用于时间的数据类型和一种仅用于日期的数据类型。您必须使用 DateTime ——它始终同时具有这两个组件——这经常导致错误,尤其是在比较场景中。(另一种选择是求助于第三方库,例如 NodaTime。)
从 .NET 6 开始,现在有类型可以仅存储日期或时间。它们分别称为 DateOnly 和 TimeOnly。
这就是如何检索当前时间并将其存储在 TimeOnly 变量中的方法
TimeOnly now = TimeOnly.FromDateTime(DateTime.Now);
DateOnly today = DateOnly.FromDateTime(DateTime.Now);
如何处理持续时间?
如果您有两个 DateTime 值,您可以轻松计算它们之间的差值(即差)。结果是一个 TimeSpan 类型的值。让我们看看如何在实践中做到这一点
var start = new DateTime(2023, 10, 5, 10, 0, 0);
var end = new DateTime(2023, 10, 6, 7, 25, 0);
TimeSpan delta = end - start;
上面的代码声明了两个 DateTime 值,使用构造函数传递年、月、日、小时、分钟和秒。然后,使用减号运算符,我们计算两个值之间的差值,并将其分配给 TimeSpan 类型的新变量。
TimeSpan 对象有多个属性,使您可以检索其值的部分,例如 TotalMinutes、TotalHours、TotalSeconds 等。
您还可以使用其静态工厂方法创建 TimeSpan 值。例如,如果您需要表示 50 分钟的持续时间,这就是您要做的
var duration = TimeSpan.FromMinutes(50);
C# 中时间的实际应用
让我们继续介绍 C# 中与时间相关的编程的一些实际应用。
显示当前日期和/或时间
许多程序可能需要在其 UI 上显示当前日期和/或时间。如您所见,DateTime.Now 属性可用于检索该值。在格式化方面,您可以使用 ToString() 的多种变体之一来根据您的需要格式化值。您还可以使用更具体的方法,例如 ToLongTimeString()、ToLongDateString(), ToShortDateString(), ToShortTimeString().
记录“历史”数据
每当您需要存储事件的时间和日期时,您不应仅使用 DateTime.Now 来检索时刻。这是因为此属性返回的值的 Kind 属性设置为 Local。这意味着该值对于生成它的计算机是本地的,但没有任何时区概念。在这些情况下,正确的方法是将值保存为 UTC,并且仅在显示时将其转换为本地时间。
要获取当前的 UTC 日期和时间,您只需使用 DateTime.UtcNow 属性
var utcNow = DateTime.UtcNow;
另一种选择是使用不同的类型:您可以使用 DateTimeOffset 而不是 DateTime:
DateTimeOffset localWithOffset = DateTimeOffset.Now;
DateTimeOffset 类型包含常规的本地日期,但它也存储了与 UTC 的偏移量。这种方法的优点是保留了本地时间的时间,这有助于可视化,同时在需要时可以转换为世界协调时间 (UTC)。
定义到期日期
业务中的一个常见场景是需要定义到期日期:试用期的最终日期、合同或其他法律条款的结束日期、个人访问令牌的到期日期等等。
通过使用 DateTime 及其同伴的 AddDays() 方法,很容易得出这些日期
var today = DateTime.Today;
DateTime tenDaysLater = today.AddDays(10);
DateTime twoMonthsLater = today.AddMonths(2);
DateTime nextYear = today.AddYears(1);
没有 Subtract 方法。为了从 DateTime 对象中减去,您只需为 Addxxx 方法提供负值即可。
验证或解析来自文件的 DateTime 值
另一个常见场景是必须解析存储在文本文件中的日期和时间——例如,.CSV 文件。由于无法保证这些值实际上是有效的,请确保以健壮的方式编写代码。以下代码从 .CSV 文件中的一行中提取并解析日期。代码假设日期在第二列中
void ParseLine(string line)
{
string[] parts = line.Split(',');
if (parts.Length < 3)
throw new InvalidOperationException("File with wrong data!");
string dateCandidate = parts[1];
if (!DateTime.TryParse(dateCandidate, out DateTime date))
{
throw new InvalidOperationException("Invalid date!");
}
// do something useful with date
}
如您所见,没有为该方法提供日期格式。如果您自己尝试此代码,请确保日期采用 ISO-8601 格式,它将起作用。其他格式可能有效,也可能无效,具体取决于您系统的区域性。
总结
时间处理是编程中的一个庞大主题。它既迷人又复杂,并且充满了错误和漏洞的机会。这篇文章是对该主题的温和介绍。您已经了解了时间处理在 C# 中是如何工作的,您应该使用的主要类型是什么,甚至还了解了一些实际场景。
然而,这只是冰山一角。我不可能在一篇博文的范围内涵盖关于这个主题的所有知识。因此,以下是一些您应该自行研究的项目
- 详细了解 不同种类——意思是,它的 Kind 属性可以假设的不同可能值——DateTime 可以假设的不同可能值,以及它们对您的代码的影响
- 详细了解 TimeZoneInfo 类以及如何处理需要处理 时区 的代码
- 研究如何安排未来事件以及夏令时如何为表格带来很多复杂性
感谢您的阅读,下次再见。
这篇文章由 Carlos Schults 撰写。Carlos 是一位顾问和软件工程师,在桌面、Web 和移动开发方面拥有经验。虽然他的主要语言是 C#,但他拥有多种语言和平台的经验。他的主要兴趣包括自动化测试、版本控制和代码质量。