如何生产和QUOT;人类可读QUOT;字符串重新present时间跨度 [英] How to produce "human readable" strings to represent a TimeSpan

查看:170
本文介绍了如何生产和QUOT;人类可读QUOT;字符串重新present时间跨度的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个时间跨度重presenting时间的客户端已连接到我的服务器的数量。我想显示时间跨度给用户。但我不希望过于冗长,以显示该信息(例如:2小时3分钟32.2345sec =过于详细)

例如:如果连接的时间...

 > 0秒和< 1分钟-----> 0秒
> 1分钟的车和< 1小时-----> 0分0秒
> 1小时和< 1天-----> 0小时0分
> 1天-----> 0天0小时
 

当然,在情况下,数字为1(如:1秒,1分钟,1小时,1天),我想提出的案文奇(例如:1秒,1分钟,1个小时, 1天)。

反正轻松地实现这一点没有一个巨大集合的if / else子句的?以下是我目前做的事情。

 公共字符串GetReadableTimeSpan(时间跨度值)
{
    串持续时间;

    如果(value.TotalMinutes&小于1)
        持续时间= value.Seconds +秒;
    否则,如果(value.TotalHours< 1)
        持续时间= value.Minutes +纪要+ value.Seconds +秒;
    否则,如果(value.TotalDays< 1)
        持续时间= value.Hours +小时+ value.Minutes +纪要;
    其他
        持续时间= value.Days +天+ value.Hours +小时;

    如果(duration.StartsWith(1秒)|| duration.EndsWith(1秒))
        持续时间= duration.Replace(1秒,1秒);

    如果(duration.StartsWith(1分钟)|| duration.EndsWith(1分钟))
        持续时间= duration.Replace(1分钟,1分钟);

    如果(duration.StartsWith(1小时)|| duration.EndsWith(1小时))
        持续时间= duration.Replace(1小时,1小时);

    如果(duration.StartsWith(1天))
        持续时间= duration.Replace(1天,1天);

    返回时间;
}
 

解决方案

