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

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);

Related

C# Datetime.ParseExact for a parsing a string containing UTC text

I have a date time string that looks like this:
13.08.2014 17:17:45.000 UTC-60
I am trying to parse it into a C# date time object but it is not working as I expected.
Here is what I tried:
DateTime.ParseExact(dateToParse, "dd.MM.yyyy hh:mm:ss.fff Z", CultureInfo.InvariantCulture);
DateTime.ParseExact(dateToParse, "dd.MM.yyyy hh:mm:ss.fff UTC", CultureInfo.InvariantCulture);
DateTime.ParseExact(checkInDate, "dd.MM.yyyy hh:mm:ss.fff", CultureInfo.InvariantCulture);
They all return same error
{"String was not recognized as a valid DateTime."}
Some of the existing questions like this did not help either.
Any suggestions?
First, your main problem there with parsing is that your're using hh for 24h format. That should be HH. This should work:
DateTime.ParseExact("13.08.2014 17:17:45.000", "dd.MM.yyyy HH:mm:ss.fff", null, System.Globalization.DateTimeStyles.AssumeUniversal)
As for the UTC part, that's not standard format, so I suggest you to create a helper method that splits this string in 2, parse the first part as provided above, and parse the number after UTC and either add that to your DateTime:
myDate.AddMinutes(Int32.Parse("-60"))
Or create a DateTimeOffset. In either case, you must parse them individually.
How much control do you have over the time format.
.Net datetime parsing expects 2 things that are wrong with the current time format that you are trying to parse:
First, you have 24 hour time, so in your format you must use HH for hours, the lower case hh implies that the hours will be 12 hour format.
The UTC issue is another one that will require you to modify the string first, .Net expects timezone information in the form of HH:mm, so the following string and conversion will work, notice the key differences
var dateToParse = "13.08.2014 17:17:45.000 -01:00";
var value = DateTimeOffset.ParseExact(dateToParse, "dd.MM.yyyy HH:mm:ss.fff zzz", CultureInfo.InvariantCulture);
Use DateTimeOffset to maintain the TimeZone information
HH to map the hours
zzz to map the timezone information
So, to address you question, how can we parse the string into a format that we can then use to parse into a date time:
dateToParse = "13.08.2014 17:17:45.000 UTC-60";
string utc = null;
if (dateToParse.Contains("UTC"))
{
var tokens = dateToParse.Split(new string[] { "UTC" }, StringSplitOptions.None);
dateToParse = tokens[0];
utc = tokens[1];
int minutes = int.Parse(utc);
var offset = TimeSpan.FromMinutes(minutes);
bool negative = offset.Hours < 0;
dateToParse += (negative ? "-" : "") + Math.Abs(offset.Hours).ToString().PadLeft(2,'0') + ":" + offset.Minutes.ToString().PadLeft(2,'0');
}
var value = DateTimeOffset.ParseExact(dateToParse, "dd.MM.yyyy HH:mm:ss.fff zzz", CultureInfo.InvariantCulture);
To be honest, that was more complicated than I thought, there might be some regex expressions that might help, but this first principals approach to manipulating the string first works with your string.
Finally, now that we have a DateTimeOffset value, you can easily convert this into any local or other timezone without too much hassel, if you need to:
var asUtc = dateValue.UtcDateTime;
var asLocal = dateValue.LocalDateTime;
var asSpecific = dateValue.ToOffset(TimeSpan.FromHours(10)).DateTime;

c# DateTime.ParseExact error

