2010-08-20 81 views
4

我想以这种方式来格式化C#的时间跨度:自定义字符串格式

XXX天(S)YYY小时(S)ZZZ分钟

条件:

  1. 额外秒数应该被截断

  2. 天(s)是我想要的最大单位。我想34天出现34天,而不是1个月4天等。

  3. 如果时间跨度少于一天,我不希望一天的部分出现。同样,如果跨度小于1小时,我只需要显示分钟部分。

有没有什么办法可以做到这一点使用内置的格式字符串或没有办法,除了写我自己的功能?

编辑:目前使用我自己的这个功能。这需要时间跨度以分钟为输入(TimeSpan.TotalMinutes)

private static string GetTimeStringFromMinutes(double p) 
     { 
      var minutes = (int) p; 
      int hours = minutes/60; 
      minutes = minutes % 60; 
      int days = hours/24; 
      hours = hours%24; 
      string dayPart = days + " day(s) "; 
      string hoursPart = hours + " hour(s) "; 
      string minutesPart = minutes + " minute(s)"; 
      if (days != 0) 
       return (dayPart + hoursPart + minutesPart); 
      if (hours != 0) 
       return (hoursPart + minutesPart); 
      return (minutesPart); 
     } 
+0

我只是好奇......如果天数大于零但小时数为零会发生什么?例如,你会显示“XX天,0小时,YY分钟”还是显示“XX天,YY分钟”?你的代码似乎是做前者的。 – 2010-08-20 10:39:14

+0

是的,在这种情况下,我希望显示0小时.. – 2010-08-20 11:10:12

回答

6

TimeSpan在.NET 4.0之前根本没有任何格式化选项,您必须通过Ticks属性将其转换为DateTime。尽管没有在DateTime.String(格式)格式化选项中远程关闭,但您必须亲自编写它。

在.NET 4.0中,TimeSpan获取了ToString(格式)覆盖。自定义格式字符串描述here。你的第三个需求将需要代码。

+0

+1提到在.NET 4.0之前没有TimeSpan格式。我不知道,并且当我不能在.NET 2.0项目中使用它时,我会浪费时间来弄清楚我需要什么格式字符串。 – Jim 2013-07-19 18:01:40

5

在.NET 3.5和更早的版本,你需要编写自己的功能。

在.NET 4中增加了对格式化TimeSpan的支持,请参阅TimeSpan.ToString(string)了解详细信息。

2

不幸的是,.Net中没有任何东西直接可用。至于我自己,我已经解决了这个问题是这样的:

public static class TimeSpanExtensions 
{ 
    public static string ToDetailedString(this TimeSpan timeSpan) 
    { 
     if (timeSpan == null) 
      throw new ArgumentNullException("timeSpan"); 

     var sb = new StringBuilder(30); 

     var current = timeSpan.ToDaysString(); 

     if (!String.IsNullOrEmpty(current)) 
      sb.Append(current); 

     current = timeSpan.ToHoursString(); 

     if (!String.IsNullOrEmpty(current)) 
     { 
      if (sb.Length > 0) 
       sb.Append(" "); 

      sb.Append(current); 
     } 

     current = timeSpan.ToMinutesString(); 

     if (!String.IsNullOrEmpty(current)) 
     { 
      if (sb.Length > 0) 
       sb.Append(" "); 

      sb.Append(current); 
     } 

     return sb.ToString(); 
    } 

    public static string ToDaysString(this TimeSpan timeSpan) 
    { 
     if (timeSpan == null) 
      throw new ArgumentNullException("timeSpan"); 

     int days = (int)timeSpan.TotalDays; 

     switch (days) 
     { 
      case 0: 
       return String.Empty; 
      case 1: 
       return "1 day"; 
      default: 
       return days + " days"; 
     } 
    } 

    public static string ToHoursString(this TimeSpan timeSpan) 
    { 
     if (timeSpan == null) 
      throw new ArgumentNullException("timeSpan"); 

     switch (timeSpan.Hours) 
     { 
      case 0: 
       return String.Empty; 
      case 1: 
       return "1 hour"; 
      default: 
       return timeSpan.Hours + " hours"; 
     } 
    } 

    public static string ToMinutesString(this TimeSpan timeSpan) 
    { 
     if (timeSpan == null) 
      throw new ArgumentNullException("timeSpan"); 

     switch (timeSpan.Minutes) 
     { 
      case 0: 
       return String.Empty; 
      case 1: 
       return "1 minute"; 
      default: 
       return timeSpan.Minutes + " minutes"; 
     } 
    } 
} 

也许这不是最优雅的解决方案,我认为这是可以做到特别是在ToDetailedString()功能有所改善,但它的作品精美绝伦。

+0

我现在也在使用我自己的方法,这需要Timespan在几分钟内作为输入...编辑以包含在我的问题中 – 2010-08-20 10:28:33

3

至少在.NET 3.5中没有任何内置的方式来满足您的需求。这是一个扩展TimeSpan以提供所需功能的类。

public static class TimeSpanEx 
{ 
    public static string FormattedString(this TimeSpan ts) 
    { 
     int days = (int)ts.TotalDays; 
     int hrs = (int)ts.Hours; 
     int mins = (int)ts.Minutes; 
     StringBuilder sb = new StringBuilder(); 

     if (days > 0) 
     { 
      sb.Append(days.ToString() + (days == 1 ? " day, " : " days, ")); 
     } 

     if (hrs > 0 || days > 0) 
     { 
      sb.Append(hrs.ToString() + (hrs == 1 ? " hour, " : " hours, ")); 
     } 

     sb.Append(mins.ToString() + (mins == 1 ? " min" : " mins")); 

     return sb.ToString(); 
    } 
}