137

I have a WP8 app, which will send the current time to a web service.

I get the datetime string by calling

DateTime.ToString("MM/dd/yyyy HH:mm:ss.fff")

For most users it works great and gives me the correct string like "09/10/2013 04:04:31.415". But for some user the resulted string is something like "09/14/2013 07.20.31.371", which causes problem in my web service.

Is it because some culture format issue? How can I make sure the result string is delimited by colon instead of dot?

Max
  • 786
  • 1
  • 7
  • 24
Eldorado
  • 1,433
  • 2
  • 10
  • 6

6 Answers6

254

Is it because some culture format issue?

Yes. Your user must be in a culture where the time separator is a dot. Both ":" and "/" are interpreted in a culture-sensitive way in custom date and time formats.

How can I make sure the result string is delimited by colon instead of dot?

I'd suggest specifying CultureInfo.InvariantCulture:

string text = dateTime.ToString("MM/dd/yyyy HH:mm:ss.fff",
                                CultureInfo.InvariantCulture);

Alternatively, you could just quote the time and date separators:

string text = dateTime.ToString("MM'/'dd'/'yyyy HH':'mm':'ss.fff");

... but that will give you "interesting" results that you probably don't expect if you get users running in a culture where the default calendar system isn't the Gregorian calendar. For example, take the following code:

using System;
using System.Globalization;
using System.Threading;

class Test
{
    static void Main()        
    {
        DateTime now = DateTime.Now;
        CultureInfo culture = new CultureInfo("ar-SA"); // Saudi Arabia
        Thread.CurrentThread.CurrentCulture = culture;
        Console.WriteLine(now.ToString("yyyy-MM-ddTHH:mm:ss.fff"));
    }
} 

That produces output (on September 18th 2013) of:

11/12/1434 15:04:31.750

My guess is that your web service would be surprised by that!

I'd actually suggest not only using the invariant culture, but also changing to an ISO-8601 date format:

string text = dateTime.ToString("yyyy-MM-ddTHH:mm:ss.fff", CultureInfo.InvariantCulture);

This is a more globally-accepted format - it's also sortable, and makes the month and day order obvious. (Whereas 06/07/2013 could be interpreted as June 7th or July 6th depending on the reader's culture.)

Jon Skeet
  • 1,261,211
  • 792
  • 8,724
  • 8,929
  • thanks Jon. I thought the result string would be exactly like the format string. I will try your suggestion. – Eldorado Sep 18 '13 at 14:03
  • 3
    Just one small consideration. When loading a CultureInfo object from a specific code I always suggest to set the `useUserOverride` parameter to false, otherwise some user settings can override the culture settings. For example in your case I suggest to use new `CultureInfo("ar-SA", false)`. – Davide Icardi Oct 29 '13 at 11:44
  • @DavideIcardi: Interesting, thanks - although in this case the purpose of using Saudi Arabia was specifically to say why using the invariant culture is probably right. Will bear that in mind for future posts though. – Jon Skeet Oct 29 '13 at 11:50
  • 7
    Halfway trough this extensive answer, I started wondering: would this be Jon again? Yep. – Grimace of Despair Nov 25 '13 at 00:20
  • How to manage same with Html.TextBoxFor(x=>x.Date,"{0:MM/dd/yyyy}")? – VISHMAY Sep 01 '16 at 11:26
  • @VISHMAY: I'm afraid I don't know how to affect the culture used by `HtmlHelper`. – Jon Skeet Sep 01 '16 at 14:40
  • Shouldn't that last call `dateTime.ToString("yyyy-MM-ddTHH:mm:ss.fff");` also have `CultureInfo.InvariantCulture` passed in? – dbc Mar 08 '21 at 14:18
  • 1
    @dbc: Yup - fixed that now, thanks. – Jon Skeet Mar 08 '21 at 14:40
11

: has special meaning: it is The time separator. (Custom Date and Time Format Strings).

Use \ to escape it:

DateTime.ToString(@"MM/dd/yyyy HH\:mm\:ss.fff")

Or use CultureInfo.InvariantCulture:

DateTime.ToString("MM/dd/yyyy HH:mm:ss.fff", CultureInfo.InvariantCulture)

I would suggest going with the second one, because / has special meaning as well (it is The date separator.), so you can have problems with that too.

MarcinJuraszek
  • 118,129
  • 14
  • 170
  • 241
8

You can use InvariantCulture because your user must be in a culture that uses a dot instead of a colon:

DateTime.ToString("MM/dd/yyyy HH:mm:ss.fff", CultureInfo.InvariantCulture);
Jon La Marr
  • 898
  • 9
  • 14
7

I bumped into this problem lately with Windows 10 from another direction, and found the answer from @JonSkeet very helpful in solving my problem.

I also did som further research with a test form and found that when the the current culture was set to "no" or "nb-NO" at runtime (Thread.CurrentThread.CurrentCulture = new CultureInfo("no");), the ToString("yyyy-MM-dd HH:mm:ss") call responded differently in Windows 7 and Windows 10. It returned what I expected in Windows 7 and HH.mm.ss in Windows 10!

I think this is a bit scary! Since I believed that a culture was a culture in any Windows version at least.

Community
  • 1
  • 1
Håkon Seljåsen
  • 511
  • 5
  • 16
  • I would be quite curious to find out what really causes this. – Lauri Peltonen Apr 20 '16 at 06:12
  • 2
    It has been recognized and fixed as a Windows 10 locaization Bug. So a windows update on the client machine will fix the issue. More details are available in this blog post: http://www.heikniemi.net/hardcoded/2015/08/windows-10-breaks-net-date-parsing-in-certain-locales/ – Håkon Seljåsen Apr 21 '16 at 08:39
  • The blog of Jouni Heikniemi, which I linked to above seems to be broken. Relevant windows updates where the issues have been fixed were listed there: 2015-10-09: KB3093266 – Windows 10 KB3088956 – Windows Server 2012 R2 and Windows 8.1 KB3088955 – Windows Server 2012 and Windows 8 KB3088957 – Windows 7 SP1, Windows Server 2008 SP2, Windows Server 2008 R2 SP1, and Windows Vista SP2 Trying to link to the blog again, this time though archive.org: http://web.archive.org/web/20161030193739/http://www.heikniemi.net/hardcoded/2015/08/windows-10-breaks-net-date-parsing-in-certain-locales/ – Håkon Seljåsen Jan 20 '17 at 10:39
4

You can use String.Format:

DateTime d = DateTime.Now;
string str = String.Format("{0:00}/{1:00}/{2:0000} {3:00}:{4:00}:{5:00}.{6:000}", d.Month, d.Day, d.Year, d.Hour, d.Minute, d.Second, d.Millisecond);
// I got this result: "02/23/2015 16:42:38.234"
Cosmin
  • 2,192
  • 2
  • 20
  • 21
0

Convert Date To String

Use name Space

using System.Globalization;

Code

string date = DateTime.ParseExact(datetext.Text, "dd-MM-yyyy", CultureInfo.InstalledUICulture).ToString("yyyy-MM-dd");
Cœur
  • 32,421
  • 21
  • 173
  • 232
Hafsal
  • 7
  • 2