I have a String was not recognized as a valid DateTime error.
Followed one of the examples from here. Which has an example that says:
dateString = "15/06/2008 08:30";
format = "g";
provider = new CultureInfo("fr-FR");
try {
result = DateTime.ParseExact(dateString, format, provider);
Console.WriteLine("{0} converts to {1}.", dateString, result.ToString());
}
catch (FormatException) {
Console.WriteLine("{0} is not in the correct format.", dateString);
}
Here's my code:
string convertToString = string.Join("", dateTimeId);
DateTime parsedDateTime = DateTime.ParseExact(convertToString, "g", CultureInfo.InvariantCulture);
I have a string array converted to string because I am reading one csv row which has a datetime value of "3/16/2002 9:20".
I also tried the format for "MM/dd/yyyy HH:mm", but still getting the same error.
Any tip or help is appreciated.
Try this format string instead
"M/dd/yyyy H:mm"
If you specify two M's for the month and two H's for the hour it will expect a leading zero for both.
Or just using DateTime.Parse should work.
Console.WriteLine(DateTime.Parse("3/16/2002 9:20", CultureInfo.InvariantCulture));
The more I look at this the more I think that "g" should have worked. It only seems to work if there are leading zeros for both the month and hour even though it doesn't put leading zeros in if you use it to format a DateTime to a string, at least for InvariantCulture.

String to DateTime conversion Failing

I'm trying to convert a string from a text file to a DateTime, but I'm getting weird results. On one computer, it works, but another, it doesn't. How would I make this work on all computers? On my last question, you said to add the culture thing, and it worked for a few minutes, but it's not working again now. Heres my code:
string[] stringArray = File.ReadAllLines("C:\\Program Files\\PointOfSales\\RecordTotals.txt");
int lines = stringArray.Length;
for (int i = 0; i < (lines / 5); i++)
{
TransactionList.Add(new Transaction
{
TotalEarned = Convert.ToDouble(stringArray[(i * 5)]),
TotalCost = Convert.ToDouble(stringArray[(i * 5) + 1]),
TotalHST = Convert.ToDouble(stringArray[(i * 5) + 2]),
Category = stringArray[(i * 5) + 3],
HoursSince2013 = Convert.ToDateTime(stringArray[(i * 5) + 4], CultureInfo.InvariantCulture)
});
}
I'm getting the error String was not recognized as a valid DateTime.
Any clues whats up? Thanks!
Edit: Using MessageBox.Show(stringArray[(i * 5) + 4]); I get 26/10/2013 11:58:03 AM
Edit: Why won't this work to convert current time to the right culture?
DateTime Today = DateTime.Now;
Today = DateTime.ParseExact(Today.ToString(), "dd/MM/yyyy HH:mm:ss tt", CultureInfo.InvariantCulture);
Your string, on that system, is not a valid date in invariant culture: 26/10/2013 11:58:03 AM. The invariant culture expects month/day/year, not day/month/year.
You should specify the same culture that is being used to generate the file that you are reading. You will need to have some way to determine or standardize on the cultures being used for writing to the file, as well as reading from it.
Edit: Why won't this work to convert current time to the right culture?
That will fail if your current culture doesn't use dd/MM/yyyy for it's format. Today.ToString() doesn't have a culture specified, or a format, so it's going to, on a US system, write out using MM/dd/yyyy format, which will cause the call to fail.
In your case, I would recommend always reading and writing using the same culture - If you write your file using: theDate.ToString(CultureInfo.InvariantCulture), then you can read using Convert.ToDateTime(theString, CultureInfo.InvariantCulture), and it will work on any system, since the same rules (Invariant culture) are used for both writing and reading.
You should use custom "dd/MM/yyyy HH:mm:ss t" format with InvariantCulture like;
string s = "26/10/2013 11:58:03 AM";
DateTime dt = DateTime.ParseExact(s, "dd/MM/yyyy HH:mm:ss tt", CultureInfo.InvariantCulture);
Console.WriteLine(dt);
Output will be;
10/26/2013 11:58:03 AM
Here a demonstration.
For more information, take a look at;
Custom Date and Time Format Strings
EDIT: If your DateTime.Now doesn't fit "dd/MM/yyyy HH:mm:ss tt" format, your program will fail. You should use InvariantCulture in all your programs with your DateTime.Now format exactly.

