System.DateTime比较('>')或('<')没有给出我的预期

时间:2015-11-05 17:45:25

标签: datetime operators

我想从列表中获取所有归档文件>的文件。今天的cutOff - 所以,我有以下的codelet

string[] MyFiles = Directory.GetFiles(MyConfig.pathTransmittedFiles, "*.adf")
        .Where(file => new FileInfo(file).LastWriteTime > dtCutOff).ToArray();

我的文件的LastWriteTime是“{11/3/2015 1:33:26 PM}”我的收藏品被dtCutOff ==“{11/3/2015 1:33:26 PM}”“ !所以'>'似乎没有用。

4 个答案:

答案 0 :(得分:1)

首先,我会尝试在没有Where子句的情况下运行它,只是为了确保您期望的所有文件确实是从Directory.GetFiles返回的初始数组的一部分。日期/时间比较完全有可能不是差异的根源。它可能与Ivan在问题评论中链接的问题更相关,或者可能与许可有关,或者其他一些事情。

接下来,请注意DateTime违反了SRP,因为它具有Kind属性,这是三个DateTimeKind枚举值之一。它可以是LocalUtcUnspecified

如果是DateTime.Now,则Kind将为DateTimeKind.LocalFile.GetLastWriteTime也会以本地类型返回其值。因此,如果您始终以问题中显示的方式从dtCutOff派生DateTime.Now,则几乎始终是正确的比较函数。

"几乎"源于DateTimeKind.Local实际上可以代表两种不同类型的事实。换句话说,实际上有四种种类,但其中两种是由一种暴露的。这被描述为" DateTime的深黑暗秘密"在Jon Skeet的博客文章More Fun with DateTime中,也提到了in the comments in the .NET Framework Reference Source。在实践中,你应该只在躲避daylight saving time过渡期间的模糊时间内遇到这种情况(例如刚刚在2015-11-01美国上周日发生)。

现在,更可能的情况是你的dtCutOff实际上不是来自DateTime.Now,而是来自用户输入或数据库查找或其他一些机制,那么它可能实际上代表了本地在其他时区的时间,而不是本地计算机上的时间。换句话说,如果dtCutOff的{​​{1}}为Kind,那么该值就是UTC。如果DateTimeKind.UtcKind,那么可能是UTC,本地时区或其他时区。

以下是踢球者:两个DateTimeKind.Unspecified值的比较评估DateTime属性背后的值。它不考虑Ticks

由于文件时间是通用时间的绝对点(无论如何都是NTFS),那么你真的应该使用Kind方法,而不是当地时间的方法。

您可以使用两种方法:

  • 使用以下代码加载File.GetLastWriteTimeUtc属性为UTC:

    modified
  • 正确填充myResult.modified = File.GetLastWriteTimeUtc(myFile);

    • 如果您从当前时间开始加载,请使用dtOffset
    • 如果您要从其他输入加载,请确保将值转换为UTC以匹配输入方案。例如,如果值是以本地时区为单位,则使用DateTime.UtcNow;如果值在另一个时区,则使用.ToUniversalTime()类中的转换函数。

  • 将您的TimeZoneInfo媒体资源改为modified而不是DateTimeOffset
  • 使用以下方式加载:

    DateTime
  • myResult.modified = new DateTimeOffset(File.GetLastWriteTimeUtc(myFile)); 定义为dtCutOff,并正确填充。

    • 如果您从当前时间开始加载,请使用DateTimeOffset
    • 如果您要从其他输入加载,请确保将偏移设置为与输入方案匹配。如果您需要从其他时区转换,请使用DateTimeOffset.UtcNow个功能。
TimeZoneInfo相比,{p> DateTimeOffset有许多优势,例如不违反SRP。它始终代表着绝对的时刻。在这种情况下,有助于了解DateTime上的比较运算符始终反映绝对时刻。 (换句话说,它在进行比较之前在内部调整为UTC。)

答案 1 :(得分:0)

由于文件每天被送入队列一次,所以不需要精度等级到毫秒或者其他东西。因此,可以接受一秒钟的TimeSpan差异来完成这个技巧并使我的案例有效。

string[] MyFiles = Directory.GetFiles(MyConfig.pathTransmittedFiles, "*.adf")
  .Where(file => new FileInfo(file).LastWriteTime - TimeSpan.FromSeconds(1) > dtCutOff)
  .ToArray();

现在我的文件修改日期“{11/3/2015 1:33:26 PM}”当我的cutOffDate为“{11/3/2015 1:33:26 PM}”时没有进入我的收藏而我的其他文件修改日期“{11/3/2015 1:33:27 PM}”已成功传递到我的收藏中!所以,它有效,这就是在所有这些建议之后它应该如何工作!谢谢大家。

答案 2 :(得分:0)

此代码有效:

var cutffDate = new DateTime(2015,1,1); // or whatever
var allFiles = Directory.GetFiles(MyConfig.pathTransmittedFiles, "*.adf");
var datedFiles = allFiles.Where(f => (new FileInfo(f)).LastWriteTime > cutffDate);

<强>更新 由于您的问题似乎与精度相关,因此您可以将比较更改为:

const long precision = 10; // vary this as needed
allFiles.Where(f =>
  (new FileInfo(f)).LastWriteTime.ToFileTime()/precision > cutffDate.ToFileTime()/precision);

或者您可以使用...LastAccessTime.Ticks/TimeSpan.TicksPerMillisecond 除此之外,您可能需要将所有DateTime值转换为UTC(LastAccessTimeUtc和DateTime.UtcNow)以确保它不是一些奇怪的时区问题

答案 3 :(得分:-1)

看起来你的Where子句lambda可能不正确。试试这个。

string[] MyFiles = Directory.GetFiles(MyConfig.pathTransmittedFiles, "*.adf").Where(file => file.modified > dtCutOff).ToArray();