How to get the culture of an IFormatProvider - c#

i am converting strings to values using a culture specified to me as a IFormatProvider.
i am trying to figure out which culture they gave me.
i realize that IFormatProvider doesn't necessarily have to correspond to a System.Globalization.Culture, but it did.
So how can i get its name?

The CultureInfo class implements IFormatProvider so you may try casting:
IFormatProvider provider = ...
CultureInfo ci = provider as CultureInfo;
if (ci != null)
{
string name = ci.DisplayName;
...
}

Related

LongTimeString has deprecated? C# IValueConverter

I'm working on Universal Store app. I've made this converter:
public object Convert(object value, Type targetType, object parameter, string language)
{
string stringDate = (string)value;
IFormatProvider culture = new CultureInfo( language );
DateTime date = DateTime.Parse(stringDate, culture);
return date.LongTimeString();
}
but Method LongTimeString is not recognized. This method is deprecated? Any solution? Thanks
DateTime doesn't have a method as LongTimeString. I think you looking for ToLongTimeString method.
return date.ToLongTimeString();
Mabe you are mixing this method with LongTimePattern property of DateTimeFormatInfo.
It's not deprecated, just not part of the WinRT API.
The solution is something like
return date.ToString("D");
But I'm not sure what exactly is supported.

CultureInfo on DateTime.ParseExact?

I don't understand Why there is an overload with IFormatProvider in DateTime.ParseExact ?
If I'm defining exactly how it should be parsed ( spaces , separators etc) , then theres should be no problem :
All these 3 examples show the same result:
example 1
CultureInfo provider =CultureInfo.CreateSpecificCulture("en-US");
var t= DateTime.ParseExact("13-2-2013", "d-M-yyyy", provider, DateTimeStyles.None);
Console.WriteLine (t); //13/02/2013 00:00:00
example 2
CultureInfo provider =CultureInfo.CreateSpecificCulture("en-US");
var t= DateTime.ParseExact("13/2/2013", "d/M/yyyy", provider, DateTimeStyles.None);
Console.WriteLine (t); //13/02/2013 00:00:00
example 3
CultureInfo provider =CultureInfo.CreateSpecificCulture("en-US");
var t= DateTime.ParseExact("13###2###2013", "d###M###yyyy", provider, DateTimeStyles.None);
Console.WriteLine (t); //13/02/2013 00:00:00
So why do i need to provide provider If I'm explicitly defining the structure ?
There are still format specifiers that are culture dependant, like the time separator (:) and the date separator (/). Those doesn't match a specific character, but the separator specified in the culture.
Because:
The specified format can include localized names of weekdays and months.
The characters : and / in the format string do not represent literal characters but rather the separator as specified by the format provider (see the bottom of the table here).
I can mainly imagine a web application and maybe a form, where the client submits informations to the server. This form also contains a datepicker, and sends the selected date based on the specific culture. So if the website used in the USA, they send 13/2/2013, while from Germany you get 13.2.2013. So how you handle the date in your server side code?
You could use sometheing like this in ASP.NET MVC (thanks to Sergey, Get CultureInfo from current visitor and setting resources based on that?):
var userLanguages = Request.UserLanguages;
CultureInfo ci;
if (userLanguages.Count > 0)
{
try
{
ci = new CultureInfo(userlanguages[0]);
}
catch(CultureNotFoundException)
{
ci = CultureInfo.InvariantCulture;
}
}
else
{
ci = CultureInfo.InvariantCulture;
}
And then parse to datetime:
var t = DateTime.ParseExact(formDateString, "d/M/yyyy", ci, DateTimeStyles.None);

How to create CultureInfo instance using the full name or convert the full name to CultureInfo code?

Is there anyway to create an instance of cultureInfo object using the full displayname:
CultureInfo userCulture = new CultureInfo("Japanese (Japan)");
or convert the full displayname to culture code:
toCultureCode("Japanese (Japan)");
would return "ja-JP"
There's no builtin method to get a culture by it's english name, so you could write one:
public static CultureInfo getCultureByEnglishName(String englishName)
{
// create an array of CultureInfo to hold all the cultures found,
// these include the users local culture, and all the
// cultures installed with the .Net Framework
CultureInfo[] cultures = CultureInfo.GetCultures(CultureTypes.AllCultures & ~CultureTypes.NeutralCultures);
// get culture by it's english name
var culture = cultures.FirstOrDefault(c =>
c.EnglishName.Equals(englishName, StringComparison.InvariantCultureIgnoreCase));
return culture;
}
DEMO
The toCultureCode is ToString:
String name = "Japanese (Japan)";
CultureInfo japanCulture = getCultureByEnglishName(name);
Console.Write(japanCulture.ToString()); // -> "ja-JP"
You can use Linq
using System.Linq;
CultureInfo culture = CultureInfo.GetCultures(CultureTypes.AllCultures).FirstOrDefault(c => c.DisplayName == "Japanese (Japan)");

ASP.Net DateTime with CultureInfo