DateTime.TryParseExact CultureInfo.InvariantCulture

Can anyone see what I'm doing wrong, I'm trying to parse the date to ensure its a valid date, if so convert it to the format I require.
I have tried different ways of doing this, but all return 01/01/0001 00:00:00.
value of string parseArrivalDate = 02/02/2013
DateTime ukDateFormat;
string ukFormat = "0:ddd, MMM d, yyyy";
DateTime.TryParseExact(parseArrivalDate, ukFormat, CultureInfo.InvariantCulture, DateTimeStyles.None, out ukDateFormat);
DateTime test = ukDateFormat;
-------------------------------------EDIT-------------------------------
OK sorry, I did not explain it very well. If I enter UK format say 27/02/2013, and when I had UK format as dd/MM/yyyy it worked ok, problem was when I was entering US or any other format, it was returning the incorrect date, so I was changing the format round thinking that was the problem.
It has now dawned on me after reading your comments, that I had the uk format correct 1st time, so my problem is, how can I change the code, so that any date format can be parsed correctly.
Hope that makes more sense
Thanks
Your string
"0:ddd, MMM d, yyyy"
has a number 0, a colon :, and a format corresponding to
"Wed, Mar 27, 2013"
for example, if the culture is "en-GB" ("English (United Kingdom)"). It probably comes from a String.Format, Console.WriteLine or similar method call, where it is put into braces {} to format a text, as in
Console.WriteLine("The date {0:ddd, MMM d, yyyy} was selected.", someDateTime);
It would work with code like:
string arrivalDateString = "Wed, Mar 27, 2013";
...
DateTime result;
string yourFormat = "ddd, MMM d, yyyy"; // no "0:" part
bool isOK = DateTime.TryParseExact(arrivalDateString, yourFormat, CultureInfo.InvariantCulture, DateTimeStyles.None, out result);
if (isOK)
{
// Worked! Answer is in 'result' variable
}
else
{
// Didn't work! 'result' variable holds midnight 1 January 0001
}
The format that corresponds to "27/03/2013" is "dd/MM/yyyy" (or "d/M/yyyy"). The format that corresponds to "03/27/2013" is "MM/dd/yyyy" (or "M/d/yyyy").
It is not possible to have one method that handles both styles of dates, since a string like
"01/04/2013" /* ambiguous */
could mean either
1 April 2013
January 4, 2013
so it's ambiguous, and there's no way we can tell what date is meant. See also Wikipedia: Calendar date → Date format.
your date string is: 02/02/2013 and the format you are using is "0:ddd, MMM d, yyyy" which is wrong, it should be MM/dd/yyyy if its month first.
DateTime ukDateFormat;
string ukFormat = "MM/dd/yyyy";
DateTime.TryParseExact(parseArrivalDate, ukFormat,CultureInfo.InvariantCulture,DateTimeStyles.None, out ukDateFormat);
DateTime test = ukDateFormat;
If the date you have specified contains day first then month, then use the format "dd/MM/yyyy", By the way you can using single d and M for both single digit and double digits day/month.
Currently you are getting the DateTime.MinValue, since parsing is failing because of the invalid format.
I have no idea what you expect, but your input string does not met your ukFormat pattern! So it's totally right behavior.
Change your pattern to ""dd/MM/yyyy"" to make TryParseExact work.
Your provided format looks a little strange. Try to replace it with this
string ukFormat = "dd/MM/yyyy";
And read the documentation on this.
Thanks everyone for helping me understand where I was going wrong, the code below is what I have came up with although not perfect as 03/06/2013 UK is different than the meaning of 03/06/2013 US.
I have added text above the text box asking people to use format dd/mm/yyyy.
string getArrivalDate = ArrivalDate;
string getDepartureDate = DepartureDate;
string dteFormat = "dd/MM/yyyy";
DateTime result;
string arrivalDateParse;
string departureDateParse;
bool arrival = DateTime.TryParseExact(getArrivalDate, dteFormat, new CultureInfo("en-GB"), DateTimeStyles.None, out result);
if (arrival)
{
arrivalDateParse = getArrivalDate;
}
else
{
arrivalDateParse = "notvalid";
}
bool depart = DateTime.TryParseExact(getDepartureDate, dteFormat, new CultureInfo("en-GB"), DateTimeStyles.None, out result);
if (depart)
{
departureDateParse = getDepartureDate;
}
else
{
departureDateParse = "notvalid";
}
if (arrivalDateParse == "notvalid" || departureDateParse == "notvalid")
{
if (Request.IsAjaxRequest())
{
return Json(new { Confirm = "Date not in correct format" }, JsonRequestBehavior.AllowGet);
}
else
{
TempData["Error"] = "Sorry your arrival date or departure date is not a valid format, please enter date as dd/mm/yyyy example 02/12/2013";
return View("~/Views/Shared/Error.cshtml");
}
If anyone can improve on the code, it would be appreciated.
Thanks
George
Rather than using InvariantCulture for this consider using RoundTrip style (ISO-8601). See this MSDN article: http://msdn.microsoft.com/en-us/library/bb882584.aspx

TimeSpan.Parse time format hhmmss

in c# i have time in format hhmmss like 124510 for 12:45:10 and i need to know the the TotalSeconds. i used the TimeSpan.Parse("12:45:10").ToTalSeconds but it does'nt take the format hhmmss. Any nice way to convert this?
This might help
using System;
using System.Globalization;
namespace ConsoleApplication7
{
class Program
{
static void Main(string[] args)
{
DateTime d = DateTime.ParseExact("124510", "hhmmss", CultureInfo.InvariantCulture);
Console.WriteLine("Total Seconds: " + d.TimeOfDay.TotalSeconds);
Console.ReadLine();
}
}
}
Note this will not handle 24HR times, to parse times in 24HR format you should use the pattern HHmmss.
Parse the string to a DateTime value, then subtract it's Date value to get the time as a TimeSpan:
DateTime t = DateTime.ParseExact("124510", "HHmmss", CultureInfo.InvariantCulture);
TimeSpan time = t - t.Date;
You have to decide the receiving time format and convert it to any consistent format.
Then, you can use following code:
Format: hh:mm:ss (12 Hours Format)
DateTime dt = DateTime.ParseExact("10:45:10", "hh:mm:ss", System.Globalization.CultureInfo.InvariantCulture);
double totalSeconds = dt.TimeOfDay.TotalSeconds; // Output: 38170.0
Format: HH:mm:ss (24 Hours Format)
DateTime dt = DateTime.ParseExact("22:45:10", "HH:mm:ss", System.Globalization.CultureInfo.InvariantCulture);
double totalSeconds = dt.TimeOfDay.TotalSeconds; // Output: 81910.0
In case of format mismatch, FormatException will be thrown with message: "String was not recognized as a valid DateTime."
You need to escape the colons (or other separators), for what reason it can't handle them, I don't know. See Custom TimeSpan Format Strings on MSDN, and the accepted answer, from Jon, to Why does TimeSpan.ParseExact not work.
In case you want to work with also milliseconds like this format "01:02:10.055" then you may do as following;
public static double ParseTheTime(string givenTime)
{
var time = DateTime.ParseExact(givenTime, "hh:mm:ss.fff", CultureInfo.InvariantCulture);
return time.TimeOfDay.TotalSeconds;
}
This code will give you corresponding seconds.
Note that you may increase the number of 'f's if you want to adjust precision points.
If you can guarantee that the string will always be hhmmss, you could do something like:
TimeSpan.Parse(
timeString.SubString(0, 2) + ":" +
timeString.Substring(2, 2) + ":" +
timeString.Substring(4, 2)))

Categories