How to parse a date with spaces? - c#

I have this date: " 1 21998", which is Feb, 1st 1998. It's a little bit malformed as there should be zeros instead of spaces, but it's in some text files I have to process. I don't know how to parse it with C#. Could anyone give me a clue?
I've tried the following but get no result:
DateTime date;
string input = " 1 21998";
if (DateTime.TryParseExact(input, "ddMMyyyy", System.Globalization.CultureInfo.InvariantCulture, System.Globalization.DateTimeStyles.None, out date))
{
Console.WriteLine("1: " + date);
}
else if (DateTime.TryParseExact(input, "ddMMyyyy", System.Globalization.CultureInfo.InvariantCulture, System.Globalization.DateTimeStyles.AllowWhiteSpaces, out date))
{
Console.WriteLine("2: " + date);
}
else if (DateTime.TryParseExact(input, "dMyyyy", System.Globalization.CultureInfo.InvariantCulture, System.Globalization.DateTimeStyles.None, out date))
{
Console.WriteLine("3: " + date);
}
else if (DateTime.TryParseExact(input, "dMyyyy", System.Globalization.CultureInfo.InvariantCulture, System.Globalization.DateTimeStyles.AllowWhiteSpaces, out date))
{
Console.WriteLine("4: " + date);
}
else if (DateTime.TryParseExact(input, " d Myyyy", System.Globalization.CultureInfo.InvariantCulture, System.Globalization.DateTimeStyles.None, out date))
{
Console.WriteLine("5: " + date);
}
else if (DateTime.TryParseExact(input, " d Myyyy", System.Globalization.CultureInfo.InvariantCulture, System.Globalization.DateTimeStyles.AllowWhiteSpaces, out date))
{
Console.WriteLine("6: " + date);
}
if (DateTime.TryParse(input, out date))
{
Console.WriteLine("7: " + date);
}
else if (DateTime.TryParse(input, System.Globalization.CultureInfo.InvariantCulture, System.Globalization.DateTimeStyles.AllowWhiteSpaces, out date))
{
Console.WriteLine("8: " + date);
}

