DateOnly.ParseExact incorrect parsing - c#

I believe there is a flaw in DateOnly.ParseExact. Refer following example. All the output dates should be same.
namespace IssueRep1
{
internal class Program
{
static void Main(string[] args)
{ string[] formats = { "dd/mm/yyyy" };
string format = formats[0];
string _strDate = "01/08/2014";
DateOnly _do1 = DateOnly.ParseExact(_strDate, formats);
DateOnly _do2 = DateOnly.ParseExact(_strDate, format);
Console.WriteLine($"{_strDate}, {_do1} {_do2}");
}
}
}
output
01/08/2014, 01-01-2014 01-01-2014
I expected all dates to be equal. August month is being converted to Jan. Can you please confirm if it is a bug or something is wrong with my understanding? How can I file a bug report in dotnet library?

What you should use is
string[] formats = { "dd/MM/yyyy" };
The format of month is MM not mm the lower case m is for minute and this is the datetime format reference

Related

User friendly date input

I have to code program, which will asks user about some data and then will print some text with this data.
Below is just piece of code (which works), there are others variables too.
class Student
{
static public DateTime birthDay;
public void GetStudentInformation()
{
Console.WriteLine("Enter student's birth date (as mm/dd/yyyy): ");
birthDay = DateTime.Parse(Console.ReadLine());
}
public void PrintStudentData(ref DateTime birthDay)
{
Console.WriteLine("Student was born in {0}", birthDay.ToString("d"));
}
}
class Program
{
static void Main(string[] args)
{
Student newStudent = new Student();
newStudent.GetStudentInformation();
newStudent.PrintStudentData(ref Student.birthDay);
Console.ReadKey()
}
}
When I'm asking about birthday I need only date, not exactly time.
There are questions:
How to change that input date by user would be in other format than mm/dd/yyyy?
How I would operate on output format date? So it wouldn't be yyyy-dd-mm but dd/mm/yyyy or dd.mm.yyyy?
I want to add I'm really beginner in C# and tried some code with CultureInfo, ParseExact, TryParse, and modyfing output string with {0:'dd/mm/yyyy'}.
Sounds like DateTime.TryParseExact is a good way to do it.
Converts the specified string representation of a date and time to its
DateTime equivalent using the specified format, culture-specific
format information, and style. The format of the string representation
must match the specified format exactly. The method returns a value
that indicates whether the conversion succeeded.
DateTime birthDay;
if(DateTime.TryParseExact(Console.ReadLine(), "MM/dd/yyyy",
CultureInfo.InvariantCulture,
DateTimeStyles.None, out birthDay)
{
// Your input string can (and will) be parsed with MM/dd/yyyy format.
}
else
{
// Invalid format or value.
}
By the way, I changed your mm to MM because mm specifier is for minutes but MM specifier is for months.
For your questions;
How to change that input date by user would be in other format than
mm/dd/yyy?
You can't. This might create a lot of ambiguous situations like what is the format of 01/02/2016? Is it dd/MM/yyyy or MM/dd/yyyy? This totally depends on where you live and which culture settings you use.
How I would operate on output format date? So it wouldn't be
yyyy-dd-mm but dd/mm/yyyy or dd.mm.yyyy?
With output, if you mean the Console.WriteLine part, this The "d" standard format specifier uses ShortDatePattern of your CurrentCulture settings where you run this code. That means the output format depends on the current culture settings. If this property has dd/MM/yyyy, you will be fine. If it is not, you should format it with customd date format specifiers like;
Console.WriteLine("Student was born in {0}",
birthDay.ToString("dd/MM/yyyy", CultureInfo.InvariantCulture));
This let user input in format day/month/year and output as dd.MM.yyyy
static void Main()
{
Student newStudent = new Student();
newStudent.GetStudentInformation();
newStudent.PrintStudentData(ref Student.birthDay);
Console.ReadKey();
logEnd();
}
class Student
{
static public DateTime birthDay;
public void GetStudentInformation()
{
Console.WriteLine("Enter student's birth date as day/month/year");
string[] formats = { "dd/MM/yyyy", "dd/M/yyyy", "d/M/yyyy", "d/MM/yyyy",
"dd/MM/yy", "dd/M/yy", "d/M/yy", "d/MM/yy"};
while (!DateTime.TryParseExact(Console.ReadLine(), formats,
System.Globalization.CultureInfo.InvariantCulture,
System.Globalization.DateTimeStyles.None,
out birthDay))
{
Console.WriteLine("Your input is incorrect. Please input again.");
}
// User input correct, birthDay can now be used
}
public void PrintStudentData(ref DateTime birthDay)
{
Console.WriteLine("Student was born in {0}", birthDay.ToString("dd.MM.yyyy"));
}
}

Format Exception Raises When Converting Simple Numeric String to Int in C#

I Had strange error when converting string in VS2015. When i use x variable, I got no error. Exception only raised when i used the date variable. Any Idea why???
Thanks
Code:
using System;
using System.Globalization;
namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
string x = "9-1-2015";
string date = "‎9‎-‎1-‎2015";
List<string> dt = date.Split('-').ToList();
List<int> lis = new List<int>();
foreach (var item in dt)
{
lis.Add(int.Parse(item));
}
}
}
}
As Jon Skeet has pointed out
Your date variable value contains non-printable characters, copy and paste your string into http://csharpindepth.com/Articles/General/Unicode.aspx#explorer
So you have to change the way it is generated or, if that's not possible/desired, remove them before you parse them to DateTime(which is what you actually want).
You can use this approach:
var unicodeCategories = new[] { UnicodeCategory.DecimalDigitNumber, UnicodeCategory.DashPunctuation };
string cleanDate = string.Concat(date.Where(c => unicodeCategories.Contains(char.GetUnicodeCategory(c))));
Now you can use DateTime.TryParseExact:
DateTime dt;
if (DateTime.TryParseExact(cleanDate, "d-M-yyyy", DateTimeFormatInfo.InvariantInfo, DateTimeStyles.None, out dt))
Console.WriteLine("Year:{0} Month:{1} Day:{2}", dt.Year, dt.Month, dt.Day);
else
Console.WriteLine("Could not be parsed to DateTime");
Output with your date: Year:2015 Month:1 Day:9
Thanks Tim Schmelter.
Yes indeed I need to clean my string var. Your code is very useful but it Doesn't work with my code. So I've modified the code to the below code. Then I Can parse the cleanDate var to DateTime Object.
string date = "9/28/2015 12:00:00 AM"; // In My Code, This Var Contain Unseen Unicode Char.
var cleanDate = new string(date.Where(c => char.IsNumber(c) || char.IsPunctuation(c) || char.IsWhiteSpace(c) || char.IsLetter(c)).ToArray());
DateTime date = DateTime.ParseExact(cleanDate, "M/d/yyyy hh:mm:ss tt", CultureInfo.InvariantCulture);
In your code, below line has some hidden spaces:
string date = "‎9‎-‎1-‎2015";
Try moving your cursor with keyboard arrows on this line and you will get my point.
Try deleting this line and Rewrite the code for this line manually (without copy paste) and it will work

