DateTime.比较方法不能用于不同的语言

本文关键字:语言 用于 比较 方法 不能 DateTime | 更新日期: 2023-09-27 18:16:16

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

// 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是因为time1DateTime值大于nowDateTime值。但是当我在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来自我的网站服务器之前保存到数据库,并与客户端的网站的datetime值在现在变量进行比较。所有的代码是我的应用程序,这是在客户端网站。这些代码首先通过。net获取远程站点数据的方法访问time1日期。因此,当dnn网站语言设置为de-DE时,"现在"变量值是天第一,这与我的网站日期是美国格式的月第一相反。因此,当比较发生时,我的服务器日期导致早于客户端站点日期!所有东西都坏了。仅供参考,我的服务器日期是1周后的日期,即6月2日,用于许可目的。

编辑:

嗨every1。我通过以下代码找到了解决方案。这个日期来自我的另一个服务器,正如我上面所说的-"6/15/2013"(更改为2013年6月2日之前)。它是字符串格式,为什么是字符串?这是一个悠久的历史。现在就让它是一个字符串吧。在转换为字符串之前,它是美国日期格式(前一个月)。现在在当前的网站,我的应用程序是,这些代码似乎工作。希望我没有错,请确认

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站点语言是德语还是英语。

DateTime.比较方法不能用于不同的语言

正如您所指出的,当用字符串表示日期时,我们对待日期的方式存在文化差异。DD/MM/YYYY格式在欧洲和世界其他地区很常见,而MM/DD/YYYY格式几乎只在美国使用(有一些例外)。还有很多其他格式。

有一个重要的格式你应该知道,那就是ISO8601标准。您通常可以将其视为时间戳,例如2013-05-31T02:20:33。有时,后面的Z表示时间是UTC。您可能还会看到一个偏移量,如-07:00或仅-0700。这些都是同一标准的一部分。最常见的用法在RFC3339中也有说明。当您实际需要将DateTime作为字符串发送时,您可能应该使用这种格式。(例外是向用户显示字符串,以及从用户收集输入。)

现在,您应该理解DateTime而不是字符串值。它在内部由64位整数表示。它不会在内部保留任何格式或区域性设置。DateTimestring之间的转换只能用于输入和输出。通常这是在您的用户界面中,或者在ASP的情况下。Net,它可以在你的网页上。

在使用DateTime的其他地方,不应该处理字符串。特别是在比较值的时候。让我们剖析一下你的代码。首先是这一行:

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

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

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类型。你可以在这里阅读更多。

:最后一行

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

这很好,但是您可能会发现使用常规布尔比较更容易,例如:

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,并了解LocalUtcUnspecified之间的区别。如果您发现需要处理应用程序中的其他时区,那么您可能还需要了解TimeZoneInfo类。