The pattern " d Myyyy" is correct for the input " 1 21998"; it's just that the parser throws its hands in the air for a variable-length concatenation.
I haven't looked at the source, but I guess the parser first tries to break up the string into individual components matching the pattern, before trying to parse the actual values.
So the parser wouldn't know whether the first one or the first two digits of your five-digit string "21998" belong to the month, even though there is no 21st month and you specified that the year will have four digits.
It works if you prepend a zero or one to the month:
" 1 021998" -> 02/01/1998
" 1 121998" -> 12/01/1998
The docs say, under "Remarks":
If format is a custom format pattern that does not include date or time separators (such as "yyyyMMddHHmm"), use the invariant culture for the provider parameter and the widest form of each custom format specifier. For example, if you want to specify hours in the format pattern, specify the wider form, "HH", instead of the narrower form, "H".
Not sure what that is about, but " dd MMyyyy" nor "ddMMyyyy" work for the original input. I guess they meant that you should write dates using their widest forms when not writing separators.
The problem isn't the spaces; it's lack thereof. These work:
"dMyyyy", " 1 2 1998" (with DateTimeStyles.AllowWhiteSpaces)
"ddMMyyyy", "01021998" (with DateTimeStyles.None)
" dd MM yyyy", " 01 02 1998" (with DateTimeStyles.None)
Given your input is fixed-length, the pattern will break again if the month is > 9 (" 1102021" won't parse either for the same reasons as before).
The easiest solution would be to parse it manually by breaking up the strings, parsing them as ints and passing them to a new DateTime(year, month, day).
var day = int.Parse(input[0..2], NumberStyles.AllowLeadingWhite);
var month = int.Parse(input[2..4], NumberStyles.AllowLeadingWhite);
var year = int.Parse(input[4..8], NumberStyles.AllowLeadingWhite);
var date = new DateTime(year, month, day);

Can you not turn all the spaces in the input into 0's and then it should be a valid date format?
input.Replace(" ", "0");
Might also want to put /'s after the 2nd and 4th index too.
input.Insert(2, "/");

Related

C# TryParseExact returns the same date for everything

I have dates that come in in this funky format, I thought I was converting them correctly via this code:
String theDate = "2212017";
DateTime date;
DateTime.TryParseExact(theDate.PadLeft(8, '0'), "MMddyyyy", System.Globalization.CultureInfo.InvariantCulture, System.Globalization.DateTimeStyles.None, out date);
MessageBox.Show("TheDate: " + theDate + " output: " + date);
Alas it always gives a date of:
1/1/0001 12:00:00 AM
For any of my funky dates:
5162018
5202020
2212017
1202019
Am I just printing it out wrong or is the TryParseExact not working like I think it should.
Parse exact needs the right number of digits, and your days value is missing leading zeros. Pad it out.
Try
DateTime.TryParseExact
(
theDate.PadLeft(8,'0'),
"ddMMyyyy",
System.Globalization.CultureInfo.InvariantCulture,
System.Globalization.DateTimeStyles.None,
out date
);

Failing to parse date in yyyyMMdd Hmm format using DateTime.TryParseExact()

I am getting my date time in a format like "20170317 630"
which means 17 March 2017 6:30 am
Here is the code block I am trying, but it is failing.
var str = "20170317 0630";
var formatedTime = "yyyyMMdd Hmm";
DateTime etaDate;
if (!DateTime.TryParseExact(str,formatedTime, CultureInfo.InvariantCulture, DateTimeStyles.None, out etaDate)) //formatedTime, CultureInfo.InvariantCulture, DateTimeStyles.None
{
Console.WriteLine("Date conversion failed " + etaDate);
}
Console.WriteLine("Date conversion passed "+etaDate);
Passing for: 20170317 0630
Failing for: 20170317 630
Please help me with this.
I'm not entirely surprised it's failing to parse that - I suspect it's greedily parsing the "63" and deeming that to be an invalid hour number.
We have exactly the same problem in Noda Time - and I don't intend to fix it. Making this work would be a huge amount of effort, and quite possibly reduce the performance for more sensible formats.
I would strongly suggest moving to a more sensible format, e.g. one of
H:mm to remove the pseudo-ambiguity
HHmm to make it all clearer
HH:mm even better, IMO - preferrably with hyphens for date parts, so yyyy-MM-dd HH:mm
You can convert from one format to another by simply detecting the length of the string, as every other part of it is a fixed length. For example, to just move to using HHmm you can do:
if (str.Length == "yyyyMMdd Hmm".Length)
{
str = str.Insert("yyyyMMdd ".Length, "0");
}
Then parse with yyyyMMdd HHmm format. If the length isn't right for either valid width, then it will fail to parse later anyway.
//split str in to strDate and strTime by using space
var strDate = "20170317"; //Date part
var strTime ="630"; //Time part
if(strTime.Length ==3) //check lenght of time part
{
strTime = "0" + strTime; //Add extra zero
}
var formatedTime = "yyyyMMdd HHmm";
DateTime etaDate;
if (!DateTime.TryParseExact(strDate + strTime,formatedTime, CultureInfo.InvariantCulture, DateTimeStyles.None, out etaDate)) //formatedTime, CultureInfo.InvariantCulture, DateTimeStyles.None
{
Console.WriteLine("Date conversion failed " + etaDate);
}
Console.WriteLine("Date conversion passed "+etaDate);

DateTime.TryParseExact constantly returns false

I have the following code which takes the element in the lines array and checks if it matches the datetime format. This check only runs on elements 37, 38, 40, 41. Given the following code and debugging print outs I can see that the output does match the parsing. Why does it return false then?
Possible Inputs:
05/03/2005 23:59:59.999
05/3/2005 23:59:59.999
5/03/2005 23:59:59.999
5/3/2005 23:59:59.999
etc...
Code:
lines[i] = lines[i] + " 23:59:59.999"; //YYYY-MM-DDThh:mm:ss[.mmm]
DateTime datetest;
if (DateTime.TryParseExact(lines[i], "MM/dd/yyyy HH:mm:ss.mmm", new CultureInfo("en-US"), DateTimeStyles.None, out datetest))
{
}
else
{
//Log and Drop
logfile.WriteLine(System.DateTime.Now.ToString("yyyy.MM.dd.HH.mm.ss") + ": Row #" + row + ", Column #" + (i) + " was not a date in the right format, dropping line. ");
logfile.WriteLine("Original: " + lines[i]);
Console.WriteLine("Date Wrong");
Console.WriteLine("Date: " + lines[i]);
string input = Console.ReadLine();
continue;
}
Console Output:
Date Wrong
Date: 5/23/2004 23:59:59.999
UPDATE:
I tried changing the parse to look for M/dd/yyyy instead. However I now get this output instead.
Date Wrong
Date: 05/23/2005 23:59:59.999
UPDATE 2:
Ok I tried changing the parse to look for "M/d/yyyy HH:mm:ss.fff" as many suggested. The output I get now is:
Date Wrong
Date: 23.59.59.999
UPDATE 3:
Ok I have now tried "M/d/y H:m:s.fff" as suggested and I am still getting output as:
Date Wrong
Date: 05/23/2005 23:59:59.999
Note: Answer based on original revision of the question before it started morphing.
Why does it return false then?
The MM format requires two digits for the month. Your date string only has one digit. Use the M month format. The milliseconds format string should be fff rather than mmm.
The following format string will parse your input
M/dd/yyyy HH:mm:ss.fff
To demonstrate:
DateTime datetest;
Console.WriteLine(DateTime.TryParseExact("5/23/2004 23:59:59.999",
"M/dd/yyyy HH:mm:ss.fff", new CultureInfo("en-US"), DateTimeStyles.None,
out datetest));
which outputs
True
If you wish to allow for single digit months then you need d instead of dd. In order for you to proceed much further, you will need to work out exactly what format of dates you wish to support.
You have the wrong datetime format that you try to parse to. Change it to: "M/dd/yyyy HH:mm:ss.fff"
In response to the comment:
DateTime datetest;
var dateTimes = new [] { "05/03/2005 23:59:59.999", "05/3/2005 23:59:59.999", "5/03/2005 23:59:59.999", "5/3/2005 23:59:59.999" };
foreach(var dateTimeToParse in dateTimes)
if (DateTime.TryParse("5/3/2005 23:59:59.999", new CultureInfo("en-US"), DateTimeStyles.None, out datetest))
Console.WriteLine(dateTimeToParse + " parses to: " + datetest);
else
Console.WriteLine("FAIL!");
Works on my machine:
05/03/2005 23:59:59.999 parses to: 2005-05-03 23:59:59
05/3/2005 23:59:59.999 parses to: 2005-05-03 23:59:59
5/03/2005 23:59:59.999 parses to: 2005-05-03 23:59:59
5/3/2005 23:59:59.999 parses to: 2005-05-03 23:59:59
I can't see the contents of lines[I], but the mismatch between the format described in the comment and the format used in the TryParse may just be your issue:
lines[i] = lines[i] + " 23:59:59.999"; //YYYY-MM-DDThh:mm:ss[.mmm]
...
if (DateTime.TryParseExact(lines[i], "MM/dd/yyyy HH:mm:ss.mmm",
Using this (like already suggested Hans and David):
class Program
{
static void Main(string[] args)
{
List<String> datetimeList = new List<string>();
datetimeList.Add("05/03/2005 23:59:59.999");
datetimeList.Add("05/3/2005 23:59:59.999");
datetimeList.Add("5/03/2005 23:59:59.999");
datetimeList.Add("5/3/2005 23:59:59.999");
DateTime datetest;
foreach (string s in datetimeList)
{
if (!DateTime.TryParseExact(s, "M/d/yyyy HH:mm:ss.fff", new CultureInfo("en-US"), DateTimeStyles.None, out datetest))
{
Console.WriteLine("Error");
}
else
{
Console.WriteLine("Success");
}
}
Console.Read();
}
}
prints 4 times "Success" .
This only a proof of concept, i don't want any upvotes.

How to combine two strings (date and time) to a single DateTime

I have two strings:
string one = "13/02/09";
string two = "2:35:10 PM";
I want to combine these two together and convert to a DateTime.
I tried the following but it doesn't work:
DateTime dt = Convert.ToDateTime(one + " " + two);
DateTime dt1 = DateTime.ParseExact(one + " " + two, "dd/MM/yy HH:mm:ss tt", CultureInfo.InvariantCulture);
What can I do to make this work?
Try like this;
string one = "13/02/09";
string two = "2:35:10 PM";
DateTime dt = Convert.ToDateTime(one + " " + two);
DateTime dt1 = DateTime.ParseExact(one + " " + two, "dd/MM/yy h:mm:ss tt", CultureInfo.InvariantCulture);
Console.WriteLine(dt1);
Here is a DEMO.
HH using a 24-hour clock from 00 to 23. For example; 1:45:30 AM -> 01 and 1:45:30 PM -> 13
h using a 12-hour clock from 1 to 12. For example; 1:45:30 AM -> 1 and 1:45:30 PM -> 1
Check out for more information Custom Date and Time Format Strings
Your issue is with your hour specifier; you want h (The hour, using a 12-hour clock from 1 to 12), not HH (The hour, using a 24-hour clock from 00 to 23).
I had different format and the above answer did not work:
string one = "2019-02-06";
string two = "18:30";
The solution for this format is:
DateTime newDateTime = Convert.ToDateTime(one).Add(TimeSpan.Parse(two));
The result will be: newDateTime{06-02-2019 18:30:00}
Try using a culture info which matches the DateTime format for your string values:
DateTime dt = Convert.ToDateTime(one + " " + two,
CultureInfo.GetCultureInfo("ro-RO"));
or modify the input string so that the hour has 2 digits:
string one = "13/02/09";
string two = "02:35:10 PM";
DateTime dt1 = DateTime.ParseExact(one + " " + two,
"dd/MM/yy HH:mm:ss tt",
CultureInfo.InvariantCulture);
The problem is that the format string that you specify is not correct.
'HH' means a dwo-digit hour, but you have a single digit hour.
Use 'h' instead.
So the full format is 'dd/MM/yy h:mm:ss tt'
The following code will do what you want. I used the UK culture to take care of the d/m/y structure of your date:
string string1 = "13/2/09";
string string2 = "2:35:10 PM";
DateTime combined = DateTime.Parse(string1 + ' ' + string2, new CultureInfo("UK"));
Use string two = "02:35:10 PM"; instead of string two = "2:35:10 PM"; and also hh instead of HH due to AM/PM format.
Below is the code:
string one = "13/02/09";
string two = "02:35:10 PM";
DateTime dateTime = DateTime.ParseExact(one + " " + two, "dd/MM/yy hh:mm:ss tt", CultureInfo.InvariantCulture);
Convert.ToDateTime uses DateTime.ParseExact with your current thread's culture, so you can make things a bit clearer by simply doing:
string date = "13/02/09";
string time = "2:35:10 PM";
DateTime dateTime = DateTime.Parse(date +" "+ time, new CultureInfo("en-GB"));
Console.WriteLine (dateTime);
That gives the result 13/02/2009 14:35:10, and forces the parse to use the en-GB date time formats. If your Windows installation is en-GB anyway, you don't need the CultureInfo(..) argument.
use DateTime.Parse () to parse the date and the time separately. Then add the time component of the second one to the first one, like this
var date = DateTime.Parse (one);
var time = DateTime.Parse (two);
var result = date + time - time.Date;

Convert different format of DateTime to specific String format

Im Getting System.datetime.now from different Machine .Each system having different datetime format as a mension below
16-Oct-12 7:25:22 PM
16/10/2012 7:10:47 PM [DD/MM/YYYY]
10/16/2012 7:10:51 PM [MM/DD/YYYY]
How To convert Different format of DateTime to specific String format ?
string sDateTime = DateTime.Now.ToString("dd/MM/yyyy hh:mm:ss tt");
First result of Google search: Custom datetime format strings from MSDN
You have to use the line of code you provided explicitly on the other machines when returning the datetime:
string sDateTime = DateTime.Now.ToString("dd/MM/yyyy hh:mm:ss tt");]
This is however not aware of time zones! If your application spans several time zones, you should take that into count too!
Or, even better, you could return the Unix time (milliseconds from 1970-01-01) as a long, and of course the timezone info too, if that is different across the machines... (Beware, .NET expoch time is from 0001-01-01 though!)
Returning Epoch time
I would recommend against using tryParse: You can not reliably determine if a date is in [DD/MM/YYYY] or [MM/DD/YYYY], only when the month of day is greater than 12... And this would lead to mysterious errors. Believe me, been there, done that (the debugging part)...
try the TryParse methode of the Datetime class
Examples from the link:
string[] dateStrings = {"05/01/2009 14:57:32.8", "2009-05-01 14:57:32.8",
"2009-05-01T14:57:32.8375298-04:00",
"5/01/2008 14:57:32.80 -07:00",
"1 May 2008 2:57:32.8 PM", "16-05-2009 1:00:32 PM",
"Fri, 15 May 2009 20:10:57 GMT" };
DateTime dateValue;
Console.WriteLine("Attempting to parse strings using {0} culture.",
CultureInfo.CurrentCulture.Name);
foreach (string dateString in dateStrings)
{
if (DateTime.TryParse(dateString, out dateValue))
Console.WriteLine(" Converted '{0}' to {1} ({2}).", dateString,
dateValue, dateValue.Kind);
else
Console.WriteLine(" Unable to parse '{0}'.", dateString);
}
Notice that in the example its not working for all given strings dates
The problem of your example is the last two formats 16/10/2012 7:10:47 PM [DD/MM/YYYY] and 10/16/2012 7:10:51 PM [MM/DD/YYYY]. If the value is 10/11/2012 7:20:10 PM how can you know that it is Oct 11, 2012 or Nov 10, 2012?
var input = new string []{ "16-Oct-12 7:25:22 PM",
"16/10/2012 7:10:47 PM",
"10/16/2012 7:10:51 PM"};
foreach (var date in input)
{
var result = DateTime.MinValue;
if (DateTime.TryParse(date, out result))
{
Console.WriteLine("Date value: {0}", result);
}
else
{
Console.WriteLine("Cannot parse value {0}", date);
}
}
As you can see, "16/10/2012 7:10:47 PM" could not be parse.
if (DateTime.TryParse(DateTime.Now.ToString("MM/dd/yyyy hh:mm:ss tt"), out result))
sDateTime = DateTime.Now.ToString("MM/dd/yyyy hh:mm:ss tt");
else
{
if (System.Threading.Thread.CurrentThread.CurrentCulture.DateTimeFormat.ShortDatePattern.Equals("dd-MMM-yy")) sDateTime = DateTime.Now.ToString("MM/dd/yyyy hh:mm:ss tt");
else sDateTime = DateTime.Now.Month +"/" + DateTime.Now.Day+ "/" + DateTime.Now.Year + " " + DateTime.Now.ToString("hh:mm:ss tt");
}

Categories