I have a date that I need to get into a DateTime object. In my code below I set the filedate to the date string that I get and then try two different formats (patern and patern2. It does not recognize the format and always falls down to the else block and I dont get the datetime object as I need it. I got the format string set up using the specifiers I found on MSDN on this page..
string filedate = "Tue Aug 12 16:01:29 CDT 2014";
string patern = "ddd MMM d hh:mm:ss CDT yyyy";
string patern2 = "ddd MMM dd hh:mm:ss CDT yyyy";
DateTime dat;
CultureInfo enUS = new CultureInfo("en-US");
string outString = "";
if (DateTime.TryParseExact(filedate, patern, enUS, System.Globalization.DateTimeStyles.None, out dat))
{
outString = (dat.ToShortDateString() + " " + dat.ToShortTimeString());
}
else if (DateTime.TryParseExact(filedate, patern2, enUS, System.Globalization.DateTimeStyles.None, out dat))
{
outString = (dat.ToShortDateString() + " " + dat.ToShortTimeString());
}
else
{
outString = filedate.Trim(); //always falling to here
}
Three problems:
Your two pattern straings are identical - why try them both?
hh means hour of 12-hour clock; 16 isn't a valid value
You should escape the CDT part as you want it as a literal
I suspect you want:
"ddd MMM d HH:mm:ss 'CDT' yyyy";
Additionally, if this is always in English, you probably want to use CultureInfo.InvariantCulture.
Finally, I suspect this is only going to be valid in the summer... in winter I'm guessing you'll have CST instead. Unfortunately this is a horrible format... you may well want to use string operations to strip out the CST/CDT (or whatever it is - will it always be central time?) before parsing. As far as I'm aware, there's no support for parsing those.
Related
The dates are recorded as follows in the logs:
08 груд. 2017 00:00:06,694
I've been using Linqpad to try to come up with a valid date time mask using the Ukrainian culture, and this is what I've tried:
var dateString = "08 груд. 2017 00:00:06,694";
DateTime date;
DateTime.TryParseExact(
dateString,
"dd MMMM. yyyy HH:mm:ss,fff",
new CultureInfo("uk-UA"),
DateTimeStyles.None,
out date);
Console.WriteLine(date);
This does not work, and the output from this script is:
1/1/0001 12:00:00 AM
This same approach has worked well for me for several other languages, so I'm puzzled as to what is happening here. As best as I can tell, the month is not being parsed correctly. I've try substituting "hrud." for the month value (from: https://www.loc.gov/aba/pcc/conser/conserhold/Mosabbr.html), but that does not work either.
MMMM format specifier for month means "full month name". You can see what are full month names for given culture with:
var culture = new CultureInfo("uk-UA");
var monthNames = culture.DateTimeFormat.MonthNames;
For this culture, december full name is "грудень", not "груд". You might think to use "short month name" format specifier MMM. You can look "short names" for month for given culture like this:
var culture = new CultureInfo("uk-UA");
var monthNames = culture.DateTimeFormat.AbbreviatedMonthNames;
However you will see that short name for december is "гру" and still not "груд". So to parse your string with default month names for your culture you need to either do:
var dateString = "08 грудень 2017 00:00:06,694";
DateTime date;
DateTime.TryParseExact(dateString, #"dd MMMM yyyy HH:mm:ss,fff", new CultureInfo("uk-UA"), DateTimeStyles.None, out date);
Or
var dateString = "08 гру. 2017 00:00:06,694";
DateTime date;
DateTime.TryParseExact(dateString, #"dd MMM. yyyy HH:mm:ss,fff", new CultureInfo("uk-UA"), DateTimeStyles.None, out date);
Another option is to adjust culture month names for your case, like this (note that it will not modify global culture settings, only month name for this particular CultureInfo instance, so there is no danger in doing this):
var dateString = "08 груд. 2017 00:00:06,694";
DateTime date;
var culture = new CultureInfo("uk-UA");
var defaultShortNames = culture.DateTimeFormat.AbbreviatedMonthNames;
var defaultShortGenitiveNames = culture.DateTimeFormat.AbbreviatedMonthGenitiveNames;
// obviously modify all month names as necessary
defaultShortNames[11] = "Груд";
defaultShortGenitiveNames[11] = "груд";
culture.DateTimeFormat.AbbreviatedMonthNames = defaultShortNames;
culture.DateTimeFormat.AbbreviatedMonthGenitiveNames = defaultShortGenitiveNames;
// store this modified culture and reuse when necessary
// that MMM format consists of 3 letters is irrelevant - it will still
// work fine with abbreviated month names of 4 characters or more
DateTime.TryParseExact(dateString, #"dd MMM. yyyy HH:mm:ss,fff", culture, DateTimeStyles.None, out date);
As others have mentioned, MMMM is the full month name and MMM is the three-character abbreviated month name, so neither will work out of the box. Rather than hard-code month names or modify the CultureInfo, I'd prefer to pre-process the string to truncate the month to the 3 characters parseable with the MMM custom format string, either with regular expressions (heavyweight) or directly:
var sb = new StringBuilder (date.Length) ;
var nc = 0 ;
foreach (var ch in date)
{
if (char.IsLetter (ch) && nc++ >= 3) continue ;
sb.Append (ch) ;
}
return DateTime.ParseExact ("dd MMM. yyyy HH:mm:ss,fff", ...) ;
I want to convert a string to a DateTime object. My string will be in this format- "18th Jul 2016" (the date can change). Obviously, .Net does not take this as a valid date format. Is there any easy way to convert this without using any third party library?
I wouldn't use String.Replace since it could be a problem is the current culture's month-name contains the strings you're going to replace.
Instead you could remove this part from the string:
string input = "18th Jul 2016";
string[] token = input.Split(); // split by space, result is a string[] with three tokens
token[0] = new string(token[0].TakeWhile(char.IsDigit).ToArray());
input = String.Join(" ", token);
DateTime dt;
if(DateTime.TryParseExact(input, "dd MMM yyyy", null, DateTimeStyles.None, out dt))
{
Console.WriteLine("Date is: " + dt.ToLongDateString());
}
If you pass null as IFormatProvider to TryParseExact the current culture's datetimeformat is used. If you want to force english names you can pass CultureInfo.InvariantCulture.
Workaround:
string dateStr = "18th Jul 2016";
dateStr = dateStr.Replace("th", "").Replace("st", "").Replace("rd", "").Replace("nd", "");
DateTime date;
if (DateTime.TryParseExact(dateStr, "dd MMM yyyy", CultureInfo.CurrentCulture,
DateTimeStyles.AssumeLocal, out date))
{
}
else
{
// error
}
Its a bit of a fudge but
string result = System.Text.RegularExpressions.Regex.Replace(dt, "[st|th|nd|rd]{2} ", " ", System.Text.RegularExpressions.RegexOptions.IgnoreCase);
DateTime d = DateTime.Parse(result);
I included the space so it doesnt try editing the months.. I did start out with [0-9]{1,2} and replacing it with the number, but that seemed overkill
string dateString = "18th Jul 2016";
dateString = Regex.Replace(dateString, #"^(\d{2})(st|nd|rd|th)", "$1");
var result = DateTime.ParseExact(dateString, "dd MMM yyyy", CultureInfo.InvariantCulture);
I have two string variables. The first one is from a label (This date will be subject to changed dependant on a datetimepicker). The second one is a time that is selected in a combo box. The format is in this example -
lblActualDate.Text - 11 June 2015
comboStartTime.Text - 12.00AM
I am getting errors about the strings not being in the correct format to convert to date time.
My aim is to make an instance with the values from a form
Here is my code -
private void btnSave_Click(object sender, EventArgs e)
{
string dateString = lblActualDate.Text + " " + comboStartTime.SelectedItem;
DateTime startTime = DateTime.ParseExact(dateString, "dd MMMM yyyy hh.mmtt", CultureInfo.InvariantCulture);
int length = int.Parse(comboLength.SelectedText);
string description = txtBoxSubject.Text;
string location = txtBoxLocation.Text;
Appointment newAppointment = new Appointment(startTime, length, description, location);
Appointments appointments = new Appointments();
appointments.Add(newAppointment);
appointments.Save();
txtBoxLocation.Clear();
txtBoxSubject.Clear();
Dispose();
}
Convert.ToDateTime uses standard date and time formats of your CurrentCulture. That means your string format doesn't match one of these formats.
You can use custom date and time formats to parse your string like;
string s = "11 June 201512.00AM";
DateTime startTime = DateTime.ParseExact(s, "dd MMMM yyyyhh.mmtt",
CultureInfo.InvariantCulture);
Also consider to put a white space between your date and time part.
Most likely you've got some combinations with one digit, and others with two digits in either the day or hour portions of your date/time.
You can allow all the possibilities by building up an array of allowable formats and passing that to ParseExact:
string[] formats = { "d MMMM yyyy h.mmtt", "d MMMM yyyy hh.mmtt", "dd MMMM yyyy h.mmtt", "dd MMMM yyyy hh.mmtt" };
DateTime startTime = DateTime.ParseExact(dateString, formats, CultureInfo.InvariantCulture, DateTimeStyles.None);
My C# project is taking xml and extracting pertinent data, one of which pieces is a date time value. The following code works correctly on my desktop running Win8.1 and .NET4. However when I run it through mono, it's failing to parse the data.
using glob = System.Globalization;
DateTimeOffset dt = DateTimeOffset.MinDate;
string[] fmts = new string[]
{
"MMM dd, yyyy hh:mm tt EDT",
"MMM dd, yyyy hh:mm tt EST",
"MMM dd, yyyy hh:mm tt CDT",
"MMM dd, yyyy hh:mm tt CST",
"MMM dd, yyyy hh:mm tt MDT",
"MMM dd, yyyy hh:mm tt MST",
"MMM dd, yyyy hh:mm tt AKST",
"MMM dd, yyyy hh:mm tt AKDT",
"MMM dd, yyyy hh:mm tt HST",
"MMM dd, yyyy hh:mm tt PST",
"MMM dd, yyyy hh:mm tt PDT"
};
var dtString = z.Substring(pos1 + 5, pos2 - pos1 - 1 - 5).Replace("ft", "").Trim();
dtString = dtString.Substring(0, 1).ToUpper() + dtString.Substring(1);
dtString = dtString.Substring(0, dtString.Length - 7)
+ dtString.Substring(dtString.Length - 7).ToUpper();
DateTimeOffset.TryParseExact(dtString, fmts,
glob.CultureInfo.InvariantCulture, glob.DateTimeStyles.None, out dt);
To check if the conversion worked ok, I do this:
if (dt == DateTimeOffset.MinDate)
Console.WriteLine("failed to convert dt = MinValue -> " + dtString);
Here's an example of the data string being processed:
raw: mar 21, 2015 10:30 am cdt
after my formatting: Mar 21, 2015 10:15 AM CDT
It's not specific to the CDT tz - I get the same issue for all timezones.
When I run $ date on the Linux box, it's reporting the same date, time and tz as my desktop, in this format (Mon Mar 23 11:31:16 EDT 2015).
The section is wrapped in a try/catch, but no exceptions are being thrown (also have Console output in there).
I can code around it by changing the string around before TryParse, but it would seem this method was designed so that this is not necessary.
Is this a bug (or am I missing something)? If so where does one report them?
Thanks
A few points:
In the code you posted, the part where you manipulate the dtString variable is meaningless to us, because you didn't include values for pos1 or pos2. It seems quite messy, and in general - that sort of manipulation should be avoided if possible. I'm not sure what it has to do with your question, if anything.
You are using the TryParseExact method, which returns a boolean true on success - so the comparison check is unnecessary. (Also, the field is called MinValue, not MinDate)
Time zone abbreviations are not valid in format strings. The letters in the string could be confused with actual custom formatting values. If you wanted to exclude them, you would place them in single-tick or double-tick quotation marks.
In general, time zone abbreviations should not be used for input. There are just too many ambiguities. For example, this list of abbreviations shows 5 possible interpretations of "CST".
The parsers that come with the DateTime and DateTimeOffset types do not understand time zone abbreviations at all. You claim it works fine on your desktop under .NET 4, but I call BS.
As you can see, it did not interpret the offset as CDT (-05:00). Instead it took the local time zone from my computer, which happens to be PDT (-07:00).
The correct way to deal with this is to parse the date input as a DateTime, then use some other mechanism to determine the offset. If you MUST use the time zone abbreviation, and you are absolutely sure you only have the time zones you showed above, and they're all from the united states, then it would go something like this:
// define the list that you care about
private static readonly Dictionary<string, TimeSpan> Abbreviations = new Dictionary<string, TimeSpan>
{
{"EDT", TimeSpan.FromHours(-4)},
{"EST", TimeSpan.FromHours(-5)},
{"CDT", TimeSpan.FromHours(-5)},
{"CST", TimeSpan.FromHours(-6)},
{"MDT", TimeSpan.FromHours(-6)},
{"MST", TimeSpan.FromHours(-7)},
{"PDT", TimeSpan.FromHours(-7)},
{"PST", TimeSpan.FromHours(-8)},
{"AKDT", TimeSpan.FromHours(-8)},
{"AKST", TimeSpan.FromHours(-9)},
{"HST", TimeSpan.FromHours(-10)}
};
static DateTimeOffset ParseInput(string input)
{
// get just the datetime part, without the abbreviation
string dateTimePart = input.Substring(0, input.LastIndexOf(" ", StringComparison.Ordinal));
// parse it to a datetime
DateTime dt;
bool success = DateTime.TryParseExact(dateTimePart, "MMM dd, yyyy hh:mm tt",
CultureInfo.InvariantCulture, DateTimeStyles.None, out dt);
// handle bad input
if (!success)
{
throw new ArgumentException("Invalid input string.", "input");
}
// get the abbreviation from the input string
string abbreviation = input.Substring(input.LastIndexOf(" ", StringComparison.Ordinal) + 1)
.ToUpperInvariant();
// look up the offset from the abbreviation
TimeSpan offset;
success = Abbreviations.TryGetValue(abbreviation, out offset);
if (!success)
{
throw new ArgumentException("Unknown time zone abbreviation.", "input");
}
// apply the offset to the datetime, and return
return new DateTimeOffset(dt, offset);
}
Now it will return the correct output:
string dtString = "Mar 21, 2015 10:15 AM CDT";
DateTimeOffset dto = ParseInput(dtString);
Console.WriteLine(dto);
Also note that if you were really trying to cover all legal US time zones, you should also consider adding HAST, HADT, CHST, SST, and AST to the list.
private string format = "dd/MM/yyyy HH:mm:ss";
DateTime fromdate = DateTime.ParseExact(GetFromScanDateTextBox.Text, format, CultureInfo.InvariantCulture);
I am getting error when executing this line string was not recognized as a Valid Date Time.
I have tried this also but it not works
DateTime fromdate = DateTime.ParseExact(GetFromScanDateTextBox.Text, format,null);
Your format string must be "d/M/yyyy", take a look at this.
Basically
MM : The month, from 01 through 12.
while
M : The month, from 1 through 12.
The same for the day part.
You are telling DateTime.ParseExact that you are expecting a string with format dd/MM/yyyy HH:mm:ss but you are giving it a string with format d/M/yyyy.
You need to change your format to just d/M/yyyy.
Also I suggest using DateTime.TryParseExact to verify the validity of your string instead of using exceptions.
var okay = DateTime.TryParseExact(
input,
new[] { "dd/MM/yyyy HH:mm:ss", "d/M/yyyy" },
new CultureInfo("en-GB"),
DateTimeStyles.None,
out dateTime);
If your input string is liable to change, TryParseExact allows you to define multiple formats as shown above, or alternatively, if it is always going to be with your current culture, just do DateTime.TryParse and do away with defining the format.
var okay = DateTime.TryParse(input, out dateTime);
If your format is always month/date/year and particularly in this case(if your date is 3rd Sept 2013) you can use:
string format = "MM/dd/yyyy";
string dateTime = "9/3/2013";
dateTime = (dateTime.Split('/')[0].Length == 1 ? "0" + dateTime.Split('/')[0] : dateTime.Split('/')[0]) + "/" + (dateTime.Split('/')[1].Length == 1 ? "0" + dateTime.Split('/')[1] : dateTime.Split('/')[1]) + "/" + dateTime.Split('/')[2];
DateTime fromdate = DateTime.ParseExact(dateTime, format, CultureInfo.InvariantCulture);
Do not provide the HH:MM:SS part in the format part
string format = "dd/MM/yyyy";
DateTime fromdate = DateTime.ParseExact(test.Text, format, CultureInfo.InvariantCulture);