我进行了下面的单元测试,它在我们的一个开发人员的机器上失败了(他在结果变量中得到一些滴答,而datetime变量是零滴答),但在其他所有机器上运行良好
[TestMethod]
public void DateTimeStringDateTimeMinCurrentCultureToNullableDateTimeSuccessTest()
{
var dateTime = new DateTime(1, 1, 1);
string value = dateTime.ToString();
var result = value.ToNullableDateTime();
Assert.AreEqual(dateTime, result);
}
以下是使用的扩展方法:
/// <summary>
/// Converts a string to a nullable DateTime. If the string is a invalid dateTime returns null.
/// Uses the current culture.
/// </summary>
public static DateTime? ToNullableDateTime(this string s)
{
//Don't use CultureInfo.CurrentCulture to override user changes of the cultureinfo.
return s.ToNullableDateTime(CultureInfo.GetCultureInfo(CultureInfo.CurrentCulture.Name));
}
/// <summary>
/// Converts a string to a nullable DateTime. If the string is a invalid dateTime returns null.
/// </summary>
public static DateTime? ToNullableDateTime(this string s, CultureInfo cultureInfo)
{
if (String.IsNullOrEmpty(s)) return null;
DateTime i;
if (DateTime.TryParse(s, cultureInfo, DateTimeStyles.None, out i)) return i;
return null;
}
我认为这可能与他使用的某些Windows日期时间设置有关。从理论上讲,ToNullableDateTime(string)
应该创建一个新的文化信息,这是用户机器中立的。 GetCultureInfo
应致电new CultureInfo(name, false)
。我唯一能想到的是,有一个缓存的文化信息,其中包含s_NameCachedCultures
中与GetCultureInfoHelper
中检查的某种与用户机器相关的修改日期时间CreateSpecificCulture
({{ 3}})。
我知道,GetDateTime
方法可以返回用户修改的日期时间,如果您使用与Windows机器相同的文化来调用它。但我一直认为,CultureInfo
在任何情况下都会返回未修改的日期时间。
所以有两个问题:
CultureInfo
存储在内部缓存中?new CultrueInfo("xy", false)
来获取未修改var list = [{ a: '1'}, {b: '2'}];
var lastObject = list.pop();
if(lastObject) {
//use object..
}
的唯一方法是什么?答案 0 :(得分:3)
当你这样做时
string value = dateTime.ToString();
这将使用CultureInfo.CurrentCulture。然后,您尝试使用...
解析此字符串CultureInfo.GetCultureInfo(CultureInfo.CurrentCulture.Name);
因此,您专门使用文化来解析与您创建字符串的字符串不同的字符串。当然会出现这种情况并未通过的情况。
我建议这个问题出现在大多数人的机器上
Assert.AreEqual(CultureInfo.CurrentCulture, CultureInfo.GetCultureInfo(CultureInfo.CurrentCulture.Name));
会通过但是在有问题的机器上它没有,你的字符串也没有。
我建议您可能要使用CultureInfo.InvariantCulture。所以......
[TestMethod]
public void DateTimeStringDateTimeMinCurrentCultureToNullableDateTimeSuccessTest()
{
DateTime dateTime = new DateTime(1, 1, 1);
string value = dateTime.ToStringInvariant();
var result = value.ToNullableDateTime();
Assert.AreEqual(dateTime, result);
}
public static string ToStringInvariant(this DateTime? date)
{
if (date.HasValue)
return date.Value.ToStringInvariant();
return null;
}
public static string ToStringInvariant(this DateTime date)
{
return date.ToString(CultureInfo.InvariantCulture);
}
/// <summary>
/// Converts a string to a nullable DateTime. If the string is a invalid dateTime returns null.
/// Uses the current culture.
/// </summary>
public static DateTime? ToNullableDateTime(this string s)
{
//Don't use CultureInfo.CurrentCulture to override user changes of the cultureinfo.
return s.ToNullableDateTime(CultureInfo.InvariantCulture);
}
/// <summary>
/// Converts a string to a nullable DateTime. If the string is a invalid dateTime returns null.
/// </summary>
public static DateTime? ToNullableDateTime(this string s, CultureInfo cultureInfo)
{
if (String.IsNullOrEmpty(s)) return null;
DateTime i;
if (DateTime.TryParse(s, cultureInfo, DateTimeStyles.None, out i)) return i;
return null;
}
答案 1 :(得分:1)
我已经监督了一些细节。该问题与GetCultureInfo返回修改后的日期时间无关,问题已经开始于使用dateTime.ToString();
的{{1}}(等于可以修改的Windows文化)。开发者机器将Thread.CurrentThread.CultureInfo
转换为DateTime(1, 1, 1)
。在任何其他计算机上,输出为01.01.01 00:00:00
。因此,使用了年份的缩写版本,这似乎被解释为本世纪的第1年&#34;在01.01.0001 00:00:00
方法中(快速侧节点:因此,对于年龄超过100岁的用户来说,使用缩写的年份版本告诉他们的出生日期是不可能的)。
这实际上是一种有趣的行为......
TryParse
导致:
for (int i = 0; i < 100; i++)
{
var year = 1900 + i;
DateTime date = new DateTime(year, 1, 1);
var parsedDate = DateTime.ParseExact(date.ToString("yy"), "yy", CultureInfo.InvariantCulture);
Console.WriteLine("{0}: {1}", year, parsedDate.ToString("yyyy"));
}
因此,任何年龄较大的86岁的缩写出生日期都会导致该功能中的日期..但这会偏离问题背景。
我认为实际问题没有真正的解决方案(除了告诉开发人员不要在UI字符串之外使用本地CultureInfos并且从不使用缩写日期作为输入)。
我们的代码本身没有这样的问题,因为我们对所有内部内容使用[...]
1928: 2028
1929: 2029
1930: 1930
1931: 1931
[...]
。我只考虑单元测试..我认为测试本身是正确的。它表明,该函数实际上没有使用缩写日期正确工作。如果识别出具有缩写年份的日期时间字符串,我将更改CultureInfo.InvariantCulture
的行为以抛出异常。
答案 2 :(得分:0)
我猜,很可能argv
位于缓存中。这可以很容易地检查单元测试(CultureInfo
)。
而不是AreSame
使用DateTime(1, 1, 1)
并检查幽灵蜱。它们是在字符串中找到的吗?您是否在两台具有不同结果的机器上尝试相同的文化(硬编码文化名称)?
同时检查差异是否是您文化中UTC的偏移量。
您可能可以使用DateTime(1, 2, 3)
。