c# - DateTime.Compare 方法不适用于不同的语言

标签 c# asp.net .net datetime dotnetnuke

我需要比较两个 DateTime我的 DotNetNuke 模块中的值,如下所示:

// This value actually comes from the database.
DateTime time1 = Convert.ToDateTime("6/2/2013 5:21:05 PM");

// Say it is now "5/31/2013 2:20:33 AM"
DateTime now = DateTime.Now;

int num = DateTime.Compare(time1, now);

如您所见,num == 1因为 DateTime time1 的值大于 DateTime now 的值.但是当我在 DotNetNuke 设置中将语言更改为德语( de-DE )时,now 的值变成- 31/5/2013 2:20:33 AM .结果是 num变成 -1 , 意思是 time1早于 now .这是不正确的,因为 time1实际上晚于 now .
time1值总是在 mm/dd/yyyy格式,因为它来自服务器。

那么,如果在 DotNetNuke 中设置了另一种语言,我如何获得正确的比较?当我在网上搜索时,我发现我可以使用以下代码更正时间:
provider = new CultureInfo("en-US");
DateTime.ParseExact("5/31/2013", "d", provider);

那是对的吗?有没有更好的方法来处理这个问题?

已编辑

忘了说时间 1 在保存到数据库之前来自我的网站服务器,并与现在变量中客户网站的日期时间值进行比较。所有代码都是我在该客户端站点中的应用程序。这些代码首先通过 .net 方法访问 time1 日期获取远程站点数据。因此,当该 dnn 站点语言设置为 de-DE 时,请查看“现在”变量值是第一天,这与我的站点日期相反,首先是美国格式月份。因此,当进行比较时,我的服务器日期结果早于客户现场日期!一切都中断了。仅供引用,我的服务器日期是 i 周后的日期,即 6 月 2 日,用于许可目的。

再次编辑:

嗨every1。我通过以下代码找到了解决方案。正如我上面所说,这个日期来自我的另一台服务器 - “6/15/2013”​​(更改它是bef4 6/2/2013)。它是字符串格式,为什么它是一个字符串?这是一个悠久的历史。现在让它成为一个字符串。在转换为字符串之前它是美国日期格式(前一个月)。现在在我的应用程序所在的当前网站中,这些代码似乎工作。希望我没有错,拜托确认
CultureInfo provider = CultureInfo.InvariantCulture;
provider = new CultureInfo("en-US");
DateTime time1 = DateTime.ParseExact("6/15/2013", "d", provider);                    
DateTime now = DateTime.Now;
int num = DateTime.Compare(time1, now);

“num”返回 1,无论 dnn 站点语言是德语还是英语,这都是正确的。

最佳答案

正如您所指出的,当日期由字符串表示时,我们如何处理日期存在文化差异。 DD/MM/YYYY格式在欧洲大部分地区和世界其他地区很常见,而 MM/DD/YYYY几乎完全由美国使用(有少数异常(exception))。还有很多其他格式。

您应该知道一种重要的格式,即 ISO8601。标准。您通常可以将此视为时间戳,例如 2013-05-31T02:20:33 .有时尾随 Z包括在内以指示时间为 UTC。您可能还会看到偏移量,例如 -07:00或只是 -0700 .这都是同一标准的一部分。最常见的用法也在 RFC3339 中表示。 .每当您实际需要发送 DateTime作为一个字符串,您可能应该使用这种格式。 (异常(exception)情况是向用户显示字符串以及从用户收集输入时。)

现在,您应该明白 DateTime不是字符串值。它在内部由一个 64 位整数表示。它在内部不保留任何格式或文化设置。 DateTime之间的转换和 string只应出于输入和输出的目的进行。通常这是在您的用户界面中,或者在 ASP.Net 的情况下,它可以在您的网页上。

与您一起工作的任何其他地方DateTime ,你根本不应该处理字符串。尤其是在比较值时。让我们剖析您的代码。首先我们有这条线:

DateTime time1 = Convert.ToDateTime("6/2/2013 5:21:05 PM");

现在你说它是从数据库中出来的,但如果是这种情况,那么你不应该有一个字符串。假设您使用的是 SQL Server 数据库(但同样的概念也适用于其他数据库),并且数据位于 DateTime 的列中。类型。当您从数据访问层检索值时,它应该作为纯 DateTime 从 SQL 流向 .Net .不涉及字符串。让我们假设您正在使用 ADO.Net 并且您有一个 DataReader .您应该将您的值(value)加载为:
DateTime time1 = (DateTime)reader["columnname"];  // good

相反,如果您正在执行以下操作:
DateTime time1 = Convert.ToDateTime(reader["columnname"].ToString());  // bad!

然后您将文化信息引入您用作中间步骤的字符串中。这可能是您的问题的根源。不需要时不要使用字符串。

另外,我会避免使用 Convert.ToDateTime一点也不。如果你确实需要解析一个字符串,你应该使用 DateTime.Parse ,如果您已经知道该字符串的确切格式,那么您应该使用 DateTime.ParseExact .

您的代码的下一行是:
DateTime now = DateTime.Now;

为此,您应该了解您从服务器上的时钟获取本地时间。这可能不是您网站用户的时间。而且由于您将其与数据库值进行比较,这意味着您也将本地时间存储在数据库中。这可能会带来很大的问题,因为服务器可能具有特定的时区设置。此外,如果时区经历了夏令时(又名夏令时)的更改,那么有些值不存在,有些值存在两次。这可能会导致重大问题,尤其是在比较这些值时。更好的方法是使用 DateTime.UtcNow ,或使用 DateTimeOffset键入而不是 DateTime类型。您可以阅读更多关于此的信息,here .

最后一行:
int num = DateTime.Compare(time1, now);

这很好,但您可能会发现使用常规 bool 比较更容易,例如:
if (time1 >= now) ...

那么如何处理文化问题呢?解析用户输入时,请执行以下操作:
// Use the culture setting of your user.  Perhaps DNN has this already.
CultureInfo provider = new CultureInfo("de-DE");

// Parse the input string, but let the provider do the work to know the format.
DateTime dt = DateTime.Parse("31/5/2013", provider);

// Send data back to the user with the same provider.
string s = dt.ToString("d", provider);

您可能更喜欢使用 TryParse 方法,以防您的用户提供错误数据:
DateTime dt;
if (!DateTime.TryParse(s, provider, DateTimeStyles.None, out dt)
{
    // handle invalid data
}

最后,您应该熟悉 DateTime.Kind ,并了解 Local 之间的区别, Utc , 和 Unspecified种。如果您发现需要在应用程序中处理其他时区,那么您可能还需要了解 TimeZoneInfo类(class)。

关于c# - DateTime.Compare 方法不适用于不同的语言,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16847289/

相关文章:

c# - EF Core 更新现有实体

asp.net - 检查是否处于集成管道模式

c# - 转发器中的 td 样式不会输出绑定(bind)值 ("This is not a scriptlet. Will output as plain text")

c# - 在具有服务层的多层架构中,一个服务调用另一个服务是否可以接受?

c# - 我们可以在 ASP.NET 中为 pagemethod 和 webmethod 使用相同的数据表吗?

c# - ASP.NET MVC (C#) 中的经典 ASP

c# - wsdl.exe 能否生成与 Visual Studio 在添加 Web 引用时生成的文件相同的文件?

c# - c#中的条件确认框

asp.net - C# 中列表框的多项选择

.net - 使用 WebApplicationFactory 将服务替换为模拟服务