I want to parse string to time, the string can be "hh:mm tt", or "hh:mmtt"
"11:00am", "11:00 am", "13:00" "5:00AM" "6:00PM" , "6:00 pm", "6:00:01 pm" etc.
I wonder how to parse it correctly. My thought is to enumerate all the formats like below.
But I feel it is awkward and there must be a better way. thanks
DateTime ret = DateTime.MinValue;
DateTime.TryParse(timeStr, CURRENT_CULTURE_FORMATPROVIDER,Style1, out ret);
if(ret == DateTime.MinValue)
{
DateTime.TryParse(timeStr,CURRENT_CULTURE_FORMATPROVIDER,Style2, out ret);
}
if(ret == DateTime.MinValue)
{
DateTime.TryParse(timeStr,CURRENT_CULTURE_FORMATPROVIDER,Style3, out ret);
}
...
return ret;
Not really an answer but not fitting to comments: reject values that are not completely clear instead of potentially guessing wrong.
While it is very tempting to guess what actual value particular string represents it is very dangerous route. The chances of guessing value wrong are higher more input "formats" you accept.
If data coming from some computer-generated source - simply rejecting unexpected data is probably best option. Consider if asking for some fixed well known culture-insensitive format works (i.e. ISO8601 optionally with timezone)
If this data coming directly from user it may be better to immediately reject the data and let user re-enter date in more precise format. If possible - simply don't let user to pick and force particular format.
If you randomly guess values incorrectly users (if they care and have to use your tool often) will learn to type values in one very particular format and have verbal instructions to only use that (like "hours two spaces colon minutes, only add PM for values in afternoon")...
Note that only some cultures (in .Net sense) have AM/PM designator, so make sure to test your code against those too.
DateTime.TryParse seems to be working for your problem. Have a look
string myTime = "5:00AM";
DateTime dt = DateTime.Now;
DateTime.TryParse(ss, out dt);
Related
I'm trying to parse a file where I get my dates as string like those:
5/18/2020 8:38:32 AM
6/8/2021 10:11:42 PM
11/24/2021 9:21:54 AM
----
I tried to use a DateTime.TryParse on my string and test the "---" case in a if statement which work but it succeed to convert only the 6/8/2021 12:41:56 PM.
I tried to use TryParseExact and specify a date format but it seem that I should make a case months with one and two digits and same the days.
I guess there is something I'm not seeing or don't know.
Thanks for you help.
It is because you are probably on a culture other than en-US which those dates are formatted in. Use IFormatProvider parameter. ie:
void Main()
{
var dates = #"5/18/2020 8:38:32 AM
6/8/2021 10:11:42 PM
11/24/2021 9:21:54 AM
----";
foreach (string s in dates.Split('\n'))
{
if (DateTime.TryParse(s, new CultureInfo("en-US"), DateTimeStyles.None, out DateTime d))
{
Console.WriteLine(d);
}
}
}
Here is the .Net fiddle link.
EDIT: Note that the version on .Net fiddle is slightly different because of the older C# version there.
Without the exact details, I have to guess:
If he only can translate the 6/8 date, you may have the wrong locale settings (you have something like MM/dd/yyyy .... but this works only for the 8th of june, what you might get wrong with 6th of august)
If you use ParseExact, you can also provide a list of valid format strings.
EDIT
Cetins answer is correct. Additionally, the title of the post is a bit confusing, because the datetime string IS consistent (in the 'en-US' local settings)
#Cetin Basoz You are right, it was indeed a culture problem. Thank you!
#nabuchodonossor You are right about the datetime string ("----" apart) being consistent. What I wanted to say was that there is no every time two digits for the days or months which would not happen if the dates were something like 05/18/2020 and 06/08/2021. Sorry, I have a hard time being precise.
I want datetime.now to return the datetime object in UK format. It does so on my local computer but when I upload the code to the server it does it in US format
DateTime doesn't have any format associated with it. Formatting is just for presentation. You can do:
string formattedDate = DateTime.Now.ToString(CultureInfo.CreateSpecificCulture("en-GB"));
Or supply a specific/custom format like:
string formattedDate = DateTime.Now.ToString("dd/MM/yyyy HH:mm:ss",
CultureInfo.InvariantCulture);
I want datetime.now to return the datetime object in UK format.
There's no such concept, any more than an int is a value "in hex" or "in decimal". A DateTime is just a DateTime - you can specify the format when you convert it to a string. It's really important to understand the difference between an inherent value, and what it looks like after it's converted to text - very few types are aware of a custom, modifiable format to use when converting themselves - it's either provided externally (as for DateTime, numbers etc) or simply fixed.
Before you convert start hard-coding a UK format though, I would strongly advise you to consider exactly what you're doing:
Ideally, avoid the conversion in the first place. A lot of the time, string conversions are unnecessary and can be problematic.
Is the text going to be consumed by another machine? Use an ISO-8601 standard format.
Is the text going to be consumed by a person? Use their culture rather than some arbitrary one you decide on.
... Or display it in a dedicated control...
You can use the overload of the ToString method: ToString("dd/MM/yyyy"), or: ToString("yy/MMM/dd"), etc. etc.
Read more about it here: https://msdn.microsoft.com/en-us/library/zdtaw1bw%28v=vs.110%29.aspx
Also sounds to me that you might want to configure your (UI-)Culture in the web.config? Then it will always be in the same format regardless of the culture of your US/Japanese/european server culture..
More about that here: https://msdn.microsoft.com/en-us/library/bz9tc508%28v=vs.140%29.aspx
LogDate = DateTime.UtcNow.AddHours(1);
I am trying to input a datetime value from the console. However, The TryParseExact method doesn't receive valid formats:
string startdate;
DateTime inputDate;
while (true)
{
Console.WriteLine("Input time [HH:MM TT]");
startdate = Console.ReadLine();
if (DateTime.TryParseExact(startdate, "hh:mm tt",
CultureInfo.CurrentCulture,
DateTimeStyles.None, out inputDate))
{
break;
}
}
Any suggestions?
If it is not accepting input that you think is valid then there are two possible causes of the problem:
1) The input is not what you think it is. This could be caused by copying and pasting from somewhere else that is including non-valid characters or something. IF you are manually typing the number then this is unlikely to be an issue.
2) The format you are accepting is not what you think it is. This is most likely since there are some subtleties that can bite you on this. The key think is to look up everything in http://msdn.microsoft.com/en-us/library/8kb3ddd4(v=vs.110).aspx and be aware that several elements you are using are culture dependant. You are obviously at least partially aware of cultures since you are explicitly stating you want the current culture. Without knowing what that culture is though its hard to say what the input should be.
A case in point is that in your format : doesn't mean a literal colon but the "Time Separator". To quote the MSDN page: "The ":" custom format specifier represents the time separator, which is used to differentiate hours, minutes, and seconds. The appropriate localized time separator is retrieved from the DateTimeFormatInfo.TimeSeparator property of the current or specified culture."
As you can see this means that it is not always :.
Often the best fix, especially since you are hard definining the format, is to use CultureInfo.InvariantCulture which will guarantee not to change depending on where you run the software, etc. Otherwise you should generate the string that specifies the correct input using the relevant components of your current culture object.
An example of how to write this without the white(true) loop / to try to make it easier for your users:
string startdate;
DateTime inputDate;
while (inputDate == null)
{
Console.WriteLine("Input time [HH:MM TT]");
startdate = Console.ReadLine();
if (!DateTime.TryParseExact
(
startdate, "hh:mm tt"
,CultureInfo.CurrentCulture
,DateTimeStyles.None
, out inputDate
))
{
Console.WriteLine(String.Format("'{0}' is an invalid value."));
//http://msdn.microsoft.com/en-us/library/8kb3ddd4(v=vs.110).aspx
Console.WriteLine(
String.Format("Example: The time now is '{0}'"
,DateTime.Now.ToString("hh:mm tt", CultureInfo.CurrentCulture))
);
}
}
Console.WriteLine("That's a valid time :)");
NB: your above code works in so much as given the correct input (for your user's current culture) the code exits the loop.
How come
w.WriteLine(Program.RegisterList[i].DateTime);
Writes : 11/20/2013 01:46:31 PM
But
w.WriteLine(Convert.ToDateTime(Program.RegisterList[i].DateTime, CultureInfo.InvariantCulture).ToString());
Writes 20/11/2013 1:46:31 PM
? Isn't invariant culture supposed to make it MM/DD/YY? I would like to use the invariant culture method incase a date slips by in DD/MM/YY format.
Thanks!
Edit: I should mention Program.RegisterList[i].DateTime is a string.
Edit2:
MessageBox.Show("11/20/2013 01:46:31 PM");
MessageBox.Show(Convert.ToDateTime("11/20/2013 01:46:31 PM", CultureInfo.InvariantCulture).ToString());
w.WriteLine(Convert.ToDateTime(Program.RegisterList[i].DateTime, CultureInfo.InvariantCulture).ToString());
You confused yourself by writing code you can't understand anymore. A simple rewrite of that one honking statement:
string s = Program.RegisterList[i].DateTime;
DateTime dt = Convert.ToDateTime(s, CultureInfo.InvariantCulture);
w.WriteLine(dt);
Which should now make it obvious that you are not using InvariantCulture to display the date, it uses the default culture. Which on your machine puts the day first.
Always write readable code, it is not slower.
CultureInvariant only guarantees that the format won't change across cultures - it should not be used to display data, only to persist data. If you're concerned about how a string is displayed, you should use a specific culture that displays how you want. More from MSDN
Having said that, I'm not sure what you mean by a "date slipping by" in a different format. Are you reading a list of dates, and some are in different format? If so, I'm afraid CultureInvariant is not the answer.
I have a datetime coming back from an XML file in the format:
20080916 11:02
as in
yyyymm hh:ss
How can I get the datetime.parse function to pick up on this? Ie parse it without erroring?
DateTime.ParseExact(input,"yyyyMMdd HH:mm",null);
assuming you meant to say that minutes followed the hours, not seconds - your example is a little confusing.
The ParseExact documentation details other overloads, in case you want to have the parse automatically convert to Universal Time or something like that.
As #Joel Coehoorn mentions, there's also the option of using TryParseExact, which will return a Boolean value indicating success or failure of the operation - I'm still on .Net 1.1, so I often forget this one.
If you need to parse other formats, you can check out the Standard DateTime Format Strings.
Thanks for the tip, i used this to get my date "20071122" parsed, I needed to add datetimestyles, I used none and it worked:
DateTime dt = DateTime.MinValue;
DateTime.TryParseExact("20071122", "yyyyMMdd", null,System.Globalization.DateTimeStyles.None, out dt);