Datetime value with different culture not formatting correctly - c#

I'm having a slight issue with Thread culture and getting a date to display properly.
I am overloading the ToString() method of the DateTime class.
With culture "en-CA", my date is coming out in the right format "yyyy/MM/dd"
but with culture "fr-CA", my date is coming out "yyyy-MM-dd"
I've made some unit test to display the issue.
The english test works but the french always fails.
Even if I change the GetDateInStringMethod to do .ToShortDateString. I still get the same issue.
[Test()]
public void ValidInEnglish()
{
Thread.CurrentThread.CurrentCulture = new CultureInfo("en-CA");
Thread.CurrentThread.CurrentCulture.DateTimeFormat.ShortDatePattern = Utility.DatePattern;
DateTime? currentDate = new DateTime(2009,02,7);
string expected = "2009/02/07";
string actual = DateUtils.GetDateInString(currentDate);
//This works
Assert.AreEqual(expected, actual);
}
[Test()]
public void ValidInFrench()
{
Thread.CurrentThread.CurrentCulture = new CultureInfo("fr-CA");
Thread.CurrentThread.CurrentCulture.DateTimeFormat.ShortDatePattern = Utility.DatePattern;
DateTime? currentDate = new DateTime(2009, 02, 7);
string expected = "2009/02/07";
string actual = DateUtils.GetDateInString(currentDate);
// This doesn't work
Assert.AreEqual(expected, actual);
}
public static string GetDateInString(DateTime? obj)
{
if (obj == null || !obj.HasValue)
{
return string.Empty;
}
return obj.Value.ToString(Utility.DatePattern);
}
public const string DatePattern = "yyyy/MM/dd";

Change this line:
return obj.Value.ToString(Utility.DatePattern);
to this:
return obj.Value.ToString(Utility.DatePattern, CultureInfo.InvariantCulture);
Read about it here: System.Globalization.InvariantCulture

That doesn't work because using french culture defaults the datetime formatter to use - instead of / as a separator character. If you want to keep your date the same no matter the culture then use CultureInfo.InvariantCulture if you want to use the french formatting the change your expected test result to "2009-02-07". If you are looking for more info check this msdn link.
And if you want a personal recommendation for a lib to use for dealing with the awesomeness that is Globalization then I'd recommend Noda Time.

Related

Why is NUnit Framework throwing DateTime AssertionException?

I'm trying to format a DateTime, but not change the property to a type of string.
My property is as follows DateTime DateApplicationReceived = FormatDateTime();
I have made a small function to do so which allows me to parse my string into a type of DateTime.
private static DateTime FormatDateTime()
{
var format = DateTime.UtcNow.ToString("G");
var dateTime = DateTime.Parse(format);
return dateTime;
}
Let's say the date & time is now: 16/01/2019 15:30:00. I use NUnit to test that my function works by doing the following assert:
public void ConvertsTime()
{
var sut = DateApplicationReceived;
Assert.That(sut, Is.EqualTo("16/01/2019 15:30:00"));
}
My test fails. The expected result ignores the format (of "G") and displays it to a different culture 2019-01/16.
Debug info:
Why does it do this? I'm explicity giving it a format & changing the culture variant doesn't seem to have any effect.
The DateTime object has no format.
So your code here is useless:
var format = DateTime.UtcNow.ToString("G");
var dateTime = DateTime.Parse(format);
This is fully equivalent to
var dateTime = DateTime.UtcNow;
In your unit test, you should compare either a DateTime with a DateTime, or a string with a string. Currently, you are comparing a DateTime with a string.
So you should change your code to:
Assert.That(sut.ToString("G"), Is.EqualTo("16/01/2019 15:30:00"));
or
Assert.That(sut, Is.EqualTo(DateTime.Parse("16/01/2019 15:30:00")));

c# unit test datetime against string

