Tech Off Thread

28 posts

Forum Read Only

This forum has been made read only by the site admins. No new threads or comments can be added.

C# Sting converstion

Back to Forum: Tech Off
  • User profile image
    the_corona

    peoples said:
    peoples said:
    *snip*

    Just one more question, I think if you call the datetime value you get a format like 11/12/2009, is it just a case of parseing out the "/" to make up the file name I want to use it as ?

     

    Thanks

    Its better to do something like

     

    string filename = string.format("d:\\logs\\{0}{1}{2}.log", myDate.Day, myDate.Month, myDate.Year);

     

    Date.ToString() looks different depending on the local of the user, so parsing out / wont work for instance for german versions of windows (+ its really ugly).

  • User profile image
    Sven Groot

    the_corona said:
    peoples said:
    *snip*

    Its better to do something like

     

    string filename = string.format("d:\\logs\\{0}{1}{2}.log", myDate.Day, myDate.Month, myDate.Year);

     

    Date.ToString() looks different depending on the local of the user, so parsing out / wont work for instance for german versions of windows (+ its really ugly).

    That's not necessary. If you want to be culture independent, just use the invariant culture:

     

    string filename = string.Format(CultureInfo.InvariantCulture, @"D:\logs\{0:ddMMyyyy}.log", myDate)

     

    This would have the same general effect as your code, without having to do manual date formatting.

  • User profile image
    the_corona

    Sven Groot said:
    the_corona said:
    *snip*

    That's not necessary. If you want to be culture independent, just use the invariant culture:

     

    string filename = string.Format(CultureInfo.InvariantCulture, @"D:\logs\{0:ddMMyyyy}.log", myDate)

     

    This would have the same general effect as your code, without having to do manual date formatting.

    ah, yes thats interesting, though I've never seen this before. I have to wonder though why you need to specify culturinvariant in that example given you very specifically ask for ddMMyyyy ?

     

    But come to think of it, Date.ToString I think also has an overload to do the formating the way you want, so even something like myDate.ToString("ddMMYYYY") - (I'm not sure of the exact syntax) - could get you a culture invariant string.

     

    Thinking about this more. does the {0:xx} in string.format end up as a string parameter to the first argument's ToString(string format)

    overload? So it ends up like

    string.format("{0:xx}", myDate) == string.format("{0}", myDate.ToString("xx"));

    Does this work in general or only with DateTime?

     

     

  • User profile image
    stevo_

    the_corona said:
    Sven Groot said:
    *snip*

    ah, yes thats interesting, though I've never seen this before. I have to wonder though why you need to specify culturinvariant in that example given you very specifically ask for ddMMyyyy ?

     

    But come to think of it, Date.ToString I think also has an overload to do the formating the way you want, so even something like myDate.ToString("ddMMYYYY") - (I'm not sure of the exact syntax) - could get you a culture invariant string.

     

    Thinking about this more. does the {0:xx} in string.format end up as a string parameter to the first argument's ToString(string format)

    overload? So it ends up like

    string.format("{0:xx}", myDate) == string.format("{0}", myDate.ToString("xx"));

    Does this work in general or only with DateTime?

     

     

    It works because the formatting system has an interface IFormattable which any type can implement, it specifies the type then must have a method ToString(string format, IFormatProvider formatProvider).

     

    The string 'format' would be the part after the colon in String.Format, and of course you can call it directly as in your example of myDate.ToString("ddMMYYYY") (which is actually an overload that doesn't require you to specify the format provider).

     

    The String.Format method works by scanning for the curly brace syntax, if it detects the colon then the following characters until the closing brace are considered the format, if the argument in question is IFormattable then it passes in the format with a format provider it either discovered itself or you provided in the Format call.

     

    If the type isn't formattable it simply calls ToString on it to get a string value.

     

    So if you want your type to have its own custom formatting like:

     

    string.Format("{0:omgbbq}", instanceofmytype).

     

    You simply need to implement IFormattable on your type and do the work to process what the format ('omgbbq' in this case) should mean.

     

    The format providers role is to allow 'outsiders' to specify their own formatter (ICustomFormatter) (albiet imo somewhat convolutedly).

     

    The concept when implementing is.. is a format provider was given, try and get a custom formatter from it, if you get one use that.. otherwise use your own built in formatting.

  • User profile image
    the_corona

    stevo_ said:
    the_corona said:
    *snip*

    It works because the formatting system has an interface IFormattable which any type can implement, it specifies the type then must have a method ToString(string format, IFormatProvider formatProvider).

     

    The string 'format' would be the part after the colon in String.Format, and of course you can call it directly as in your example of myDate.ToString("ddMMYYYY") (which is actually an overload that doesn't require you to specify the format provider).

     

    The String.Format method works by scanning for the curly brace syntax, if it detects the colon then the following characters until the closing brace are considered the format, if the argument in question is IFormattable then it passes in the format with a format provider it either discovered itself or you provided in the Format call.

     

    If the type isn't formattable it simply calls ToString on it to get a string value.

     

    So if you want your type to have its own custom formatting like:

     

    string.Format("{0:omgbbq}", instanceofmytype).

     

    You simply need to implement IFormattable on your type and do the work to process what the format ('omgbbq' in this case) should mean.

     

    The format providers role is to allow 'outsiders' to specify their own formatter (ICustomFormatter) (albiet imo somewhat convolutedly).

     

    The concept when implementing is.. is a format provider was given, try and get a custom formatter from it, if you get one use that.. otherwise use your own built in formatting.

    Awesome, thnx for the clear explanation. Learned something valuable today!

  • User profile image
    Sven Groot

    the_corona said:
    Sven Groot said:
    *snip*

    ah, yes thats interesting, though I've never seen this before. I have to wonder though why you need to specify culturinvariant in that example given you very specifically ask for ddMMyyyy ?

     

    But come to think of it, Date.ToString I think also has an overload to do the formating the way you want, so even something like myDate.ToString("ddMMYYYY") - (I'm not sure of the exact syntax) - could get you a culture invariant string.

     

    Thinking about this more. does the {0:xx} in string.format end up as a string parameter to the first argument's ToString(string format)

    overload? So it ends up like

    string.format("{0:xx}", myDate) == string.format("{0}", myDate.ToString("xx"));

    Does this work in general or only with DateTime?

     

     

    You need to specify InvariantCulture because even with a simple format like that it might have unexpected results if you use the current culture. For instance, the culture might not even use the western calendar!

     

    For example, if I do this:

    CultureInfo culture = new CultureInfo("ja-JP");
    // Japanese culture settings uses Western calendar by default; might not be true for all cultures though.
    culture.DateTimeFormat.Calendar = new JapaneseCalendar();
    Thread.CurrentThread.CurrentCulture = culture;
    
    string result = myDate.ToString("ddMMyyyy");

     

    In this case, I've changed the current culture to something that uses a different calendar. Now, if myDate is December 29th 2009, the string result will be "291221". Why? Because on the Japanese calendar, the current year is Heisei 21.

     

    It's easily imaginable that on some system, somewhere, the default culture will be set to something that doesn't produce the correct result even with the format string "ddMMyyyy". That's why you always specify the InvariantCulture if you need a specific result, even if you think it doesn't matter.

  • User profile image
    TommyCarlier

    Sven Groot said:
    the_corona said:
    *snip*

    You need to specify InvariantCulture because even with a simple format like that it might have unexpected results if you use the current culture. For instance, the culture might not even use the western calendar!

     

    For example, if I do this:

    CultureInfo culture = new CultureInfo("ja-JP");
    // Japanese culture settings uses Western calendar by default; might not be true for all cultures though.
    culture.DateTimeFormat.Calendar = new JapaneseCalendar();
    Thread.CurrentThread.CurrentCulture = culture;
    
    string result = myDate.ToString("ddMMyyyy");

     

    In this case, I've changed the current culture to something that uses a different calendar. Now, if myDate is December 29th 2009, the string result will be "291221". Why? Because on the Japanese calendar, the current year is Heisei 21.

     

    It's easily imaginable that on some system, somewhere, the default culture will be set to something that doesn't produce the correct result even with the format string "ddMMyyyy". That's why you always specify the InvariantCulture if you need a specific result, even if you think it doesn't matter.

    It's a pity that .NET doesn't make a distinction between "data strings" and "display strings". I mean, instead of ToString() you'd have ToDataString() which returns a culture-independent string of data, and ToDisplayString() which returns a culture-dependent string used for display purposes.

    In my own code, I've created some static classes with extension methods to convert values (int, long, DateTime, ...) to data strings and back. You can then write code like this:

    DateTime d = DateTime.Today;
    string s = d.ToDataString(); // s will be "2009-12-29"
    d = s.ToDateTime();

    It also knows about nullable values, so you can use s.ToDateTimeOrNull() or convert nullable DateTime to data string.

    You can find the code on CodePlex (in folder TC/src/TC.Core in the files ConvertXXX.cs).

  • User profile image
    W3bbo

    TommyCarlier said:
    Sven Groot said:
    *snip*

    It's a pity that .NET doesn't make a distinction between "data strings" and "display strings". I mean, instead of ToString() you'd have ToDataString() which returns a culture-independent string of data, and ToDisplayString() which returns a culture-dependent string used for display purposes.

    In my own code, I've created some static classes with extension methods to convert values (int, long, DateTime, ...) to data strings and back. You can then write code like this:

    DateTime d = DateTime.Today;
    string s = d.ToDataString(); // s will be "2009-12-29"
    d = s.ToDateTime();

    It also knows about nullable values, so you can use s.ToDateTimeOrNull() or convert nullable DateTime to data string.

    You can find the code on CodePlex (in folder TC/src/TC.Core in the files ConvertXXX.cs).

    Because ToDataString is essentially the same thing as serialisation, and there are dedicated classes for that. I'm happy with the current simplistic design and I don't feel it needs to be refactored any. If a class has a meaningful culture-specific string representation then always use the IFormatProvider overload.

  • User profile image
    figuerres

    TommyCarlier said:
    Sven Groot said:
    *snip*

    It's a pity that .NET doesn't make a distinction between "data strings" and "display strings". I mean, instead of ToString() you'd have ToDataString() which returns a culture-independent string of data, and ToDisplayString() which returns a culture-dependent string used for display purposes.

    In my own code, I've created some static classes with extension methods to convert values (int, long, DateTime, ...) to data strings and back. You can then write code like this:

    DateTime d = DateTime.Today;
    string s = d.ToDataString(); // s will be "2009-12-29"
    d = s.ToDateTime();

    It also knows about nullable values, so you can use s.ToDateTimeOrNull() or convert nullable DateTime to data string.

    You can find the code on CodePlex (in folder TC/src/TC.Core in the files ConvertXXX.cs).

    Tommy it can get even worse than that.....

     

    if you make a web service that passes a datetime to a client (or client to server) if the client and server are in different timezones the date and time will not be right!

    the soap dattime is just a date and time string with no timezone info.

    and .net make the date a "local" timezone based date.

     

    in some stuff i do i have to pass the datetime as a string to avoid some issues with that.

    i also have an app that has to convert date and time across timezones and has to show 2 date-time values for a given event.

    one is always eastern US time and the other can be anywhere... when i first set that up i had folks telling me it was wrong cuse they did not understand the nutty rules that some locales have for when to add or subtract time from UTC / zero.

  • User profile image
    the_corona

    Sven Groot said:
    the_corona said:
    *snip*

    You need to specify InvariantCulture because even with a simple format like that it might have unexpected results if you use the current culture. For instance, the culture might not even use the western calendar!

     

    For example, if I do this:

    CultureInfo culture = new CultureInfo("ja-JP");
    // Japanese culture settings uses Western calendar by default; might not be true for all cultures though.
    culture.DateTimeFormat.Calendar = new JapaneseCalendar();
    Thread.CurrentThread.CurrentCulture = culture;
    
    string result = myDate.ToString("ddMMyyyy");

     

    In this case, I've changed the current culture to something that uses a different calendar. Now, if myDate is December 29th 2009, the string result will be "291221". Why? Because on the Japanese calendar, the current year is Heisei 21.

     

    It's easily imaginable that on some system, somewhere, the default culture will be set to something that doesn't produce the correct result even with the format string "ddMMyyyy". That's why you always specify the InvariantCulture if you need a specific result, even if you think it doesn't matter.

    Ah, yes. AFAIK the thai system by default uses the buddist year, so 2009 is 2552.

     

    Quite confusing in fact when you're there Smiley

     

    Thread.CurrentThread.CurrentCulture = new CultureInfo("th-th");
    Console.WriteLine(DateTime.Now);

     

    Result: 29/12/2552 16:37:51

Conversation locked

This conversation has been locked by the site admins. No new comments can be made.