在 C# 中获取当前时间:指南
作者:社区 / 开发者
2024 年 4 月 26 日
导航至
无论使用哪种编程语言,获取当前时间都是编程期间的一项重要任务。C# 也不例外。因此,对于所有在 Google 上搜索“C# 当前时间”并了解了 DateTime.Now 但想了解更多信息的 C# 程序员来说,这篇文章就是为您准备的。
在本博客中,我们将介绍获取当前时间的重要性,并提供用例。然后,我们将深入探讨获取当前时间的实用方法,并回答一些关于 C# 中当前时间的常见问题。让我们深入了解一下。
先决条件
遵循本文的先决条件不多。如果您想测试显示的示例代码,您需要安装 .NET 和代码编辑器。截至撰写本文时,.NET 的最新稳定版本是 8.0 版本,这也是我将使用的版本。对于编辑器,我建议使用 Visual Studio Code,但任何编辑器都可以。
我们将从简单的示例开始。如果您熟悉 C#,您会做得很好。
C# 当前时间用例
在编程中,许多有价值的用例都需要获取当前时间,以及可选的当前日期。这就是为什么能够检索当前日期至关重要。
通常,您会在以下场景中想要获取当前时间
- 记录重要事件发生的时间以用于商业目的——例如,用户下订单,或一批新产品刚刚运到仓库。
- 记录应用程序错误的详细信息,包括当前时间和日期。
- 使用当前日期和/或时间作为参考点,在未来设置闹钟、提醒或通知(例如,“4 小时后提醒我”)。
- 在应用程序的用户界面 (UI) 上显示当前时间。
- 计算自过去某个时间点以来经过了多少时间。
如何在 C# 中获取当前日期和时间?
让我们开始探索这个“C# 当前时间”的事情。您可能知道,.NET 使用 System.DateTime结构来表示时间和日期。要获取包含当前时间的此类型的值,您可以使用以下代码
DateTime now = DateTime.Now;
拥有该值后,您可以访问对象上的 TimeOfDay 属性以仅获取时间
Console.WriteLine(now.TimeOfDay);
该属性返回一个 TimeSpan 对象,其中包含与当前时间等效的值。或者,您可以使用 TimeOnly 类型仅提取一天中的时间
TimeOnly time = TimeOnly.FromDateTime(now);
Console.WriteLine(time);
还有两种在 C# 中获取当前时间的方法:DateTime.UtcNow 和 DateTimeOffset.Now。 为了理解它们存在的原因,我们首先解决房间里的大象问题。
如何在 C# 中获取当前 UTC 时间?
从前面的示例中,您可能想知道:“当前时间”在哪里?“当前时间”与什么有关?
当您执行 DateTime.Now 时,您获得的是一个 DateTime 值,其 Kind 属性设置为 Local: 此属性可以有三个值:Unspecified、Utc 和 Local。当属性设置为 Local 时,这意味着 DateTime 值相对于其来源的机器是“本地”的。但是,此对象没有任何时区概念。换句话说,它“知道”它是在“这里”产生的,但不知道“这里”在哪里!
“本地”DateTime 值的此特征意味着,一旦它们离开产生它们的计算机的上下文,它们就几乎没有用处。如果您将它们保存到数据库、通过 HTTP 请求传输它们或以某种方式传输它们,接收者将无法从他们收到的值中重建原始时区。
此难题的解决方案是,当您需要记录重要事件发生的时间时,始终使用世界协调时间 (UTC)。要检索当前 UTC 时间,您可以执行
var utcNow = DateTime.UtcNow;
Console.WriteLine(utcNow.Kind); // 显示 "Utc"
然后,您将存储或传输该对象。当需要显示数据时,您会再次将其转换为本地时间
var utcNow = DateTime.UtcNow;
Console.WriteLine(utcNow.Kind); // 显示 "Utc"
var localNow = utcNow.ToLocalTime();
Console.WriteLine(localNow.Kind); // 显示 "Local"
我刚才说过 DateTime 对象没有时区概念。那么,ToLocalTime() 方法如何设法将 DateTime 值转换为正确的本地时间呢?
嗯,这个特定对象没有时区概念,但它使用来自 TimeZoneInfo 类的信息,该类有。稍后会详细介绍时区。现在,让我们介绍检索 C# 中当前时间的最后一种方法。
C# 带偏移量的当前时间
您刚刚了解了如何检索当前 UTC 时间。一般来说,当您的用例是明确记录事件时间时,这是首选方法。但是,这种方法存在一个问题。
如果您有一个 DateTime 值,其 Kind 属性设置为 Utc,并且您将其保存到数据库,然后再将其取回,则 Kind 将为 Unspecified。换句话说,Kind 信息不会往返;当您离开单台机器的边界时,它总是会丢失。
因此,如果您使用 DateTime 类型,则使用 UTC 依赖于约定。每个人都必须在同一页面上;每个人都必须意识到您正在使用 UTC。从长远来看,这不是最糟糕的问题;这是广泛的最佳实践,您应该在记录事件时使用 UTC,因此幸运的是,采用此约定不应给您带来太多麻烦。
但是,如果能比这更安全一点,岂不是更好吗?当然,这就是 DateTimeOffset 类型派上用场的地方。这是一种不同的类型,除了包含日期和时间外,还包含一个偏移量,即与 UTC 的正或负差值。
要检索带有偏移量的当前日期和时间,请执行以下操作
DateTimeOffset now = DateTimeOffset.Now;
这是我当前的偏移量: 这如何解决我们的问题?SQL Server 数据库包含一个 datetimeoffset 类型。具有此类型的列保留传递给它的偏移量信息。这样,您就不必仅仅依靠约定来使用 UTC。您甚至可以通过使用 DateTimeOffset 类型检索 UTC 中的当前日期和时间,将这两种方法结合使用
var now = DateTimeOffset.UtcNow;
总结
处理时间是编程中非常重要的任务,但由于它是一个非常混乱的领域,因此常常会出错。
在本文中,您学习了在 C# 中检索当前时间的不同方法。主要要点是,将 DateTime 的 Kind 设置为 Local 通常不是正确的选择。您最好使用 Kind 设置为 Utc 的值,甚至使用 DateTimeOffset。
对于计算,始终使用世界协调时间。例如
DateTime start = DateTime.Now;
// 发生了很多事情
DateTime end = DateTime.Now;
var timeElapsed = end - start;
上面的代码看起来可能足够无辜,但它隐藏了一个错误。如果在两个变量的初始化之间发生夏令时转换,您最终会得到一个错误的值,该值多了一个小时或少了一个小时。对于这样的计算,DateTime.UtcNow 是您需要的朋友。
如果您经常处理带时间戳的数据并需要存储解决方案,请务必查看 InfluxDB 和 InfluxDB C# 客户端库。
C# 当前时间常见问题解答
我们现在将回答一些关于处理 C# 中当前时间的常见问题。
是否可以使用 C# 以不同的时区显示当前时间?
是的,当然可以。假设出于某种原因,我需要使用东京时区显示当前时间。您需要做的第一件事是获取当前时间
var now = DateTime.UtcNow;
如果我使用 DateTime.Now, 事情也会一样。但我使用了 UtcNow,因为我们刚刚讨论了它如何成为最佳实践。下一步是检索目标时区
TimeZoneInfo tokyoTimeZone = TimeZoneInfo.FindSystemTimeZoneById("Tokyo Standard Time");
最后,您执行转换
var nowInTokyo = TimeZoneInfo.ConvertTime(now, tokyoTimeZone);
结果是一个 DateTime 值,设置为东京的当前时间。
如何在 C# 中格式化当前时间输出?
只需在 DateTime 或 DateTimeOffset 对象上调用 ToString(),您将获得一个根据您机器当前区域性格式化的字符串。以下是一些示例
using System.Globalization;
Thread.CurrentThread.CurrentCulture = new CultureInfo("en-US"); // 显示 2/16/2024 10:58:38 PM
Console.WriteLine(DateTime.UtcNow.ToString());
Thread.CurrentThread.CurrentCulture = new CultureInfo("pt-BR"); // 显示 16/02/2024 22:58:38
Console.WriteLine(DateTime.UtcNow.ToString());
Thread.CurrentThread.CurrentCulture = new CultureInfo("ja-JP"); // 显示 2024/02/16 22:58:38
Console.WriteLine(DateTime.UtcNow.ToString());
当然,还有其他显示日期和时间的方法。例如,您可以使用日期和时间的默认长字符串表示形式。它也随区域性而变化,因此我使用了与上一个示例中相同的三种区域性
using System.Globalization;
Thread.CurrentThread.CurrentCulture = new CultureInfo("en-US");
Console.WriteLine();
Console.WriteLine("英语,美国");
Console.WriteLine(DateTime.UtcNow.ToLongDateString());
Console.WriteLine(DateTime.UtcNow.ToLongTimeString());
Console.WriteLine();
Console.WriteLine("葡萄牙语,巴西");
Thread.CurrentThread.CurrentCulture = new CultureInfo("pt-BR");
Console.WriteLine(DateTime.UtcNow.ToLongDateString());
Console.WriteLine(DateTime.UtcNow.ToLongTimeString());
Console.WriteLine();
Console.WriteLine("日语,日本");
Thread.CurrentThread.CurrentCulture = new CultureInfo("ja-JP");
Console.WriteLine(DateTime.UtcNow.ToLongDateString());
Console.WriteLine(DateTime.UtcNow.ToLongTimeString());
以下是结果
英语,美国
2024 年 2 月 16 日星期五
晚上 11:03:07
葡萄牙语,巴西
2024 年 2 月 16 日,星期五
23:03:07
日语,日本
2024
年2
月16
日星期五
23:03:07
当然,您可以使用 自定义格式字符串,您从中可以获得无数种选择。
C# 中 Datetime.Now 和 today 有什么区别?
我们的最后一个问题:C# 中 DateTime.Now 和 DateTime.Today 有什么区别?它们都返回 DateTime 值。但区别在于,通过使用 DateTime.Today,时间部分设置为零。因此,您可以在仅对日期组件感兴趣而对时间不感兴趣的情况下使用 DateTime.Today。
由于现在您有 DateOnly 类型用于该用例,因此我不会使用 DateTime.Today。
这篇文章由 Carlos Schults 撰写。Carlos 是一位熟练的软件工程师,也是众多客户的杰出技术作家。他的热情是深入了解事物的本质(原始来源),并以平易近人和信息丰富的技术内容吸引读者。