number - ¿Cómo puedo String.Format un objeto TimeSpan con un formato personalizado en.NET?
string.format c# number (18)
Aquí está mi método de extensión :
public static string ToFormattedString(this TimeSpan ts)
{
const string separator = ", ";
if (ts.TotalMilliseconds < 1) { return "No time"; }
return string.Join(separator, new string[]
{
ts.Days > 0 ? ts.Days + (ts.Days > 1 ? " days" : " day") : null,
ts.Hours > 0 ? ts.Hours + (ts.Hours > 1 ? " hours" : " hour") : null,
ts.Minutes > 0 ? ts.Minutes + (ts.Minutes > 1 ? " minutes" : " minute") : null,
ts.Seconds > 0 ? ts.Seconds + (ts.Seconds > 1 ? " seconds" : " second") : null,
ts.Milliseconds > 0 ? ts.Milliseconds + (ts.Milliseconds > 1 ? " milliseconds" : " millisecond") : null,
}.Where(t => t != null));
}
Ejemplo de llamada:
string time = new TimeSpan(3, 14, 15, 0, 65).ToFormattedString();
Salida:
3 days, 14 hours, 15 minutes, 65 milliseconds
¿Cuál es la forma recomendada de formatear objetos TimeSpan
en una cadena con un formato personalizado?
Aquí está mi versión. Muestra solo todo lo que sea necesario, maneja la pluralización, los negativos, y traté de hacerlo liviano.
Ejemplos de salida
0 seconds
1.404 seconds
1 hour, 14.4 seconds
14 hours, 57 minutes, 22.473 seconds
1 day, 14 hours, 57 minutes, 22.475 seconds
Código
public static class TimeSpanExtensions
{
public static string ToReadableString(this TimeSpan timeSpan)
{
int days = (int)(timeSpan.Ticks / TimeSpan.TicksPerDay);
long subDayTicks = timeSpan.Ticks % TimeSpan.TicksPerDay;
bool isNegative = false;
if (timeSpan.Ticks < 0L)
{
isNegative = true;
days = -days;
subDayTicks = -subDayTicks;
}
int hours = (int)((subDayTicks / TimeSpan.TicksPerHour) % 24L);
int minutes = (int)((subDayTicks / TimeSpan.TicksPerMinute) % 60L);
int seconds = (int)((subDayTicks / TimeSpan.TicksPerSecond) % 60L);
int subSecondTicks = (int)(subDayTicks % TimeSpan.TicksPerSecond);
double fractionalSeconds = (double)subSecondTicks / TimeSpan.TicksPerSecond;
var parts = new List<string>(4);
if (days > 0)
parts.Add(string.Format("{0} day{1}", days, days == 1 ? null : "s"));
if (hours > 0)
parts.Add(string.Format("{0} hour{1}", hours, hours == 1 ? null : "s"));
if (minutes > 0)
parts.Add(string.Format("{0} minute{1}", minutes, minutes == 1 ? null : "s"));
if (fractionalSeconds.Equals(0D))
{
switch (seconds)
{
case 0:
// Only write "0 seconds" if we haven''t written anything at all.
if (parts.Count == 0)
parts.Add("0 seconds");
break;
case 1:
parts.Add("1 second");
break;
default:
parts.Add(seconds + " seconds");
break;
}
}
else
{
parts.Add(string.Format("{0}{1:.###} seconds", seconds, fractionalSeconds));
}
string resultString = string.Join(", ", parts);
return isNegative ? "(negative) " + resultString : resultString;
}
}
Este es el enfoque que usé yo mismo con el formato condicional. y lo publico aquí porque creo que esta es una manera limpia.
$"{time.Days:#0:;;//}{time.Hours:#0:;;//}{time.Minutes:00:}{time.Seconds:00}"
ejemplo de resultados:
00:00
(mínimo)
1:43:04
(cuando tenemos horas)
15:03:01
(cuando las horas son más de 1 dígito)
2:4:22:04
(cuando tenemos días).
El formateo es fácil. time.Days:#0:;;//
el formato anterior ;;
es para cuando el valor es positivo. los valores negativos son ignorados y para los valores cero tenemos ;;//
para ocultarlo en una cadena formateada. Tenga en cuenta que la barra invertida escapada es necesaria, de lo contrario no formateará correctamente.
Esto es asombroso:
string.Format("{0:00}:{1:00}:{2:00}",
(int)myTimeSpan.TotalHours,
myTimeSpan.Minutes,
myTimeSpan.Seconds);
Esto es un dolor en VS 2010, aquí está mi solución alternativa.
public string DurationString
{
get
{
if (this.Duration.TotalHours < 24)
return new DateTime(this.Duration.Ticks).ToString("HH:mm");
else //If duration is more than 24 hours
{
double totalminutes = this.Duration.TotalMinutes;
double hours = totalminutes / 60;
double minutes = this.Duration.TotalMinutes - (Math.Floor(hours) * 60);
string result = string.Format("{0}:{1}", Math.Floor(hours).ToString("00"), Math.Floor(minutes).ToString("00"));
return result;
}
}
}
Personalmente, me gusta este enfoque:
TimeSpan ts = ...;
string.Format("{0:%d}d {0:%h}h {0:%m}m {0:%s}s", ts);
Puede hacer esto tan personalizado como desee sin problemas:
string.Format("{0:%d}days {0:%h}hours {0:%m}min {0:%s}sec", ts);
string.Format("{0:%d}d {0:%h}h {0:%m}'' {0:%s}''''", ts);
Quería devolver una cadena como "1 día, 2 horas y 3 minutos" y también tener en cuenta si, por ejemplo, los días o minutos son 0 y luego no se muestran. gracias a John Rasch por su respuesta, que el mío es apenas una extensión de
TimeSpan timeLeft = New Timespan(0, 70, 0);
String.Format("{0}{1}{2}{3}{4}{5}",
Math.Floor(timeLeft.TotalDays) == 0 ? "" :
Math.Floor(timeLeft.TotalDays).ToString() + " ",
Math.Floor(timeLeft.TotalDays) == 0 ? "" : Math.Floor(timeLeft.TotalDays) == 1 ? "day " : "days ",
timeLeft.Hours == 0 ? "" : timeLeft.Hours.ToString() + " ",
timeLeft.Hours == 0 ? "" : timeLeft.Hours == 1 ? "hour " : "hours ",
timeLeft.Minutes == 0 ? "" : timeLeft.Minutes.ToString() + " ",
timeLeft.Minutes == 0 ? "" : timeLeft.Minutes == 1 ? "minute " : "minutes ");
Sencillo. Utilice TimeSpan.ToString
con c, go G. Obtenga más información en http://msdn.microsoft.com/en-us/library/ee372286.aspx
Si desea el formato de duración similar a youtube, dada la cantidad de segundos
int[] duration = { 0, 4, 40, 59, 60, 61, 400, 4000, 40000, 400000 };
foreach (int d in duration)
{
Console.WriteLine("{0, 6} -> {1, 10}", d, d > 59 ? TimeSpan.FromSeconds(d).ToString().TrimStart("00:".ToCharArray()) : string.Format("0:{0:00}", d));
}
Salida:
0 -> 0:00
4 -> 0:04
40 -> 0:40
59 -> 0:59
60 -> 1:00
61 -> 1:01
400 -> 6:40
4000 -> 1:06:40
40000 -> 11:06:40
400000 -> 4.15:06:40
También puedes ir con:
Dim ts As New TimeSpan(35, 21, 59, 59) ''(11, 22, 30, 30) ''
Dim TimeStr1 As String = String.Format("{0:c}", ts)
Dim TimeStr2 As String = New Date(ts.Ticks).ToString("dd.HH:mm:ss")
EDITAR:
También puedes mirar Strings.Format .
Dim ts As New TimeSpan(23, 30, 59)
Dim str As String = Strings.Format(New DateTime(ts.Ticks), "H:mm:ss")
Una forma es crear un objeto DateTime
y usarlo para formatear:
new DateTime(myTimeSpan.Ticks).ToString(myCustomFormat)
// or using String.Format:
String.Format("{0:HHmmss}", new DateTime(myTimeSpan.Ticks))
Esta es la forma en que sé. Espero que alguien pueda sugerir una mejor manera.
Usé el código a continuación. Es largo, pero sigue siendo una expresión y produce resultados muy amigables, ya que no genera días, horas, minutos o segundos si tienen valor de cero.
En la muestra produce salida: "4 días, 1 hora y 3 segundos".
TimeSpan sp = new TimeSpan(4,1,0,3);
string.Format("{0}{1}{2}{3}",
sp.Days > 0 ? ( sp.Days > 1 ? sp.ToString(@"d/ /d/a/y/s/ "): sp.ToString(@"d/ /d/a/y/ ")):string.Empty,
sp.Hours > 0 ? (sp.Hours > 1 ? sp.ToString(@"h/ /h/o/u/r/s/ ") : sp.ToString(@"h/ /h/o/u/r/ ")):string.Empty,
sp.Minutes > 0 ? (sp.Minutes > 1 ? sp.ToString(@"m/ /m/i/n/u/t/e/s/ ") :sp.ToString(@"m/ /m/i/n/u/t/e/ ")):string.Empty,
sp.Seconds > 0 ? (sp.Seconds > 1 ? sp.ToString(@"s/ /s/e/c/o/n/d/s"): sp.ToString(@"s/ /s/e/c/o/n/d/s")):string.Empty);
Yo iría con
myTimeSpan.ToString("hh//:mm//:ss");
Yo uso este método Soy belga y hablo holandés, así que el plural de horas y minutos no es solo agregar ''s'' al final, sino casi una palabra diferente de singular.
Puede parecer largo, pero es muy legible, creo:
public static string SpanToReadableTime(TimeSpan span)
{
string[] values = new string[4]; //4 slots: days, hours, minutes, seconds
StringBuilder readableTime = new StringBuilder();
if (span.Days > 0)
{
if (span.Days == 1)
values[0] = span.Days.ToString() + " dag"; //day
else
values[0] = span.Days.ToString() + " dagen"; //days
readableTime.Append(values[0]);
readableTime.Append(", ");
}
else
values[0] = String.Empty;
if (span.Hours > 0)
{
if (span.Hours == 1)
values[1] = span.Hours.ToString() + " uur"; //hour
else
values[1] = span.Hours.ToString() + " uren"; //hours
readableTime.Append(values[1]);
readableTime.Append(", ");
}
else
values[1] = string.Empty;
if (span.Minutes > 0)
{
if (span.Minutes == 1)
values[2] = span.Minutes.ToString() + " minuut"; //minute
else
values[2] = span.Minutes.ToString() + " minuten"; //minutes
readableTime.Append(values[2]);
readableTime.Append(", ");
}
else
values[2] = string.Empty;
if (span.Seconds > 0)
{
if (span.Seconds == 1)
values[3] = span.Seconds.ToString() + " seconde"; //second
else
values[3] = span.Seconds.ToString() + " seconden"; //seconds
readableTime.Append(values[3]);
}
else
values[3] = string.Empty;
return readableTime.ToString();
}//end SpanToReadableTime
Tenga en cuenta: esta respuesta es para .Net 4.0 y superior. Si desea formatear un TimeSpan en .Net 3.5 o inferior, consulte la respuesta de JohannesH .
Las cadenas de formato TimeSpan personalizadas se introdujeron en .Net 4.0. Puede encontrar una referencia completa de los especificadores de formato disponibles en la página Cadenas de formato de TimeSpan personalizado de MSDN.
Aquí hay un ejemplo de cadena de formato de intervalo de tiempo:
string.Format("{0:hh//:mm//:ss}", myTimeSpan); //example output 15:36:15
( ACTUALIZACIÓN ) y aquí hay un ejemplo usando la interpolación de cadenas C # 6:
$"{myTimeSpan:hh//:mm//:ss}"; //example output 15:36:15
Necesita escapar del carácter ":" con una "/" (que a su vez debe escaparse a menos que esté usando una cadena literal).
Este extracto de la página de cadenas de formato de TimeSpan personalizado de MSDN explica cómo evitar ":" y "." Caracteres en una cadena de formato:
Los especificadores de formato TimeSpan personalizados no incluyen símbolos separadores de marcador de posición, como los símbolos que separan días de horas, horas de minutos o segundos de segundos fraccionarios. En cambio, estos símbolos se deben incluir en la cadena de formato personalizado como literales de cadena. Por ejemplo, "dd.hh: mm" define un período (.) Como el separador entre días y horas, y dos puntos (:) como el separador entre horas y minutos.
Dim duration As New TimeSpan(1, 12, 23, 62)
DEBUG.WriteLine("Time of Travel: " + duration.ToString("dd/.hh/:mm/:ss"))
Funciona para el Marco 4
if (timeSpan.TotalDays < 1)
return timeSpan.ToString(@"hh/:mm/:ss");
return timeSpan.TotalDays < 2
? timeSpan.ToString(@"d/ /d/a/y/ hh/:mm/:ss")
: timeSpan.ToString(@"d/ /d/a/y/s/ hh/:mm/:ss");
Todos los caracteres literales deben ser escapados.