在C#中获取当前时间:指南

导航至

获取当前时间是在编程过程中的一个重要任务,无论使用哪种编程语言。C#也不例外。因此,对于所有那些搜索了“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.UtcNowDateTimeOffset.Now。为了理解它们为什么存在,我们首先来谈谈这个问题。

如何在C#中获取当前的UTC时间?

从上一个示例中,你可能想知道:“当前时间”是什么意思?“当前时间”相对于什么而言?”

当你执行 DateTime.Now 时,你得到的是一个 DateTime 值,其 Kind 属性设置为 Local:[图片链接] 这个属性可以有三个值: UnspecifiedUtcLocal。当属性设置为 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 时间的当前时间。一般来说,当您的用例是明确记录事件时间时,这就是您应该采取的方式。然而,这种方法存在问题。

如果您有一个其 Kind 属性设置为 UtcDateTime 值,并将其保存到数据库中,然后将其取回,则 Kind 将变为 Unspecified。换句话说,Kind 信息不会往返;当您离开单个机器的边界时,它总是丢失。

因此,如果您在使用 DateTime 类型时使用 UTC,则依赖于约定。每个人都必须保持一致;每个人都必须意识到您正在使用 UTC。从大局来看,这并不是最糟糕的问题;这是一个广泛采用的最好做法,即在记录事件时使用 UTC,所以幸运的是,采用此约定不应给您带来太多麻烦。

但不是更好有一个比这更多的安全性吗?当然,会的,这就是 DateTimeOffset 类型的用武之地。这是一种不同的类型,除了包含日期和时间外,还包含一个偏移量,即与 UTC 的正负差异。

要获取带偏移量的当前日期和时间,请这样做

DateTimeOffset now = DateTimeOffset.Now;

这是我的当前偏移量: 这如何解决我们的问题?SQL Server 数据库包含一个 datetimeoffset 类型。具有此类型的列会保留传递给它的偏移量信息。这样,您就不再完全依赖于约定来使用 UTC。您甚至可以使用两种方法结合使用,通过使用 DateTimeOffset 类型获取 UTC 中的当前日期和时间

var now = DateTimeOffset.UtcNow;

总结

处理时间是编程中的一项重要任务,但由于它是如此混乱的领域,因此它通常会被错误地处理。

在这篇文章中,您学习了不同的方法来获取 C# 中的当前时间。主要的经验是,使用其 Kind 设置为 LocalDateTime 通常是一个错误的选择。您最好使用其 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#中格式化当前时间输出?

只需对 DateTimeDateTimeOffset 对象调用 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("English, United States");

Console.WriteLine(DateTime.UtcNow.ToLongDateString());

Console.WriteLine(DateTime.UtcNow.ToLongTimeString());

Console.WriteLine();

Console.WriteLine("Portuguese, Brazil");

Thread.CurrentThread.CurrentCulture = new CultureInfo("pt-BR");

Console.WriteLine(DateTime.UtcNow.ToLongDateString());

Console.WriteLine(DateTime.UtcNow.ToLongTimeString());

Console.WriteLine();

Console.WriteLine("Japanese, Japan");

Thread.CurrentThread.CurrentCulture = new CultureInfo("ja-JP");

Console.WriteLine(DateTime.UtcNow.ToLongDateString());

Console.WriteLine(DateTime.UtcNow.ToLongTimeString());

以下是结果

English, United States

星期五,2024年2月16日

晚上11:03:07

Portuguese, Brazil

sexta-feira, 16 de fevereiro de 2024

23:03:07

Japanese, Japan

2024216日金曜日

23:03:07

当然,您还可以使用 自定义格式字符串,您有无数的选择。

C#中DateTime.Now和today的区别是什么?

我们最后的疑问:C#中 DateTime.NowDateTime.Today 的区别是什么?它们都返回一个 DateTime 值。但区别在于,通过使用 DateTime.Today,时间部分被设置为0。所以您会在仅对日期组件感兴趣而不对时间感兴趣的情况下使用 DateTime.Today

鉴于现在您有 DateOnly 类型用于此用例,我不会使用 DateTime.Today

本文由Carlos Schults编写。 Carlos 是一位技艺娴熟的软件工程师,也是一位经验丰富的技术作家,为多家客户服务。他的热情是深入探索事物的本质(原始来源),并利用易于理解和富有信息量的技术内容吸引读者。