I am doing a unit test for datetime and it fails because Test Name:
GetDateTime2 Result Message: Assert.AreEqual failed.
Expected:<28/05/2017 20:00:00 (System.String)>. Actual:<28/05/2017
20:00:00 (System.DateTime)>.
Is there any way of comparing the string against the datetime of do i have to change the properties of string date and string time?
public void GetDateTime()
{
FootballEvent football = new FootballEvent();
football.Time = "20:00:00";
football.Date = "28/05/2017";
var footballtime = football.GetDateTime();
var expected = "28/05/2017 20:00:00";
Assert.AreEqual(expected, footballtime);
}
as some people have stated within the comments why not just make a DateTime object then compare them?
Example:
var footballtime = football.GetDateTime();
var expected = "28/05/2017 20:00:00";
DateTime expectedDate = DateTime.Parse(expected);
Assert.AreEqual(expectedDate, footballtime);
You could call ToString() with whatever format you want your time to be in for comparison.
var expected = "28/05/2017 20:00:00";
//Use HH for 00-23, use H for 0-23, use hh for 01-12 and use h for 1-12
Assert.AreEqual(expected, footballtime.ToString("dd/MM/yyyy HH:mm:ss"));
However it seems like you should be comparing both in the proper format (DateTime).
Ask yourself why you are initializing the times via string (football.Time = "20:00:00";), why not use the proper data type for Dates and Times (DateTime)

How to get date only if time is 00:00:00 from DateTime c#

I want to convert DateTime object to string. What I want to achieve is following things:
Get Date only out of it if Time is 00:00:00.
Get Date and Time if both are present.
I want to achieve this using CurrentCulture.DateTimeFormat and
Convert.ToString(DateTime, IFormatProvider), otherwise I know how
to do this using .ToString() Extension method.
I have tried following things:
Thread.CurrentPrincipal = principal;
CultureInfo culture = (CultureInfo)CultureInfo.CurrentCulture.Clone();
culture.DateTimeFormat.ShortDatePattern = MPAResource.DateFormat;
culture.DateTimeFormat.LongTimePattern = "hh:mm:ss tt";
culture.DateTimeFormat.ShortTimePattern = "hh:mm:ss tt";
culture.DateTimeFormat.FullDateTimePattern = MPAResource.DateTimeFormat;
Thread.CurrentThread.CurrentCulture = culture;
Then:
string x = Convert.ToString(x.ExpectedJoiningDate, CultureInfo.CurrentCulture);
Output is 09-Oct-2015 11:00 AM. I want 09-Oct-2015 11:00 AM if time is there and 09-Oct-2015 if time is not there.
But above line gives me only date even if time is present with date.
Seems to me like this is pretty straight forward:
var dt = x.ExpectedJoiningDate;
string x = (dt.TimeOfDay == TimeSpan.Zero)?dt.ToShortDateString():dt.ToString();
PS: you can use a culture as parameter in ToString if you like. See https://msdn.microsoft.com/en-us/library/aa326720(v=vs.71).aspx for details on how to do this.
Tim made the remark that the OP wants to use Convert.ToString. It doesn't compute, so I refuse. Why doesn't it compute? Here's the code for Convert.ToString:
public static string ToString(DateTime value, IFormatProvider provider)
{
return value.ToString(provider);
}
Yes people, that's basically the same.
That said, if you're stubborn, I guess you can implement IFormatProvider in your own little class, change the format provider based on the condition, then pass that instead of the default format provider. Then, congrats, you've created a lot of senseless code that gives the exact same results using Convert.ToString.
After a while a wrote method for myself.
public static string ConvertToMyDateTimeFormat(Nullable<DateTime> value, CultureInfo IFormateProvider)
{
if (value.HasValue)
{
if (value.Value.TimeOfDay.Ticks > 0)
{
return value.Value.ToString(IFormateProvider);
}
else
{
return value.Value.ToString(IFormateProvider.DateTimeFormat.ShortDatePattern);
}
}
else
{
return string.Empty;
}
}

String date time format

