String to DateTime conversion Failing - c#

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.

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;

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

Adding two dates to eachother

string final = Convert.ToString(DateTime.Parse(date, System.Globalization.CultureInfo.InvariantCulture) + TimeSpan.Parse(duration));
Hi, I use the above code to add two date's to eachother. It do work very well on Windows and returns the required format yyyy-MM-dd HH:mm:ss in a correct fashion. HOWEVER, when on Linux building with Mono it returns the following format dd/MM/yyyy HH:mm:ss which is not what I want.
How can I specify that I ONLY want the first formatting and nothing else? I tried playing around with ParseExact but it did not do very well. What I've heard ParseExact should not really be needed for this?
Here is a example of input:
string date = "2014-10-30 10:00:04"; // On windows
string duration = "05:02:10"; // duration to be added to date
Greetings.
Use ToString("yyyy-MM-dd HH:mm:ss") instead of Convert.ToString.
string date = "2014-10-30 10:00:04";
string duration = "05:02:10";
DateTime dt1 = DateTime.Parse(date, CultureInfo.InvariantCulture);
TimeSpan ts = TimeSpan.Parse(duration, CultureInfo.InvariantCulture);
DateTime dtFinal = dt1.Add(ts);
string final = dtFinal.ToString("yyyy-MM-dd HH:mm:ss", CultureInfo.InvariantCulture);
Convert.ToString uses your current culture's date separator, use CultureInfo.InvariantCulture.
Read: Custom Date and Time Format Strings
You can use the ToString() Method of the DateTime object.
var dt = DateTime.Now;
dt.ToString("yyyy-MM-dd HH:mm");
Using your code:
string _final = (DateTime.Parse(date, System.Globalization.CultureInfo.InvariantCulture) + TimeSpan.Parse(duration)).ToString("yyyy-MM-dd HH:mm:ss");

DateTime.ToString() does not work as expected with slash as date-separator

I want to convert the date time to "MM/dd/yyyy" and when i am converting to this format the date is getting like "xx-xx-xxxx". I have written code like
var format = "MM/dd/yyyy HH:mm";
DateTime dt = DateTime.Now;
var dateString = dt.toString(format); // the value i am getting is 05-28-2014 12:47 but i require the 'dateString' value to be `05/28/2014 12:53`.
What is the issue with that.
Your currrent culture's date-separator seems to be - that's why you get it. You have to specify InvariantCulture:
string dateString = dt.toString("MM/dd/yyyy HH:mm", CultureInfo.InvariantCulture);
See: The "/" Custom Format Specifier
The "/" custom format specifier represents the date separator, which
is used to differentiate years, months, and days. The appropriate
localized date separator is retrieved from the
DateTimeFormatInfo.DateSeparator property of the current or specified
culture.
Another way is to escape the / with \:
string dateString = dt.toString(#"MM\/dd\/yyyy HH\:mm");
But in my opinion, if you already know the special meaning of / as "current culture's date-separator", it's better(in terms of readability) to use the correct CultureInfo (or InvariantCulture) instead.
This depends on your current culture date-separator. Try to include InvariantCulture as follows:
var dateStringFormat= dt.toString("MM/dd/yyyy HH:mm", CultureInfo.InvariantCulture);
Another way from #TimSchmelter's answer is to escape special symbols / and : so they are not treated as day and time separators.
var dateString = dt.toString(#"MM\/dd\/yyyy HH\:mm");
you will specified the format while converting date and time i.e. DateTime.Now.ToString("MM/dd/yyyy hh:mm ss tt")
for more ref.
http://msdn.microsoft.com/en-us/library/system.datetime.aspx

For valid DateTime(Error shows string was not recognized )

I am trying to convert my string formated value to date type with format dd/MM/yyyy. It runs fine but when I enter fromdate(dd/MM/yyyy) in textbox its fine and todate(dd/MM/yyyy) in textbox then it gives an error that string was not recognized as a valid datetime.What is the problem exactly i dont know. same code run on another appliction its run fine but in my application it shows Error.
Below I have used array for required format and split also used.
string fromdate = punchin.ToString();
string[] arrfromdate = fromdate.Split('/');
fromdate = arrfromdate[1].ToString() + "/" + arrfromdate[0].ToString() + "/" + arrfromdate[2].ToString();
DateTime d1 = DateTime.Parse(fromdate.ToString());
try with DateTime.TryParseExact as below
DateTime date;
if (DateTime.TryParseExact(inputText, "MM/dd/yyyy",
CultureInfo.InvariantCulture,
DateTimeStyles.None,
out date))
{
// Success
}
if you know the format of input date time you don't need to do any string manipulation.
But you need to give correct Date and Time Format String
I got 5/13/2013 12:21:35 PM in string fromdate
Use DateTime.TryParseExact, You don't have to split your string based on / and then get first three items from the array instead you can simply do:
DateTime dt;
if (DateTime.TryParseExact("5/13/2013 12:21:35 PM",
"M/d/yyyy hh:mm:ss tt",
CultureInfo.InvariantCulture,
DateTimeStyles.None,
out dt))
{
//date is fine
}
Using single d and single M as it can accomodate single digit as well as double digits day/Month part. You can simply pass punchin as the string parameter, Calling ToString on string types is redundant.
Try :
DateTime.ParseExact(fromdate, "MM/dd/yy", CultureInfo.InvariantCulture)
Obviously you can reformat the above, and use different providers by creating an instance of CultureInfo related to the string you are parsing, and you can modify the format string to reflect that culture or to accommodate more date parts

Categories