Regarding DateTime Format "%h:%m:%s" allowing hour as "00"

I have a TextBox to enter time in the format "%h:%m:%s".
The allowed time inputs:
01:20:00
12:20:00
I am converting the string taken from TextBox using:
DateTime.TryParseExact("00:20:00", "%h:%m:%s",
culture, DateTimeStyles.None, out newData);
But above code converts hour 00 to 12 when providing the data through newData. I want to throw error in this case. Please provide your inputs.
It seems that you should try to parse to a TimeSpan instead of DateTime.
Use the following string.Format pattern to convert to a TimeSpan:
var pattern = #"hh\:mm\:ss";
see MSDN for more details: http://msdn.microsoft.com/en-us/library/ee372287(v=vs.110).aspx
UPDATED
Working Sample code:
namespace ConsoleApplication2
{
class Program
{
static void Main(string[] args)
{
DateTime newData;
TimeSpan newSpan;
DateTime.TryParseExact("00:20:00", "%h:%m:%s",
CultureInfo.DefaultThreadCurrentCulture, DateTimeStyles.None, out newData);
Console.WriteLine(newData);
// 8/5/2014 12:20:00 AM
TimeSpan.TryParseExact("00:20:00", #"hh\:mm\:ss",
CultureInfo.DefaultThreadCurrentCulture, TimeSpanStyles.None, out newSpan);
Console.WriteLine(newSpan);
// 00:20:00
Console.WriteLine(newSpan.Hours);
// 0
Console.WriteLine(newSpan.TotalHours);
// 0.33~
Console.ReadLine();
}
}
}
You should be using upper-case "H" for 24-hour time.