I am using the Vimeo API and I want to convert the string <upload_date> to a short date format, {0:d} or {0:dd/mm/yyyy}.
This is my code but it doesn't seem to be working for me.
select new VimeoVideo
{
Date = String.Format("{0:d}",(item.Element("upload_date").Value)),
};
return Vids.ToList();
}
public class VimeoVideo
{
public string Date { get; set; }
}
As Oleg suggested you can try to parse your value to DateTime and then format it (use try catch if needed). That should work (not 100% sure since I don't know what item's type is).
var myDate = DateTime.Parse(item.Element("upload_date").Value);
Date = String.Format("{0:d}", myDate);
http://msdn.microsoft.com/it-it/library/1k1skd40(v=VS.80).aspx
Just verify the type of the Value property.. The above string formatter works for System.DateTime structure.. I assume in your case its string type object. According to the given sample date time string i have written this code.. Try out this.
CultureInfo provider = CultureInfo.InvariantCulture;
var format = "yyyy-MM-dd HH:mm:ss";
var dt = DateTime.ParseExact(item.Element("upload_date").Value, format, provider);
Date = string.Format("{0:d}", dt);
Hope it works..

Set Default DateTime Format c#

Is there a way of setting or overriding the default DateTime format for an entire application. I am writing an app in C# .Net MVC 1.0 and use alot of generics and reflection. Would be much simpler if I could override the default DateTime.ToString() format to be "dd-MMM-yyyy". I do not want this format to change when the site is run on a different machine.
Edit -
Just to clarify I mean specifically calling the ToString, not some other extension function, this is because of the reflection / generated code. Would be easier to just change the ToString output.
The "default format" of a datetime is:
ShortDatePattern + ' ' + LongTimePattern
at least in the current mono implementation.
This is particularly painful in case you want to display something like 2001-02-03T04:05:06Z i.e. the date and time combined as specified in ISO 8606, but not a big problem in your case:
using System;
using System.Globalization;
using System.Threading;
namespace test {
public static class Program {
public static void Main() {
CultureInfo culture = (CultureInfo)CultureInfo.CurrentCulture.Clone();
culture.DateTimeFormat.ShortDatePattern = "dd-MMM-yyyy";
culture.DateTimeFormat.LongTimePattern = "";
Thread.CurrentThread.CurrentCulture = culture;
Console.WriteLine(DateTime.Now);
}
}
}
This will set the default behavior of ToString on datetimes to return the format you expect.
It is dependent on your application's localization-settings. Change that accordingly to get correct format.
Otherwise have a helper-class or an extension-method which always handles your DateTime.
public static string ToMyDateTime(this DateTime dateTime) {
return dateTime.ToString("dd-MMMM-yy");
}
DateTime.ToString() combines the custom format strings returned by the ShortDatePattern and LongTimePattern properties of the DateTimeFormatInfo. You can specify these patterns in DateTimeFormatInfo.CurrentInfo.
I've never tried this my self.
If you want to be sure that your culture stays the same, just set it yourself to avoid troubles.
System.Globalization.CultureInfo ci = new System.Globalization.CultureInfo("nl-BE");
System.Threading.Thread.CurrentThread.CurrentCulture = ci;
System.Threading.Thread.CurrentThread.CurrentUICulture = ci;
The above example sets the culture of the thread to Belgian-Dutch.
CurrentCulture does all the date and time handling and CurrentUICulture handles UI localization like resources.
I'm not sure if this would work for a web app, but you could try to set the DateTimeFormat property for the current culture.
Check this and specially this.
Using .Net 6 put something like this in your program.cs after app.UseAuthentication()/app.UseAuthorization() and before app.MapControllerRoute(...):
var ci = new CultureInfo("en-US");
ci.DateTimeFormat.ShortDatePattern = "MM/dd/yyyy";
app.UseRequestLocalization(new RequestLocalizationOptions
{
DefaultRequestCulture = new Microsoft.AspNetCore.Localization.RequestCulture(ci),
SupportedCultures = new List<CultureInfo> { ci },
SupportedUICultures = new List<CultureInfo> { ci }
});
Here I'm changing the short date format, but you can also change currency symbol, decimal separator, etc.
You can write an ExtensionMethod like this:
public static string ToMyString(this DateTime dateTime)
{
return dateTime.ToString("needed format");
}

Categories

Resources