Respostas:
Observe: esta resposta é para .Net 4.0 e superior. Se você deseja formatar um TimeSpan em .Net 3.5 ou abaixo, consulte a resposta de JohannesH .
As seqüências de caracteres personalizadas no formato TimeSpan foram introduzidas no .Net 4.0. Você pode encontrar uma referência completa dos especificadores de formato disponíveis na página Strings de formato do MSDN Custom TimeSpan .
Aqui está um exemplo de sequência de formato de período de tempo:
string.Format("{0:hh\\:mm\\:ss}", myTimeSpan); //example output 15:36:15
( UPDATE ) e aqui está um exemplo usando a interpolação de string C # 6:
$"{myTimeSpan:hh\\:mm\\:ss}"; //example output 15:36:15
Você precisa escapar do caractere ":" com um "\" (que deve ser escapado, a menos que você esteja usando uma string literal).
Este trecho da página Strings de formato de tempo personalizado do MSDN explica como escapar do ":" e "." caracteres em uma sequência de formato:
Os especificadores de formato TimeSpan personalizados não incluem símbolos separadores de espaços reservados, como os símbolos que separam dias de horas, horas de minutos ou segundos de segundos fracionários. Em vez disso, esses símbolos devem ser incluídos na string de formato personalizado como literais de string. Por exemplo, "dd.hh: mm" define um ponto (.) Como o separador entre dias e horas e dois pontos (:) como o separador entre horas e minutos.
myTimeSpan = new TimeSpan(15, 35, 54);
instrução myTimeSpan .ToString("hh\\mm\\ss");
resultará 15m35s54
. Eu não acho que é isso que você pretendia, pois colocaria um m depois do seu horário e um s depois dos seus minutos.
$"{myTimeSpan.TotalHours}:{myTimeSpan:mm\\:ss}"
. Do ponto de vista do usuário, pode ser melhor exibir os dias, porém, ninguém quer descobrir mentalmente quantos dias existem em mais de 200 horas.
Para o .NET 3.5 e inferior, você pode usar:
string.Format ("{0:00}:{1:00}:{2:00}",
(int)myTimeSpan.TotalHours,
myTimeSpan.Minutes,
myTimeSpan.Seconds);
Código extraído de uma resposta Jon Skeet em bytes
Para o .NET 4.0 e superior, consulte a resposta DoctaJonez .
Uma maneira é criar um DateTime
objeto e usá-lo para formatar:
new DateTime(myTimeSpan.Ticks).ToString(myCustomFormat)
// or using String.Format:
String.Format("{0:HHmmss}", new DateTime(myTimeSpan.Ticks))
É assim que eu sei. Espero que alguém possa sugerir uma maneira melhor.
Simples. Use TimeSpan.ToString
com c, g ou G. Mais informações no MSDN
Eu iria com
myTimeSpan.ToString("hh\\:mm\\:ss");
Dim duration As New TimeSpan(1, 12, 23, 62)
DEBUG.WriteLine("Time of Travel: " + duration.ToString("dd\.hh\:mm\:ss"))
Funciona para o Framework 4
Pessoalmente, gosto desta abordagem:
TimeSpan ts = ...;
string.Format("{0:%d}d {0:%h}h {0:%m}m {0:%s}s", ts);
Você pode fazer isso da maneira que desejar, sem 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);
Você também pode ir com:
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:
Você também pode olhar para Strings.Format .
Dim ts As New TimeSpan(23, 30, 59)
Dim str As String = Strings.Format(New DateTime(ts.Ticks), "H:mm:ss")
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 os caracteres literais devem ser escapados.
Eu usei o código abaixo. É longo, mas ainda assim é uma expressão e produz uma saída muito amigável, pois não gera dias, horas, minutos ou segundos se tiverem valor zero.
Na amostra, produz saída: "4 dias 1 hora 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);
String timeComponent(int value, String name) { return value > 0 ? value + " " + name + (value > 1 ? "s" : ""); }
Chame isso para cada componente (por exemplo timeComponent(sp.Days, "day")
) e use String.join
para inserir os espaços.
Eu uso esse método Sou belga e falo holandês, portanto, o plural de horas e minutos não está apenas adicionando 's' ao final, mas quase uma palavra diferente de singular.
Pode parecer longo, mas é muito legível, eu acho:
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
Essa é a abordagem que eu usei com formatação condicional. e eu posto aqui porque acho que é uma maneira limpa.
$"{time.Days:#0:;;\\}{time.Hours:#0:;;\\}{time.Minutes:00:}{time.Seconds:00}"
exemplo de saídas:
00:00
(mínimo)
1:43:04
(quando temos horas)
15:03:01
(quando o horário tiver mais de 1 dígito)
2:4:22:04
(quando tivermos dias.)
A formatação é fácil. time.Days:#0:;;\\
o formato anterior ;;
é para quando o valor é positivo. valores negativos são ignorados. e para valores zero, temos ;;\\
para ocultá-lo em uma string formatada. observe que a barra invertida escapada é necessária, caso contrário, ela não será formatada corretamente.
Aqui está o meu método de extensão :
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));
}
Chamada de exemplo:
string time = new TimeSpan(3, 14, 15, 0, 65).ToFormattedString();
Resultado:
3 days, 14 hours, 15 minutes, 65 milliseconds
Isso é uma dor no VS 2010, aqui está minha solução 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;
}
}
}
O Substring
método funciona perfeitamente quando você deseja apenas Horas: Minutos: Segundos. É um código simples, limpo e fácil de entender.
var yourTimeSpan = DateTime.Now - DateTime.Now.AddMinutes(-2);
var formatted = yourTimeSpan.ToString().Substring(0,8);// 00:00:00
Console.WriteLine(formatted);
Aqui está a minha versão. Ele mostra apenas o necessário, lida com pluralização, negativos e tentei torná-lo leve.
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
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;
}
}
Se você deseja um formato de duração semelhante ao youtube, dado o número 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));
}
Resultado:
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
Eu queria retornar uma string como "1 dia, 2 horas e 3 minutos" e também levar em consideração se, por exemplo, dias ou minutos são 0 e depois não os mostramos. graças a John Rasch por sua resposta, que a minha é apenas uma extensão do
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 ");