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

时间:2013-05-30 23:06:44

标签: c# asp.net .net datetime dotnetnuke

我需要在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因为DateTime的{​​{1}}值大于time1的{​​{1}}值。但是当我在DotNetNuke设置中将语言更改为德语(DateTime)时,now的值变为 - de-DE。结果是now变为31/5/2013 2:20:33 AM,意味着num 早于而不是-1。这是不正确的,因为time1实际上晚于now

time1值始终为now格式,因为它来自服务器。

那么,如果在DotNetNuke中设置了另一种语言,我如何得到正确的比较?当我搜索网页时,我发现我可以使用以下代码更正时间:

time1

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

被修改

忘记说时间1来自我的网站服务器,然后保存到数据库并与客户网站的现在变量中的日期时间值进行比较。所有代码都是我的应用程序,位于该客户端站点。这些代码在第一次访问的时间1日期通过.net方法获取远程站点数据。所以当该dnn站点语言被设置为de-DE look' now'变量值是第一天,它与我的站点日期相反,是美国格式月份。因此,当进行比较时,我的服务器日期早于客户站点日期!一切都破了。我的服务器日期是一个星期后的日期,这是6月2日的许可证目的。

再次编辑:

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

mm/dd/yyyy

" NUM"返回1,无论dnn网站语言是德语还是英语,都是正确的。

1 个答案:

答案 0 :(得分:2)

正如您所指出的,当字符串表示日期时,我们如何处理日期存在文化差异。 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类型的列中。从数据访问层检索值时,它应该从SQL流向.Net,作为纯DateTime。没有涉及字符串。我们假设您使用的是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;

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

最后一行:

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类。