How to format the HH:mm:ss separators of a TimeSpan in a culture-aware manner?
Asked Answered
A

3

10

I'm working on an app that may be seen in many countries in the world. There are not many countries that show hours, minutes and seconds with something other than : as a seperator but there are a few and I want to make sure that times are formatted correctly for their region. DateTime is great at this but TimeSpan isn't. These snippets are from my immediate Window in Visual Studio 2010 using .Net 4 with my region set to Malayalam (India). The dateTime.Now call also reflects how time is shown on my clock, Microsoft Outlook and other areas.

DateTime.Now.ToString()
"02-10-12 17.00.58"

http://msdn.microsoft.com/en-us/library/dd784379.aspx Says "If formatProvider is null, the DateTimeFormatInfo object that is associated with the current culture is used. If format is a custom format string, the formatProvider parameter is ignored." It stands to reason then that i shouldn't need to even pass in the Current CultureInfo. The format i want here is hh.mm.ss but obvioulsy hh:mm:ss when in most other languages, and if there are anoy other poossibilities, it should automatically reflect those too - basically TimeSpan should be culture-Aware, just as DateTime is.

However:

timeRemaining.ToString()
"00:02:09"
timeRemaining.ToString("c")
"00:02:09"
timeRemaining.ToString("c", CultureInfo.CurrentCulture)
"00:02:09"
timeRemaining.ToString("g")
"0:02:09"
timeRemaining.ToString("G")
"0:00:02:09.0000000"
timeRemaining.ToString("t")
"00:02:09"
timeRemaining.ToString("g", CultureInfo.CurrentCulture)
"0:02:09"
timeRemaining.ToString("g", CultureInfo.CurrentUICulture)
"0:02:09"
timeRemaining.ToString("G", CultureInfo.CurrentUICulture)
"0:00:02:09.0000000"
timeRemaining.ToString("G", CultureInfo.CurrentCulture)
"0:00:02:09.0000000"
timeRemaining.ToString("t", CultureInfo.CurrentCulture)
"00:02:09"

I'm looking for a simple, single line to output a timeSpan in a culture-Aware manner. Any ideas are appreciated.

Aspa answered 2/10, 2012 at 22:22 Comment(0)
C
8

Looks like a bug, you can report it at connect.microsoft.com. Meanwhile, a workaround is to take advantage of DateTime formatting. Like this:

using System;
using System.Globalization;

class Program {
    static void Main(string[] args) {
        var ci = CultureInfo.GetCultureInfo("ml-IN");
        System.Threading.Thread.CurrentThread.CurrentCulture = ci;
        var ts = new TimeSpan(0, 2, 9);
        var dt = new DateTime(Math.Abs(ts.Ticks));
        Console.WriteLine(dt.ToString("HH:mm:ss"));
        Console.ReadLine();
    }
}

Output:

00.02.09

Castilian answered 2/10, 2012 at 22:53 Comment(2)
But a much simpler workaround if you are going to use a format string is ts.ToString("h'.'mm'.'ss"). Works since .NET 4.0. This hard-codes the period of course. If you want to use the time separator of the culture, read it from CultureInfo.CurrentCulture.DateTimeFormat.TimeSeparator, put it inside apostrophes and use it together with h, mm and ss in a format string for the TimeSpan.Mcewen
Hard to see how that's "simpler". It certainly won't be accurate with such code ignoring the time format overrides that the user specified in Control Panel.Castilian
M
4

This is more like a comment, but needs some space, so I write it as an answer.

While string formatting of DateTime has been in .NET for a very long time, formatting of TimeSpan was new in .NET 4.0 (Visual Studio 2010).

A culture has a DateTimeFormatInfo object which is used by DateTime and includes info on whether to use colon : or period . or something else between hours, minutes and seconds. Now, TimeSpan does not seem to use this DateTimeFormatInfo object, and there is nothing called "TimeSpanFormatInfo".

Here's an example:

// we start from a non-read-only invariant culture
Thread.CurrentThread.CurrentCulture = new CultureInfo("");

// change time separator of DateTime format info of the culture
CultureInfo.CurrentCulture.DateTimeFormat.TimeSeparator = "<-->";

var dt = new DateTime(2013, 7, 8, 13, 14, 15);
Console.WriteLine(dt);  // writes "07/08/2013 13<-->14<-->15"

var ts = new TimeSpan(13, 14, 15);
Console.WriteLine(ts);  // writes "13:14:15"
Mcewen answered 8/7, 2013 at 10:40 Comment(0)
S
1

I'm looking for a simple, single line to output a timeSpan in a culture-Aware manner.

Then I think you're best off using the DateTime class to do the formatting for you:

string display = new DateTime(timespan.Ticks).ToLongTimeString();

Assuming that timespan holds a positive duration between 0 and 24 hours long.

Sidecar answered 30/1, 2015 at 14:7 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.