要摆脱复杂的,如果和交换机构建可以使用字典查找了的CustomFormatter基于TotalSeconds正确的格式字符串,并相应地格式化所提供的时间跨度

 公共字符串GetReadableTimespan(时间跨度TS)
{
     //格式及其临界值的基础上totalseconds
     VAR截止=新的排序列表<长串> {
       {60,{3:•}},
       {60 * 60,{2:M},{3:•}},
       {24 * 60 * 60,{1:H},{2:M}},
       {Int64.MaxValue,{0:D},{1:1 H}}
     };

     //找到最近的最佳匹配
     VAR查找= cutoff.Keys.ToList()
                   .BinarySearch((长)ts.TotalSeconds);
     //负值表示最接近的匹配
     附近VAR =找到℃的Math.Abs​​(查找)-1:查找;
     //使用自定义格式来得到字符串
     返回的String.Format(
         新HMSFormatter(),
         截止[cutoff.Keys [近],
         ts.Days,
         ts.Hours,
         ts.Minutes,
         ts.Seconds);
}

//格式化为复数/单数形式
//秒/小时/天
公共类HMSFormatter:ICustomFormatter,的IFormatProvider
{
   字符串[0],_singular;

   公共HMSFormatter(){}

   私人HMSFormatter(复数串,串奇)
   {
     [0] =复数;
     _singular =单数;
   }

   公共对象的GetFormat(类型formatType)
   {
       返回formatType == typeof运算(ICustomFormatter)本:空;
   }

   公共字符串格式(字符串格式,对象阿根廷,IFormatProvider的formatProvider)
   {
     如果(ARG!= NULL)
     {
         字符串格式化;
         开关(格式)
         {
             案S://第二
                FMT =的String.Format(新HMSFormatter({0}秒,{0}二),{0},ARG);
                打破;
             案M://分钟
                FMT =的String.Format(新HMSFormatter({0}分钟,{0}分钟),{0},ARG);
                打破;
              情况下的H://小时
                FMT =的String.Format(新HMSFormatter({0}小时,{0}小时),{0},ARG);
                打破;
              案D://天
                FMT =的String.Format(新HMSFormatter({0}天,{0}天),{0},ARG);
                打破;
              默认:
                //复数/单数
                FMT =的String.Format((int)的ARG→1 [0]:_singular,ARG); //看剧组在这里诠释...
                打破;
         }
         返回FMT;
     }
     返回的String.Format(格式,ARG);
   }
}
 

I have a TimeSpan representing the amount of time a client has been connected to my server. I want to display that TimeSpan to the user. But I don't want to be overly verbose to displaying that information (ex: 2hr 3min 32.2345sec = too detailed!)

For example: If the connection time is...

> 0 seconds and < 1 minute   ----->  0 Seconds
> 1 minute  and < 1 hour     ----->  0 Minutes, 0 Seconds
> 1 hour    and < 1 day      ----->  0 Hours, 0 Minutes
> 1 day                      ----->  0 Days, 0 Hours

And of course, in cases where the numeral is 1 (ex: 1 seconds, 1 minutes, 1 hours, 1 days), I would like to make the text singular (ex: 1 second, 1 minute, 1 hour, 1 day).

Is there anyway to easily implement this without a giant set of if/else clauses? Here is what I'm currently doing.

public string GetReadableTimeSpan(TimeSpan value)
{
    string duration;

    if (value.TotalMinutes < 1)
        duration = value.Seconds + " Seconds";
    else if (value.TotalHours < 1)
        duration = value.Minutes + " Minutes, " + value.Seconds + " Seconds";
    else if (value.TotalDays < 1)
        duration = value.Hours + " Hours, " + value.Minutes + " Minutes";
    else
        duration = value.Days + " Days, " + value.Hours + " Hours";

    if (duration.StartsWith("1 Seconds") || duration.EndsWith(" 1 Seconds"))
        duration = duration.Replace("1 Seconds", "1 Second");

    if (duration.StartsWith("1 Minutes") || duration.EndsWith(" 1 Minutes"))
        duration = duration.Replace("1 Minutes", "1 Minute");

    if (duration.StartsWith("1 Hours") || duration.EndsWith(" 1 Hours"))
        duration = duration.Replace("1 Hours", "1 Hour");

    if (duration.StartsWith("1 Days"))
        duration = duration.Replace("1 Days", "1 Day");

    return duration;
}

解决方案

To get rid of the complex if and switch constructs you can use a Dictionary lookup for the correct format string based on TotalSeconds and a CustomFormatter to format the supplied Timespan accordingly.

public string GetReadableTimespan(TimeSpan ts)
{
     // formats and its cutoffs based on totalseconds
     var cutoff = new SortedList<long, string> { 
       {60, "{3:S}" },
       {60*60, "{2:M}, {3:S}"},
       {24*60*60, "{1:H}, {2:M}"},
       {Int64.MaxValue , "{0:D}, {1:H}"}
     };

     // find nearest best match
     var find = cutoff.Keys.ToList()
                   .BinarySearch((long)ts.TotalSeconds);
     // negative values indicate a nearest match
     var near = find<0?Math.Abs(find)-1:find;
     // use custom formatter to get the string
     return String.Format(
         new HMSFormatter(), 
         cutoff[cutoff.Keys[near]], 
         ts.Days, 
         ts.Hours, 
         ts.Minutes, 
         ts.Seconds);
}

// formatter for plural/singular forms of
// seconds/hours/days
public class HMSFormatter:ICustomFormatter, IFormatProvider
{
   string _plural, _singular;

   public HMSFormatter() {}

   private HMSFormatter(string plural, string singular)
   {
     _plural =  plural;
     _singular = singular;
   }

   public object GetFormat(Type formatType)
   {
       return formatType == typeof(ICustomFormatter)?this:null;
   }   

   public string Format(string format, object arg, IFormatProvider formatProvider)
   {
     if (arg !=null)
     {
         string fmt;
         switch (format)
         {
             case "S": // second
                fmt = String.Format(new HMSFormatter("{0} Seconds", "{0} Second"),"{0}", arg);
                break;
             case "M": // minute
                fmt =  String.Format(new HMSFormatter("{0} Minutes","{0} Minute"),"{0}", arg);
                break;
              case "H": // hour
                fmt =  String.Format(new HMSFormatter("{0} Hours","{0} Hour"), "{0}",arg);
                break;
              case "D": // day
                fmt = String.Format(new HMSFormatter("{0} Days","{0} Day"), "{0}", arg);
                break;              
              default:
                // plural/ singular             
                fmt = String.Format((int)arg>1?_plural:_singular,arg);  // watch the cast to int here...
                break;
         }
         return fmt;
     }
     return String.Format(format, arg);
   }
}

这篇关于如何生产和QUOT;人类可读QUOT;字符串重新present时间跨度的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