是否有一种更智能的方法来生成DateTime对象的“time since”

时间:2010-08-01 19:41:17

标签: c# datetime timespan

我让这段代码在过去花费一些时间并生成一个可读的字符串来表示它的存在时间。

  1. 我原本以为Timespan.Hours会给你几个小时,即使它过去多了一天,但它看起来像是分解成单独的组件(几天,几个月等)。我怎么会在几小时前得到(即使它超过1天?

  2. 下面是否有更简洁的方式来编写这种类型的代码,因为它看起来很漂亮。

  3. 这是代码

            DateTime when = GetDateTimeinPast();
            TimeSpan ts = DateTime.Now.Subtract(when);
    
            switch (ts.Days)
            {
                case 0:
                   if (ts.Hours < 1)
                        b.Append( ts.Minutes + " minutes ago");
                   else
                       b.Append( ts.Hours + " hours ago");
                    break;
                case 1:
                    b.Append( " yesterday");
                    break;
                case 2:
                case 3:                
                case 4:
    
                    b.Append( "on " + when.DayOfWeek.ToString());
                    break;
                default:
                    b.Append(ts.Days + " days ago");
                    break;
            }
    

5 个答案:

答案 0 :(得分:15)

在时间范围对象中使用TotalHours属性或其他Total[TimeUnit]属性。

对于1:10(hh:mm)的时间跨度,它相当于1 Hours和10 Minutes或1.167 TotalHours和70 TotalMinutes

至于清理它,坚持使用if / else分支,如前所述。开关/外壳无法帮助您满足这些条件,仅适用于特定值。像这样:

DateTime when = GetDateTimeinPast();
TimeSpan ts = DateTime.Now.Subtract(when);
if (ts.TotalHours < 1)
    b.AppendFormat("{0} minutes ago", (int)ts.TotalMinutes);
else if (ts.TotalDays < 1)
    b.AppendFormat("{0} hours ago", (int)ts.TotalHours);
//etc...

答案 1 :(得分:2)

一个非常晚的答案,但我觉得有必要这样做,并且搜索常见的JS术语,例如“C#momentjs datetime”或“C#timeago”,显示的结果根本没有帮助 - 我不想维护带有硬编码魔术数字的额外代码,不会对本地化有帮助。所以,最后,在另一个SO答案中的一条评论中,我找到了这个库:

Humanizer for .NET - https://github.com/Humanizr/Humanizer#humanize-datetime

用法:

DateTime.UtcNow.AddHours(-2).Humanize() => "2 hours ago"

它也可以本地化!

答案 2 :(得分:1)

作为替代方案,我有一个解决方案可以在数周,数月和数年之后完成这项工作。这种方法有点不同它从过去到未来都有所进步,首先尝试重大步骤,如果它超过了切换到下一个较小的步骤。

PeriodOfTimeOutput.cs

答案 3 :(得分:0)

我知道这是一篇很老的帖子,但在搜索了这个主题并阅读了Jeff Mercado的回答之后,我使用递归来提出这个解决方案

<rich:collapsiblePanel id="panelId" expanded="false"
        switchType="ajax" header="Awesomeness"
        onswitch="console.log(this.children[0].value);">
    ------
    Some amazing content
    ------
</rich:collapsiblePanel>

用作

private string PeriodOfTimeOutput(TimeSpan tspan, int level = 0)
{
    string how_long_ago = "ago";
    if (level >= 2) return how_long_ago;
    if (tspan.Days > 1)
        how_long_ago = string.Format("{0} Days ago", tspan.Days);
    else if (tspan.Days == 1)
        how_long_ago = string.Format("1 Day {0}", PeriodOfTimeOutput(new TimeSpan(tspan.Hours, tspan.Minutes, tspan.Seconds), level + 1));
    else if (tspan.Hours >= 1)
        how_long_ago = string.Format("{0} {1} {2}", tspan.Hours, (tspan.Hours > 1) ? "Hours" : "Hour", PeriodOfTimeOutput(new TimeSpan(0, tspan.Minutes, tspan.Seconds), level + 1));
    else if (tspan.Minutes >= 1)
        how_long_ago = string.Format("{0} {1} {2}", tspan.Minutes, (tspan.Minutes > 1) ? "Minutes" : "Minute", PeriodOfTimeOutput(new TimeSpan(0, 0, tspan.Seconds), level + 1));
    else if (tspan.Seconds >= 1)
        how_long_ago = string.Format("{0} {1} ago", tspan.Seconds, (tspan.Seconds > 1) ? "Seconds" : "Second");        
    return how_long_ago;
}

答案 4 :(得分:0)

如果您希望获得更多灵活性和更智能的结果,那么在名为 ToTimeDifferenceString()Olive framework中有一种扩展方法。

它有一个名为precisionParts的参数。例如:

myDate.ToTimeDifferenceString(1)

返回&#34; 2天前&#34;

myDate.ToTimeDifferenceString(2)

返回&#34; 2天4小时前&#34;