Replace an extra number from date

I have OCR extracted date string due to image quality second slash of date comes as 1,
i.e. date comes as 23/0212014 where 1 before year should be / actually. I have tried to replace 1 with regex but its not working.
DateTime.TryParseExact does not work and code i have tried is:
string mm = "23/0212014";
var rex = new Regex(#"(?:((\d{2}\/\d{2})1(\d{4})))");
mm = rex.Replace(mm, "");
How to convert it to proper date (dd/MM/yyyy)?
DateTime.TryParseExact works fine for me:
using System;
using System.Globalization;
class Test
{
static void Main()
{
string text = "23/0212014";
DateTime result;
if (DateTime.TryParseExact(text, "dd/MM'1'yyyy",
CultureInfo.InvariantCulture,
DateTimeStyles.None, out result))
{
Console.WriteLine(result);
}
else
{
Console.WriteLine("Failed to parse");
}
}
}
Output:
23/02/2014 00:00:00
(Once you've parsed it as a DateTime you can reformat it however you want, of course.)
I would definitely try to use this rather than regular expressions.

How to convert any type of date to dd/mm/yyyy

I receive text from a *.csv file in any date format
For example: dd/mm/yy or dd/mm/yyyy or mm/dd/yyyy or 4 may 2010......
How I can convert to just a single type of format: dd/mm/yyyy ?
I'm working on C#, .NET 3.5, WinForms
Thanks in advance
If you're receiving data in multiple formats and you can't identify them, you've got problems. What does "09/07/2010" mean? September 7th or July 9th? This is the first thing to get straight in your mind, and it has nothing to do with technology. You have two contradictory formats - how are you going to deal with them? Sample the file and pick whichever looks most likely? Treat each line separately, favouring one format over another? Ask the user?
Once you've parsed the data correctly, formatting it in the desired way is easy, as per John's answer. Note that you must use "MM" for the month, not "mm" which represents minutes. You should also specify which culture to use (affecting the date separators) assuming you don't just want to take the system default.
DateTime.Parse("your data").ToString("dd/MM/yyyy");
Check out TryParseExact.
public static string FormatDate(string input, string goalFormat, string[] formats)
{
var c = CultureInfo.CurrentCulture;
var s = DateTimeStyles.None;
var result = default(DateTime);
if (DateTime.TryParseExact(input, formats, c, s, out result))
return result.ToString(goalFormat);
throw new FormatException("Unhandled input format: " + input);
}
Example Usage
var formats - new[] { "dd/MM/yy", "dd/MM/yyyy" };
var next = csvReader.Get("DateField");
var formattedDate = FormatDate(next, "dd/MM/yyyy", formats);
using System;
using System.Collections.Generic;
using System.Text;
using System.Globalization;
namespace dateconvert
{
class Program
{
static void Main(string[] args)
{
DateTime x = Convert.ToDateTime("02/28/10");
Console.WriteLine(string.Format(x.ToString("d", DateTimeFormatInfo.InvariantInfo)));
DateTime y = Convert.ToDateTime("May 25, 2010");
Console.WriteLine(string.Format(y.ToString("d", DateTimeFormatInfo.InvariantInfo)));
DateTime z = Convert.ToDateTime("12 May 2010");
Console.WriteLine(string.Format(z.ToString("d", DateTimeFormatInfo.InvariantInfo)));
Console.Read();
}
}
}
String.Format("{0:MM/dd/yyyy}", DateTime.Now);
String.Format("{0:dd/MM/yyyy}", DateTime.Now);
etc.
Source: http://www.csharp-examples.net/string-format-datetime/
You simply want to be using the DateTime.ParseExact together with the DateTime.ToString methods.
The straight DateTime.Parse method has its uses of course, and can be clever for parsing dates that you know are in a specific culture/locale, but since it seems dates given to you may be in an arbitrary format that cannot be recognised, you may want to specifically use ParseExact.
Example:
var myDate = DateTime.ParseExact("07/14/2010", "MM/dd/yyyy",
CultureInfo.CurrentCulture);
var standardDateString = myDate.ToString("dd/MM/yyyy");

Categories