One general question:
Does the DateTime object stores the CultureInfo with it, or you need to use the Formatter to format the DateTime according to current culture ?
I have a class property that retuns a DateTime. Within that property I am setting the DateTime object with current culture information using CultureInfo object. Below is the code for class property I am using:
public DateTime PrintedQuoteDate {
get {
DateTime printQuoteDate = DateTime.Today;
// cInfo = CultureInfo object
return Convert.ToDateTime(printQuoteDate , cInfo);
}
}
So my question is when I will use the above property in my code, will it have the corrosponding culture information that I am setting in its get method, or I will have to use the same CONVERT code for formatting date time. The restriction here is that the Property should return only DateTime type.
Any idea, suggestions
DateTime does not store any Culture what so ever. In fact it does not even hold a reference to a TimeZone, all it knows is whether it is a UTC DateTime or not. This is handled by an internal enum.
You need to specify a format provider (every culture in itself is a format provider) when using the ToString method of a DateTime, otherwise it will use the culture (really the culture and not the UI Culture) of the current thread.
You can get a predifined culture by using the ISO country/locale codes like this:
var us = new CultureInfo("en-US");
var british = new CultureInfo("en-GB");
var danish = new CultureInfo("da");
As you can see for danish it is enough to specify the language since there are no other locales (to my knowledge).

How to remove DateTime.Parse dependency on System.Threading.Thread.CurrentThread.CurrentCulture

Consider the following code:
class Program
{
static void Main(string[] args)
{
try
{
System.Threading.Thread.CurrentThread.CurrentCulture = new CultureInfo("fo-FO");
var s = DateTime.MaxValue.ToString("yyyy-MM-ddTHH:mm:ssZ");
var d = DateTime.Parse(s, CultureInfo.InvariantCulture);
Console.WriteLine("Was able to parse with fo-FO");
}
catch (Exception e)
{
Console.WriteLine("Exception: {0}", e);
}
try
{
System.Threading.Thread.CurrentThread.CurrentCulture = new CultureInfo("en-US");
var s = DateTime.MaxValue.ToString("yyyy-MM-ddTHH:mm:ssZ");
var d = DateTime.Parse(s, CultureInfo.InvariantCulture);
Console.WriteLine("Was able to parse with en-US");
}
catch (Exception e)
{
Console.WriteLine("Exception: {0}", e);
}
}
}
The output is:
Exception: System.FormatException: String was not recognized as a valid DateTime.
at System.DateTimeParse.Parse(String s, DateTimeFormatInfo dtfi, DateTimeStyles styles)
at System.DateTime.Parse(String s, IFormatProvider provider)
at DateTimeTest2.Program.Main(String[] args) in C:\Projects\DateTimeTest2\DateTimeTest2\Program.cs:line 17
Was able to parse with en-US
This code fragment proves that DateTime.Parse uses Thread.CurrentThread.CurrentCulture regardless of the fact that the "InvariantCulture" is being passed in. I find this so unintuitive that I consider it a "bug".
Why do we have to pass in a CultureInfo if it is in fact ignored by DateTime.Parse in any case? Is there a way of calling DateTime.Parse in a way that is independent of the CurrentCulture?
This code fragment proves that DateTime.Parse uses Thread.CurrentThread.CurrentCulture regardless of the fact that the "InvariantCulture" is being passed in
I'm not sure how this example proves that. The strings passed to DateTime.Parse are different, so it's not completely surprising that different results ensue.
The first string has the time formatted as 23.59.59, which (apparently) InvariantCulture cannot parse; the second string has the time formatted as 23:59:59, which InvariantCulture can parse. What's the problem?
edit to add, since apparently it makes a difference, I am running with .NET 2.0 and the strings produced by fo-FO and en-US are respectively
9999-12-31T23.59.59Z
and
9999-12-31T23:59:59Z
from MSDN:
The invariant culture is
culture-insensitive. Your application
specifies the invariant culture by
name using an empty string ("") or by
its language identifier.
InvariantCulture retrieves an instance
of the invariant culture. It is
associated with the English language
but not with any country/region.
I could not find any reference to using the current thread's culture, as that would be counter-intuitive as you said.
You could (as a workaround) cache the current thread's culture, set it to a known good culture (en-US), perform your parsing, then set the thread's culture back to the old value.
CultureInfo ci = System.Threading.Thread.CurrentThread.CurrentCulture;
System.Threading.Thread.CurrentThread.CurrentCulture = new CultureInfo("en-US");
var s = DateTime.MaxValue.ToString("yyyy-MM-ddTHH:mm:ssZ");
var d = DateTime.Parse(s, CultureInfo.InvariantCulture);
System.Threading.Thread.CurrentThread.CurrentCulture = ci;
This will guarantee you know what culture is being used to parse the DateTime string and will not affect outside calling code because the culture is never changed from an outside perspective.
If you do not want to respect any timezones in the parsing you could use
var d = DateTime.Parse(s, CultureInfo.InvariantCulture, DateTimeStyles.RoundtripKind);
or
var d = DateTime.Parse(s, CultureInfo.InvariantCulture, DateTimeStyles.AdjustToUniversal);
Both parses use InvariantCulture, which is the actually a hard-coded reference to the 'en-US' culture (there may be casses where the InvariantCulture is not 'en-US' but I haven't come accross them).
Replace your use of InvariantCulture with new CultureInfo("en-US") and it will become obvious why the first parse doesn't work.
In addition to what AakashM wrote:
I tried running it in .NET 3.5 SP1. In the second case, I get a System.FormatException stating that the value of the DateTime is out of range.

Categories