有没有更智能的方法来生成“自”以来的时间?与 DateTime 对象

发布于 2024-09-12 12:51:35 字数 959 浏览 1 评论 0原文

我有这段代码可以获取过去的时间并生成一个可读的字符串来表示它是多久以前的。

  1. 我本以为 Timespan.Hours 会给你几个小时,即使它是过去的多个日子,但看起来它会将其分解为单独的组成部分(天,月等)。我如何获得总小时数(即使它超过 1 天?

  2. 有没有更简洁的方法来编写下面这种类型的代码,因为它看起来相当意大利面条式。

这是代码。

        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;
        }

i have this code to take a time in the past and generate a readable string to represent how long ago it was.

  1. I would have thought Timespan.Hours would give you hours even if its multiple daye in the past but it looks like it breaks it down into its seperate components (days, months, etc). How would i get total hours ago (even if its more than 1 day?

  2. Is there any cleaner way to write this type of code below as it seems pretty spagetti-ish.

Here is the code

        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;
        }

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

水水月牙 2024-09-19 12:51:35

使用时间跨度对象中的 TotalHours 属性或其他 Total[TimeUnit] 属性。

对于 1:10 (hh:mm) 的时间跨度,它相当于 1 小时 和 10 分钟 或 1.167 TotalHours 和 70 总分钟数


至于清理它,请像之前一样坚持使用 if/else 分支。 switch/case 不会帮助您解决这些情况,仅适用于特定值。像这样:

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...

C# 8 及更高版本,您可以使用 switch 表达式和属性模式将其进一步压缩为单个表达式。

(DateTime.Now - when) switch
{
    { TotalHours: < 1 } ts => $"{ts.Minutes} minutes ago",
    { TotalDays: < 1 } ts => $"{ts.Hours} hours ago",
    { TotalDays: < 2 } => $"yesterday",
    { TotalDays: < 5 } => $"on {when.DayOfWeek}",
    var ts => $"{ts.Days} days ago",
};

Use the TotalHours property or other Total[TimeUnit] properties in the timespan object.

For a timespan of 1:10 (hh:mm), it equates to 1 Hours and 10 Minutes or 1.167 TotalHours and 70 TotalMinutes.


As for cleaning it up, stick to using if/else branches as you had earlier. switch/case will not help you with these conditions, only for specific values. Something like this:

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...

C# 8 and up, you could use switch expressions and property patterns to condense it further to a single expression.

(DateTime.Now - when) switch
{
    { TotalHours: < 1 } ts => 
quot;{ts.Minutes} minutes ago",
    { TotalDays: < 1 } ts => 
quot;{ts.Hours} hours ago",
    { TotalDays: < 2 } => 
quot;yesterday",
    { TotalDays: < 5 } => 
quot;on {when.DayOfWeek}",
    var ts => 
quot;{ts.Days} days ago",
};
明媚殇 2024-09-19 12:51:35

一个很晚的答案,但我觉得有必要这样做,并且搜索常见的 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"

而且它也是可本地化的!

A very late answer, but I felt the need for this, and searching for common JS terms such as "C# momentjs datetime" or "C# timeago" showed results which were not at all helpful - I don't want to maintain extra code with hardcoded magic numbers and which won't be localization-friendly. So, finally, in one of the comments in another SO answer, I found the library:

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

Usage:

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

And it's localizable too!

习惯成性 2024-09-19 12:51:35

作为替代方案,我有一个解决方案,可以在几天、几周、几个月甚至几年的时间内完成此任务。方法有点不同,它从过去迈向未来,首先尝试大步骤,如果超出,则切换到下一个较小的步骤。

PeriodOfTimeOutput.cs

As an alternative, I have a solution that does that beyond days with weeks, months and years. The approach is a bit different It advances from the past to the future, first trying the big steps and if it overshoots switching to the next smaller one.

PeriodOfTimeOutput.cs

水染的天色ゝ 2024-09-19 12:51:35

我知道这是一篇旧文章,但在搜索这个主题并阅读 Jeff Mercado 的答案后,我使用递归想出了这个解决

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;
}

方案

var tspan = DateTime.Now.Subtract(reqDate);
string how_long_ago = PeriodOfTimeOutput(tspan);

I know this is an old post, but I came up with this solution using recursion after searching for this topic and reading Jeff Mercado's answer

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;
}

used as such

var tspan = DateTime.Now.Subtract(reqDate);
string how_long_ago = PeriodOfTimeOutput(tspan);
久随 2024-09-19 12:51:35

如果您想要更大的灵活性和更智能的结果,那么 Olive 框架,名为 ToTimeDifferenceString()

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

myDate.ToTimeDifferenceString(1)

返回“2 天前”

myDate.ToTimeDifferenceString(2)

返回“2 天 4 小时前”

If you want more flexibility and smarter-looking outcome, then there is an extension method for this in the Olive framework named ToTimeDifferenceString().

It has a parameter named precisionParts. For example:

myDate.ToTimeDifferenceString(1)

which returns "2 days ago"

or

myDate.ToTimeDifferenceString(2)

which returns "2 days and 4 hours ago"

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文