【问题标题】:Is there a better way to trim a DateTime to a specific precision? [duplicate]有没有更好的方法将 DateTime 修剪到特定的精度? [复制]
【发布时间】:2010-09-14 05:52:35
【问题描述】:

将 DateTime 对象修剪到特定精度的最佳方法是什么?例如,如果我有一个值为“2008-09-29 09:41:43”的 DateTime,但我只希望它精确到分钟,有没有比这更好的方法呢?

private static DateTime TrimDateToMinute(DateTime date)
{
    return new DateTime(
        date.Year, 
        date.Month, 
        date.Day, 
        date.Hour, 
        date.Minute, 
        0);
}

我真正想要的是让它可变,以便我可以将其精度设置为秒、分钟、小时或天。

【问题讨论】:

    标签: c# .net datetime


    【解决方案1】:

    我喜欢这种方法。有人提到保留日期类型等很好。这样做是因为您不必创建新的日期时间。 DateTime 是从原始 DateTime 正确克隆的,它只是减去剩余的刻度。

    public static DateTime FloorTime(DateTime dt, TimeSpan interval) 
    {
      return dt.AddTicks(-1 * (dt.Ticks % interval.Ticks));
    }
    

    用法:

    dt = FloorTime(dt, TimeSpan.FromMinutes(5)); // floor to the nearest 5min interval
    dt = FloorTime(dt, TimeSpan.FromSeconds(1)); // floor to the nearest second
    dt = FloorTime(dt, TimeSpan.FromDays(1));    // floor to the nearest day
    

    【讨论】:

    • 由于 DateTime 格式是一种结构(值类型),任何操作都会创建一个新值,即使它没有以这种方式呈现。 stackoverflow.com/a/1859266/955444
    • 是的,但它被 DateTime 代码正确克隆,因此确实保留了时区。我将稍微改写我的答案以更清楚。谢谢。
    【解决方案2】:
    static class Program
    {
        //using extension method:
        static DateTime Trim(this DateTime date, long roundTicks)
        {
            return new DateTime(date.Ticks - date.Ticks % roundTicks, date.Kind);
        }
    
        //sample usage:
        static void Main(string[] args)
        {
            Console.WriteLine(DateTime.Now);
            Console.WriteLine(DateTime.Now.Trim(TimeSpan.TicksPerDay));
            Console.WriteLine(DateTime.Now.Trim(TimeSpan.TicksPerHour));
            Console.WriteLine(DateTime.Now.Trim(TimeSpan.TicksPerMillisecond));
            Console.WriteLine(DateTime.Now.Trim(TimeSpan.TicksPerMinute));
            Console.WriteLine(DateTime.Now.Trim(TimeSpan.TicksPerSecond));
            Console.ReadLine();
        }
    
    }
    

    【讨论】:

    • 我非常喜欢这个,如果我使用的是 3.5 框架,这就是我会采取的路线,除非那里还有更好的东西。不幸的是,我使用的是 2.0,所以我必须坚持你的第一个答案。谢谢!
    • 如果您将其设为通用扩展方法,则值得保留 DateTimeKind (Unspecified/Utc/Local):return new DateTime(date.Ticks - date.Ticks % roundTicks, date.种类);
    • ... 或一个也保留 Kind 属性的单行: d = d.AddTicks(-(d.Ticks + 30*TimeSpan.TicksPerSecond) % TimeSpan.TicksPerMinute);
    • @Joe 谢谢伙计,在花了 2 小时调试过期的身份验证令牌后,我来到这里写了同样的评论 :))
    【解决方案3】:

    这里提供了一些很好的解决方案,但是当我需要这样做时,我只是这样做:

    DateTime truncDate;
    truncDate = date.Date; // trim to day
    truncDate = date.Date + TimeSpan.Parse(string.Format("{0:HH:00:00}", date)); // trim to hour
    truncDate = date.Date + TimeSpan.Parse(string.Format("{0:HH:mm}", date)); // trim to minute
    truncDate = date.Date + TimeSpan.Parse(string.Format("{0:HH:mm:ss}", date)); // trim to second
    

    希望对你有帮助。

    【讨论】:

    • 不起作用,只返回当天+00:00:00
    • @katz:很抱歉,我在发布回复时测试了这个解决方案,我刚刚再次测试它,它工作得很好。你确定你不只测试上面的第一个选项(修剪到今天)吗?我不相信上面所有的 TimeSpan.Parse 方法调用都会在 00:00:00 返回给您。你确定你使用的是一个不同的变量(除了变量“日期”本身)来接收这些操作的结果(就像我在我的例子中使用的“truncDate”)?如果您使用“日期”变量本身,上面的第一个操作会将其截断为日期,从而影响下面的所有其他结果。
    • @katz:使用不同的变量(如“truncDate”),不要按顺序执行上述所有操作,然后打印结果。我的代码只是一个示例,但每个操作(每个代码行)都应该单独使用,具体取决于您想要的精度(天、小时、分钟或秒)。例如,尝试只执行最后一行(修剪到第二行),然后打印结果。
    • @katz:对不起,在“trim to hour”代码行中,这是一个错误,我刚刚编辑了代码。似乎字符串格式“{0:HH}”没有返回(如我所料)日期的小时部分,所以我将其更改为“{0:HH:00:00}”,效果很好。另一个代码行是正确的。我在上面的 cmets 中所做的所有观察仍然有效。
    • 感谢您的支持。随着变化一切正常:) +1
    【解决方案4】:

    你可以使用枚举

    public enum DateTimePrecision
    {
      Hour, Minute, Second
    }
    
    public static DateTime TrimDate(DateTime date, DateTimePrecision precision)
    {
      switch (precision)
      {
        case DateTimePrecision.Hour:
          return new DateTime(date.Year, date.Month, date.Day, date.Hour, 0, 0);
        case DateTimePrecision.Minute:
          return new DateTime(date.Year, date.Month, date.Day, date.Hour, date.Minute, 0);
        case DateTimePrecision.Second:
          return new DateTime(date.Year, date.Month, date.Day, date.Hour, date.Minute, date.Second);
        default:
          break;
      }
    }
    

    并根据需要展开。

    【讨论】:

    • 对于小时和分钟,我想知道分钟和秒是否应该四舍五入而不是使用 0?
    • 当然,如果需要,您可以将代码调整为舍入而不是截断;我经常发现截断感觉更自然,因为这实际上是时钟的行为方式。
    • 当你只需要一次时 - return new DateTime(dt.Year, 1, 1)
    • 请记住保留DateTime.Kind
    【解决方案5】:
    DateTime dt = new DateTime()
    dt = dt.AddSeconds(-dt.Second)
    

    以上代码将修剪秒数。

    【讨论】:

    • 它不会修剪毫秒,会导致错误的dt
    • 那么只需添加 .AddMillisceconds() 即可。在我看来,这个答案优于其他答案,因为它的样板要少得多。但请纠正我。
    【解决方案6】:
        static DateTime TrimDate(DateTime date, long roundTicks)
        {
            return new DateTime(date.Ticks - date.Ticks % roundTicks);
        }
    
        //sample usage:
        static void Main(string[] args)
        {
            Console.WriteLine(DateTime.Now);
            Console.WriteLine(TrimDate(DateTime.Now, TimeSpan.TicksPerDay));
            Console.WriteLine(TrimDate(DateTime.Now, TimeSpan.TicksPerHour));
            Console.WriteLine(TrimDate(DateTime.Now, TimeSpan.TicksPerMillisecond));
            Console.WriteLine(TrimDate(DateTime.Now, TimeSpan.TicksPerMinute));
            Console.WriteLine(TrimDate(DateTime.Now, TimeSpan.TicksPerSecond));
            Console.ReadLine();
        }
    

    【讨论】:

    • 请删除重复的答案。我相信一个很好的答案就足够了
    猜你喜欢
    • 2013-04-04
    • 1970-01-01
    • 1970-01-01
    • 2019-07-01
    • 1970-01-01
    • 2020-06-13
    • 2013-04-06
    • 1970-01-01
    • 2019-12-08
    相关资源
    最近更新 更多